home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume35
/
describe
/
part01
next >
Wrap
Text File
|
1993-02-04
|
56KB
|
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...