home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume35 / describe / part02 < prev    next >
Encoding:
Text File  |  1993-02-03  |  53.8 KB  |  1,925 lines

  1. Newsgroups: comp.sources.misc
  2. From: tim@deakin.edu.au (Tim Cook)
  3. Subject: v35i013:  describe - File Descriptions, Part02/03
  4. Message-ID: <1993Feb2.061426.20441@sparky.imd.sterling.com>
  5. X-Md4-Signature: c2f6282134575033da9a9fb4b1b7dfed
  6. Date: Tue, 2 Feb 1993 06:14:26 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: tim@deakin.edu.au (Tim Cook)
  10. Posting-number: Volume 35, Issue 13
  11. Archive-name: describe/part02
  12. Environment: UNIX, DBM
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # Contents:  INSTALL Makefile describe.1 dl.1 enddesc.c getdesc.3
  19. #   getdesc.c other/CONTEMPTIBILITY other/dumpdesc.c other/lslR2dl.pl
  20. #   patches/BSD-mv.patch patches/CONTEMPTIBLE.patch
  21. #   patches/UUNET-ftpd.patch perror2.c setdesc.c
  22. # Wrapped by kent@sparky on Mon Feb  1 10:15:03 1993
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 2 (of 3)."'
  26. if test -f 'INSTALL' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'INSTALL'\"
  28. else
  29.   echo shar: Extracting \"'INSTALL'\" \(1679 characters\)
  30.   sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
  31. XInstallation instructions for dls/describe.
  32. X
  33. X1.   Make sure you have DBM or NDBM-compatible library routines.  If
  34. X     you haven't, I recommend Ozan Yigit's SDBM, available at various
  35. X     Anonymous FTP sites, including rana.cc.deakin.oz.au.
  36. X
  37. X2.   Make sure you have directory reading routines (opendir(3),
  38. X     readdir(3), etc.).  If you haven't got any, try getting the
  39. X     non-commercial version by Doug Gwyn, also available at various
  40. X     Anonymous FTP sites.
  41. X
  42. X3.   Read config.h and modify if necessary.
  43. X
  44. X4.   Read Makefile and modify if necessary.
  45. X
  46. X5.   Make.
  47. X
  48. X6.   Install binaries and man pages where you want them (you should
  49. X     have modified Makefile appropriately).
  50. X
  51. X7.   For your anonymous ftp area, install a copy of dl in
  52. X     ~ftp/bin/ls.  If your system uses shared libraries (SunOS is one
  53. X     that does), you should install a statically linked version of dl.
  54. X     See the Makefile for details.
  55. X
  56. X     You should provide some information on dl in a prominent README
  57. X     file or at login time for anonymous FTP users.  You may also
  58. X     want/need to change the way dl responds to various options in
  59. X     order to get it to work better with your version of ftpd (check
  60. X     that the MGET command works, in particular).  Others have been
  61. X     known to do this, and I haven't come up with a definitive set of
  62. X     answers to this and other related problems yet. 
  63. X
  64. X8.   (Optional)  Investigate the patches in the "patches" directory.
  65. X     These are for modifying common (and commonly available in source
  66. X     form) file utiltities to make them aware of file descriptions.
  67. X     Instructions on how to use them are in each patch file.
  68. X
  69. X9.   Start describing files.
  70. END_OF_FILE
  71.   if test 1679 -ne `wc -c <'INSTALL'`; then
  72.     echo shar: \"'INSTALL'\" unpacked with wrong size!
  73.   fi
  74.   # end of 'INSTALL'
  75. fi
  76. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  77.   echo shar: Will not clobber existing file \"'Makefile'\"
  78. else
  79.   echo shar: Extracting \"'Makefile'\" \(3225 characters\)
  80.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  81. X# Makefile -    Makefile for dls
  82. X#
  83. X# $Id: Makefile,v 1.14 1993/01/29 05:05:42 tim Exp tim $
  84. X#
  85. X# Copyright (c) 1991,1992 Tim Cook.
  86. X# Non-profit distribution allowed.  See README for details.
  87. X
  88. X
  89. X# If your NDBM routines are in libndbm.a
  90. X#LIBS =        -lndbm
  91. X#
  92. X# If you are using DBM, or NDBM on SunOS or Ultrix, where the NDBM
  93. X# routines are in libdbm
  94. XLIBS =        -ldbm
  95. X#
  96. X# If you are on Solaris 2.0, the NDBM libraries are in libc
  97. X#LIBS =
  98. X#
  99. X# If you are on a version of DYNIX where the getopt routines are in
  100. X# libseq
  101. X#LIBS =        -ldbm -lseq
  102. X
  103. X# You will need to include strpbrk.o, unless you have it in a library.
  104. XEXTRAS =    perror2.o
  105. X#EXTRAS =    strpbrk.o perror2.o
  106. X
  107. X# If you don't like it, change it.
  108. XBINDIR =    /usr/local/bin
  109. X
  110. X# This is what _I_ do.  You will no doubt have to change these.  See
  111. X# the "install" target as well.
  112. XINSTALLBIN =    root install -c -s -o bin -g bin -m 751
  113. X#INSTALLBIN =    install -c -s -m 751
  114. X#
  115. X# This is a local shell script
  116. XINSTALLMAN =    instman
  117. X
  118. XSHAR =        shar -n $(PACKAGE_NAME) -a -s "Tim Cook <tim@deakin.edu.au>" \
  119. X           -l50 -o shar
  120. X
  121. X# I have not used GCC to compile dl/describe, but it would need at
  122. X# least these two options.
  123. X#CC =        gcc -traditional -fpcc-struct-return
  124. XCOPT =        -O
  125. X#COPT =        -g
  126. XCFLAGS =    $(COPT) -I.
  127. XLDFLAGS =    $(COPT)
  128. X#
  129. X# If you have an OS with shared libraries, this will allow you to
  130. X# build a "static" executable of dl, which you will need for your
  131. X# Anonymous FTP setup.  The following is for SunOS.
  132. XSTATIC_LDFLAGS =    -Bstatic $(LD_FLAGS)
  133. X# And this is for GCC
  134. X#STATIC_LDFLAGS =    -static $(LD_FLAGS)
  135. X
  136. X#
  137. X# The Makefile should not need to be modified past this point
  138. X#############################################################
  139. X
  140. XDISTRIB =    README INSTALL
  141. X
  142. XSOURCE =    Makefile config.h list.h version.h dl.c describe.c list.c \
  143. X        allocate.c pathname.c getdesc.c setdesc.c enddesc.c \
  144. X        strpbrk.c perror2.c
  145. X
  146. XDOCUMENTATION =    dl.1 describe.1 getdesc.3
  147. X
  148. XOTHER =        other/CONTEMPTIBILITY other/descopt other/dumpdesc.c \
  149. X        other/lslR2dl.pl
  150. X
  151. XPATCHES =    patches/BSD-mv.patch patches/GNU-compress.patch \
  152. X        patches/GNU-mv.patch patches/UUNET-ftpd.patch \
  153. X        patches/CONTEMPTIBLE.patch
  154. X
  155. XPACKAGE =    $(DISTRIB) $(SOURCE) $(DOCUMENTATION) $(OTHER) \
  156. X        $(PATCHES)
  157. X
  158. XPACKAGE_NAME =    describe
  159. X
  160. XDL_REQ =    getdesc.o enddesc.o pathname.o list.o allocate.o
  161. X
  162. XDESCRIBE_REQ =    getdesc.o setdesc.o enddesc.o $(EXTRAS)
  163. X
  164. Xall : dl describe
  165. X
  166. Xinstall : all installbin installman
  167. X
  168. Xinstallbin :
  169. X    $(INSTALLBIN) dl $(BINDIR)
  170. X    $(INSTALLBIN) describe $(BINDIR)
  171. X
  172. Xinstallman :
  173. X    $(INSTALLMAN) dl.1
  174. X    $(INSTALLMAN) describe.1
  175. X    $(INSTALLMAN) getdesc.3
  176. X
  177. Xshar : $(PACKAGE)
  178. X    chmod 640 $(PACKAGE)
  179. X    $(SHAR) $(PACKAGE)
  180. X
  181. Xtar : $(PACKAGE)
  182. X    chmod 640 $(PACKAGE)
  183. X    tar cvf - $(PACKAGE) | compress > $(PACKAGE_NAME).tar.Z
  184. X
  185. Xdl : dl.o $(DL_REQ)
  186. X    $(CC) $(LDFLAGS) -o $@ dl.o $(DL_REQ) $(LIBS)
  187. X
  188. Xdl-static : dl.o $(DL_REQ)
  189. X    $(CC) $(STATIC_LDFLAGS) -o $@ dl.o $(DL_REQ) $(LIBS)
  190. X
  191. Xdescribe : describe.o $(DESCRIBE_REQ)
  192. X    $(CC) $(LDFLAGS) -o $@ describe.o $(DESCRIBE_REQ) $(LIBS)
  193. X
  194. Xdl.c :    config.h list.h
  195. X
  196. Xdescribe.c : config.h version.h
  197. X
  198. Xgetdesc.c : config.h
  199. X
  200. Xsetdesc.c : config.h
  201. X
  202. Xenddesc.c : config.h
  203. X
  204. Xlist.c : config.h list.h
  205. X
  206. Xallocate.c : config.h
  207. X
  208. Xpathname.c : config.h
  209. X
  210. Xstrpbrk.o : strpbrk.c
  211. X    $(CC) -c -O $*.c
  212. X
  213. Xclean :
  214. X    rm -f *.o core
  215. X
  216. Xclobber : clean
  217. X    rm -f dl describe
  218. END_OF_FILE
  219.   if test 3225 -ne `wc -c <'Makefile'`; then
  220.     echo shar: \"'Makefile'\" unpacked with wrong size!
  221.   fi
  222.   # end of 'Makefile'
  223. fi
  224. if test -f 'describe.1' -a "${1}" != "-c" ; then 
  225.   echo shar: Will not clobber existing file \"'describe.1'\"
  226. else
  227.   echo shar: Extracting \"'describe.1'\" \(2945 characters\)
  228.   sed "s/^X//" >'describe.1' <<'END_OF_FILE'
  229. X.\" describe.1 -    Man page for describe
  230. X.\"
  231. X.\" Copyright (c) 1991, 1992 Tim Cook.
  232. X.\" Non-profit distribution allowed.  See README for details.
  233. X.\"
  234. X.\" $Id: describe.1,v 1.5 1992/12/02 05:43:46 tim Exp $
  235. X.\"
  236. X.TH DESCRIBE 1 "2 Dec, 1992"
  237. X.UC 4
  238. X.\"
  239. X.SH NAME
  240. Xdescribe - Set or list a descriptive comment for a file
  241. X.SH SYNOPSIS
  242. X.B describe
  243. X.I file description
  244. X.br
  245. X.B describe -c
  246. X.I file other-file
  247. X.br
  248. X.B describe -f
  249. X.I description-file
  250. X.RI "[\|" directory "\|]"
  251. X.br
  252. X.B describe -d
  253. X.I file ...
  254. X.br
  255. X.B describe -l
  256. X.RI "[\|" directory "\|]"
  257. X.br
  258. X.B describe -v
  259. X.\"
  260. X.SH DESCRIPTION
  261. X.B Describe
  262. Xsets, deletes or lists file descriptions, as used by
  263. X.BR dl (1).
  264. XTo set the description on one file, use the first form shown above.
  265. XTo copy a description from one file to another, use the
  266. X.B -c
  267. Xoption, as shown above (note that null descriptions are copied).
  268. XTo set descriptions on a number of files, put the descriptions into a file,
  269. Xthen use the
  270. X.B -f
  271. Xoption as shown above
  272. X(leaving off
  273. X.I directory
  274. Ximplies the current directory).  If you use a hyphen (-) as the name of the
  275. Xdescriptions file,
  276. X.B describe
  277. Xwill read standard input for the list of descriptions.
  278. XTo delete the description for one or more files, use the
  279. X.B -d
  280. Xoption as shown above.
  281. XTo list all the descriptions set for files in a directory, use the
  282. X.B -l
  283. Xoption (again, leaving off
  284. X.I directory
  285. Xmeans the current directory).
  286. X.LP
  287. XA
  288. X.I description-file
  289. Xis a simple text file.
  290. XEach line should list the file name (quoted with double quotes if it
  291. Xcontains white-space), followed by white-space, followed by the
  292. Xdescription.
  293. XThe description itself may contain white-space, and is only terminated
  294. Xby an end-of-line.
  295. XComments may appear in a description file, as a line that starts with a
  296. Xhash (#) character.
  297. X.LP
  298. XIf you set a description to null,
  299. X.B describe
  300. Xwill attempt to delete any
  301. Xexisting description, which will achieve the same result.
  302. X.LP
  303. XThe current version of the
  304. X.B describe
  305. Xpackage can be displayed by using the
  306. X.B -v
  307. Xoption to
  308. X.BR describe .
  309. X.LP
  310. XDescriptions are stored in DBM files.
  311. XEach description is keyed by the file name, and the file name is also
  312. Xkeyed by the file's inode-number.
  313. XThis means that renaming or editing the file in the same directory will
  314. Xnot mean the loss of its description.
  315. XIf you wish to ``optimize'' the description database of a directory,
  316. Xyou can do so in the following manner:
  317. X.LP
  318. X.nf
  319. X    % describe -l > /tmp/descriptions
  320. X    % rm .desc.*
  321. X    % describe -f /tmp/descriptions
  322. X.fi
  323. X.LP
  324. XNOTE:  Old descriptions can be passed on to irrelevant files if you
  325. Xcreate a new file that uses the same inode that the originally
  326. Xdescribed file used.  This can be avoided by either deleting the
  327. Xdescription when the original file is deleted, or making sure you set
  328. Xa new description when you create new files, even if you set it to
  329. Xnull.
  330. X.\"
  331. X.SH FILES
  332. XFor each directory, a
  333. X.B .desc.pag
  334. Xand
  335. X.B .desc.dir
  336. X(DBM files) are used to store descriptions.
  337. X.\"
  338. X.SH SEE\ ALSO
  339. X.BR dl (1)
  340. END_OF_FILE
  341.   if test 2945 -ne `wc -c <'describe.1'`; then
  342.     echo shar: \"'describe.1'\" unpacked with wrong size!
  343.   fi
  344.   # end of 'describe.1'
  345. fi
  346. if test -f 'dl.1' -a "${1}" != "-c" ; then 
  347.   echo shar: Will not clobber existing file \"'dl.1'\"
  348. else
  349.   echo shar: Extracting \"'dl.1'\" \(1932 characters\)
  350.   sed "s/^X//" >'dl.1' <<'END_OF_FILE'
  351. X.\" dl.1 -    Man page for descriptive ls
  352. X.\"
  353. X.\" Copyright (c) 1991, 1992 Tim Cook.
  354. X.\" Non-profit distribution allowed.  See README for details.
  355. X.\"
  356. X.\" $Id: dl.1,v 1.3 1992/12/02 05:12:20 tim Exp $
  357. X.\"
  358. X.TH DL 1 "2 Dec, 1992"
  359. X.UC 4
  360. X.SH NAME
  361. Xdl \- Descriptive ls
  362. X.SH SYNOPSIS
  363. X.B dl
  364. X.RI "[\|" options "\|]"
  365. X.RI "[\|" "file " .\|.\|.\|]
  366. X.\"
  367. X.SH DESCRIPTION
  368. X.B Dl
  369. Xlists files and directories in the manner of
  370. X.BR ls (1),
  371. Xbut includes a descriptive comment for each
  372. X.I file
  373. Xthat has a description set.
  374. XBy default,
  375. X.B dl
  376. Xlists the file name, size of the file in bytes and the description.
  377. XIf the file is a directory, a hyphen (-) is shown instead of the size,
  378. Xand if the file is a directory that contains other directories, an equals
  379. Xsign (=) is shown.
  380. X.LP
  381. XDescriptions are set by
  382. X.BR describe (1)
  383. Xand are stored in a hidden file in the same directory as the files for
  384. Xwhich descriptions are held.
  385. X.\" The descriptions are matched to files by name
  386. X.\" and inode-number, so renaming or editing the file in the same directory
  387. X.\" will not cause the loss of its description.
  388. X.LP
  389. XOptions:
  390. X.TP
  391. X.BI \-d
  392. XList the date and time of each file.  The last modification date and time
  393. Xare listed after the file size, in the same format used by
  394. X.BR ls (1).
  395. X.TP
  396. X.BI \-e
  397. XList everything, even inaccessible files.
  398. XBy default, files that cannot be read or executed are ignored.
  399. X.TP
  400. X.BI \-t
  401. XSort by last modification time.  Most recently modified files come first.
  402. X.TP
  403. X.BI \-f width
  404. XUse a maximum of
  405. X.I width
  406. Xcolumns to display the file name.
  407. XIf a file name is longer than
  408. X.I width,
  409. Xit may expand into the area used to show the size.
  410. XIf this overflows, the size and other information will be listed on a
  411. Xseparate line.
  412. X.TP
  413. X.BI \-R
  414. XRecursively list any subdirectories encountered, just like
  415. X.BR ls (1).
  416. X.\"
  417. X.SH FILES
  418. XFor each directory, a
  419. X.B .desc.pag
  420. Xand
  421. X.B .desc.dir
  422. X(DBM files) are used to store descriptions.
  423. X.\"
  424. X.SH SEE\ ALSO
  425. X.BR ls (1),
  426. X.BR describe (1)
  427. END_OF_FILE
  428.   if test 1932 -ne `wc -c <'dl.1'`; then
  429.     echo shar: \"'dl.1'\" unpacked with wrong size!
  430.   fi
  431.   # end of 'dl.1'
  432. fi
  433. if test -f 'enddesc.c' -a "${1}" != "-c" ; then 
  434.   echo shar: Will not clobber existing file \"'enddesc.c'\"
  435. else
  436.   echo shar: Extracting \"'enddesc.c'\" \(5828 characters\)
  437.   sed "s/^X//" >'enddesc.c' <<'END_OF_FILE'
  438. X/* enddesc.c -    Initialise/deallocate description database
  439. X *
  440. X * Copyright (c) 1991, 1992 Tim Cook.
  441. X * Non-profit distribution allowed.  See README for details.
  442. X */
  443. X
  444. Xstatic char rcsid[] = "$Id: enddesc.c,v 1.4 1993/01/29 04:17:43 tim Exp tim $";
  445. X
  446. X#include <sys/param.h>
  447. X#include <sys/errno.h>
  448. X#include "config.h"
  449. X
  450. X#ifdef TEST
  451. X#include <stdio.h>
  452. X#endif
  453. X
  454. X#ifndef MAXPATHLEN
  455. X#define MAXPATHLEN    1024
  456. X#endif
  457. X
  458. Xextern int errno ;
  459. X#ifdef NDBM
  460. XDBM *_desc_database = (DBM *) NULL ;
  461. X#define DB_OPEN        (_desc_database != (DBM *) NULL)
  462. X#else
  463. Xstatic int _db_open = FALSE ;
  464. X#define DB_OPEN        _db_open
  465. X#endif
  466. X
  467. X
  468. XVOID enddesc ()
  469. X{
  470. X#ifdef NDBM
  471. X   if (_desc_database)
  472. X      dbm_close (_desc_database) ;
  473. X#else
  474. X   dbmclose () ;
  475. X#endif
  476. X   }
  477. X
  478. X
  479. X/*
  480. X * This is support routine for getdesc() and setdesc(), and should not
  481. X * normally be called by the programmer. 
  482. X */
  483. X
  484. Xint _initdesc (directory, open_flags)
  485. X   char *directory ;
  486. X   int open_flags ;
  487. X{
  488. X   static char desc_file[MAXPATHLEN+1] = "" ;
  489. X   static int db_flags ;
  490. X
  491. X   if (! directory || *directory == EOS)
  492. X      directory = "." ;
  493. X
  494. X   if (open_flags == db_flags && strcmp (directory, desc_file) == 0)
  495. X      return DB_OPEN ;        /* Tell 'em what we said before */
  496. X
  497. X   /* Otherwise, we need to try to open a database */
  498. X   {
  499. X      char *p ;
  500. X#ifndef NDBM
  501. X      char *q ;
  502. X#include <sys/stat.h>
  503. X      struct stat status ;
  504. X#endif
  505. X
  506. X      DBM_close (_desc_database) ;
  507. X
  508. X      strcpy (desc_file, directory) ;
  509. X      db_flags = open_flags ;
  510. X
  511. X      /* Find end of "desc_file" */
  512. X      for (p = desc_file ; *p != EOS ; p++) ;
  513. X
  514. X#ifdef NDBM
  515. X
  516. X      /* By crikey, it's easier this way! */
  517. X
  518. X      strcpy (p, "/.desc") ;
  519. X
  520. X#ifdef TEST
  521. X      printf ("Opening new database\n") ;
  522. X#endif
  523. X      if ((_desc_database = dbm_open (desc_file, db_flags, 0666))
  524. X               == (DBM *) NULL) {
  525. X     return FALSE ; }
  526. X
  527. X#else    /* NDBM */
  528. X
  529. X      _db_open = FALSE ;    /* We just closed it above */
  530. X
  531. X      strcpy (p, "/.desc.pag") ;
  532. X      q = strrchr (p, '.') ;
  533. X
  534. X      if (stat (desc_file, &status) != -1) {
  535. X
  536. X     /* Database exists */
  537. X
  538. X     *q = EOS ;        /* Hide ".pag" */
  539. X     if (dbminit (desc_file) < 0) {
  540. X        return FALSE ; }
  541. X     else
  542. X        _db_open = TRUE ; }
  543. X      else {
  544. X
  545. X     /* No database */
  546. X
  547. X#include <fcntl.h>
  548. X     if (db_flags & O_RDWR) {
  549. X        int fd ;
  550. X
  551. X        /* Create .desc.(pag|dir) files */
  552. X        if ((fd = open (desc_file, db_flags | O_EXCL, 0666))
  553. X          < 0)
  554. X           return FALSE ;
  555. X        close (fd) ;
  556. X        strcpy (q, ".dir") ;
  557. X        if ((fd = open (desc_file, db_flags | O_EXCL, 0666))
  558. X          < 0)
  559. X           return FALSE ;
  560. X        close (fd) ;
  561. X
  562. X        /* Start up DBM */
  563. X        *q = EOS ;        /* Hide ".dir" */
  564. X        if (dbminit (desc_file) == 0)
  565. X           _db_open = TRUE ; }
  566. X     else {
  567. X        errno = ENOENT ;
  568. X        return FALSE ; } }
  569. X#endif    /* NDBM */
  570. X
  571. X      /* Return "desc_file" to just a directory name */
  572. X      *p = EOS ;
  573. X      }
  574. X   return TRUE ;
  575. X   }
  576. X
  577. X
  578. X/*
  579. X * Another support routine for getdesc() and setdesc().  This returns
  580. X * FALSE if unsuccessful.
  581. X */
  582. X
  583. Xchar *_desc_pathname ;
  584. Xchar *_desc_directory ;
  585. Xchar *_desc_name ;
  586. X
  587. X
  588. X_desc_parse_path (pathname, directory, name)
  589. X   char *pathname ;
  590. X   char *directory ;
  591. X   char *name ;
  592. X{
  593. X   static char misc_static[MAXPATHLEN] ;
  594. X   static char cwd[] = "." ;
  595. X
  596. X#ifdef TEST
  597. X   printf ("(_desc_parse_path called)\n") ;
  598. X#endif
  599. X
  600. X   if (pathname) {
  601. X      _desc_pathname = pathname ;
  602. X      if (name) {
  603. X     if (directory && *directory)
  604. X        _desc_directory = directory ;
  605. X     else
  606. X        _desc_directory = cwd ;
  607. X     _desc_name = name ; }
  608. X      else {    /* Path only */
  609. X     if (strlen (_desc_pathname) >
  610. X#ifdef __STDC__
  611. X           (size_t)
  612. X#endif
  613. X           MAXPATHLEN)
  614. X        return FALSE ;
  615. X
  616. X     /* Split path into directory and name */
  617. X
  618. X     _desc_directory = strcpy (misc_static, pathname) ;
  619. X     _desc_name = strrchr (_desc_directory, '/') ;
  620. X
  621. X     /* Clean out any superfluous trailing slashes */
  622. X
  623. X     while (_desc_name > _desc_directory && !_desc_name[1]) {
  624. X        *_desc_name = '\0' ;
  625. X        _desc_name = strrchr (_desc_directory, '/') ; }
  626. X
  627. X     if (_desc_name) {
  628. X
  629. X        /* We have a slash and something after it */
  630. X
  631. X        if (_desc_name == _desc_directory) {
  632. X
  633. X           /* The only slash is at start of string, ie, directory is "/" */
  634. X
  635. X           _desc_name = pathname + 1 ;
  636. X           _desc_directory[1] = '\0' ; }
  637. X
  638. X        else {
  639. X
  640. X           *_desc_name = '\0' ;        /* Kill slash */
  641. X           _desc_name++ ; } }
  642. X
  643. X     else {
  644. X
  645. X        if (_desc_name) {
  646. X
  647. X           /* We have something that ends in "/"; delete it and recurse */
  648. X
  649. X           *_desc_name = '\0' ;
  650. X           return _desc_parse_path (pathname) ; }
  651. X
  652. X        else {
  653. X
  654. X           /* No slash */
  655. X
  656. X           strcpy (_desc_directory, cwd) ;
  657. X           _desc_name = pathname ; } } } }
  658. X
  659. X   else {
  660. X
  661. X      /* No pathname, but should have directory and name */
  662. X
  663. X      if (! name) {
  664. X     return FALSE ; }
  665. X
  666. X      _desc_directory = directory ;
  667. X      _desc_name = name ;
  668. X
  669. X      if (directory && *directory) {
  670. X
  671. X     /* Construct path from directory and name */
  672. X
  673. X     if ((strlen (directory) + strlen (name)) >=
  674. X#ifdef __STDC__
  675. X           (size_t)
  676. X#endif
  677. X           MAXPATHLEN)
  678. X        return FALSE ;
  679. X     _desc_pathname = strcpy (misc_static, directory) ;
  680. X     strcat (_desc_pathname, "/") ;
  681. X     strcat (_desc_pathname, name) ; }
  682. X
  683. X      else {
  684. X
  685. X     /* Null directory; path == name */
  686. X
  687. X     _desc_pathname = name ; } }
  688. X
  689. X   return TRUE ;
  690. X   }
  691. X
  692. X
  693. X#ifdef TEST
  694. X
  695. Xint main (argc, argv)
  696. X   int argc ;
  697. X   char **argv ;
  698. X{
  699. X   char pathname[MAXPATHLEN] ;
  700. X   char directory[MAXPATHLEN] ;
  701. X   char name[MAXPATHLEN] ;
  702. X
  703. X   while (! feof (stdin)) {
  704. X      printf (" test pathname: ") ;
  705. X      fgets (pathname, MAXPATHLEN, stdin) ;
  706. X      printf ("test directory: ") ;
  707. X      fgets (directory, MAXPATHLEN, stdin) ;
  708. X      printf ("     test name: ") ;
  709. X      fgets (name, MAXPATHLEN, stdin) ;
  710. X      if (_desc_parse_path (pathname, directory, name))
  711. X     printf (
  712. X"---\n  _desc_pathname: %s\n _desc_directory: %s\n _desc_name: %s\n",
  713. X         _desc_pathname, _desc_directory, _desc_name) ;
  714. X      else
  715. X     perror (" error") ; }
  716. X   }
  717. X#endif
  718. END_OF_FILE
  719.   if test 5828 -ne `wc -c <'enddesc.c'`; then
  720.     echo shar: \"'enddesc.c'\" unpacked with wrong size!
  721.   fi
  722.   # end of 'enddesc.c'
  723. fi
  724. if test -f 'getdesc.3' -a "${1}" != "-c" ; then 
  725.   echo shar: Will not clobber existing file \"'getdesc.3'\"
  726. else
  727.   echo shar: Extracting \"'getdesc.3'\" \(2569 characters\)
  728.   sed "s/^X//" >'getdesc.3' <<'END_OF_FILE'
  729. X.\" getdesc.3 -    Man page for getdesc(), setdesc() and enddesc()
  730. X.\"
  731. X.\" Copyright (c) 1991, 1992 Tim Cook.
  732. X.\" Non-profit distribution allowed.  See README for details.
  733. X.\"
  734. X.\" $Id: getdesc.3,v 1.3 1992/12/02 05:06:10 tim Exp $
  735. X.\"
  736. X.TH GETDESC 3 "2 Dec, 1992"
  737. X.\"
  738. X.SH NAME
  739. Xgetdesc, setdesc, enddesc \- File description routines
  740. X.\"
  741. X.SH SYNOPSIS
  742. X.LP
  743. X.B
  744. X#include <sys/types.h>
  745. X.LP
  746. X.BI "char *getdesc (char *" "pathname" ,
  747. X.BI "char *" "dir" ,
  748. X.BI "char *" "name" ,
  749. X.BI "ino_t " "inode" );
  750. X.LP
  751. X.BI "int setdesc (char *" "pathname" ,
  752. X.BI "char *" "dir" ,
  753. X.BI "char *" "name" ,
  754. X.BI "ino_t " "inode" ,
  755. X.BI "char *" "desc" );
  756. X.LP
  757. X.B  "void enddesc ();"
  758. X.\"
  759. X.SH DESCRIPTION
  760. X.B getdesc(\|)
  761. Xreturns a description for a file located in directory
  762. X.I dir
  763. Xwith either a basename of
  764. X.I name
  765. Xor an inode number of
  766. X.I inode.
  767. XIf
  768. X.I name
  769. Xand
  770. X.I pathname
  771. Xare null or
  772. X.I inode
  773. Xis zero, their values will not be used to locate the description.
  774. XIf
  775. X.I dir
  776. Xand
  777. X.I name
  778. Xare both null, the directory and basename are extracted from
  779. X.I pathname.
  780. XThe best plan is to supply as much information as you have to
  781. X.BR getdesc(\|) .
  782. X.LP
  783. XNote that the pointer returned by
  784. X.B getdesc(\|)
  785. Xpoints to storage allocated by the DBM routines linked with
  786. X.BR getdesc(\|) ,
  787. Xwhich means that the value in this storage may be overwritten by any
  788. Xcalls to DBM routines.
  789. XIn particular, calling
  790. X.B setdesc(\|)
  791. X(which uses DBM routines) and passing it a pointer returned by
  792. X.B getdesc(\|)
  793. Xis not recommended.
  794. X.LP
  795. X.B setdesc(\|)
  796. Xsets a description for a file, specified as specified to
  797. X.BR getdesc(\|) .
  798. XAt least one of the
  799. X.I name
  800. Xor
  801. X.I pathname
  802. Xparameter to 
  803. X.I setdesc
  804. Xmust be specified.
  805. XIf the
  806. X.I inode
  807. Xparameter is zero,
  808. X.I setdesc
  809. Xwill attempt to look up the file's inode number.
  810. XAny null-terminated string can be used as a description, although it is
  811. Xadvised that a file description be human-readable.
  812. XIf
  813. X.I desc
  814. Xis null,
  815. X.B setdesc(\|)
  816. Xwill attempt to delete any existing description for the file.
  817. XIf a description database does not exist, it will be created.
  818. X.LP
  819. X.B enddesc(\|)
  820. Xdeallocates any resources that may have been allocated by
  821. X.B getdesc(\|)
  822. Xor
  823. X.BR setdesc(\|) .
  824. X.\"
  825. X.SH RETURN VALUE
  826. X.B getdesc(\|)
  827. Xreturns null if no description was found, with
  828. X.B errno
  829. Xset as possible explanation.
  830. X.LP
  831. X.B setdesc(\|)
  832. Xreturns 0 (FALSE) if it was unable to set a description, with
  833. X.B errno
  834. Xset as possible explanation.  It returns non-zero (TRUE) if
  835. Xsuccessful.
  836. X.\"
  837. X.SH FILES
  838. XFor each directory, a
  839. X.B .desc.pag
  840. Xand
  841. X.B .desc.dir
  842. X(DBM files) are used to store descriptions.
  843. X.\"
  844. X.SH "SEE ALSO"
  845. X.BR dl (1),
  846. X.BR describe (1)
  847. END_OF_FILE
  848.   if test 2569 -ne `wc -c <'getdesc.3'`; then
  849.     echo shar: \"'getdesc.3'\" unpacked with wrong size!
  850.   fi
  851.   # end of 'getdesc.3'
  852. fi
  853. if test -f 'getdesc.c' -a "${1}" != "-c" ; then 
  854.   echo shar: Will not clobber existing file \"'getdesc.c'\"
  855. else
  856.   echo shar: Extracting \"'getdesc.c'\" \(2129 characters\)
  857.   sed "s/^X//" >'getdesc.c' <<'END_OF_FILE'
  858. X/* getdesc.c -    Get file description
  859. X *
  860. X * Copyright (c) 1991, 1992 Tim Cook.
  861. X * Non-profit distribution allowed.  See README for details.
  862. X */
  863. X
  864. Xstatic char rcsid[] = "$Id: getdesc.c,v 1.2 1992/12/02 03:45:17 tim Exp $";
  865. X
  866. X#include "config.h"
  867. X#include <fcntl.h>
  868. X#include <sys/errno.h>
  869. X
  870. Xextern int errno ;
  871. Xextern int _desc_parse_path () ;
  872. Xextern char *_desc_pathname ;
  873. Xextern char *_desc_directory ;
  874. Xextern char *_desc_name ;
  875. Xextern int _initdesc () ;
  876. X#ifdef NDBM
  877. Xextern DBM *_desc_database ;
  878. X#endif
  879. X
  880. X
  881. Xchar *getdesc (pathname, directory, name, inode)
  882. X   char *pathname ;
  883. X   char *directory ;
  884. X   char *name ;
  885. X   ino_t inode ;
  886. X{
  887. X   static datum key, value ;
  888. X
  889. X   if (! pathname && ! name) {
  890. X      if (! inode) {
  891. X     errno = EINVAL ;
  892. X     return NULL_CP ; }
  893. X      else {
  894. X     _desc_name = name ;
  895. X     _desc_pathname = pathname ;
  896. X     if (directory && *directory)
  897. X        _desc_directory = directory ;
  898. X     else
  899. X        _desc_directory = "." ; } }
  900. X   else if (! _desc_parse_path (pathname, directory, name)) {
  901. X      errno = EINVAL ;
  902. X      return NULL_CP ; }
  903. X
  904. X   if (_initdesc (_desc_directory, O_RDONLY)) {
  905. X
  906. X      /* We have a description database */
  907. X
  908. X      int found = FALSE ;
  909. X
  910. X      if (_desc_name) {
  911. X
  912. X     /* Check for it by name */
  913. X
  914. X     key.dptr = _desc_name ;
  915. X     key.dsize = strlen (_desc_name) ;
  916. X     if (key.dsize == sizeof (ino_t))
  917. X        key.dsize++ ;
  918. X     value = DBM_fetch (_desc_database, key) ;
  919. X     found = value.dptr != NULL_CP ; }
  920. X
  921. X      if (! found && inode) {
  922. X
  923. X     /* Check for it by inode */
  924. X
  925. X     key.dptr = (char *) &inode ;
  926. X     key.dsize = sizeof (ino_t) ;
  927. X     value = DBM_fetch (_desc_database, key) ;
  928. X     if (value.dptr != NULL_CP) {
  929. X        char temp[sizeof (ino_t) + 1] ;
  930. X
  931. X        /* Now use the name we got using the inode */
  932. X
  933. X        if (value.dsize == sizeof (ino_t)) {
  934. X           strncpy (temp, value.dptr, sizeof (ino_t)) ;
  935. X           temp[sizeof (ino_t) + 1] = EOS ;
  936. X           key.dptr = temp ;
  937. X           key.dsize = sizeof (temp) ; }
  938. X        else {
  939. X           key.dptr = value.dptr ;
  940. X           key.dsize = value.dsize ; }
  941. X        value = DBM_fetch (_desc_database, key) ;
  942. X        found = value.dptr != NULL_CP ; } }
  943. X
  944. X      if (found)
  945. X     return value.dptr ;
  946. X      }
  947. X   return NULL_CP ;
  948. X   }
  949. END_OF_FILE
  950.   if test 2129 -ne `wc -c <'getdesc.c'`; then
  951.     echo shar: \"'getdesc.c'\" unpacked with wrong size!
  952.   fi
  953.   # end of 'getdesc.c'
  954. fi
  955. if test -f 'other/CONTEMPTIBILITY' -a "${1}" != "-c" ; then 
  956.   echo shar: Will not clobber existing file \"'other/CONTEMPTIBILITY'\"
  957. else
  958.   echo shar: Extracting \"'other/CONTEMPTIBILITY'\" \(5593 characters\)
  959.   sed "s/^X//" >'other/CONTEMPTIBILITY' <<'END_OF_FILE'
  960. XSubject: Why not make dl(1) compatible with ls(1)?
  961. X
  962. X
  963. XAuthor: Tim Cook <tim@deakin.edu.au>
  964. XDate: 5 Mar 1992
  965. X
  966. X
  967. X1. Introduction
  968. X
  969. X   Many people have suggested or asked for dl(1) to be made "compatible"
  970. X   with ls(1).  By this they mean they want either a flag for dl(1) that
  971. X   will make it revert to ls(1), or they want it to revert to ls(1) if
  972. X   it is given any flag not known to dl(1).
  973. X
  974. X   The desire for this is driven by the desire to cater for people who
  975. X   run programs that communicate with FTP daemons.  One such popular
  976. X   program is "ftpget", which automatically connects to an FTP daemon
  977. X   via the "anonymous" mechanism and fetches a whole directory tree.
  978. X
  979. X   These programs rely on the output from the FTP daemon being
  980. X   recognisable.  This usually means that they therefore rely on the
  981. X   output from a LIST command (more commonly known as the "dir" command
  982. X   at the client end) to be in some variant of "ls -l" format.
  983. X
  984. X
  985. X2. What to do?
  986. X
  987. X   As the author of dl(1), and the one who has taken responsiblity for
  988. X   how dl(1) functions, and how it is developed, I feel it necessary to
  989. X   respond to this suggested change.
  990. X
  991. X   I can either respond in agreement, implement the change, and
  992. X   (optionally) justify the change,  or I can dismiss the suggestion and
  993. X   (not really optionally) justify such a dismissal.
  994. X
  995. X   Or, I can try and do both.
  996. X
  997. X
  998. X3. Why I didn't want to make this change.
  999. X
  1000. X   I did not want to add this "compatibility" feature to dl(1), because
  1001. X   it is not what dl(1) is about.  Dl(1) is about being a utility that
  1002. X   lists directory entries along with descriptive comments.
  1003. X
  1004. X   To make dl(1) revert back to ls(1) is to do something that was never
  1005. X   intended, and would cloud dl(1)'s purpose.  How many Unix utilities
  1006. X   do you know of that deliberately emulate other Unix utilities in
  1007. X   certain circumstances.
  1008. X
  1009. X   To leave dl(1) as it is; as a self-contained, single-purpose utility,
  1010. X   however, would be very much in line with the philosophy of Unix,
  1011. X   which is to maintain functional integrity and modularity .  As
  1012. X   experience has shown, it is always best to follow this philosophy
  1013. X   in the Unix environment.
  1014. X
  1015. X   The other argument I considered in resisting this change, was that it
  1016. X   was not dl(1) that needed to be changed.  Dl(1) was quite adequately
  1017. X   providing information on files to users of Anonymous FTP.  The vast
  1018. X   majority of Anonymous FTP users are humans.  Dl(1)'s foremost purpose
  1019. X   is to serve human users, but there is no reason why a program could
  1020. X   not read dl(1)'s output.  I have made a deliberate decision to keep
  1021. X   dl(1)'s output determinable.  It is also possible to discern it from
  1022. X   "ls -l" output without too much programmatical effort.  So, why not
  1023. X   change these utilities that need the "ls -l" output?  Surely they are
  1024. X   the place where the deficiency rests?
  1025. X
  1026. X   This argument was always held strong by me, especially because I work
  1027. X   with VMS, and while there are plenty of VMS-based Anonymous FTP
  1028. X   sites, I doubt there are any that produce "ls -l" compatible output.
  1029. X   The big push towards a higher-level interface to the entire Internet
  1030. X   FTP Archive (manifested mainly in Archie at present) remains very
  1031. X   Unix-centric, and this needs to change.  The developers of Archie
  1032. X   have acknowledged this fact, and are addressing it.
  1033. X
  1034. X   The last argument against changing dl(1) was sort-of a political one.
  1035. X   If I attached a "safety blanket" to dl(1), it would undermine its
  1036. X   acceptance among Anonymous FTP users.  Obviously I don't desire such
  1037. X   a thing, because I want to see every Anonymous FTP site on the
  1038. X   Internet using dl(1), because I honestly believe it is "the way to
  1039. X   go".  The present "standard" of "ls -Alg" output is just not suited
  1040. X   to the purpose.
  1041. X
  1042. X
  1043. X4. But we all want to please most of the people, most of the time.
  1044. X
  1045. X   Recently I gave up a little ground on this issue, and decided I would
  1046. X   provide an unofficial patch to dl(1) that would provide the desired
  1047. X   "escape to ls(1)".  This patch can be found in the
  1048. X   "CONTEMPTIBLE.patch" file in the "describe" distribution.
  1049. X
  1050. X   I did this just so that others who were unable to do it would not be
  1051. X   left out in the cold, and so that those who feel they have to provide
  1052. X   for users of programs that talk to FTP daemons would still be able to
  1053. X   provide for users who can be helped by more useful output from LIST.
  1054. X
  1055. X
  1056. X5. The future.
  1057. X
  1058. X   I can't say whether my unofficial patch will ever become official.  I
  1059. X   doubt it will, but I also doubt I will remove it.
  1060. X
  1061. X   It is possible that in the future, FTP daemon software will be
  1062. X   changed so that it has a "human interface" and a "machine interface".
  1063. X   If this happens, my unofficial patch, and this debate, will become
  1064. X   irrelevant.  Of course, it could be argued that there already is a
  1065. X   remote file transfer machine interface, in the form of NFS.  Well, I
  1066. X   was thinking of something that falls between NFS and FTP.  Perhaps a
  1067. X   more popular, more portable Prospero.
  1068. X
  1069. X   I seriously hope that, in the near future, the use of Anonymous FTP
  1070. X   by humans (and hence, the use of dl(1) in Anonymous FTP) is
  1071. X   obsoleted by some such system.  God knows the Internet needs
  1072. X   something better.
  1073. X
  1074. X
  1075. XUPDATE, 5 May 1992:
  1076. X
  1077. X   There is now another approach.  The Anonymous FTP administrator can
  1078. X   now install UUNET's FTP daemon (available in source form from
  1079. X   ftp.uu.net), and subsequently patch it to use "plain ls" when a
  1080. X   user starts an Anonymous FTP session with a password beginning with
  1081. X   "-" (hyphen).  This patch is available with "describe" as the file
  1082. X   "UUNET-ftpd.patch".
  1083. END_OF_FILE
  1084.   if test 5593 -ne `wc -c <'other/CONTEMPTIBILITY'`; then
  1085.     echo shar: \"'other/CONTEMPTIBILITY'\" unpacked with wrong size!
  1086.   fi
  1087.   # end of 'other/CONTEMPTIBILITY'
  1088. fi
  1089. if test -f 'other/dumpdesc.c' -a "${1}" != "-c" ; then 
  1090.   echo shar: Will not clobber existing file \"'other/dumpdesc.c'\"
  1091. else
  1092.   echo shar: Extracting \"'other/dumpdesc.c'\" \(1524 characters\)
  1093.   sed "s/^X//" >'other/dumpdesc.c' <<'END_OF_FILE'
  1094. X/* dumpdesc.c -    Dump description database
  1095. X *
  1096. X * An unsupported utility to dump all entries in a ".desc" database.
  1097. X */
  1098. X
  1099. X#include "config.h"
  1100. X#include <stdio.h>
  1101. X#include <sys/file.h>
  1102. X
  1103. X#ifndef MAXPATHLEN
  1104. X#define MAXPATHLEN     1024
  1105. X#endif
  1106. X
  1107. Xextern int _initdesc () ;
  1108. X
  1109. X#ifdef NDBM
  1110. Xextern DBM *_desc_database ;
  1111. X#endif
  1112. X
  1113. X
  1114. Xint main (argc, argv)
  1115. X   int argc ;
  1116. X   char **argv ;
  1117. X{
  1118. X   datum key, content ;
  1119. X
  1120. X   if (argc > 2) {
  1121. X      fprintf (stderr, "usage: %s [dir]\n", argv[0]) ;
  1122. X      exit (1) ; }
  1123. X
  1124. X   if (_initdesc ((argc < 2) ? "." : argv[1], O_RDONLY)) {
  1125. X      char name[MAXPATHLEN] ;
  1126. X      ino_t inode ;
  1127. X      int entries = 0 ;
  1128. X
  1129. X      for (key = DBM_firstkey (_desc_database) ; key.dptr ; key =
  1130. X         DBM_nextkey (_desc_database, key)) {
  1131. X         entries++ ;
  1132. X     content = DBM_fetch (_desc_database, key) ;
  1133. X     if (content.dptr) {
  1134. X        if (key.dsize == sizeof (ino_t)) {
  1135. X           /* I-node */
  1136. X           strncpy (name, content.dptr, content.dsize) ;
  1137. X           name[content.dsize] = '\0' ;
  1138. X           memcpy (&inode, key.dptr, sizeof (ino_t)) ;
  1139. X           /* This may not work if ino_t isn't "long unsigned" */
  1140. X           printf ("inode:  %10lu,       -  `%s'\n", inode,
  1141. X          name) ; }
  1142. X        else {
  1143. X           strncpy (name, key.dptr, key.dsize) ;
  1144. X           name[key.dsize] = '\0' ;
  1145. X           if (key.dsize > 16) {
  1146. X          printf ("name:   %-s\n                          -  `%s'\n",
  1147. X             name, content.dptr) ; }
  1148. X           else {
  1149. X          printf ("name:   %-16s  -  `%s'\n", name, content.dptr) ; }
  1150. X        } } }
  1151. X
  1152. X      printf ("\nTotal entries: %d\n", entries) ;
  1153. X      }
  1154. X   }
  1155. END_OF_FILE
  1156.   if test 1524 -ne `wc -c <'other/dumpdesc.c'`; then
  1157.     echo shar: \"'other/dumpdesc.c'\" unpacked with wrong size!
  1158.   fi
  1159.   # end of 'other/dumpdesc.c'
  1160. fi
  1161. if test -f 'other/lslR2dl.pl' -a "${1}" != "-c" ; then 
  1162.   echo shar: Will not clobber existing file \"'other/lslR2dl.pl'\"
  1163. else
  1164.   echo shar: Extracting \"'other/lslR2dl.pl'\" \(5809 characters\)
  1165.   sed "s/^X//" >'other/lslR2dl.pl' <<'END_OF_FILE'
  1166. X#!/usr/local/bin/perl
  1167. X#
  1168. X# This converts an "ls -lR" type listing to a "dl -d" listing.  Lines
  1169. X# that are recognised as a file listing are re-formatted.  All others
  1170. X# are just copied as-is.
  1171. X#
  1172. X# Tim Cook, 31 Jan 1992
  1173. X
  1174. X# Constants
  1175. X
  1176. X#
  1177. X# We have a look at where the month appears on lines that list files,
  1178. X# then use this to make a decision on what will be acceptable.
  1179. X#
  1180. X
  1181. X# Number of lines to look at to decide where month is appearing
  1182. X$lines_to_check = 50 ;
  1183. X
  1184. X# If the month appears before this on a line, we opt not to do anything
  1185. X$minimum_month_offset = 28 ;
  1186. X
  1187. X# Later on, the month is allowed to appear this much before or after
  1188. X# what we originally saw.
  1189. X$month_drift = 3 ;
  1190. X
  1191. X# The number of columns to hold the filename and size output
  1192. X# (equivalent to the value given to dl's "-f" option).
  1193. X$filename_columns = 14 ;
  1194. X
  1195. X
  1196. X#################
  1197. X# START PROGRAM #
  1198. X#################
  1199. X
  1200. X# Do we have a "-f" option?
  1201. X
  1202. Xif ($#ARGV >= 0 && substr ($ARGV[0], 0, 1) eq '-') {
  1203. X   $_ = shift (@ARGV) ;
  1204. X   if (@_ = /^-f([0-9][0-9]*)$/) {
  1205. X      $filename_columns = shift (@_) ; }
  1206. X   else {
  1207. X      if ($#ARGV >= 0) {
  1208. X         $_ = shift (@ARGV) ;
  1209. X         if (@_ = /^([0-9][0-9]*)$/) {
  1210. X            $filename_columns = shift (@_) ; }
  1211. X     else {
  1212. X            $error = 1 ; } }
  1213. X      else {
  1214. X         $error = 1 ; } }
  1215. X
  1216. X   if ($error) {
  1217. X      print (STDERR "usage: lslR2dl [-f filename_columns] [file ...]\n") ;
  1218. X      exit (1) ; }
  1219. X   }
  1220. X
  1221. X# (Something more useful)
  1222. X$filename_size_width = $filename_columns + 9 ;
  1223. X
  1224. X#
  1225. X# Locate where the month can be found.  Must match at least 7 out
  1226. X# of 10 records that actually list a file
  1227. X#
  1228. X
  1229. Xfor ($i = 0 ; $i < $lines_to_check ; $i++) {
  1230. X   if ($_ = <>) {
  1231. X#      print ("Input: $_") ;
  1232. X      if (length ($_) > ($minimum_month_offset+10) && index ($_, ' ') != -1) {
  1233. X         # Look for a month
  1234. X         @matches =
  1235. X      /([0-9] (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [ 0-9][0-9])/ ;
  1236. X         # Record where it was found
  1237. X         if ($#matches == 1) {
  1238. X            push (@locations, index ($_, $matches[0])) ; } }
  1239. X      push (@input, $_) ; }
  1240. X   else {
  1241. X      $i = $lines_to_check ; } }
  1242. X
  1243. X# Find out how popular the most popular location was
  1244. X
  1245. X@locations = sort (@locations) ;
  1246. Xpush (@locations, -1) ;        # This is a dummy value
  1247. X$no_locations = $#locations ;
  1248. X
  1249. Xwhile ($location = shift (@locations)) {
  1250. X   if ($location == $last_location) {
  1251. X      # Same as last one
  1252. X      $popularity++ ; }
  1253. X   else {
  1254. X      # New value
  1255. X      if ($popularity > $best_popularity) {
  1256. X         # Previous value's popularity is higher than the previous best
  1257. X         $most_popular = $last_location ;
  1258. X         $best_popularity = $popularity ; }
  1259. X      $popularity = 1 ; }
  1260. X  $last_location = $location ; }
  1261. X
  1262. X# Test popularity ratio
  1263. X
  1264. Xif (($best_popularity / $no_locations) < 0.7
  1265. X      && $best_popularity > $minimum_month_offset) {
  1266. X   print (STDERR
  1267. X   "lslR2dl: Are you sure that this is ls -lR output?  I can't understand it.\n") ;
  1268. X   exit (2) ; }
  1269. X
  1270. X#printf ("Number of files listed: $no_locations\n" .
  1271. X#   "Most popular location of month: $most_popular\nPopularity: %1.4f\n",
  1272. X#   $best_popularity / $no_locations) ;
  1273. X
  1274. X#
  1275. X# Now we have a popular location at which to find the month (plus two
  1276. X# leading characters).  We will allow positive and negative offsets
  1277. X# from this point in order to match all future file listings.
  1278. X# Anything that does not match is simply copied to output.
  1279. X#
  1280. X
  1281. X# This is now based on what we found above
  1282. X$minimum_month_offset = $most_popular + 2 - $month_drift ;
  1283. X$maximum_month_offset = $most_popular + 2 + $month_drift ;
  1284. X
  1285. X$more = 1 ;
  1286. X
  1287. Xwhile ($more) {
  1288. X
  1289. X   # Get input
  1290. X
  1291. X   if ($#input < 0 && eof ()) {
  1292. X      $more = 0 ; }
  1293. X   else {
  1294. X      if ($#input >= 0) {
  1295. X         $_ = shift (@input) ; }
  1296. X      else {
  1297. X         $_ = <> ; }
  1298. X
  1299. X      # See if it is a file listing
  1300. X
  1301. X      if (length ($_) > ($minimum_month_offset+10) && index ($_, ' ') != -1) {
  1302. X         # Look for a month
  1303. X         @matches =
  1304. X      /([0-9] (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [ 0-9][0-9])/ ;
  1305. X
  1306. X         if ($#matches == 1) {
  1307. X
  1308. X            $month_offset = index ($_, $matches[0]) + 2 ;
  1309. X            if ($month_offset >= $minimum_month_offset
  1310. X                  && $month_offset <= $maximum_month_offset) {
  1311. X
  1312. X               # It is
  1313. X
  1314. X               # Extract data
  1315. X
  1316. X               chop ;
  1317. X           ($month, $day, $year_or_time, $filename) =
  1318. X                  split (' ', substr ($_, $month_offset, 999)) ;
  1319. X               $_ = substr ($_, 0, $month_offset) ;
  1320. X               if (substr ($_, 0, 1) eq 'd') {
  1321. X                  # We have a directory
  1322. X                  $filename .= '/' ;
  1323. X                  $links = substr ($_, 10, 4) ;
  1324. X                  # Does it contain other directories?
  1325. X                  if ($links > 2) {
  1326. X                     $size = '=' ; }
  1327. X                  else {
  1328. X                     $size = '-' ; } }
  1329. X               else {
  1330. X                  # Normal file
  1331. X                  split (' ') ; $size = pop (@_) ; }
  1332. X
  1333. X               # Format data
  1334. X
  1335. X               $filename_length = length ($filename) ;
  1336. X               $size_length = length ($size) ;
  1337. X               if (($filename_length + $size_length) >
  1338. X                 $filename_size_width - 2) {
  1339. X                  # We need to do a line break after the filename
  1340. X                  $_ = $filename . "\n"
  1341. X                     . ' ' x ($filename_size_width - length ($size))
  1342. X                     . $size ; }
  1343. X           else {
  1344. X                  $_ = $filename . ' ' x ($filename_size_width
  1345. X                 - $filename_length - $size_length) . $size ; }
  1346. X# Un-comment this and comment out the next two lines if you prefer the
  1347. X# US date format
  1348. X#               $_ .= ' ' . sprintf ("%s %2d %5s\n", $month, $day
  1349. X#                  $year_or_time) ;
  1350. X               $_ .= ' ' . sprintf ("%2d %s %5s\n", $day, $month,
  1351. X                  $year_or_time) ;
  1352. X               } } }
  1353. X
  1354. X      # Print
  1355. X
  1356. X      print ;
  1357. X      }
  1358. X   }
  1359. END_OF_FILE
  1360.   if test 5809 -ne `wc -c <'other/lslR2dl.pl'`; then
  1361.     echo shar: \"'other/lslR2dl.pl'\" unpacked with wrong size!
  1362.   fi
  1363.   # end of 'other/lslR2dl.pl'
  1364. fi
  1365. if test -f 'patches/BSD-mv.patch' -a "${1}" != "-c" ; then 
  1366.   echo shar: Will not clobber existing file \"'patches/BSD-mv.patch'\"
  1367. else
  1368.   echo shar: Extracting \"'patches/BSD-mv.patch'\" \(3224 characters\)
  1369.   sed "s/^X//" >'patches/BSD-mv.patch' <<'END_OF_FILE'
  1370. XThe enclosed patch can be applied to BSD mv (which I got from UUNET's
  1371. Xbsd-sources package, which can be found on ftp.uu.net in the directory
  1372. Xpackages/bsd-sources/bin/mv) to give it a "-d" flag which will
  1373. Xinstruct mv to move file descriptions with files (see the file
  1374. X"GNU-mv.patch", also).
  1375. X
  1376. XThe patched mv.c must be compiled with the DESCRIPTIONS macro defined,
  1377. Xand linked with setdesc.o, getdesc.o, enddesc.o and pathname.o from
  1378. Xthe dl/describe package and the DBM library used with dl/describe.
  1379. X
  1380. XInstructions on the use of the bsd-sources package can be found in
  1381. Xpackages/bsd-sources/README.Z.
  1382. X
  1383. XNote that I cannot guarantee that this will work, as I was unable to
  1384. Xget it to link on my system.
  1385. X
  1386. XThe SCCS id contained in the BSD source of mv.c that I generated this
  1387. Xpatch from was as follows:
  1388. X
  1389. X    mv.c    5.11 (Berkeley) 4/3/91
  1390. X
  1391. X
  1392. X*** mv.c.dist    Thu Apr  2 17:25:04 1992
  1393. X--- mv.c    Thu Apr  2 17:49:01 1992
  1394. X***************
  1395. X*** 58,61 ****
  1396. X--- 58,64 ----
  1397. X  
  1398. X  int fflg, iflg;
  1399. X+ #ifdef DESCRIPTIONS
  1400. X+ int dflg;
  1401. X+ #endif
  1402. X  
  1403. X  main(argc, argv)
  1404. X***************
  1405. X*** 71,75 ****
  1406. X      char path[MAXPATHLEN + 1];
  1407. X  
  1408. X!     while (((ch = getopt(argc, argv, "-if")) != EOF))
  1409. X          switch((char)ch) {
  1410. X          case 'i':
  1411. X--- 74,84 ----
  1412. X      char path[MAXPATHLEN + 1];
  1413. X  
  1414. X!     while (((ch = getopt(argc, argv,
  1415. X! #ifdef DESCRIPTIONS
  1416. X!                  "-idf"
  1417. X! #else
  1418. X!                  "-if"
  1419. X! #endif
  1420. X!                  )) != EOF))
  1421. X          switch((char)ch) {
  1422. X          case 'i':
  1423. X***************
  1424. X*** 76,79 ****
  1425. X--- 85,93 ----
  1426. X              iflg = 1;
  1427. X              break;
  1428. X+ #ifdef DESCRIPTIONS
  1429. X+         case 'd':
  1430. X+             dflg = 1;
  1431. X+             break;
  1432. X+ #endif
  1433. X          case 'f':
  1434. X              fflg = 1;
  1435. X***************
  1436. X*** 128,131 ****
  1437. X--- 142,154 ----
  1438. X      struct stat sb;
  1439. X      int ask, ch;
  1440. X+ #ifdef DESCRIPTIONS
  1441. X+     int return_status;
  1442. X+     char *from_description;
  1443. X+     int from_ino;
  1444. X+ 
  1445. X+     if (dflg)
  1446. X+         if (!stat(from, &sb))
  1447. X+             from_ino = sb.st_ino;
  1448. X+ #endif
  1449. X  
  1450. X      /*
  1451. X***************
  1452. X*** 152,157 ****
  1453. X          }
  1454. X      }
  1455. X!     if (!rename(from, to))
  1456. X          return(0);
  1457. X  
  1458. X      if (errno != EXDEV) {
  1459. X--- 175,204 ----
  1460. X          }
  1461. X      }
  1462. X! #ifdef DESCRIPTIONS
  1463. X!     if (dflg) {
  1464. X!         /* Get description of "from" */
  1465. X!         char *p = getdesc(from, NULL, NULL, from_ino);
  1466. X!         if (p) {
  1467. X!             if (from_description =
  1468. X!                 (char *) malloc(strlen(p) + 1)) {
  1469. X!                 strcpy(from_description, p);
  1470. X!             } else
  1471. X!                 error(NULL);
  1472. X!         }
  1473. X!     }
  1474. X! #endif
  1475. X!     if (!rename(from, to)) {
  1476. X! #ifdef DESCRIPTIONS
  1477. X!         if (dflg) {
  1478. X!             /* Set description on "to" */
  1479. X!             if (setdesc(to, NULL, NULL, 0, from_description))
  1480. X!                 /* Delete description on "from" */
  1481. X!                 setdesc(from, NULL, NULL, from_ino, NULL);
  1482. X!             if (from_description)
  1483. X!                 free(from_description);
  1484. X!         }
  1485. X! #endif
  1486. X          return(0);
  1487. X+     }
  1488. X  
  1489. X      if (errno != EXDEV) {
  1490. X***************
  1491. X*** 169,174 ****
  1492. X--- 216,235 ----
  1493. X          return(1);
  1494. X      }
  1495. X+ #ifdef DESCRIPTIONS
  1496. X+     return_status = S_ISREG(sb.st_mode) ?
  1497. X+         fastcopy(from, to, &sb) : copy(from, to);
  1498. X+         if (dflg && !return_status) {
  1499. X+         /* Set description on "to" */
  1500. X+         if (setdesc(to, NULL, NULL, 0, from_description))
  1501. X+             /* Delete description on "from" */
  1502. X+             setdesc(from, NULL, NULL, from_ino, NULL);
  1503. X+         if (from_description)
  1504. X+             free(from_description);
  1505. X+     }
  1506. X+     return(return_status);
  1507. X+ #else
  1508. X      return(S_ISREG(sb.st_mode) ?
  1509. X          fastcopy(from, to, &sb) : copy(from, to));
  1510. X+ #endif
  1511. X  }
  1512. X  
  1513. END_OF_FILE
  1514.   if test 3224 -ne `wc -c <'patches/BSD-mv.patch'`; then
  1515.     echo shar: \"'patches/BSD-mv.patch'\" unpacked with wrong size!
  1516.   fi
  1517.   # end of 'patches/BSD-mv.patch'
  1518. fi
  1519. if test -f 'patches/CONTEMPTIBLE.patch' -a "${1}" != "-c" ; then 
  1520.   echo shar: Will not clobber existing file \"'patches/CONTEMPTIBLE.patch'\"
  1521. else
  1522.   echo shar: Extracting \"'patches/CONTEMPTIBLE.patch'\" \(2301 characters\)
  1523.   sed "s/^X//" >'patches/CONTEMPTIBLE.patch' <<'END_OF_FILE'
  1524. XThere are some people who have expressed the opinion that dl(1) in the
  1525. XAnonymous FTP realm needs one more thing -- backwards compatiblity
  1526. Xwith the traditional "ls -l" output.  This is because there are
  1527. Xvarious programs in existence that gather information via Anonymous
  1528. XFTP connections, and they have been written to understand with the most
  1529. Xcommon type of FTP directory listing only.
  1530. X
  1531. XThis is an _unofficial_ patch that I am providing for those who have
  1532. Xsuch an opinion, which I do not share.  As it is, if you put a copy of
  1533. X/bin/ls in ~ftp/bin/ls.orig and compile dl with -DCONTEMPTIBLE, all
  1534. Xyou have to do is add "-C" to a "dir" (or whatever your FTP client
  1535. Xuses) command and the standard "ls -l" output should appear.  If not,
  1536. Xit is probably the fault of your ftpd(8).
  1537. X
  1538. XMake no mistake, this will NEVER be an official part of dl(1).  It is
  1539. Xnot the purpose of an FTP server to be compatible with every TD&H's
  1540. Xclever chunk of AI.  FTP server's were designed to provide human-
  1541. Xreadable directory listings, and dl's sole aim in this area is to
  1542. Xincrease that readability.
  1543. X
  1544. X
  1545. X*** dl.c.dist    Thu Apr  2 18:08:58 1992
  1546. X--- dl.c    Tue May  5 12:23:55 1992
  1547. X***************
  1548. X*** 38,41 ****
  1549. X--- 38,45 ----
  1550. X  extern char *pathname () ;
  1551. X  
  1552. X+ #ifdef CONTEMPTIBLE
  1553. X+ #define    THE_REAL_LS    "/bin/ls.orig"    /* A copy of your real ls(1) */
  1554. X+ #endif
  1555. X+ 
  1556. X  #define strgencpy(new, old) \
  1557. X      (new = strcpy ((char *) allocate (strlen (old) + 1), old))
  1558. X***************
  1559. X*** 93,96 ****
  1560. X--- 97,104 ----
  1561. X     extern int optind, opterr ;
  1562. X  
  1563. X+ #ifdef CONTEMPTIBLE
  1564. X+    char **save_argv = argv ;
  1565. X+ #endif
  1566. X+ 
  1567. X     int option ;
  1568. X     struct list file_list, dir_list ;
  1569. X***************
  1570. X*** 100,104 ****
  1571. X  
  1572. X     opterr = 0 ;
  1573. X!    while ((option = getopt (argc, argv, "deitf:R")) != EOF) {
  1574. X        switch ((char) option) {
  1575. X           case 'd' :
  1576. X--- 108,118 ----
  1577. X  
  1578. X     opterr = 0 ;
  1579. X!    while ((option = getopt (argc, argv, 
  1580. X! #ifdef CONTEMPTIBLE
  1581. X!          "deitf:CR"
  1582. X! #else
  1583. X!      "deitf:R"
  1584. X! #endif
  1585. X!      )) != EOF) {
  1586. X        switch ((char) option) {
  1587. X           case 'd' :
  1588. X***************
  1589. X*** 113,116 ****
  1590. X--- 127,136 ----
  1591. X       case 'R' :
  1592. X          recursive = TRUE ; break ;
  1593. X+ #ifdef CONTEMPTIBLE
  1594. X+      case 'C' :
  1595. X+         /* Exec the real ls(1) */
  1596. X+         execv (THE_REAL_LS, save_argv) ;
  1597. X+         break ;
  1598. X+ #endif
  1599. X       case '?' :
  1600. X              break ; } }
  1601. END_OF_FILE
  1602.   if test 2301 -ne `wc -c <'patches/CONTEMPTIBLE.patch'`; then
  1603.     echo shar: \"'patches/CONTEMPTIBLE.patch'\" unpacked with wrong size!
  1604.   fi
  1605.   # end of 'patches/CONTEMPTIBLE.patch'
  1606. fi
  1607. if test -f 'patches/UUNET-ftpd.patch' -a "${1}" != "-c" ; then 
  1608.   echo shar: Will not clobber existing file \"'patches/UUNET-ftpd.patch'\"
  1609. else
  1610.   echo shar: Extracting \"'patches/UUNET-ftpd.patch'\" \(3416 characters\)
  1611.   sed "s/^X//" >'patches/UUNET-ftpd.patch' <<'END_OF_FILE'
  1612. XThere is a popular freely-available FTPD that comes from UUNET.  This
  1613. Xis a patch to that FTPD that enables "dl"-format listings when you log
  1614. Xin as "anonymous" and specify a password without a leading hyphen (-).
  1615. X
  1616. XThis patch was prompted by David Datta, who posted this:
  1617. X
  1618. X> Message-ID: <1992Mar9.170131.16984@uwm.edu>
  1619. X> Newsgroups: comp.archives.admin
  1620. X> To: comp.archives.admin
  1621. X> Subject: Re: Using descriptive listing programs instead of 'ls -l'
  1622. X> From: datta@cs.uwp.edu (David Datta)
  1623. X> Date: 9 Mar 92 17:01:31 GMT
  1624. X> 
  1625. X> 
  1626. X> Since I posted the query, a suggestion to use the UUNET ftpd feature of
  1627. X> using a '-' in the password to turn off the extended features and have
  1628. X> it also turn off the extended ls program has been implimented. If
  1629. X> anyone would like the DIFFs to the UUNET ftpd to allow for 'ls' and
  1630. X> 'ls.old', please e-mail me.
  1631. X> 
  1632. X> The solution is now, if you log in with a '-' as the first character of
  1633. X> your password, the extended listings are turned off.
  1634. X> --
  1635. X> -Dave datta@cs.uwp.edu.
  1636. X> Visit the music FTP archives at cs.uwp.edu (131.210.1.4)
  1637. X
  1638. X
  1639. XHe sent me the patch, and I added it, with a few modifications (most
  1640. Xnotably, I disabled "dl" listings for non-anonymous users).
  1641. X
  1642. XThe following patch should be applied to the WUARCHIVE ftpd source
  1643. X(available from ftp.uu.net in /networking/archival/ftp/ftpd.wuarchive.shar.Z),
  1644. Xthen compiled with the DL_LIST macro defined.  Note that nothing needs
  1645. Xto be linked with any describe object modules.
  1646. X
  1647. XTo use this feature, set up your Anonymous FTP directories as normal,
  1648. Xbut add "dl" (using that name) to ~ftp/bin.  If you would normally
  1649. Xlink "dl" with shared libraries (as found on SunOS and others), you
  1650. Xwill need to use a staically linked "dl".  See the Makefile for
  1651. Xdetails.
  1652. X
  1653. X
  1654. X*** ftpcmd.y.orig    Fri Dec 27 17:45:12 1991
  1655. X--- ftpcmd.y    Fri Sep 25 17:40:58 1992
  1656. X***************
  1657. X*** 48,52 ****
  1658. X--- 48,55 ----
  1659. X  #include <string.h>
  1660. X  #include "support/ftw.h"
  1661. X  
  1662. X+ #ifdef DL_LIST
  1663. X+ extern    int dolreplies;
  1664. X+ #endif
  1665. X  extern    struct sockaddr_in data_dest;
  1666. X  extern    int logged_in;
  1667. X***************
  1668. X*** 271,275 ****
  1669. X--- 274,283 ----
  1670. X              if (cmdlogging) syslog(LOG_INFO, "LIST");
  1671. X              if ($2)
  1672. X+ #ifdef DL_LIST
  1673. X+                 retrieve((anonymous && dolreplies) ? "/bin/dl"
  1674. X+                      : "/bin/ls -lga", "");
  1675. X+ #else
  1676. X                  retrieve("/bin/ls -lgA", "");
  1677. X+ #endif
  1678. X          }
  1679. X      |    LIST check_login SP pathname CRLF
  1680. X***************
  1681. X*** 277,281 ****
  1682. X--- 285,295 ----
  1683. X              if (cmdlogging) syslog(LOG_INFO, "LIST %s", $4);
  1684. X              if ($2 && $4 != NULL)
  1685. X+ #ifdef DL_LIST
  1686. X+                 retrieve((anonymous && dolreplies)
  1687. X+                      ? "/bin/dl %s" : "/bin/ls -lgA %s",
  1688. X+                      $4);
  1689. X+ #else
  1690. X                  retrieve("/bin/ls -lgA %s", $4);
  1691. X+ #endif
  1692. X              if ($4 != NULL)
  1693. X                  free($4);
  1694. X
  1695. X
  1696. X*** ftpd.c.orig    Thu Sep 24 16:17:49 1992
  1697. X--- ftpd.c    Fri Sep 25 17:42:10 1992
  1698. X***************
  1699. X*** 1278,1282 ****
  1700. X--- 1278,1287 ----
  1701. X      int c;
  1702. X  
  1703. X+ #ifdef DL_LIST
  1704. X+     (void) sprintf(line, (anonymous && dolreplies) ? "/bin/dl %s"
  1705. X+                : "/bin/ls -lgA %s", filename);
  1706. X+ #else
  1707. X      (void) sprintf(line, "/bin/ls -lgA %s", filename);
  1708. X+ #endif
  1709. X      fin = ftpd_popen(line, "r");
  1710. X      lreply(211, "status of %s:", filename);
  1711. X***************
  1712. X*** 1742,1746 ****
  1713. X--- 1747,1757 ----
  1714. X               */
  1715. X              if (dirname[0] == '-' && *dirlist == NULL && transflag == 0) {
  1716. X+ #ifdef DL_LIST
  1717. X+                 retrieve((anonymous && dolreplies)
  1718. X+                      ? "/bin/dl %s" : "/bin/ls %s",
  1719. X+                      dirname);
  1720. X+ #else
  1721. X                  retrieve("/bin/ls %s", dirname);
  1722. X+ #endif
  1723. X                  return;
  1724. X              }
  1725. END_OF_FILE
  1726.   if test 3416 -ne `wc -c <'patches/UUNET-ftpd.patch'`; then
  1727.     echo shar: \"'patches/UUNET-ftpd.patch'\" unpacked with wrong size!
  1728.   fi
  1729.   # end of 'patches/UUNET-ftpd.patch'
  1730. fi
  1731. if test -f 'perror2.c' -a "${1}" != "-c" ; then 
  1732.   echo shar: Will not clobber existing file \"'perror2.c'\"
  1733. else
  1734.   echo shar: Extracting \"'perror2.c'\" \(1281 characters\)
  1735.   sed "s/^X//" >'perror2.c' <<'END_OF_FILE'
  1736. X/* perror2 -    Like perror(3), but with two string prefixes
  1737. X *
  1738. X * SYNOPSIS
  1739. X *    void perror2 (const char *str1, const char *str2) ;
  1740. X *
  1741. X * DESCRIPTION
  1742. X *    Prints str1, then a colon and a space, then str2, then a colon and
  1743. X *    a space, then the error message corresponding to the contents of
  1744. X *    errno, then a newline on stderr.
  1745. X */
  1746. X
  1747. Xstatic char rcsid[] = "$Id: perror2.c,v 1.2 1992/12/02 03:49:59 tim Exp $";
  1748. X
  1749. Xextern int strlen () ;
  1750. X
  1751. X
  1752. Xvoid perror2 (str1, str2)
  1753. X   char *str1, *str2 ;
  1754. X{
  1755. X   extern int errno ;
  1756. X   extern char *sys_errlist[] ;
  1757. X   extern int sys_nerr ;
  1758. X   register int save_errno = errno ;
  1759. X   static char unknown_error[] = "Unknown error" ;
  1760. X   static char colon_space[2] = {':', ' '} ;
  1761. X   static char newline = '\n' ;
  1762. X   char *p ;
  1763. X
  1764. X   if (save_errno < 0 || save_errno >= sys_nerr)
  1765. X      p = unknown_error ;
  1766. X   else
  1767. X      p = sys_errlist[save_errno] ;
  1768. X   write (2, str1, strlen (str1)) ;
  1769. X   write (2, colon_space, sizeof (colon_space)) ;
  1770. X   write (2, str2, strlen (str2)) ;
  1771. X   write (2, colon_space, sizeof (colon_space)) ;
  1772. X   write (2, p, strlen (p)) ;
  1773. X   write (2, &newline, 1) ;
  1774. X   }
  1775. X
  1776. X
  1777. X#ifdef TEST
  1778. X
  1779. Xint main (argc, argv)
  1780. X   int argc ;
  1781. X   char **argv ;
  1782. X{
  1783. X   extern int errno ;
  1784. X
  1785. X   errno = atoi (argv[1]) ;
  1786. X   perror2 (argv[2], argv[3]) ;
  1787. X   exit (1) ;
  1788. X   }
  1789. X
  1790. X#endif    /* TEST */
  1791. END_OF_FILE
  1792.   if test 1281 -ne `wc -c <'perror2.c'`; then
  1793.     echo shar: \"'perror2.c'\" unpacked with wrong size!
  1794.   fi
  1795.   # end of 'perror2.c'
  1796. fi
  1797. if test -f 'setdesc.c' -a "${1}" != "-c" ; then 
  1798.   echo shar: Will not clobber existing file \"'setdesc.c'\"
  1799. else
  1800.   echo shar: Extracting \"'setdesc.c'\" \(2540 characters\)
  1801.   sed "s/^X//" >'setdesc.c' <<'END_OF_FILE'
  1802. X/* setdesc.c -    Set a file description
  1803. X *
  1804. X * Copyright (c) 1991, 1992 Tim Cook.
  1805. X * Non-profit distribution allowed.  See README for details.
  1806. X */
  1807. X
  1808. Xstatic char rcsid[] = "$Id: setdesc.c,v 1.3 1992/12/02 03:51:00 tim Exp $";
  1809. X
  1810. X#include "config.h"
  1811. X#include <fcntl.h>
  1812. X#include <sys/stat.h>
  1813. X#include <sys/errno.h>
  1814. X
  1815. Xextern int errno ;
  1816. Xextern int _desc_parse_path () ;
  1817. Xextern char *_desc_pathname ;
  1818. Xextern char *_desc_directory ;
  1819. Xextern char *_desc_name ;
  1820. Xextern int _initdesc () ;
  1821. X#ifdef NDBM
  1822. Xextern DBM *_desc_database ;
  1823. X#endif
  1824. X
  1825. X
  1826. Xint setdesc (pathname, directory, name, inode, description)
  1827. X   char *pathname ;
  1828. X   char *directory ;
  1829. X   char *name ;
  1830. X   ino_t inode ;
  1831. X   char *description ;
  1832. X{
  1833. X   datum key, content ;
  1834. X
  1835. X   if (! _desc_parse_path (pathname, directory, name)) {
  1836. X      errno = EINVAL ;
  1837. X      return FALSE ; }
  1838. X
  1839. X   if (! inode) {
  1840. X      struct stat file_status ;
  1841. X
  1842. X      if (stat (_desc_pathname, &file_status) == 0)
  1843. X     inode = file_status.st_ino ; }
  1844. X
  1845. X   if (description == NULL_CP || *description == EOS) {
  1846. X      /* Set the description to null?  This means delete */
  1847. X
  1848. X      if (! _initdesc (_desc_directory, O_RDWR))
  1849. X         /* If there is no database, that's OK */
  1850. X         return (errno == ENOENT) ;
  1851. X
  1852. X      if (inode) {
  1853. X     key.dptr = (char *) &inode ;
  1854. X     key.dsize = sizeof (ino_t) ;
  1855. X     DBM_delete (_desc_database, key) ; }
  1856. X      key.dptr = _desc_name ;
  1857. X      key.dsize = strlen (_desc_name) ;
  1858. X      if (key.dsize == sizeof (ino_t))
  1859. X     key.dsize++ ;
  1860. X      DBM_delete (_desc_database, key) ;
  1861. X      return TRUE ; }
  1862. X
  1863. X   if (! _initdesc (_desc_directory, O_RDWR | O_CREAT))
  1864. X      return FALSE ;
  1865. X
  1866. X   /* Store the description, indexed by the file name */
  1867. X
  1868. X   key.dptr = _desc_name ;
  1869. X   key.dsize = strlen (_desc_name) ;
  1870. X
  1871. X   /*
  1872. X    * Name and inode keys are distinguished by the key length.  Inode
  1873. X    * keys are all "sizeof (ino_t)" long, while all other keys are
  1874. X    * name keys.
  1875. X    */
  1876. X
  1877. X   if (key.dsize == sizeof (ino_t))
  1878. X      /*
  1879. X       * To distinguish this from an inode key, we'll store the
  1880. X       * terminating null byte as well
  1881. X       */
  1882. X      key.dsize++ ;
  1883. X
  1884. X   content.dptr = description ;
  1885. X   content.dsize = strlen (description) + 1 ;
  1886. X   if (DBM_store (_desc_database, key, content) < 0)
  1887. X      return FALSE ;
  1888. X
  1889. X   if (inode) {
  1890. X
  1891. X      /* Store the file name, indexed by the inode number */
  1892. X
  1893. X      key.dptr = (char *) &inode ;
  1894. X      key.dsize = sizeof (ino_t) ;
  1895. X      content.dptr = _desc_name ;
  1896. X      content.dsize = strlen (_desc_name) ;
  1897. X      if (DBM_store (_desc_database, key, content) < 0)
  1898. X     return FALSE ;
  1899. X      }
  1900. X   return TRUE ;
  1901. X   }
  1902. END_OF_FILE
  1903.   if test 2540 -ne `wc -c <'setdesc.c'`; then
  1904.     echo shar: \"'setdesc.c'\" unpacked with wrong size!
  1905.   fi
  1906.   # end of 'setdesc.c'
  1907. fi
  1908. echo shar: End of archive 2 \(of 3\).
  1909. cp /dev/null ark2isdone
  1910. MISSING=""
  1911. for I in 1 2 3 ; do
  1912.     if test ! -f ark${I}isdone ; then
  1913.     MISSING="${MISSING} ${I}"
  1914.     fi
  1915. done
  1916. if test "${MISSING}" = "" ; then
  1917.     echo You have unpacked all 3 archives.
  1918.     rm -f ark[1-9]isdone
  1919. else
  1920.     echo You still must unpack the following archives:
  1921.     echo "        " ${MISSING}
  1922. fi
  1923. exit 0
  1924. exit 0 # Just in case...
  1925.