home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3931 < prev    next >
Encoding:
Text File  |  1991-08-29  |  23.9 KB  |  913 lines

  1. Path: wupost!uunet!munnari.oz.au!murtoa.cs.mu.oz.au!csv.viccol.edu.au!timcc
  2. From: timcc@csv.viccol.edu.au (Tim Cook)
  3. Newsgroups: alt.sources
  4. Subject: dl v1.6, part 2 of 3
  5. Message-ID: <1991Aug21.173913.6832@csv.viccol.edu.au>
  6. Date: 21 Aug 91 22:39:13 GMT
  7. Organization: Computer Services, Victoria College, Melbourne
  8. Lines: 903
  9.  
  10. #!/bin/sh
  11. # This is part 02 of a multipart archive
  12. # ============= dl.c ==============
  13. if test -f 'dl.c' -a X"$1" != X"-c"; then
  14.     echo 'x - skipping dl.c (File already exists)'
  15. else
  16. echo 'x - extracting dl.c (Text)'
  17. sed 's/^X//' << 'SHAR_EOF' > 'dl.c' &&
  18. /* dl.c -    Descriptive ls
  19. X *
  20. X * Copyright (c) 1991 Tim Cook.
  21. X * Non-profit distribution allowed.  See README for details.
  22. X */
  23. X
  24. static char rcsid[] = "$Header: dl.c 1.6 91/08/21 $" ;
  25. X
  26. #include "config.h"
  27. #include <stdio.h>
  28. #include <sys/param.h>
  29. #include <sys/stat.h>
  30. #include <sys/file.h>
  31. #include <list.h>
  32. X
  33. #ifdef SYSV
  34. #include <time.h>
  35. #else
  36. #include <sys/time.h>
  37. #endif
  38. X
  39. #ifndef MAXPATHLEN
  40. #define MAXPATHLEN    1024
  41. #endif
  42. X
  43. extern time_t time () ;
  44. extern UID_T getuid () ;
  45. extern int getgroups () ;
  46. X
  47. extern char *getdesc () ;
  48. extern VOID enddesc () ;
  49. extern char *pathname () ;
  50. X
  51. #define strgencpy(new, old) \
  52. X    (new = strcpy ((char *) allocate (strlen (old) + 1), old))
  53. X
  54. static struct file_info {
  55. X   ino_t inode ;
  56. X   u_short mode ;
  57. X   short nlink ;
  58. X   off_t size ;
  59. X   time_t mtime ;
  60. X   char name[4] ;    /* This can actually contain a string of any
  61. X               length, I'm just giving the compiler the
  62. X               opportunity to align. */
  63. X   } ;
  64. X
  65. /*
  66. X * How much space needed for a struct file_info that contains string "s"
  67. X */
  68. #define file_info_size(s) \
  69. X    (sizeof (struct file_info) - 3 + strlen (s))
  70. X
  71. /* options */
  72. static int show_date = FALSE ;
  73. static int sort_by_date = FALSE ;
  74. static int even_inaccessible = FALSE ;
  75. static int filename_columns = 14 ;
  76. static int recursive = FALSE ;
  77. X
  78. /* other globals */
  79. #define FROM_ARGV    0
  80. #define FROM_DIR    1
  81. X
  82. static time_t six_months_ago ;
  83. static struct file_info not_there ;    /* Symbolic value */
  84. static int name_and_size_columns ;
  85. static int space = FALSE ;        /* If TRUE, we need to print a blank
  86. X                       line before anything else */
  87. static int printed_anything = FALSE ;
  88. static UID_T uid ;
  89. static int no_groups ;
  90. static UID_T groups[NGROUPS] ;
  91. X
  92. static VOID_PTR get_element_from_argv () ;
  93. static VOID build_and_sort_list () ;
  94. static struct file_info *get_file_info () ;
  95. static VOID list_file () ;
  96. static VOID list_directory () ;
  97. X
  98. X
  99. int main (argc, argv)
  100. X   int argc ;
  101. X   char **argv ;
  102. {
  103. X   extern char *optarg ;
  104. X   extern int optind, opterr ;
  105. X
  106. X   int option ;
  107. X   struct list file_list, dir_list ;
  108. X   struct file_info *file_info ;
  109. X   char *dir_name ;
  110. X   int multiple_args ;
  111. X
  112. X   opterr = 0 ;
  113. X   while ((option = getopt (argc, argv, "deitf:R")) != EOF) {
  114. X      switch ((char) option) {
  115. X         case 'd' :
  116. X        show_date = TRUE ; break ;
  117. X         case 'e' :
  118. X     case 'i' :
  119. X        even_inaccessible = TRUE ; break ;
  120. X         case 't' :
  121. X        sort_by_date = TRUE ; break ;
  122. X         case 'f' :
  123. X        filename_columns = atoi (optarg) ; break ;
  124. X     case 'R' :
  125. X        recursive = TRUE ; break ;
  126. X     case '?' :
  127. X            break ; } }
  128. X
  129. X   multiple_args = (argc - optind) > 1 ;
  130. X
  131. X   name_and_size_columns = filename_columns + 8 ;
  132. X
  133. X   if (show_date)
  134. X      six_months_ago = time ((time_t *) 0) - (182 * 24 * 60 * 60) ;
  135. X
  136. X   if (! even_inaccessible) {
  137. X      uid = (UID_T) getuid () ;
  138. X      no_groups = getgroups (NGROUPS, groups) ; }
  139. X
  140. X   if (optind == argc) {
  141. X      list_directory ("", FALSE) ;
  142. X      enddesc () ;
  143. X      exit (0) ; }
  144. X
  145. X   list_init (&file_list) ;
  146. X   build_and_sort_list (&file_list, NULL_CP, FROM_ARGV, (char *) argv,
  147. X      (char *) &optind) ;
  148. X
  149. X   list_init (&dir_list) ;
  150. X   while ((file_info = get_file_info (&file_list, NULL_CP))
  151. X      != (struct file_info *) NULL) {
  152. X      if (file_info != ¬_there) {
  153. X     if (file_info->mode & S_IFDIR)
  154. X        /* Collect these for later */
  155. X            list_push (&dir_list, (VOID_PTR) file_info->name,
  156. X           strlen (file_info->name) + 1) ;
  157. X     else {
  158. X        list_file (file_info, NULL_CP) ; } } }
  159. X   list_free (&file_list) ;
  160. X
  161. X   /* Now, the directories we collected above */
  162. X   while ((dir_name = (char *) list_shift (&dir_list)))
  163. X      list_directory (dir_name, multiple_args) ;
  164. X   list_free (&dir_list) ;
  165. X
  166. X   enddesc () ;
  167. X   exit (0) ;
  168. X   }
  169. X
  170. X
  171. static
  172. VOID_PTR get_element_from_argv (param_1, param_2)
  173. X   char *param_1, *param_2 ;
  174. {
  175. X   int *argc ;
  176. X   char **argv ;
  177. X
  178. X   argv = (char **) param_1 ;
  179. X   argc = (int *) param_2 ;
  180. X   return (VOID_PTR) argv[(*argc)++] ;
  181. X   }
  182. X
  183. X
  184. static
  185. VOID_PTR get_element_from_dir (param_1, param_2)
  186. X   char *param_1 ;    /* directory pointer (DIR *) */
  187. X   char *param_2 ;    /* name of directory */
  188. {
  189. X   DIRENT *dir_entry ;
  190. X
  191. X   for (dir_entry = readdir ((DIR *) param_1) ;
  192. X        dir_entry != (DIRENT *) NULL && dir_entry->d_name[0] == '.' ;
  193. X    dir_entry = readdir ((DIR *) param_1)) ;
  194. X   if (dir_entry == (DIRENT *) NULL)
  195. X      return (VOID_PTR) NULL ;
  196. X   return (VOID_PTR) dir_entry->d_name ;
  197. X   }
  198. X
  199. X
  200. static
  201. int file_info_date_cmp (info_1, info_2)
  202. X   struct file_info **info_1, **info_2 ;
  203. {
  204. X   return (int) ((*info_2)->mtime - (*info_1)->mtime) ;
  205. X   }
  206. X
  207. X
  208. static
  209. int compare_str (str_1, str_2)
  210. X   char **str_1, **str_2 ;
  211. {
  212. X   return strcmp (*str_1, *str_2) ;
  213. X   }
  214. X
  215. X
  216. static
  217. VOID build_and_sort_list (file_list, directory, where_from, param_1, param_2)
  218. X   struct list *file_list ;
  219. X   char *directory ;
  220. X   int where_from ;
  221. X   char *param_1, *param_2 ;
  222. {
  223. X   VOID_PTR (*get_element) () ;
  224. X   struct stat file_status ;
  225. X   char *name ;
  226. X
  227. X   if (where_from == FROM_ARGV)
  228. X      get_element = get_element_from_argv ;
  229. X   else
  230. X      get_element = get_element_from_dir ;
  231. X
  232. X   if (sort_by_date) {
  233. X      struct file_info *file_info ;
  234. X
  235. X      file_info = (struct file_info *)
  236. X     allocate (sizeof (struct file_info) + MAXPATHLEN) ;
  237. X
  238. X      while ((name = (char *) get_element (param_1, param_2)) != NULL_CP) {
  239. X     if (stat (pathname (directory, name), &file_status) == -1)
  240. X        perror (name) ;
  241. X     else {
  242. X        file_info->inode = file_status.st_ino ;
  243. X        file_info->mode = file_status.st_mode ;
  244. X        file_info->nlink = file_status.st_nlink ;
  245. X        file_info->size = file_status.st_size ;
  246. X        file_info->mtime = file_status.st_mtime ;
  247. X        strcpy (file_info->name, name) ;
  248. X        list_push (file_list, (VOID_PTR) file_info,
  249. X           file_info_size (name)) ;
  250. X        } }
  251. X
  252. X      free ((VOID_PTR) file_info) ;
  253. X
  254. X      list_sort (file_list, file_info_date_cmp) ; }
  255. X
  256. X   else {    /* Sort by name */
  257. X      while ((name = (char *) get_element (param_1, param_2)) != NULL_CP) {
  258. X     list_push (file_list, (VOID_PTR) name,
  259. X        ((where_from == FROM_ARGV) ? 0 : (strlen (name) + 1))) ; }
  260. X      list_sort (file_list, compare_str) ; }
  261. X   }
  262. X
  263. X
  264. static
  265. struct file_info *get_file_info (file_list, directory)
  266. X   struct list *file_list ;
  267. X   char *directory ;
  268. {
  269. X   static struct stat status ;    /* Tongue twister */
  270. X   char *name ;
  271. X   int listable ;
  272. X   int n ;
  273. X
  274. X   if (sort_by_date)
  275. X      return (struct file_info *) list_shift (file_list) ;
  276. X   else {
  277. X      name = (char *) list_shift (file_list) ;
  278. X      if (name == (char *) NULL)
  279. X     return (struct file_info *) NULL ;
  280. X      else
  281. X     if (stat (pathname (directory, name), &status) == -1) {
  282. X        perror (name) ;
  283. X        return ¬_there ; }
  284. X     else {
  285. X        if (! even_inaccessible) {
  286. X           if (uid == (UID_T) status.st_uid)
  287. X          listable = status.st_mode & 0500 ;
  288. X           else {
  289. X          for (n = 0 ; n < no_groups ; n++) {
  290. X             if (groups[n] == (GID_T) status.st_gid) {
  291. X            listable = status.st_mode & 050 ;
  292. X            n = no_groups + 1 ; } }
  293. X          if (n == no_groups)
  294. X             listable = status.st_mode & 05 ; } }
  295. X        else
  296. X           listable = TRUE ;
  297. X        if (! listable)
  298. X           return ¬_there ;
  299. X        else {
  300. X           static struct file_info *file_info ;
  301. X
  302. X           if (! file_info)
  303. X          file_info = (struct file_info *)
  304. X             allocate (sizeof (struct file_info) + MAXPATHLEN) ;
  305. X           file_info->inode = status.st_ino ;
  306. X           file_info->mode = status.st_mode ;
  307. X           file_info->nlink = status.st_nlink ;
  308. X           file_info->size = status.st_size ;
  309. X           file_info->mtime = status.st_mtime ;
  310. X           strcpy (file_info->name, name) ;
  311. X           return file_info ; } } }
  312. X   }
  313. X
  314. X
  315. static
  316. VOID list_directory (directory_name, show_directory)
  317. X   char *directory_name ;
  318. X   int show_directory ;
  319. {
  320. X   DIR *dirp ;
  321. X   struct list file_list, dir_list ;
  322. X   struct file_info *file_info ;
  323. X
  324. X   space = FALSE ;
  325. X   if (show_directory) {
  326. X      if (printed_anything) {
  327. X     printc ('\n') ; }
  328. X      printf ("%s:\n", directory_name) ;
  329. X      printed_anything = TRUE ; }
  330. X
  331. X   if ((dirp = opendir (*directory_name == EOS ? "." : directory_name))
  332. X         == (DIR *) NULL) {
  333. X      perror (directory_name) ; }
  334. X   else {
  335. X      list_init (&file_list) ;
  336. X      build_and_sort_list (&file_list, directory_name, FROM_DIR,
  337. X         (char *) dirp, directory_name) ;
  338. X      list_init (&dir_list) ;
  339. X      while ((file_info = get_file_info (&file_list, directory_name))
  340. X         != (struct file_info *) NULL) {
  341. X     if (file_info != ¬_there) {
  342. X        if (recursive && file_info->mode & S_IFDIR)
  343. X           /* Save this for later */
  344. X           list_push (&dir_list, (VOID_PTR) file_info->name,
  345. X          strlen (file_info->name) + 1) ;
  346. X        list_file (file_info, directory_name) ; } }
  347. X      list_free (&file_list) ;
  348. X      closedir (dirp) ;
  349. X
  350. X      if (recursive) {
  351. X     char *saved_dir ;
  352. X     char *path, *sub_dir ;
  353. X
  354. X         /* Now, the directories we saved earlier */
  355. X     while ((saved_dir = (char *) list_shift (&dir_list))) {
  356. X        path = pathname (directory_name, saved_dir) ;
  357. X        list_directory (strgencpy (sub_dir, path), TRUE) ;
  358. X        free ((VOID_PTR) sub_dir) ; }
  359. X     list_free (&dir_list) ; } }
  360. X
  361. X   space = TRUE ;
  362. X   }
  363. X
  364. X
  365. X      
  366. X
  367. static
  368. VOID list_file (file_info, directory)
  369. X   struct file_info *file_info ;
  370. X   char *directory ;
  371. {
  372. X   static char month[][12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  373. X      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"} ;
  374. X   char out_name[MAXPATHLEN+2] ;    /* What to print */
  375. X   char *desc ;
  376. X   static char size[12] ;
  377. X   static char date[16] ;
  378. X   int name_len, size_len, gap ;
  379. X   struct tm *tm_time ;
  380. X
  381. X   desc = getdesc (directory, file_info->name, file_info->inode) ;
  382. X
  383. X   /* Now we only need what we will show */
  384. X   strcpy (out_name, file_info->name) ;
  385. X
  386. X   name_len = strlen (out_name) ;
  387. X   /* If it is a directory, make it obvious */
  388. X   if (file_info->mode & S_IFDIR) {
  389. X      strcat (out_name, "/") ;
  390. X      name_len++ ;
  391. X      size[1] = EOS ;
  392. X      size_len = 1 ;
  393. X      if (file_info->nlink > 2) {    /* Denotes a directory that contains */
  394. X     size[0] = '=' ; }        /* one or more sub-directories */
  395. X      else {
  396. X     size[0] = '-' ; } }
  397. X   else {
  398. X      sprintf (size, "%d", file_info->size) ;
  399. X      size_len = strlen (size) ; }
  400. X   if (name_len + size_len < name_and_size_columns)
  401. X      gap = name_and_size_columns - name_len ;
  402. X   else {
  403. X      print (out_name) ;
  404. X      out_name[0] = '\n' ; out_name[1] = EOS ;
  405. X      gap = name_and_size_columns ; }
  406. X   if (show_date) {
  407. X      tm_time = localtime (&file_info->mtime) ;
  408. X      if (six_months_ago > file_info->mtime) {
  409. X     /* The bloody thing is more than 6 months old! */
  410. #ifdef US_DATE_FORMAT
  411. X     sprintf (date, " %s %2d  %d ", month[tm_time->tm_mon],
  412. X        tm_time->tm_mday, tm_time->tm_year + 1900) ;
  413. #else
  414. X     sprintf (date, " %2d %s  %d ", tm_time->tm_mday,
  415. X        month[tm_time->tm_mon], tm_time->tm_year + 1900) ;
  416. #endif
  417. X         }
  418. X      else {
  419. #ifdef US_DATE_FORMAT
  420. X     sprintf (date, " %s %2d %02d:%02d ", month[tm_time->tm_mon],
  421. X        tm_time->tm_mday, tm_time->tm_hour, tm_time->tm_min) ;
  422. #else
  423. X     sprintf (date, " %2d %s %02d:%02d ", tm_time->tm_mday,
  424. X         month[tm_time->tm_mon], tm_time->tm_hour, tm_time->tm_min) ;
  425. #endif
  426. X      } }
  427. X   else {
  428. X      date[0] = ' ' ;
  429. X      date[1] = EOS ; }
  430. X
  431. X   if (space) {
  432. X      printc ('\n') ;
  433. X      space = FALSE ; }
  434. X   printf ("%s %*s%s %s\n", out_name, gap, size, date,
  435. #ifdef PASS_NULL_TO_PRINTF
  436. X      desc
  437. #else
  438. X      (desc == NULL_CP) ? "" : desc
  439. #endif
  440. X      ) ;
  441. X   printed_anything = TRUE ;
  442. X   }
  443. SHAR_EOF
  444. chmod 0640 dl.c ||
  445. echo 'restore of dl.c failed'
  446. fi
  447. # ============= describe.c ==============
  448. if test -f 'describe.c' -a X"$1" != X"-c"; then
  449.     echo 'x - skipping describe.c (File already exists)'
  450. else
  451. echo 'x - extracting describe.c (Text)'
  452. sed 's/^X//' << 'SHAR_EOF' > 'describe.c' &&
  453. /* describe.c -    Set or list a descriptive comment for a file
  454. X *
  455. X * Copyright (c) 1991 Tim Cook.
  456. X * Non-profit distribution allowed.  See README for details.
  457. X */
  458. X
  459. static char rcsid[] = "$Header: describe.c 1.6 91/08/21 $" ;
  460. X
  461. #include "config.h"
  462. #include <stdio.h>
  463. #include <sys/param.h>
  464. #include <sys/file.h>
  465. #include <sys/stat.h>
  466. X
  467. #ifdef SYSV
  468. #include <fcntl.h>        /* for O_CREAT, etc. */
  469. #endif
  470. X
  471. #ifndef MAXPATHLEN
  472. #define MAXPATHLEN    1024
  473. #endif
  474. X
  475. extern char *getdesc () ;
  476. extern int setdesc () ;
  477. extern VOID enddesc () ;
  478. X
  479. static char *program_name ;
  480. X
  481. static VOID usage () ;
  482. static VOID set_from_file () ;
  483. static VOID list_descriptions () ;
  484. X
  485. X
  486. int main (argc, argv)
  487. X   int argc ;
  488. X   char **argv ;
  489. {
  490. X   extern char *optarg ;
  491. X   extern int optind, opterr ;
  492. X   int delete_desc = FALSE ;
  493. X   struct stat status ;
  494. X   int option ;
  495. X   char *directory ;
  496. X
  497. X   program_name = argv[0] ;
  498. X   while ((option = getopt (argc, argv, "dlsf:")) != EOF) {
  499. X      switch (option) {
  500. X     case 's':
  501. X     case 'f':    /* Set descriptions from file */
  502. X        if (delete_desc)
  503. X           usage () ;
  504. X        if (optind >= argc)
  505. X           directory = "." ;
  506. X        else
  507. X           directory = argv[optind] ;
  508. X        set_from_file (optarg, directory) ;
  509. X        enddesc () ;
  510. X        exit (0) ;
  511. X        break ;
  512. X         case 'l':    /* List directory */
  513. X        if (delete_desc)
  514. X           usage () ;
  515. X        if (optind >= argc)
  516. X           directory = "." ;
  517. X        else
  518. X           directory = argv[optind] ;
  519. X        list_descriptions (directory) ;
  520. X        enddesc () ;
  521. X        exit (0) ;
  522. X        break ;
  523. X         case 'd':    /* Delete description(s) */
  524. X        delete_desc = TRUE ;
  525. X        break ;
  526. X         default:
  527. X        usage () ; } }
  528. X
  529. X   if (delete_desc) {
  530. X      char directory[MAXPATHLEN+1] ;
  531. X      char file_name[MAXPATHLEN+1] ;
  532. X
  533. X      if (optind >= argc)
  534. X     usage () ;
  535. X      for ( ; optind < argc ; optind++) {
  536. X     split_pathname (argv[optind], directory, file_name) ;
  537. X     if (stat (argv[optind], &status) == -1) {
  538. X        perror2 (program_name, argv[optind]) ; }
  539. X     if (! setdesc (directory, file_name, status.st_ino, NULL_CP))
  540. X        perror2 (program_name, argv[optind]) ; } }
  541. X
  542. X   else {
  543. X
  544. X      /* Set description of specified file */
  545. X
  546. X      char directory[MAXPATHLEN+1] ;
  547. X      char file_name[MAXPATHLEN+1] ;
  548. X
  549. X      if (argc != 3)
  550. X     usage () ;
  551. X
  552. X      split_pathname (argv[1], directory, file_name) ;
  553. X      if (stat (argv[1], &status) == -1) {
  554. X     perror2 (program_name, argv[1]) ;
  555. X     exit (1) ; }
  556. X      if (! setdesc (directory, file_name, status.st_ino, argv[2]))
  557. X     perror2 (program_name, argv[1]) ;
  558. X      }
  559. X
  560. X   enddesc () ;
  561. X   }
  562. X
  563. X
  564. static
  565. VOID usage ()
  566. {
  567. X   fprintf (stderr, "\
  568. usage: %s <file> <description>\n\
  569. X   or: %s -s <descriptions-file> [<directory>]\n\
  570. X   or: %s -d <file> ...\n\
  571. X   or: %s -l [<directory>]\n",
  572. X      program_name, program_name, program_name, program_name) ;
  573. X   exit (2) ;
  574. X   }
  575. X
  576. X
  577. static
  578. VOID set_from_file (file, directory)
  579. X   char *file ;
  580. X   char *directory ;
  581. {
  582. X   FILE *descriptions ;
  583. X   char file_name[MAXPATHLEN+1] ;
  584. X   char buffer[1024] ;
  585. X   char description[256] ;
  586. X   struct stat status ;
  587. X   int n ;
  588. X
  589. X   if (strcmp (file, "-") == 0)
  590. X      descriptions = stdin ;
  591. X   else {
  592. X      if ((descriptions = fopen (file, "r")) == (FILE *) NULL) {
  593. X     perror2 (program_name, file) ;
  594. X     exit (1) ; } }
  595. X   if (chdir (directory) == -1) {
  596. X      perror2 (program_name, directory) ;
  597. X      exit (1) ; }
  598. X   while (! feof (descriptions)) {
  599. X      if (fgets (buffer, sizeof (buffer), descriptions) != NULL_CP) {
  600. X     n = sscanf (buffer, "\"%[^\"]\" %[^\n]\n", file_name, description) ;
  601. X     if (n < 2)
  602. X        n = sscanf (buffer, "%s %[^\n]\n", file_name, description) ;
  603. X     if (n == 2 && file_name[0] != '#') {
  604. X        if (stat (file_name, &status) == -1) {
  605. X           perror2 (program_name, file_name) ; }
  606. X        else {
  607. X           if (! setdesc (directory, file_name, status.st_ino,
  608. X             description))
  609. X          perror2 (program_name, file_name) ; } } }
  610. X      }
  611. X   fclose (descriptions) ;
  612. X   }
  613. X
  614. X
  615. static
  616. VOID list_descriptions (directory)
  617. X   char *directory ;
  618. {
  619. X   char file_name[MAXPATHLEN+1] ;
  620. X   int file_name_length ;
  621. X   int gap ;
  622. X   DIR *dir ;
  623. X   DIRENT *dir_entry ;
  624. X   char *desc ;
  625. #ifdef SYSV
  626. X   int namlen ;
  627. #endif
  628. X
  629. X   /*
  630. X    * Loop through all the files in this directory, seeing if we can
  631. X    * find a description for each one.
  632. X    */
  633. X
  634. X   if ((dir = opendir (*directory == EOS ? "." : directory)) == (DIR *) NULL) {
  635. X      perror ("opendir") ;
  636. X      exit (1) ; }
  637. X   while ((dir_entry = readdir (dir)) != (DIRENT *) NULL) {
  638. X
  639. X      if ((desc = getdesc (directory, dir_entry->d_name, dir_entry->d_ino))
  640. X        != NULL_CP) {
  641. X
  642. X     /* Print it out! */
  643. #ifdef SYSV
  644. X     file_name_length = strlen (dir_entry->d_name) ;
  645. #else
  646. X     file_name_length = dir_entry->d_namlen ;
  647. #endif
  648. X     strncpy (file_name, dir_entry->d_name, file_name_length) ;
  649. X     file_name[file_name_length] = EOS ;
  650. X
  651. X     if (strpbrk (file_name, " \t") != NULL_CP) {
  652. X        printc ('"') ;
  653. X        print (file_name) ;
  654. X        printc ('"') ;
  655. X        gap = 18 - file_name_length ; }
  656. X     else {
  657. X        print (file_name) ;
  658. X        gap = 20 - file_name_length ; }
  659. X     printc (' ') ;        /* We need at least one space */
  660. X     while (gap-- > 0)
  661. X        printc (' ') ;
  662. X     print (desc) ;
  663. X     printc ('\n') ; } }
  664. X
  665. X   }
  666. SHAR_EOF
  667. chmod 0640 describe.c ||
  668. echo 'restore of describe.c failed'
  669. fi
  670. # ============= list.c ==============
  671. if test -f 'list.c' -a X"$1" != X"-c"; then
  672.     echo 'x - skipping list.c (File already exists)'
  673. else
  674. echo 'x - extracting list.c (Text)'
  675. sed 's/^X//' << 'SHAR_EOF' > 'list.c' &&
  676. /* list.c -    List manipulation routines
  677. X *
  678. X * SYNOPSIS
  679. X *    #include <list.h>
  680. X *
  681. X *    void list_init (struct list *list) ;
  682. X *
  683. X *        Initializes the list.  Does not free any storage that
  684. X *        may have been allocated to the list.
  685. X *
  686. X *    void list_free (struct list *list) ;
  687. X *
  688. X *        Deallocates and initializes the list.
  689. X *
  690. X *    void list_push (struct list *list, void *element, size_t length) ;
  691. X *
  692. X *        Adds the element to the end of the list.  If length is
  693. X *        non-zero, a copy is made of the data pointed to by element,
  694. X *        and the address of the copy is added to the list instead.
  695. X *
  696. X *    void *list_pop (struct list *list) ;
  697. X *
  698. X *        Returns the last element in the list and removes it.
  699. X *
  700. X *    void *list_shift (struct list *list) ;
  701. X *
  702. X *        Returns the first element in the list and removes it
  703. X *
  704. X *    void *list_element (struct list *list, int element_no) ;
  705. X *
  706. X *        Returns the specified element (elements are numbered
  707. X *        starting from 0), or NULL if the list does not contain
  708. X *        any elements.  Has no effect on the contents of the
  709. X *        list.
  710. X *
  711. X *    int list_elements (struct list *list) ;
  712. X *
  713. X *        Returns the number of elements in the list.
  714. X *
  715. X *    int list_empty (struct list *list) ;
  716. X *
  717. X *        Returns non-zero if the list contains any elements,
  718. X *        zero otherwise.
  719. X *
  720. X *    void list_sort (struct list *list, int (*compare) ()) ;
  721. X *
  722. X *        Sorts the list using compare() (like qsort(3))
  723. X *
  724. X * NOTE: list_init(), list_element(), list_elements() and list_empty()
  725. X *     are implemented as macros.
  726. X *
  727. X * Copyright (c) 1991 Tim Cook.
  728. X * Non-profit distribution allowed.  See README for details.
  729. X */
  730. X
  731. static char rcsid[] = "$Header: list.c 1.5 91/08/21 $" ;
  732. X
  733. #define _LIST_C_
  734. X
  735. #define VOID_PTR    char *
  736. #define VOID_PTR_PTR    char **
  737. X
  738. #include "config.h"
  739. #include <list.h>
  740. X
  741. #ifndef NULL
  742. #define NULL    0
  743. #endif
  744. X
  745. extern VOID_PTR allocate () ;
  746. extern VOID_PTR re_allocate () ;
  747. X
  748. #ifndef INITIAL_LIST_ENTRIES
  749. #define INITIAL_LIST_ENTRIES    512
  750. #endif
  751. #ifndef DATA_BLOCK_SIZE
  752. #define DATA_BLOCK_SIZE        16384
  753. #endif
  754. X
  755. /*
  756. X * This must be defined to an unsigned integer data type to which
  757. X * pointer types can be freely cast.
  758. X */
  759. X
  760. #define PTR_CARD    unsigned long
  761. X
  762. X
  763. VOID list_free (list)
  764. X   struct list *list ;
  765. {
  766. X   if (! list_empty (list) && list->s_start != (VOID_PTR_PTR) NULL) {
  767. X      free ((VOID_PTR) list->s_start) ;
  768. X      if (list->data) {
  769. X     int i ;
  770. X
  771. X     for (i = 2 ; list->data[i] ; i++)
  772. X        free (list->data[i]) ;
  773. X     free ((VOID_PTR) list->data) ; }
  774. X      list_init (list) ; }        /* May as well */
  775. X   }
  776. X
  777. X
  778. VOID list_push (list, element, length)
  779. X   struct list *list ;
  780. X   VOID_PTR element ;
  781. X   size_t length ;
  782. {
  783. X   if (length) {
  784. X      size_t data_block_size ;
  785. X      int new_block = 0 ;
  786. X
  787. #ifdef ALIGN
  788. X      /* Make sure subsequent data is stored aligned */
  789. #if ALIGN == 2
  790. X      if (length & 1)
  791. X     length++ ;
  792. #else
  793. X      /*
  794. X       * ALIGN must be a power of 2 (reasonable to expect), but at
  795. X       * least we don't need to do a divide.
  796. X       */
  797. X      if (length & (ALIGN - 1))
  798. X     length += ALIGN - (length & (ALIGN - 1)) ;
  799. #endif
  800. #endif
  801. X
  802. X      if (length > DATA_BLOCK_SIZE)
  803. X     data_block_size = length ;
  804. X      else
  805. X     data_block_size = DATA_BLOCK_SIZE ;
  806. X
  807. X      /*
  808. X       * Allocate storage for data pointed to by list element
  809. X       */
  810. X      if (! list->data) {
  811. X     /* No blocks allocated at all, set it up */
  812. X     list->data = (VOID_PTR_PTR) allocate (sizeof (VOID_PTR_PTR) * 4) ;
  813. X     new_block = 2 ; }
  814. X      else {
  815. X     /* We have some storage, but do we have enough? */
  816. X     if ((PTR_CARD) list->data[0] + length > (PTR_CARD) list->data[1]) {
  817. X        /* Nope, allocate new block */
  818. X
  819. X        for (new_block = 2 ; list->data[new_block] ; new_block++) ;
  820. X        list->data = (VOID_PTR_PTR) re_allocate (list->data,
  821. X           sizeof (VOID_PTR_PTR) * new_block + 2) ; } }
  822. X
  823. X      if (new_block) {
  824. X     /*
  825. X      * The contents of the array pointed to by list->data is as
  826. X      * follows:
  827. X      *
  828. X      *    The first element points to the first free byte of storage.
  829. X      *    The second to the first inaccessible byte.
  830. X      *    Subsequent elements contain a NULL-terminated list of all
  831. X      *    blocks.
  832. X      */
  833. X     list->data[new_block] = allocate (data_block_size) ;
  834. X     list->data[new_block+1] = (VOID_PTR) NULL ;
  835. X     list->data[0] = list->data[new_block] ;
  836. X     list->data[1] = (VOID_PTR)
  837. X           ((PTR_CARD) list->data[new_block] + data_block_size) ; }
  838. X
  839. X      /* Copy data pointed to by list element */
  840. X      memcpy (list->data[0], element, length) ;
  841. X      /* Now, make sure we add the right pointer to the list */
  842. X      element = list->data[0] ;
  843. X      /* Adjust free pointer */
  844. X      list->data[0] = (VOID_PTR) ((PTR_CARD) list->data[0] + length) ;
  845. X      }
  846. X
  847. X   /* Now, add the "pointer" itself */
  848. X   if (list_empty (list)) {
  849. X      list->s_start = (VOID_PTR_PTR) allocate (
  850. X         sizeof (VOID_PTR) * INITIAL_LIST_ENTRIES) ;
  851. X      list->s_end = list->s_start + INITIAL_LIST_ENTRIES ;
  852. X      list->start = list->s_start ;
  853. X      list->end = list->start ; }
  854. X   else {
  855. X      if (list->end >= list->s_end) {
  856. X     /* We need to re-allocate */
  857. X     register PTR_CARD x, y, z ;
  858. X
  859. X     x = (PTR_CARD) list->s_end - (PTR_CARD) list->s_start ;
  860. X     y = (PTR_CARD) list->start - (PTR_CARD) list->s_start ;
  861. X     z = (PTR_CARD) list->end - (PTR_CARD) list->s_start ;
  862. X     x = x << 1 ;    /* Double allocation size */
  863. X     list->s_start = (VOID_PTR_PTR) re_allocate (list->s_start, x) ;
  864. X     list->s_end = (VOID_PTR_PTR) ((PTR_CARD) list->s_start + x) ;
  865. X     list->start = (VOID_PTR_PTR) ((PTR_CARD) list->s_start + y) ;
  866. X     list->end = (VOID_PTR_PTR) ((PTR_CARD) list->s_start + z) ; } }
  867. X
  868. X   *list->end = element ;
  869. X   list->end++ ;
  870. X   }
  871. X
  872. X
  873. VOID_PTR list_shift (list)
  874. X   struct list *list ;
  875. {
  876. X   if (list_empty (list))
  877. X      return (VOID_PTR) NULL ;
  878. X   else
  879. X      if (list->start >= list->end)
  880. X     return (VOID_PTR) NULL ;
  881. X      else
  882. X     return *list->start++ ;
  883. X   }
  884. X
  885. X
  886. VOID_PTR list_pop (list)            /* WORK */
  887. X   struct list *list ;
  888. {
  889. X   if (list_empty (list))
  890. X      return (VOID_PTR) NULL ;
  891. X   else
  892. X      if (list->end < list->start)             /* WORK */
  893. X     return (VOID_PTR) NULL ;
  894. X      else
  895. X     return *list->end-- ;
  896. X   }
  897. X
  898. X
  899. VOID list_sort (list, compare)
  900. X   struct list *list ;
  901. X   int (*compare) () ;
  902. {
  903. X   if (! list_empty (list))
  904. X      qsort (list->start, (int) list_elements (list),
  905. X     sizeof (VOID_PTR), compare) ;
  906. X   }
  907. SHAR_EOF
  908. chmod 0640 list.c ||
  909. echo 'restore of list.c failed'
  910. fi
  911. echo End of part 2, continue with part 3
  912. exit 0
  913.