home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-02-03 | 55.0 KB | 1,981 lines |
- Newsgroups: comp.sources.misc
- From: tim@deakin.edu.au (Tim Cook)
- Subject: v35i012: describe - File Descriptions, Part01/03
- Message-ID: <csm-v35i012=describe.001203@sparky.IMD.Sterling.COM>
- X-Md4-Signature: da7f0b40525d7523a8d71a222e28446a
- Date: Tue, 2 Feb 1993 06:14:03 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: tim@deakin.edu.au (Tim Cook)
- Posting-number: Volume 35, Issue 12
- Archive-name: describe/part01
- Environment: UNIX, DBM
-
- Have you ever wondered what on earth "xfrg2.2.tar.Z" was? Are you
- wondering whether "foo" is really a scratch file? Does it ashame you
- especially, seeing that these files were created by you?
-
- I have the solution for you... File Descriptions.
-
- I'm sure some operating system or another once had the ability to set
- a descriptive comment on a file, but Unix wasn't one of them. It is
- possible, however, to retro-fit onto Unix an implementation that works
- quite well.
-
- In this package, I have provided a utility to set/delete/list file
- descriptions (describe), and a directory listing utility that shows
- any file descriptions that are set next to the respective files (dl).
-
- Implementation
- --------------
- The storage/retrieval of file-descriptions is implemented in the
- following way:
-
- All file descriptions are stored in a DBM file called .desc,
- in the same directory as the files described. This in fact
- means that you have two files, .desc.pag and .desc.dir.
-
- Each description is indexed by the name of the file (excluding
- any path information). To provide a better chance of finding
- the description after the file has been renamed (within the
- same directory), the name is also indexed by the inode-number.
- This means that the file's description will still be found
- after it has been renamed (within the same directory) or
- re-written by an editor. To prevent the two indexes from
- becoming mixed up, whenever a name/description pair are stored
- with a name that is the same size as an inode-number, the name
- is stored with a trailing null byte.
-
- Purpose
- -------
- My reason for coming up with this idea is simple. I got tired of
- logging on to some distant site's anonymous FTP area, and coming
- across something like:
-
- -rw-r--r-- 1 root 214807 May 22 1989 3c503.tar.Z
- -rw-r--r-- 1 bin 27751 Aug 22 16:35 bonnie
- -rw-rw-r-- 1 uucp 65383 Aug 23 02:54 dynafeed.tar.Z
- -rw-r--r-- 1 bin 10444 Nov 3 21:58 fpipe
- -rw-r--r-- 1 bin 47138 Aug 22 16:41 opaque (good name!)
- -rw-r--r-- 1 don 683759 May 29 23:21 psiber.tar.Z
-
- You know? You sit there and think ... "some of those sound
- interesting, but it wouldn't be nice for me to download them just to
- find out what they are...".
-
- If there is no other demand for describe/dl, there should be as a
- replacement for ls in anonymous FTP areas. And that's how simple it
- is, once you have dl installed, simply copy it to ~ftp/bin/ls, and
- the FTP daemon will use it instead of standard ls for anonymous
- logins. The output of dl was actually designed with anonymous FTP
- use in mind (who cares who owns the file or which group it belongs
- to?).
-
- Of course, the site administrator has to provide meaningful
- descriptions for what has been put in the anonymous FTP area. I don't
- think it would be too hard to generate descriptions files from an
- index of something like comp.sources.misc, though. A dozen lines of
- perl should do it.
-
- An Example
- ----------
- As an example of what an anonymous FTP site that uses dl looks like,
- try my back yard, archive.viccol.edu.au.
-
- E-mail: tim@deakin.edu.au
-
- Tim Cook
- ----------------
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: README config.h describe.c dl.c list.c other other/descopt
- # patches patches/GNU-compress.patch patches/GNU-mv.patch
- # Wrapped by kent@sparky on Mon Feb 1 10:15:03 1993
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 1 (of 3)."'
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(5222 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- XDescription
- X-----------
- XHave you ever wondered what on earth "xfrg2.2.tar.Z" was? Are you
- Xwondering whether "foo" is really a scratch file? Does it ashame you
- Xespecially, seeing that these files were created by you?
- X
- XI have the solution for you... File Descriptions.
- X
- XI'm sure some operating system or another once had the ability to set
- Xa descriptive comment on a file, but Unix wasn't one of them. It is
- Xpossible, however, to retro-fit onto Unix an implementation that works
- Xquite well.
- X
- XIn this package, I have provided a utility to set/delete/list file
- Xdescriptions (describe), and a directory listing utility that shows
- Xany file descriptions that are set next to the respective files (dl).
- X
- XImplementation
- X--------------
- XThe storage/retrieval of file-descriptions is implemented in the
- Xfollowing way:
- X
- X All file descriptions are stored in a DBM file called .desc,
- X in the same directory as the files described. This in fact
- X means that you have two files, .desc.pag and .desc.dir.
- X
- X Each description is indexed by the name of the file (excluding
- X any path information). To provide a better chance of finding
- X the description after the file has been renamed (within the
- X same directory), the name is also indexed by the inode-number.
- X This means that the file's description will still be found
- X after it has been renamed (within the same directory) or
- X re-written by an editor. To prevent the two indexes from
- X becoming mixed up, whenever a name/description pair are stored
- X with a name that is the same size as an inode-number, the name
- X is stored with a trailing null byte.
- X
- X
- XPurpose
- X-------
- XMy reason for coming up with this idea is simple. I got tired of
- Xlogging on to some distant site's anonymous FTP area, and coming
- Xacross something like:
- X
- X-rw-r--r-- 1 root 214807 May 22 1989 3c503.tar.Z
- X-rw-r--r-- 1 bin 27751 Aug 22 16:35 bonnie
- X-rw-rw-r-- 1 uucp 65383 Aug 23 02:54 dynafeed.tar.Z
- X-rw-r--r-- 1 bin 10444 Nov 3 21:58 fpipe
- X-rw-r--r-- 1 bin 47138 Aug 22 16:41 opaque (good name!)
- X-rw-r--r-- 1 don 683759 May 29 23:21 psiber.tar.Z
- X
- XYou know? You sit there and think ... "some of those sound
- Xinteresting, but it wouldn't be nice for me to download them just to
- Xfind out what they are...".
- X
- XIf there is no other demand for describe/dl, there should be as a
- Xreplacement for ls in anonymous FTP areas. And that's how simple it
- Xis, once you have dl installed, simply copy it to ~ftp/bin/ls, and
- Xthe FTP daemon will use it instead of standard ls for anonymous
- Xlogins. The output of dl was actually designed with anonymous FTP
- Xuse in mind (who cares who owns the file or which group it belongs
- Xto?).
- X
- XOf course, the site administrator has to provide meaningful
- Xdescriptions for what has been put in the anonymous FTP area. I don't
- Xthink it would be too hard to generate descriptions files from an
- Xindex of something like comp.sources.unix, though. A dozen lines of
- Xperl should do it.
- X
- XAn Example
- X----------
- XAs an example of what an anonymous FTP site that uses dl looks like,
- Xtry my back yard, archive.viccol.edu.au.
- X
- XCopyright
- X---------
- XThe whole system is Copyright (c) Tim Cook 1991, 1992, apart from
- Xstrpbrk.c which is Copyright (c) 1985 Regents of the University of
- XCalifornia. All together, the package can be distributed provided no
- Xprofit is made from any distribution, and all copyright notices remain
- Xintact.
- X
- XThe Author
- X----------
- XTim Cook, Systems Programmer, Computing & Communications Services,
- XDeakin University.
- X
- XE-mail: tim@deakin.edu.au
- X
- X(Note that Victoria College (viccol) has merged with Deakin
- XUniversity.)
- X
- XMiscellaneous
- X-------------
- XThe "dl" command used to be known as "dls", but Ultrix already had a
- X"dls" command, which is for "DECnet ls", so I changed it.
- X
- XThe dl/describe package was developed under DYNIX version 3.0.12 and
- X3.1.2, which is a BSD 4.2 based version of Unix. This means that
- Xdl/describe should compile on "most" BSD 4.2 derived systems. I have
- Xpersonally had success compiling it on SunOS 4.1 and Solaris 2.0
- Xsystems. It has also compiled on several SYSV-based systems. See
- XINSTALL, config.h and Makefile for porting details.
- X
- XCould I ask all those who install dl in their Anonymous FTP areas to
- Xdrop me a line? Any criticisms or suggestions gladly accepted. I am
- Xquite interested in what people think of this idea.
- X
- XI am also interested in seeing the results of any porting efforts, so
- Xthat I can incorporate them in later releases. Depending on the level
- Xof my spare time, I would even be prepared to assist you in porting
- Xthis to your particular brand of Unix. I have a desire to see this
- Xpropagate as far as possible around the world of Unix anonymous FTP
- Xsites.
- X
- XThe Future for dl/describe
- X---------------------------
- XSo far, dl has been installed in only a few Anonymous FTP
- Xinstallations. I would like to lobby, or have others lobby some of
- Xthe larger or more popular sites to have them think about dl.
- X
- XTo make dl seem better though, I will be adding the following (I
- Xcan't say when though):
- X
- X 1. Better co-operation with ftpd and the archie system.
- X
- X 2. Add to the set of patches to make commonly used file utilities
- X aware of file descriptions.
- X
- X 3. Better portability.
- END_OF_FILE
- if test 5222 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'config.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'config.h'\"
- else
- echo shar: Extracting \"'config.h'\" \(7107 characters\)
- sed "s/^X//" >'config.h' <<'END_OF_FILE'
- X/* config.h - Configuration and portability definitions
- X *
- X * Copyright (c) 1991,1992 Tim Cook.
- X * Non-profit distribution allowed. See README for details.
- X *
- X * $Id: config.h,v 1.7 1993/01/29 04:32:37 tim Exp tim $
- X */
- X
- X#ifndef _CONFIG_H_
- X#define _CONFIG_H_
- X
- X/*****************************************************************************
- X * SVR4.
- X *
- X * If you are running System V, Release 4, define SVR4, which will
- X * activate the following assumptions:
- X * - readdir, etc requires <dirent.h>
- X * - readdir return struct dirent
- X * - No "d_namlen" field in DIRENT structure
- X * - Include <fcntl.h> to get O_CREAT, etc.
- X */
- X/* #define SVR4 /* */
- X
- X/*****************************************************************************
- X * SYSV
- X *
- X * If you have a System V or System V based system, define SYSV. This
- X * will activate the following assumptions:
- X * - Include <time.h> instead of <sys/time.h>.
- X * - No "d_namlen" field in DIRENT structure.
- X * - Include <fcntl.h> to get O_CREAT, etc.
- X */
- X/* #define SYSV /* */
- X
- X/*****************************************************************************
- X * Date orientation.
- X *
- X * For those who prefer seeing the month before the day of the month
- X * in dates, define US_DATE_FORMAT.
- X */
- X/* #define US_DATE_FORMAT /* */
- X
- X/*****************************************************************************
- X * Display of symbolic links.
- X *
- X * If you want "dl" to display the contents of a symbolic link,
- X * preceded by "-> " if there is no description for the link. Define
- X * SHOW_SYMLINK. If your system does not have symbolic links, do not
- X * define SHOW_SYMLINK.
- X */
- X#define SHOW_SYMLINK /* */
- X
- X/*****************************************************************************
- X * DBM library
- X *
- X * If you have an NDBM-compatible library, define NDBM, otherwise, you
- X * will need DBM. If you have a version of DBM that does not include
- X * the dbmclose(3) routine, define NO_DBMCLOSE.
- X */
- X#define NDBM /* */
- X/* #define NO_DBMCLOSE /* */
- X
- X/*****************************************************************************
- X * Directory reading routines.
- X *
- X * Check your man page for directory(3) and define one of DIRENT,
- X * SYS_DIR or SYS_NDIR to denote where the necessary include file is.
- X * If your readdir(3) returns a "struct direct" pointer, define
- X * DIRECT, otherwise it will be assumed that readdir(3) returns a
- X * "struct dirent" pointer.
- X */
- X#ifdef SVR4
- X
- X#define DIRENT
- X#define NO_D_NAMLEN /* No d_namlen field in dirent structure */
- X
- X#else /* SVR4 */
- X
- X#ifdef SYSV
- X#define NO_D_NAMLEN
- X#endif
- X
- X/* #define DIRENT /* to include <dirent.h> */
- X#define SYS_DIR /* to include <sys/dir.h> */
- X/* #define SYS_NDIR /* to include <sys/ndir.h> */
- X
- X#define DIRECT /* readdir(3) returns "struct direct *" */
- X
- X#endif /* SVR4 */
- X
- X/*****************************************************************************
- X * Uid/gid types
- X *
- X * Define these to what is returned by getuid(2) and getgid(2) (check
- X * the man pages). If not defined, "uid_t" and "gid_t" will be used
- X * (from <sys/types.h>).
- X */
- X#ifndef SVR4
- X/* #define UID_T int /* */
- X/* #define GID_T int /* */
- X#endif
- X
- X/*****************************************************************************
- X * Data alignment
- X *
- X * If your architecture requires particular data items to be aligned,
- X * you may need to define this (you will if you get a "bus error" when
- X * you attempt a "dl -t"). Define it to 2 for word alignment or 4 for
- X * longword alignment.
- X */
- X
- X#ifdef sparc
- X#define ALIGN 4 /* Longword alignment */
- X#endif
- X
- X/* #define ALIGN 2 /* Word alignment */
- X
- X/*****************************************************************************
- X * strings.h/string.h
- X *
- X * If you have no <string.h> on your system, define STRINGS and
- X * <strings.h> will be included instead. Check the manual page for
- X * strcat(3).
- X */
- X#ifndef SVR4
- X/* #define STRINGS /* */
- X#endif
- X
- X/*****************************************************************************
- X * str(r)chr/(r)index
- X *
- X * If you have no str(r)chr(3) on your system, define INDEX and
- X * (r)index(3) will be used instead.
- X */
- X#ifndef SVR4
- X/* #define INDEX /* */
- X#endif
- X
- X/*****************************************************************************
- X * memcpy/bcopy
- X *
- X * If you have no memcpy(3), memset(3) etc., but you do have bcopy(3),
- X * bzero(3), etc., define BCOPY.
- X */
- X#ifndef SVR4
- X/* #define BCOPY /* */
- X#endif
- X
- X/*****************************************************************************
- X * Void types
- X *
- X * If your compiler does not handle any of these types, define them to
- X * something it will handle. The recognised types will be used if
- X * these macros are not defined.
- X */
- X
- X/* #define VOID int /* replacement for "void" */
- X/* #define VOID_PTR char * /* replacement for "void *" */
- X/* #define VOID_PTR_PTR char ** /* replacement for "void **" */
- X
- X
- X/*****************************************************************************
- X * NOTHING PAST HERE SHOULD NEED TO BE MODIFIED *
- X *****************************************************************************/
- X
- X#ifdef NDBM
- X
- X# include <ndbm.h>
- X# define DBM_fetch(db, key) dbm_fetch (db, key)
- X# define DBM_store(db, key, val) \
- X dbm_store(db, key, val, DBM_REPLACE)
- X# define DBM_delete(db, key) dbm_delete (db, key)
- X# define DBM_firstkey(db) dbm_firstkey (db)
- X# define DBM_nextkey(db, key) dbm_nextkey (db)
- X
- X# define DBM_close(db) if (! (db)) ; else dbm_close (db)
- X
- X#else
- X
- X# include <dbm.h>
- X# define DBM_fetch(db, key) fetch (key)
- X# define DBM_store(db, key, val) \
- X store(key, val)
- X# define DBM_delete(db, key) delete (key)
- X# define DBM_firstkey(db) firstkey ()
- X# define DBM_nextkey(db, key) nextkey (key)
- X
- X# ifdef NO_DBMCLOSE
- X# define DBM_close(db)
- X# else
- X# define DBM_close(db) dbmclose ()
- X# endif
- X
- X# ifdef NULL
- X# undef NULL /* Aaaaaaarrrrgghhh! */
- X# endif
- X#endif
- X
- X/* This will probably be needed by one of the next three */
- X#include <sys/types.h>
- X
- X#ifdef DIRENT
- X# include <dirent.h>
- X# undef DIRENT
- X#else
- X# ifdef SYS_DIR
- X# include <sys/dir.h>
- X# undef SYS_DIR
- X# else
- X# ifdef SYS_NDIR
- X# include <sys/ndir.h>
- X# undef SYS_NDIR
- X# endif
- X# endif
- X#endif
- X
- X#ifdef DIRECT
- X# define DIRENT struct direct
- X# undef DIRECT
- X#else
- X# define DIRENT struct dirent
- X#endif
- X
- X#ifndef UID_T
- X#define UID_T uid_t
- X#endif
- X#ifndef GID_T
- X#define GID_T gid_t
- X#endif
- X
- X#ifdef ALIGN
- X# if ALIGN == 1
- X# undef ALIGN
- X# endif
- X#endif
- X
- X#ifdef STRINGS
- X# include <strings.h>
- X# undef STRINGS
- X#else
- X# include <string.h>
- X#endif
- X
- X#ifdef INDEX
- X# define strchr index
- X# define strrchr rindex
- X# undef INDEX
- X#endif
- X
- X#ifdef BCOPY
- X# define memcpy(d,s,n) bcopy(s,d,n)
- X# define memzero(s,n) bzero(s,n)
- X# undef BCOPY
- X#else
- X# define memzero(s,n) memset(s,'\0',n)
- X#endif
- X
- X#ifndef VOID
- X# define VOID void
- X#endif
- X#ifndef VOID_PTR
- X# define VOID_PTR void *
- X#endif
- X#ifndef VOID_PTR_PTR
- X# define VOID_PTR_PTR void **
- X#endif
- X
- X/* Miscellaneous */
- X#ifndef TRUE
- X#define TRUE 1
- X#define FALSE 0
- X#endif
- X
- X#ifndef EOS
- X#define EOS '\0'
- X#endif
- X
- X#ifndef NULL_CP
- X#define NULL_CP ((char *) 0)
- X#endif
- X
- X#ifndef print
- X#define print(s) fputs (s, stdout)
- X#define printc(c) putc (c, stdout)
- X#endif
- X
- X#endif /* _CONFIG_H_ */
- END_OF_FILE
- if test 7107 -ne `wc -c <'config.h'`; then
- echo shar: \"'config.h'\" unpacked with wrong size!
- fi
- # end of 'config.h'
- fi
- if test -f 'describe.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'describe.c'\"
- else
- echo shar: Extracting \"'describe.c'\" \(6025 characters\)
- sed "s/^X//" >'describe.c' <<'END_OF_FILE'
- X/* describe.c - Set or list a descriptive comment for a file
- X *
- X * Copyright (c) 1991, 1992 Tim Cook.
- X * Non-profit distribution allowed. See README for details.
- X */
- X
- Xstatic char rcsid[] = "$Id: describe.c,v 1.15 1993/01/29 03:53:22 tim Exp tim $";
- X
- X#include "config.h"
- X#include <stdio.h>
- X#include <sys/param.h>
- X#include <sys/file.h>
- X#include <sys/stat.h>
- X
- X#if defined(SYSV) || defined(SVR4)
- X#include <fcntl.h> /* for O_CREAT, etc. */
- X#endif
- X
- X#ifndef MAXPATHLEN
- X#define MAXPATHLEN 1024
- X#endif
- X
- Xextern char *getdesc () ;
- Xextern int setdesc () ;
- Xextern VOID enddesc () ;
- X
- Xstatic char *program_name ;
- X
- Xstatic VOID usage () ;
- Xstatic VOID set_description () ;
- Xstatic VOID set_from_file () ;
- Xstatic VOID list_descriptions () ;
- X
- Xstatic VOID describe_version () ;
- X
- X
- X
- Xint main (argc, argv)
- X int argc ;
- X char **argv ;
- X{
- X extern int errno ;
- X extern char *optarg ;
- X extern int optind, opterr ;
- X int option ;
- X static char options[] = "dlcvf:" ;
- X
- X#define UNDEFINED 0
- X#define DELETE_DESC 'd'
- X#define LIST_DIR 'l'
- X#define COPY_DESC 'c'
- X#define SET_FROM_FILE 'f'
- X int mode = UNDEFINED ;
- X
- X char *description ;
- X char *directory ;
- X char *description_file ;
- X
- X program_name = argv[0] ;
- X while ((option = getopt (argc, argv, options)) != EOF) {
- X if (option == 'v') {
- X describe_version ();
- X exit (0); }
- X
- X if (mode != UNDEFINED)
- X /* Can't do more than one thing at a time, dearie! */
- X usage () ;
- X
- X if (option == ':' || strchr (options, (char) option) == NULL_CP)
- X /* Bad option */
- X usage () ;
- X
- X if (option == SET_FROM_FILE)
- X description_file = optarg ;
- X mode = option ; }
- X
- X
- X /* Do the work */
- X switch (mode) {
- X case SET_FROM_FILE:
- X /* Set descriptions from file */
- X
- X if (optind >= argc)
- X directory = "." ;
- X else
- X directory = argv[optind] ;
- X set_from_file (description_file, directory) ;
- X break ;
- X
- X case DELETE_DESC:
- X /* Delete description(s) */
- X
- X if (optind >= argc)
- X usage () ;
- X
- X for ( ; optind < argc ; optind++)
- X set_description (argv[optind], NULL_CP, NULL_CP) ;
- X break ;
- X
- X case LIST_DIR:
- X /* List directory */
- X
- X if (optind >= argc)
- X directory = "." ;
- X else
- X directory = argv[optind] ;
- X list_descriptions (directory) ;
- X break ;
- X
- X case COPY_DESC:
- X /* Copy description from another file or directory */
- X
- X if (optind != (argc - 2))
- X /* Not enough arguments */
- X usage () ;
- X
- X errno = 0 ;
- X description = getdesc (argv[optind+1], NULL_CP, NULL_CP, 0) ;
- X if (! errno) {
- X char desc[1024] ;
- X
- X strncpy (desc, description, sizeof (desc)) ;
- X desc[sizeof (desc) - 1] = '\0' ;
- X set_description (argv[optind], NULL_CP, desc) ; }
- X else
- X perror2 (program_name, argv[optind+1]) ;
- X break ;
- X
- X default:
- X /* Set description of specified file */
- X
- X if (argc != 3)
- X usage () ;
- X
- X set_description (argv[1], NULL_CP, argv[2]) ;
- X }
- X
- X enddesc () ;
- X
- X exit (0) ;
- X }
- X
- X
- Xstatic
- XVOID usage ()
- X{
- X describe_version ();
- X
- X fprintf (stderr, "\
- Xusage: %s <file> <description>\n\
- X or: %s -c <file> <other-file>\n\
- X or: %s -f <descriptions-file> [<directory>]\n\
- X or: %s -d <file> ...\n\
- X or: %s -l [<directory>]\n",
- X program_name, program_name, program_name, program_name, program_name) ;
- X exit (2) ;
- X }
- X
- X
- Xstatic
- XVOID set_description (file, directory, description)
- X char *file ;
- X char *directory ;
- X char *description ;
- X{
- X struct stat status ;
- X
- X if (stat (file, &status) == -1) {
- X perror2 (program_name, file) ;
- X exit (1) ; }
- X if (! setdesc (file, directory, NULL_CP, status.st_ino, description))
- X perror2 (program_name, file) ;
- X }
- X
- X
- Xstatic
- XVOID set_from_file (file, directory)
- X char *file ;
- X char *directory ;
- X{
- X FILE *descriptions ;
- X char file_name[MAXPATHLEN+1] ;
- X char buffer[1024] ;
- X char description[256] ;
- X struct stat status ;
- X int n ;
- X
- X if (strcmp (file, "-") == 0)
- X descriptions = stdin ;
- X else {
- X if ((descriptions = fopen (file, "r")) == (FILE *) NULL) {
- X perror2 (program_name, file) ;
- X exit (1) ; } }
- X if (chdir (directory) == -1) {
- X perror2 (program_name, directory) ;
- X exit (1) ; }
- X
- X while (! feof (descriptions)) {
- X if (fgets (buffer, sizeof (buffer), descriptions) != NULL_CP) {
- X n = sscanf (buffer, "\"%[^\"]\" %[^\n]\n", file_name, description) ;
- X if (n < 2)
- X n = sscanf (buffer, "%s %[^\n]\n", file_name, description) ;
- X if (n == 2 && file_name[0] != '#')
- X set_description (file_name, directory, description) ;
- X }
- X }
- X
- X fclose (descriptions) ;
- X }
- X
- X
- Xstatic
- XVOID list_descriptions (directory)
- X char *directory ;
- X{
- X char file_name[MAXPATHLEN+1] ;
- X int file_name_length ;
- X int gap ;
- X DIR *dir ;
- X DIRENT *dir_entry ;
- X char *desc ;
- X
- X /*
- X * Loop through all the files in this directory, seeing if we can
- X * find a description for each one.
- X */
- X
- X if ((dir = opendir (*directory == EOS ? "." : directory)) == (DIR *) NULL) {
- X perror ("opendir") ;
- X exit (1) ; }
- X while ((dir_entry = readdir (dir)) != (DIRENT *) NULL) {
- X
- X if ((desc = getdesc (NULL_CP, directory, dir_entry->d_name,
- X dir_entry->d_ino)) != NULL_CP) {
- X
- X /* Print it out! */
- X#ifdef NO_D_NAMLEN
- X file_name_length = strlen (dir_entry->d_name) ;
- X#else
- X file_name_length = dir_entry->d_namlen ;
- X#endif
- X strncpy (file_name, dir_entry->d_name, file_name_length) ;
- X file_name[file_name_length] = EOS ;
- X
- X if (strpbrk (file_name, " \t") != NULL_CP) {
- X printc ('"') ;
- X print (file_name) ;
- X printc ('"') ;
- X gap = 18 - file_name_length ; }
- X else {
- X print (file_name) ;
- X gap = 20 - file_name_length ; }
- X printc (' ') ; /* We need at least one space */
- X while (gap-- > 0)
- X printc (' ') ;
- X print (desc) ;
- X printc ('\n') ; } }
- X
- X }
- X
- X
- Xstatic
- XVOID describe_version ()
- X{
- X#include "version.h"
- X
- X#ifdef __STDC__
- X fprint (stderr, "This is \"" PACKAGE_NAME "\", version "
- X PACKAGE_VERSION "\n");
- X#else
- X fprintf (stderr, "This is \"%s\", version %s\n",
- X PACKAGE_NAME, PACKAGE_VERSION);
- X#endif
- X }
- END_OF_FILE
- if test 6025 -ne `wc -c <'describe.c'`; then
- echo shar: \"'describe.c'\" unpacked with wrong size!
- fi
- # end of 'describe.c'
- fi
- if test -f 'dl.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dl.c'\"
- else
- echo shar: Extracting \"'dl.c'\" \(12166 characters\)
- sed "s/^X//" >'dl.c' <<'END_OF_FILE'
- X/* dl.c - Descriptive ls
- X *
- X * Copyright (c) 1991,1992 Tim Cook.
- X * Non-profit distribution allowed. See README for details.
- X */
- X
- Xstatic char rcsid[] = "$Id: dl.c,v 1.13 1993/01/29 04:23:25 tim Exp tim $" ;
- X
- X#include "config.h"
- X#include <stdio.h>
- X#include <sys/param.h>
- X#include <sys/stat.h>
- X#include <sys/file.h>
- X#include <list.h>
- X
- X#ifdef SYSV
- X#include <time.h>
- X#else
- X#include <sys/time.h>
- X#endif
- X
- X#ifndef MAXPATHLEN
- X#define MAXPATHLEN 1024
- X#endif
- X
- X#ifndef NGROUPS
- X/* This is likely on (old?) SYSV */
- X#define NGROUPS 16 /* A safe guess */
- X#endif
- X
- X
- Xextern time_t time () ;
- Xextern UID_T getuid () ;
- Xextern int getgroups () ;
- X
- Xextern char *getdesc () ;
- Xextern VOID enddesc () ;
- Xextern char *pathname () ;
- X
- X#define strgencpy(new, old) \
- X (new = strcpy ((char *) allocate (strlen (old) + 1), old))
- X
- Xstatic struct file_info {
- X ino_t inode ;
- X u_short mode ;
- X short nlink ;
- X off_t size ;
- X time_t mtime ;
- X char name[4] ; /* This can actually contain a string of any
- X length, I'm just giving the compiler the
- X opportunity to align. */
- X } ;
- X
- X/*
- X * How much space needed for a struct file_info that contains string "s"
- X */
- X#define file_info_size(s) \
- X (sizeof (struct file_info) - 3 + strlen (s))
- X
- X/* options */
- Xstatic int show_date = FALSE ;
- Xstatic int sort_by_date = FALSE ;
- Xstatic int even_inaccessible = FALSE ;
- Xstatic int filename_columns = 14 ;
- Xstatic int recursive = FALSE ;
- X
- X/* other globals */
- X#define FROM_ARGV 0
- X#define FROM_DIR 1
- X
- Xstatic time_t six_months_ago ;
- Xstatic struct file_info not_there ; /* Symbolic value */
- Xstatic int name_and_size_columns ;
- Xstatic int space = FALSE ; /* If TRUE, we need to print a blank
- X line before anything else */
- Xstatic int printed_anything = FALSE ;
- Xstatic UID_T uid ;
- Xstatic int no_groups ;
- Xstatic UID_T groups[NGROUPS] ;
- X
- Xstatic VOID_PTR get_element_from_argv () ;
- Xstatic VOID build_and_sort_list () ;
- Xstatic struct file_info *get_file_info () ;
- Xstatic VOID list_file () ;
- Xstatic VOID list_directory () ;
- X
- X
- Xint main (argc, argv)
- X int argc ;
- X char **argv ;
- X{
- X extern char *optarg ;
- X extern int optind, opterr ;
- X
- X int option ;
- X struct list file_list, dir_list ;
- X struct file_info *file_info ;
- X char *dir_name ;
- X int multiple_args ;
- X
- X opterr = 0 ;
- X while ((option = getopt (argc, argv, "deitf:R")) != EOF) {
- X switch ((char) option) {
- X case 'd' :
- X show_date = TRUE ; break ;
- X case 'e' :
- X case 'i' :
- X even_inaccessible = TRUE ; break ;
- X case 't' :
- X sort_by_date = TRUE ; break ;
- X case 'f' :
- X filename_columns = atoi (optarg) ; break ;
- X case 'R' :
- X recursive = TRUE ; break ;
- X case '?' :
- X break ; } }
- X
- X multiple_args = (argc - optind) > 1 ;
- X
- X name_and_size_columns = filename_columns + 8 ;
- X
- X if (show_date)
- X six_months_ago = time ((time_t *) 0) - (182 * 24 * 60 * 60) ;
- X
- X if (! even_inaccessible) {
- X uid = (UID_T) getuid () ;
- X no_groups = getgroups (NGROUPS, groups) ; }
- X
- X if (optind == argc) {
- X list_directory ("", FALSE) ;
- X enddesc () ;
- X exit (0) ; }
- X
- X list_init (&file_list) ;
- X build_and_sort_list (&file_list, NULL_CP, FROM_ARGV, (char *) argv,
- X (char *) &optind) ;
- X
- X list_init (&dir_list) ;
- X while ((file_info = get_file_info (&file_list, NULL_CP))
- X != (struct file_info *) NULL) {
- X if (file_info != ¬_there) {
- X if (file_info->mode & S_IFDIR)
- X /* Collect these for later */
- X list_push (&dir_list, (VOID_PTR) file_info->name,
- X strlen (file_info->name) + 1) ;
- X else {
- X list_file (file_info, NULL_CP) ; } } }
- X list_free (&file_list) ;
- X
- X /* Now, the directories we collected above */
- X while ((dir_name = (char *) list_shift (&dir_list)))
- X list_directory (dir_name, multiple_args) ;
- X list_free (&dir_list) ;
- X
- X enddesc () ;
- X exit (0) ;
- X }
- X
- X
- Xstatic
- XVOID_PTR get_element_from_argv (param_1, param_2)
- X char *param_1, *param_2 ;
- X{
- X int *argc ;
- X char **argv ;
- X
- X argv = (char **) param_1 ;
- X argc = (int *) param_2 ;
- X return (VOID_PTR) argv[(*argc)++] ;
- X }
- X
- X
- Xstatic
- XVOID_PTR get_element_from_dir (param_1, param_2)
- X char *param_1 ; /* directory pointer (DIR *) */
- X char *param_2 ; /* name of directory */
- X{
- X DIRENT *dir_entry ;
- X
- X for (dir_entry = readdir ((DIR *) param_1) ;
- X dir_entry != (DIRENT *) NULL && dir_entry->d_name[0] == '.' ;
- X dir_entry = readdir ((DIR *) param_1)) ;
- X if (dir_entry == (DIRENT *) NULL)
- X return (VOID_PTR) NULL ;
- X return (VOID_PTR) dir_entry->d_name ;
- X }
- X
- X
- Xstatic
- Xint file_info_date_cmp (info_1, info_2)
- X struct file_info **info_1, **info_2 ;
- X{
- X return (int) ((*info_2)->mtime - (*info_1)->mtime) ;
- X }
- X
- X
- Xstatic
- Xint compare_str (str_1, str_2)
- X char **str_1, **str_2 ;
- X{
- X return strcmp (*str_1, *str_2) ;
- X }
- X
- X
- Xstatic
- XVOID build_and_sort_list (file_list, directory, where_from, param_1, param_2)
- X struct list *file_list ;
- X char *directory ;
- X int where_from ;
- X char *param_1, *param_2 ;
- X{
- X VOID_PTR (*get_element) () ;
- X struct stat file_status ;
- X char *name ;
- X
- X if (where_from == FROM_ARGV)
- X get_element = get_element_from_argv ;
- X else
- X get_element = get_element_from_dir ;
- X
- X if (sort_by_date) {
- X struct file_info *file_info ;
- X
- X file_info = (struct file_info *)
- X allocate (sizeof (struct file_info) + MAXPATHLEN) ;
- X
- X while ((name = (char *) get_element (param_1, param_2)) != NULL_CP) {
- X if (lstat (pathname (directory, name), &file_status) == -1)
- X perror (name) ;
- X else {
- X file_info->inode = file_status.st_ino ;
- X file_info->mode = file_status.st_mode ;
- X file_info->nlink = file_status.st_nlink ;
- X file_info->size = file_status.st_size ;
- X file_info->mtime = file_status.st_mtime ;
- X strcpy (file_info->name, name) ;
- X list_push (file_list, (VOID_PTR) file_info,
- X file_info_size (name)) ;
- X } }
- X
- X free ((VOID_PTR) file_info) ;
- X
- X list_sort (file_list, file_info_date_cmp) ; }
- X
- X else { /* Sort by name */
- X while ((name = (char *) get_element (param_1, param_2)) != NULL_CP) {
- X list_push (file_list, (VOID_PTR) name,
- X ((where_from == FROM_ARGV) ? 0 : (strlen (name) + 1))) ; }
- X list_sort (file_list, compare_str) ; }
- X }
- X
- X
- Xstatic
- Xstruct file_info *get_file_info (file_list, directory)
- X struct list *file_list ;
- X char *directory ;
- X{
- X static struct stat status ; /* Tongue twister */
- X char *name ;
- X int listable ;
- X int n ;
- X
- X if (sort_by_date)
- X return (struct file_info *) list_shift (file_list) ;
- X else {
- X name = (char *) list_shift (file_list) ;
- X if (name == (char *) NULL)
- X return (struct file_info *) NULL ;
- X else
- X if (lstat (pathname (directory, name), &status) == -1) {
- X perror (name) ;
- X return ¬_there ; }
- X else {
- X if (! even_inaccessible) {
- X if (uid == (UID_T) status.st_uid)
- X listable = status.st_mode & 0500 ;
- X else {
- X for (n = 0 ; n < no_groups ; n++) {
- X if (groups[n] == (GID_T) status.st_gid) {
- X listable = status.st_mode & 050 ;
- X n = no_groups + 1 ; } }
- X if (n == no_groups)
- X listable = status.st_mode & 05 ; } }
- X else
- X listable = TRUE ;
- X if (! listable)
- X return ¬_there ;
- X else {
- X static struct file_info *file_info ;
- X
- X if (! file_info)
- X file_info = (struct file_info *)
- X allocate (sizeof (struct file_info) + MAXPATHLEN) ;
- X file_info->inode = status.st_ino ;
- X file_info->mode = status.st_mode ;
- X file_info->nlink = status.st_nlink ;
- X file_info->size = status.st_size ;
- X file_info->mtime = status.st_mtime ;
- X strcpy (file_info->name, name) ;
- X return file_info ; } } }
- X }
- X
- X
- Xstatic
- XVOID list_directory (directory_name, show_directory)
- X char *directory_name ;
- X int show_directory ;
- X{
- X DIR *dirp ;
- X struct list file_list, dir_list ;
- X struct file_info *file_info ;
- X
- X space = FALSE ;
- X if (show_directory) {
- X if (printed_anything) {
- X printc ('\n') ; }
- X printf ("%s:\n", directory_name) ;
- X printed_anything = TRUE ; }
- X
- X if ((dirp = opendir (*directory_name == EOS ? "." : directory_name))
- X == (DIR *) NULL) {
- X perror (directory_name) ; }
- X else {
- X list_init (&file_list) ;
- X build_and_sort_list (&file_list, directory_name, FROM_DIR,
- X (char *) dirp, directory_name) ;
- X list_init (&dir_list) ;
- X while ((file_info = get_file_info (&file_list, directory_name))
- X != (struct file_info *) NULL) {
- X if (file_info != ¬_there) {
- X if (recursive && file_info->mode & S_IFDIR)
- X /* Save this for later */
- X list_push (&dir_list, (VOID_PTR) file_info->name,
- X strlen (file_info->name) + 1) ;
- X list_file (file_info, directory_name) ; } }
- X list_free (&file_list) ;
- X closedir (dirp) ;
- X
- X if (recursive) {
- X char *saved_dir ;
- X char *path, *sub_dir ;
- X
- X /* Now, the directories we saved earlier */
- X while ((saved_dir = (char *) list_shift (&dir_list))) {
- X path = pathname (directory_name, saved_dir) ;
- X list_directory (strgencpy (sub_dir, path), TRUE) ;
- X free ((VOID_PTR) sub_dir) ; }
- X list_free (&dir_list) ; } }
- X
- X space = TRUE ;
- X }
- X
- X
- X
- X
- Xstatic
- XVOID list_file (file_info, directory)
- X struct file_info *file_info ;
- X char *directory ;
- X{
- X static char month[][12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"} ;
- X char out_name[MAXPATHLEN+2] ; /* What to print */
- X char *desc ;
- X#ifdef SHOW_SYMLINK
- X int symlink = 0 ;
- X#endif
- X static char size[12] ;
- X static char date[16] ;
- X int name_len, size_len, gap ;
- X struct tm *tm_time ;
- X
- X if (directory)
- X desc = getdesc (NULL_CP, directory, file_info->name, file_info->inode) ;
- X else
- X desc = getdesc (file_info->name, NULL_CP, NULL_CP, file_info->inode) ;
- X
- X#ifdef SHOW_SYMLINK
- X /* If file is a symbolic link, and has no description, we will */
- X /* generate a description that indicates what file it points to */
- X#ifndef S_ISLNK
- X#define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK)
- X#endif
- X if ((! desc) && S_ISLNK (file_info->mode)) {
- X desc = (char *) allocate (1024) ;
- X
- X memzero (desc, 1024);
- X symlink = TRUE ;
- X strcpy (desc, "-> ") ;
- X if (readlink (pathname (directory, file_info->name), &(desc[3]), 1021)
- X == -1)
- X strcat (desc, "(symbolic link)") ;
- X }
- X#endif
- X
- X /* Now we only need what we will show */
- X strcpy (out_name, file_info->name) ;
- X
- X name_len = strlen (out_name) ;
- X /* If it is a directory, make it obvious */
- X if (file_info->mode & S_IFDIR) {
- X strcat (out_name, "/") ;
- X name_len++ ;
- X size[1] = EOS ;
- X size_len = 1 ;
- X if (file_info->nlink > 2) { /* Denotes a directory that contains */
- X size[0] = '=' ; } /* one or more sub-directories */
- X else {
- X size[0] = '-' ; } }
- X else {
- X sprintf (size, "%d", file_info->size) ;
- X size_len = strlen (size) ; }
- X if (name_len + size_len < name_and_size_columns)
- X gap = name_and_size_columns - name_len ;
- X else {
- X print (out_name) ;
- X out_name[0] = '\n' ; out_name[1] = EOS ;
- X gap = name_and_size_columns ; }
- X if (show_date) {
- X tm_time = localtime (&file_info->mtime) ;
- X if (six_months_ago > file_info->mtime) {
- X /* The bloody thing is more than 6 months old! */
- X#ifdef US_DATE_FORMAT
- X sprintf (date, " %s %2d %d ", month[tm_time->tm_mon],
- X tm_time->tm_mday, tm_time->tm_year + 1900) ;
- X#else
- X sprintf (date, " %2d %s %d ", tm_time->tm_mday,
- X month[tm_time->tm_mon], tm_time->tm_year + 1900) ;
- X#endif
- X }
- X else {
- X#ifdef US_DATE_FORMAT
- X sprintf (date, " %s %2d %02d:%02d ", month[tm_time->tm_mon],
- X tm_time->tm_mday, tm_time->tm_hour, tm_time->tm_min) ;
- X#else
- X sprintf (date, " %2d %s %02d:%02d ", tm_time->tm_mday,
- X month[tm_time->tm_mon], tm_time->tm_hour, tm_time->tm_min) ;
- X#endif
- X } }
- X else {
- X date[0] = ' ' ;
- X date[1] = EOS ; }
- X
- X if (space) {
- X printc ('\n') ;
- X space = FALSE ; }
- X printf ("%s %*s%s %s\n", out_name, gap, size, date,
- X#ifdef PASS_NULL_TO_PRINTF
- X desc
- X#else
- X (desc == NULL_CP) ? "" : desc
- X#endif
- X ) ;
- X printed_anything = TRUE ;
- X
- X#ifdef SHOW_SYMLINK
- X if (symlink) {
- X free (desc); }
- X#endif
- X }
- END_OF_FILE
- if test 12166 -ne `wc -c <'dl.c'`; then
- echo shar: \"'dl.c'\" unpacked with wrong size!
- fi
- # end of 'dl.c'
- fi
- if test -f 'list.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'list.c'\"
- else
- echo shar: Extracting \"'list.c'\" \(6164 characters\)
- sed "s/^X//" >'list.c' <<'END_OF_FILE'
- X/* list.c - List manipulation routines
- X *
- X * SYNOPSIS
- X * #include <list.h>
- X *
- X * void list_init (struct list *list) ;
- X *
- X * Initializes the list. Does not free any storage that
- X * may have been allocated to the list.
- X *
- X * void list_free (struct list *list) ;
- X *
- X * Deallocates and initializes the list.
- X *
- X * void list_push (struct list *list, void *element, size_t length) ;
- X *
- X * Adds the element to the end of the list. If length is
- X * non-zero, a copy is made of the data pointed to by element,
- X * and the address of the copy is added to the list instead.
- X *
- X * void *list_pop (struct list *list) ;
- X *
- X * Returns the last element in the list and removes it.
- X *
- X * void *list_shift (struct list *list) ;
- X *
- X * Returns the first element in the list and removes it
- X *
- X * void *list_element (struct list *list, int element_no) ;
- X *
- X * Returns the specified element (elements are numbered
- X * starting from 0), or NULL if the list does not contain
- X * any elements. Has no effect on the contents of the
- X * list.
- X *
- X * int list_elements (struct list *list) ;
- X *
- X * Returns the number of elements in the list.
- X *
- X * int list_empty (struct list *list) ;
- X *
- X * Returns non-zero if the list contains any elements,
- X * zero otherwise.
- X *
- X * void list_sort (struct list *list, int (*compare) ()) ;
- X *
- X * Sorts the list using compare() (like qsort(3))
- X *
- X * NOTE: list_init(), list_element(), list_elements() and list_empty()
- X * are implemented as macros.
- X *
- X * Copyright (c) 1991, 1992 Tim Cook.
- X * Non-profit distribution allowed. See README for details.
- X */
- X
- Xstatic char rcsid[] = "$Id: list.c,v 1.6 1992/12/02 03:46:20 tim Exp $";
- X
- X#define _LIST_C_
- X
- X#define VOID_PTR char *
- X#define VOID_PTR_PTR char **
- X
- X#include "config.h"
- X#include <list.h>
- X
- X#ifndef NULL
- X#define NULL 0
- X#endif
- X
- Xextern VOID_PTR allocate () ;
- Xextern VOID_PTR re_allocate () ;
- X
- X#ifndef INITIAL_LIST_ENTRIES
- X#define INITIAL_LIST_ENTRIES 512
- X#endif
- X#ifndef DATA_BLOCK_SIZE
- X#define DATA_BLOCK_SIZE 16384
- X#endif
- X
- X/*
- X * This must be defined to an unsigned integer data type to which
- X * pointer types can be freely cast.
- X */
- X
- X#define PTR_CARD unsigned long
- X
- X
- XVOID list_free (list)
- X struct list *list ;
- X{
- X if (! list_empty (list) && list->s_start != (VOID_PTR_PTR) NULL) {
- X free ((VOID_PTR) list->s_start) ;
- X if (list->data) {
- X int i ;
- X
- X for (i = 2 ; list->data[i] ; i++)
- X free (list->data[i]) ;
- X free ((VOID_PTR) list->data) ; }
- X list_init (list) ; } /* May as well */
- X }
- X
- X
- XVOID list_push (list, element, length)
- X struct list *list ;
- X VOID_PTR element ;
- X size_t length ;
- X{
- X if (length) {
- X size_t data_block_size ;
- X int new_block = 0 ;
- X
- X#ifdef ALIGN
- X /* Make sure subsequent data is stored aligned */
- X#if ALIGN == 2
- X if (length & 1)
- X length++ ;
- X#else
- X /*
- X * ALIGN must be a power of 2 (reasonable to expect), but at
- X * least we don't need to do a divide.
- X */
- X if (length & (ALIGN - 1))
- X length += ALIGN - (length & (ALIGN - 1)) ;
- X#endif
- X#endif
- X
- X if (length > DATA_BLOCK_SIZE)
- X data_block_size = length ;
- X else
- X data_block_size = DATA_BLOCK_SIZE ;
- X
- X /*
- X * Allocate storage for data pointed to by list element
- X */
- X if (! list->data) {
- X /* No blocks allocated at all, set it up */
- X list->data = (VOID_PTR_PTR) allocate (sizeof (VOID_PTR_PTR) * 4) ;
- X new_block = 2 ; }
- X else {
- X /* We have some storage, but do we have enough? */
- X if ((PTR_CARD) list->data[0] + length > (PTR_CARD) list->data[1]) {
- X /* Nope, allocate new block */
- X
- X for (new_block = 2 ; list->data[new_block] ; new_block++) ;
- X list->data = (VOID_PTR_PTR) re_allocate (list->data,
- X sizeof (VOID_PTR_PTR) * new_block + 2) ; } }
- X
- X if (new_block) {
- X /*
- X * The contents of the array pointed to by list->data is as
- X * follows:
- X *
- X * The first element points to the first free byte of storage.
- X * The second to the first inaccessible byte.
- X * Subsequent elements contain a NULL-terminated list of all
- X * blocks.
- X */
- X list->data[new_block] = allocate (data_block_size) ;
- X list->data[new_block+1] = (VOID_PTR) NULL ;
- X list->data[0] = list->data[new_block] ;
- X list->data[1] = (VOID_PTR)
- X ((PTR_CARD) list->data[new_block] + data_block_size) ; }
- X
- X /* Copy data pointed to by list element */
- X memcpy (list->data[0], element, length) ;
- X /* Now, make sure we add the right pointer to the list */
- X element = list->data[0] ;
- X /* Adjust free pointer */
- X list->data[0] = (VOID_PTR) ((PTR_CARD) list->data[0] + length) ;
- X }
- X
- X /* Now, add the "pointer" itself */
- X if (list_empty (list)) {
- X list->s_start = (VOID_PTR_PTR) allocate (
- X sizeof (VOID_PTR) * INITIAL_LIST_ENTRIES) ;
- X list->s_end = list->s_start + INITIAL_LIST_ENTRIES ;
- X list->start = list->s_start ;
- X list->end = list->start ; }
- X else {
- X if (list->end >= list->s_end) {
- X /* We need to re-allocate */
- X register PTR_CARD x, y, z ;
- X
- X x = (PTR_CARD) list->s_end - (PTR_CARD) list->s_start ;
- X y = (PTR_CARD) list->start - (PTR_CARD) list->s_start ;
- X z = (PTR_CARD) list->end - (PTR_CARD) list->s_start ;
- X x = x << 1 ; /* Double allocation size */
- X list->s_start = (VOID_PTR_PTR) re_allocate (list->s_start, x) ;
- X list->s_end = (VOID_PTR_PTR) ((PTR_CARD) list->s_start + x) ;
- X list->start = (VOID_PTR_PTR) ((PTR_CARD) list->s_start + y) ;
- X list->end = (VOID_PTR_PTR) ((PTR_CARD) list->s_start + z) ; } }
- X
- X *list->end = element ;
- X list->end++ ;
- X }
- X
- X
- XVOID_PTR list_shift (list)
- X struct list *list ;
- X{
- X if (list_empty (list))
- X return (VOID_PTR) NULL ;
- X else
- X if (list->start >= list->end)
- X return (VOID_PTR) NULL ;
- X else
- X return *list->start++ ;
- X }
- X
- X
- XVOID_PTR list_pop (list) /* WORK */
- X struct list *list ;
- X{
- X if (list_empty (list))
- X return (VOID_PTR) NULL ;
- X else
- X if (list->end < list->start) /* WORK */
- X return (VOID_PTR) NULL ;
- X else
- X return *list->end-- ;
- X }
- X
- X
- XVOID list_sort (list, compare)
- X struct list *list ;
- X int (*compare) () ;
- X{
- X if (! list_empty (list))
- X qsort (list->start, (int) list_elements (list),
- X sizeof (VOID_PTR), compare) ;
- X }
- END_OF_FILE
- if test 6164 -ne `wc -c <'list.c'`; then
- echo shar: \"'list.c'\" unpacked with wrong size!
- fi
- # end of 'list.c'
- fi
- if test ! -d 'other' ; then
- echo shar: Creating directory \"'other'\"
- mkdir 'other'
- fi
- if test -f 'other/descopt' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'other/descopt'\"
- else
- echo shar: Extracting \"'other/descopt'\" \(349 characters\)
- sed "s/^X//" >'other/descopt' <<'END_OF_FILE'
- X#!/bin/sh
- X# descopt - Optimize description database in a given directory
- X
- Xcase $# in
- X 1 ) ;;
- X * )
- X echo "usage: $0 <directory>"
- X exit 1 ;;
- X esac
- X
- Xdirectory="$1"
- X
- Xdescribe -l "$directory" > "/tmp/descopt.$$"
- X
- Xrm -f "${directory}/.desc.pag" "${directory}/.desc.dir"
- X
- Xdescribe -f "/tmp/descopt.$$" "$directory"
- X
- Xrm -f "/tmp/descopt.$$"
- END_OF_FILE
- if test 349 -ne `wc -c <'other/descopt'`; then
- echo shar: \"'other/descopt'\" unpacked with wrong size!
- fi
- # end of 'other/descopt'
- fi
- if test ! -d 'patches' ; then
- echo shar: Creating directory \"'patches'\"
- mkdir 'patches'
- fi
- if test -f 'patches/GNU-compress.patch' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'patches/GNU-compress.patch'\"
- else
- echo shar: Extracting \"'patches/GNU-compress.patch'\" \(3559 characters\)
- sed "s/^X//" >'patches/GNU-compress.patch' <<'END_OF_FILE'
- XThis patch can be applied to GNU compress, to give it a "-s" flag
- X("-d" and "-D" were taken already) which will instruct compress to
- Xmove descriptions as it compresses or uncompresses files.
- X
- XTo create a file-descriptions-compatible GNU compress, follow these
- Xinstructions:
- X
- X 1. Patch compress.c.
- X (Something like "cd [compress source directory] ; patch < [this-file]")
- X
- X 2. Compile compress.c with the DESCRIPTIONS macro defined. It is
- X probably best to edit the Makefile that comes with compress,
- X adding "-DDESCRIPTIONS" to the CFLAGS macro.
- X
- X 3. Link compress.c, insuring you include getdesc.o, setdesc.o and
- X enddesc.o from dl/describe and the DBM library you used with
- X dl/describe. Again, editing of the Makefile is recommended here
- X
- X 4. Install as appropriate.
- X
- X 5. (Suggestion) "% alias compress compress -s"
- X
- XThis patch was generated against compress.c from compress-4.0.1.tar.Z,
- Xwhich is distributed via GNU.
- X
- X
- X*** compress.c.dist Wed Sep 7 04:32:07 1988
- X--- compress.c Mon May 4 17:47:55 1992
- X***************
- X*** 387,391 ****
- X--- 387,395 ----
- X fprintf(stderr,"Usage: compress [-cdDfivV] [-b maxbits] [file ...]\n");
- X # else
- X+ # ifdef DESCRIPTIONS
- X+ fprintf(stderr,"Usage: compress [-cdDfsvV] [-b maxbits] [file ...]\n");
- X+ # else
- X fprintf(stderr,"Usage: compress [-cdDfvV] [-b maxbits] [file ...]\n");
- X+ # endif /* DESCRIPTIONS */
- X # endif /* MSDOS */
- X
- X***************
- X*** 397,401 ****
- X--- 401,409 ----
- X fprintf(stderr,"Usage: compress [-cdfivV] [-b maxbits] [file ...]\n");
- X # else
- X+ # ifdef DESCRIPTIONS
- X+ fprintf(stderr,"Usage: compress [-cdfsvV] [-b maxbits] [file ...]\n");
- X+ # else
- X fprintf(stderr,"Usage: compress [-cdfvV] [-b maxbits] [file ...]\n");
- X+ # endif
- X # endif /* MSDOS */
- X
- X***************
- X*** 440,443 ****
- X--- 448,458 ----
- X int do_decomp = 0;
- X
- X+ #ifdef DESCRIPTIONS
- X+ extern char *getdesc();
- X+ extern int setdesc();
- X+
- X+ int descriptions = 0;
- X+ #endif
- X+
- X /*****************************************************************
- X * TAG( main )
- X***************
- X*** 470,473 ****
- X--- 485,491 ----
- X * -b: Parameter limits the max number of bits/code.
- X *
- X+ * -s: Output file is given same description as input file.
- X+ * This is subject to DESCRIPTIONS being #defined.
- X+ *
- X * file ...: Files to be compressed. If none specified, stdin
- X * is used.
- X***************
- X*** 492,496 ****
- X char tempname[100];
- X char **filelist, **fileptr;
- X! char *cp, *rindex(), *malloc();
- X struct stat statbuf;
- X extern onintr();
- X--- 510,514 ----
- X char tempname[100];
- X char **filelist, **fileptr;
- X! char *cp, *rindex(), *malloc(), *strcpy();
- X struct stat statbuf;
- X extern onintr();
- X***************
- X*** 618,621 ****
- X--- 636,644 ----
- X quiet = 1;
- X break;
- X+ #ifdef DESCRIPTIONS
- X+ case 's':
- X+ descriptions = 1;
- X+ break;
- X+ #endif
- X default:
- X fprintf(stderr, "Unknown flag: '%c'; ", **argv);
- X***************
- X*** 1498,1501 ****
- X--- 1521,1536 ----
- X fprintf(stderr, " -- file unchanged");
- X } else { /* ***** Successful Compression ***** */
- X+ #ifdef DESCRIPTIONS
- X+ if (descriptions) { /* Copy description */
- X+ char *description = getdesc (ifname, NULL, NULL, 0);
- X+ if (description) {
- X+ description = strcpy (
- X+ (char *) malloc (strlen (description) + 1), description);
- X+ if (! setdesc (ofname, NULL, NULL, 0, description))
- X+ perror (ofname);
- X+ free (description);
- X+ }
- X+ }
- X+ #endif
- X exit_stat = 0;
- X mode = statbuf.st_mode & 07777;
- END_OF_FILE
- if test 3559 -ne `wc -c <'patches/GNU-compress.patch'`; then
- echo shar: \"'patches/GNU-compress.patch'\" unpacked with wrong size!
- fi
- # end of 'patches/GNU-compress.patch'
- fi
- if test -f 'patches/GNU-mv.patch' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'patches/GNU-mv.patch'\"
- else
- echo shar: Extracting \"'patches/GNU-mv.patch'\" \(6151 characters\)
- sed "s/^X//" >'patches/GNU-mv.patch' <<'END_OF_FILE'
- XThe enclosed patch can be applied to GNU mv (which is contained in the
- XGNU Fileutils package) to give it a "-d" flag which will instruct mv
- Xto move file descriptions with files.
- X
- XTo create a file-descriptions-compatible GNU mv, follow these
- Xinstructions:
- X
- X 1. Patch mv.c from the fileutils package
- X (something like "cd [fileutils-src-dir] ; patch < [this-file]).
- X
- X 2. Compile mv.c with the DESCRIPTIONS macro defined.
- X
- X 3. Link mv.c, insuring you include getdesc.o, setdesc.o and
- X enddesc.o from dl/describe and the DBM library you used with
- X dl/describe.
- X
- X 4. Install as appropriate.
- X
- X 5. (Suggestion:) "% alias mv mv -d"
- X
- XNote that running the GNU fileutils "configure" script, then adjusting
- Xthe generated Makefile is probably the best course of action to take
- Xafter applying this patch.
- X
- XThis patch was generated against mv.c from the GNU fileutils package,
- Xversion 3.2.
- X
- X
- X*** mv.c.dist Mon Mar 9 14:14:00 1992
- X--- mv.c Tue May 5 12:18:02 1992
- X***************
- X*** 78,81 ****
- X--- 78,86 ----
- X int stdin_tty;
- X
- X+ #ifdef DESCRIPTIONS
- X+ /* If nonzero, move description with file (if possible) */
- X+ int describe;
- X+ #endif
- X+
- X struct option long_options[] =
- X {
- X***************
- X*** 87,90 ****
- X--- 92,98 ----
- X {"verbose", 0, &verbose, 1},
- X {"version-control", 1, NULL, 'V'},
- X+ #ifdef DESCRIPTIONS
- X+ {"describe", 0, NULL, 'd'},
- X+ #endif
- X {NULL, 0, NULL, 0}
- X };
- X***************
- X*** 107,113 ****
- X interactive = override_mode = verbose = update = 0;
- X errors = 0;
- X
- X! while ((c = getopt_long (argc, argv, "bfiuvS:V:", long_options, (int *) 0))
- X! != EOF)
- X {
- X switch (c)
- X--- 115,129 ----
- X interactive = override_mode = verbose = update = 0;
- X errors = 0;
- X+ #ifdef DESCRIPTIONS
- X+ describe = 0;
- X+ #endif
- X
- X! while ((c = getopt_long (argc, argv,
- X! #ifdef DESCRIPTIONS
- X! "bfiuvdS:V:",
- X! #else
- X! "bfiuvS:V:",
- X! #endif
- X! long_options, (int *) 0)) != EOF)
- X {
- X switch (c)
- X***************
- X*** 138,141 ****
- X--- 154,162 ----
- X version = optarg;
- X break;
- X+ #ifdef DESCRIPTIONS
- X+ case 'd':
- X+ describe = 1;
- X+ break;
- X+ #endif
- X default:
- X usage ();
- X***************
- X*** 203,206 ****
- X--- 224,232 ----
- X {
- X char *to_backup = NULL;
- X+ #ifdef DESCRIPTIONS
- X+ char *from_description = NULL;
- X+
- X+ extern int setdesc ();
- X+ #endif
- X
- X if (lstat (from, &from_stats) != 0)
- X***************
- X*** 247,250 ****
- X--- 273,289 ----
- X {
- X char *tmp_backup = find_backup_file_name (to);
- X+ #ifdef DESCRIPTIONS
- X+ char *to_description = NULL;
- X+
- X+ if (describe)
- X+ {
- X+ char *p = getdesc (to, NULL, NULL, to_stats.st_ino);
- X+ if (p)
- X+ {
- X+ to_description = (char *) alloca (strlen (p) + 1);
- X+ strcpy (to_description, p);
- X+ }
- X+ }
- X+ #endif
- X if (tmp_backup == NULL)
- X error (1, 0, "virtual memory exhausted");
- X***************
- X*** 262,265 ****
- X--- 301,315 ----
- X to_backup = NULL;
- X }
- X+ #ifdef DESCRIPTIONS
- X+ else if (describe)
- X+ {
- X+ if (! setdesc (to_backup, NULL, NULL, 0, to_description))
- X+ {
- X+ if (verbose)
- X+ error (0, errno, "cannot set description on backup `%s'",
- X+ to_backup);
- X+ }
- X+ }
- X+ #endif
- X }
- X }
- X***************
- X*** 273,278 ****
- X--- 323,354 ----
- X printf ("%s -> %s\n", from, to);
- X
- X+ #ifdef DESCRIPTIONS
- X+ if (describe)
- X+ {
- X+ char *p = getdesc (from, NULL, NULL, from_stats.st_ino);
- X+
- X+ if (p)
- X+ {
- X+ from_description = (char *) alloca (strlen (p) + 1);
- X+ strcpy (from_description, p);
- X+ }
- X+ }
- X+ #endif
- X+
- X if (rename (from, to) == 0)
- X {
- X+ #ifdef DESCRIPTIONS
- X+ if (describe)
- X+ {
- X+ if (! setdesc (to, NULL, NULL, to_stats.st_ino, from_description))
- X+ {
- X+ if (verbose)
- X+ error (0, errno, "cannot set description of `%s'", to);
- X+ }
- X+ else
- X+ /* Delete the description for what the file used to be called */
- X+ setdesc (from, NULL, NULL, from_stats.st_ino, NULL);
- X+ }
- X+ #endif
- X return 0;
- X }
- X***************
- X*** 288,292 ****
- X if (copy (from, to))
- X goto un_backup;
- X!
- X if (unlink (from))
- X {
- X--- 364,381 ----
- X if (copy (from, to))
- X goto un_backup;
- X! #ifdef DESCRIPTIONS
- X! else if (describe)
- X! {
- X! if (! setdesc (to, NULL, NULL, to_stats.st_ino, from_description))
- X! {
- X! if (verbose)
- X! error (0, errno, "cannot set description of `%s'", to);
- X! }
- X! else
- X! /* Delete description on original file */
- X! setdesc (from, NULL, NULL, from_stats.st_ino, NULL);
- X! }
- X! #endif
- X!
- X if (unlink (from))
- X {
- X***************
- X*** 302,305 ****
- X--- 391,399 ----
- X if (rename (to_backup, to))
- X error (0, errno, "cannot un-backup `%s'", to);
- X+ #ifdef DESCRIPTIONS
- X+ else if (describe)
- X+ /* Delete the description on the backup we have just deleted */
- X+ setdesc (to_backup, NULL, NULL, 0, NULL);
- X+ #endif
- X }
- X return 1;
- X***************
- X*** 426,436 ****
- X usage ()
- X {
- X! fprintf (stderr, "\
- X Usage: %s [options] source dest\n\
- X %s [options] source... directory\n\
- X Options:\n\
- X [-bfiuv] [-S backup-suffix] [-V {numbered,existing,simple}]\n\
- X [--backup] [--force] [--interactive] [--update] [--verbose]\n\
- X [--suffix=backup-suffix] [--version-control={numbered,existing,simple}]\n",
- X program_name, program_name);
- X exit (1);
- X--- 520,541 ----
- X usage ()
- X {
- X! fprintf (stderr,
- X! #ifdef DESCRIPTIONS
- X! "\
- X Usage: %s [options] source dest\n\
- X %s [options] source... directory\n\
- X Options:\n\
- X+ [-bdfiuv] [-S backup-suffix] [-V {numbered,existing,simple}]\n\
- X+ [+backup] [+describe] [+force] [+interactive] [+update] [+verbose]\n\
- X+ [+suffix=backup-suffix] [+version-control={numbered,existing,simple}]\n",
- X+ #else
- X+ "\
- X+ Usage: %s [options] source dest\n\
- X+ %s [options] source... directory\n\
- X+ Options:\n\
- X [-bfiuv] [-S backup-suffix] [-V {numbered,existing,simple}]\n\
- X [--backup] [--force] [--interactive] [--update] [--verbose]\n\
- X [--suffix=backup-suffix] [--version-control={numbered,existing,simple}]\n",
- X+ #endif
- X program_name, program_name);
- X exit (1);
- END_OF_FILE
- if test 6151 -ne `wc -c <'patches/GNU-mv.patch'`; then
- echo shar: \"'patches/GNU-mv.patch'\" unpacked with wrong size!
- fi
- # end of 'patches/GNU-mv.patch'
- fi
- echo shar: End of archive 1 \(of 3\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-