home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / CMDS / tar.shar / tar.c < prev   
C/C++ Source or Header  |  2009-11-06  |  20KB  |  928 lines

  1. char scid[]="$Header: tar.c,v 1.5  08/06/89 SrT/stp $";
  2.  
  3. /*
  4.  * Modified for use under OS-9/68k  (08/03/89)
  5.  * Stephan Paschedag  stp@ethz.uucp   ..cernvax!ethz!stp
  6.  *
  7.  * 12/15/90 blars  Add z option for file list from stdin.
  8.  *
  9.  * 11/08/90 blars  Make sure created directories are writable.
  10.  *           Clean up some creation mode stuff.
  11.  *           Convert - to _ in file names.
  12.  *
  13.  * 08/06/89  V1.5  Allow extraction of entire directories,
  14.  *                 allow extraction of single files in subdirectories,
  15.  *                 creates automatically missing directories.
  16.  *                 continues now correctly after some errors
  17.  *                 handles directories from unix archives correctly (stp)
  18.  *
  19.  * Modified for use under OS-9/6809
  20.  * Simmule Turner   simmy@nu.cs.fsu.edu   70651,67
  21.  *
  22.  * Compilation for OS-9/6809:  cc -m=3k tar.c
  23.  *     Use extra memory for recursive directory descents.
  24.  *
  25.  * 07/17/88  V1.4  Allow extraction of specified file(s)....
  26.  *                 from archive named on the command line
  27.  *                 with wildcard matching *,?. (SrT)
  28.  *
  29.  * 07/14/88  V1.3  Added verbose TOC ala unix.  Cleaned up
  30.  *                 printing routines, use decimal instead of
  31.  *                 octal. Removed conditional compilation. (SrT)
  32.  *
  33.  * 07/13/88  V1.2  Tries to set the correct file permissions.
  34.  *                 Send diagnostics to stderr.  Use lseek's
  35.  *                 for TOC generation when a rbf device. (SrT)
  36.  *
  37.  * 07/12/88  V1.1  Added option of reading/writing
  38.  *                 archive to stdin/stdout (SrT)
  39.  *
  40.  * 07/12/88  V1.0  Initial port (SrT)
  41.  *                 added dummy fv options
  42.  * SrT */
  43.  
  44. /* tar - tape archiver          Author: Michiel Huisjes */
  45.  
  46. /* Usage: tar [cxt][mfvz] tapefile [files]
  47.  *
  48.  * Bugs:
  49.  *  This tape archiver should only be used as a program to read or make
  50.  *  simple tape archives. Its basic goal is to read (or build) UNIX V7 tape
  51.  *  archives and extract the named files. It is not wise to use it on
  52.  *  raw magnetic tapes. It doesn't know anything about linked files,
  53.  *  except when the involved fields are filled in.
  54.  */
  55.  
  56. #include <stdio.h>
  57. #include <direct.h>
  58. #include <modes.h>
  59. #include <sgstat.h>
  60. #include <time.h>
  61. #ifndef OSK
  62. #  include <utime.h>
  63. #else
  64. #  include <types.h>
  65. #  include <errno.h>
  66. #  include <strings.h>
  67. #endif
  68.  
  69. #define STDIN   0
  70. #define STDOUT  1
  71.  
  72. typedef char BOOL;
  73. #define TRUE    1
  74. #define FALSE   0
  75.  
  76. #define HEADER_SIZE     512
  77. #define NAME_SIZE       100
  78. #define BLOCK_BOUNDARY   20
  79.  
  80. typedef union {
  81.   char hdr_block[HEADER_SIZE];
  82.   struct m {
  83.     char m_name[NAME_SIZE];
  84.     char m_mode[8];
  85.     char m_uid[8];
  86.     char m_gid[8];
  87.     char m_size[12];
  88.     char m_time[12];
  89.     char m_checksum[8];
  90.     char m_linked;
  91.     char m_link[NAME_SIZE];
  92.   } member;
  93. } HEADER;
  94.  
  95. HEADER header;
  96.  
  97. #define INT_TYPE    (sizeof(header.member.m_uid))
  98. #define LONG_TYPE   (sizeof(header.member.m_size))
  99.  
  100. #define NIL_HEADER  ((HEADER *) 0)
  101. #define NIL_PTR     ((char *) 0)
  102. #define BLOCK_SIZE  512
  103.  
  104. #define flush()     print(NIL_PTR)
  105.  
  106. BOOL show_fl, creat_fl, ext_fl, verbose_fl, modtime_fl, stdinfiles_fl;
  107.  
  108. char modestr[11], stbuf[132];
  109. struct sgbuf opts;
  110. struct fildes ofdbuf;
  111. #ifdef OSK
  112. char *dummy = NULL;
  113. #endif
  114.  
  115. int tar_fd;
  116. #ifdef OSK
  117. char usage[] = "Syntax : tar [ctx][mfvz] tarfile [file(s)...]\nFunction: Builds and extracts from Unix tape archive files\nOptions:\n   c : create archive\n   t : list contents\n   x : extract from archive";
  118. #else
  119. char usage[] = "Usage: tar [ctx][mfvz] tarfile [file(s)...]";
  120. #endif
  121. char io_buffer[BLOCK_SIZE];
  122.  
  123. int total_blocks;
  124. long convert();
  125. char **match();
  126.  
  127. block_size() {
  128.     return ((int) ((convert(header.member.m_size, LONG_TYPE)
  129.             + (long) BLOCK_SIZE - 1) / (long) BLOCK_SIZE));
  130. }
  131.  
  132. error(s1, s2)
  133. char *s1, *s2;
  134. {
  135. #ifdef OSK
  136.   fprintf(stderr,"%s %s\n", s1, s2 ? s2 : "");
  137.   exit(1);
  138. #else
  139.   string_print(NIL_PTR, "%s %s\r\l", s1, s2 ? s2 : "");
  140.   flush();
  141.   exit(1);
  142. #endif
  143. }
  144.  
  145. main(argc, argv)
  146. int argc;
  147. register char *argv[];
  148. {
  149.     register char *ptr;
  150. #ifdef OSK
  151.     char **p = &dummy;
  152. #else
  153.     char **p = "\0";
  154. #endif
  155.     int i;
  156.  
  157.   pflinit();
  158.  
  159.   if (argc < 3)
  160.     error(usage, NIL_PTR);
  161.  
  162.   for (ptr = argv[1]; *ptr; ptr++) {
  163.     switch (*ptr) {
  164.         case 'c' :
  165.             creat_fl = TRUE;
  166.             break;
  167.         case 't' :
  168.             show_fl = TRUE;
  169.             break;
  170.         case 'x' :
  171.             ext_fl  = TRUE;
  172.             if (argc > 3)
  173.                 p = &argv[3];
  174.             break;
  175. /*
  176.  * Modifiers
  177.  * SrT */
  178.         case 'f':
  179.             break;
  180.         case 'm':
  181.             modtime_fl = TRUE;
  182.             break;
  183.         case 'v':
  184.             verbose_fl = TRUE;
  185.             break;
  186.     case 'z':
  187.         stdinfiles_fl = TRUE;
  188.         break;
  189.         default :
  190.             error(usage, NIL_PTR);
  191.     }
  192.   }
  193.  
  194.   if (creat_fl + ext_fl + show_fl != 1)
  195.     error(usage, NIL_PTR);
  196.  
  197.   if (argv[2][0] == '-')
  198.      tar_fd = creat_fl ? STDOUT : STDIN;
  199.   else
  200.      tar_fd = creat_fl ? creat(argv[2],3) : open(argv[2],1);
  201.  
  202.   if (tar_fd < 0) {
  203. #ifdef OSK
  204.     exit(_errmsg(errno,"cannot open archive. "));
  205. #else
  206.     error("Cannot open ", argv[2]);
  207. #endif
  208.   }
  209.  
  210.   if (creat_fl) {
  211.     for (i = 3; i < argc; i++)
  212.       add_file(argv[i]);
  213.     if(stdinfiles_fl) {
  214.         char line[256];
  215.  
  216.     while(fgets(line, 256, stdin) != NULL) {
  217.         ptr = index(line, '\n');
  218.         if(ptr) *ptr = '\0';
  219.         add_file(line);
  220.     }
  221.     }
  222.     adjust_boundary();
  223.   }
  224.   else
  225.     tarfile (p);
  226.  
  227.   flush();
  228.   exit(0);
  229. }
  230.  
  231. BOOL get_header()
  232. {
  233.   register int check,c;
  234.  
  235.   mread(tar_fd, &header, sizeof(header));
  236.   if (header.member.m_name[0] == '\0')
  237.     return FALSE;
  238.  
  239.   check = (int) convert(header.member.m_checksum, INT_TYPE);
  240.  
  241.   if (check != (c = checksum()))
  242.     error("tar: header checksum error.", NIL_PTR);
  243.  
  244.   return TRUE;
  245. }
  246.  
  247. tarfile(p)
  248.     char **p;
  249. {
  250.   register char *ptr;
  251.   register char *mem_name;
  252.   char *atime();
  253.   int i;
  254.   register char **q;
  255.   register char *pp;
  256.  
  257.   _gs_opt(tar_fd,&opts);
  258.  
  259.   while (get_header()) {
  260.     mem_name = header.member.m_name;
  261.     if (ext_fl) {
  262.         if (*p) {
  263. /* extract entire directories (08/05/89 stp) */
  264.             if (mem_name[strlen(mem_name)-1] == '/') {
  265.               mem_name[strlen(mem_name)-1] = '\0';
  266.               if (q=match(p,mem_name)) {
  267.                 pp = (char *) malloc(strlen(mem_name)+3);
  268.                 strcpy(pp,mem_name);
  269.                 strncat(pp,"/*",3);
  270.                 *q = pp;
  271.                 mkdir(mem_name);
  272.               }
  273.             }
  274.             else {
  275.               if (match(p,mem_name)) {
  276.                 extract(mem_name);
  277.               }
  278.               else
  279.                 skip_entry();
  280.             }
  281.         }
  282.         else {
  283.             if (is_dir(mem_name)) {
  284.                 for (ptr = mem_name; *ptr != '/'; ptr++);
  285.                 *ptr = '\0';
  286.                 mkdir(mem_name);
  287.             }
  288.             else {
  289.               extract(mem_name);
  290.             }
  291.         }
  292.     }
  293.     else  {
  294.         if (!verbose_fl)
  295. #ifdef OSK
  296.             printf("%s",mem_name);
  297. #else
  298.             string_print(NIL_PTR, "%s", mem_name);
  299. #endif
  300.         else {
  301.             u29mode((int) convert(header.member.m_mode,INT_TYPE));
  302. #ifdef OSK
  303.             printf("%s ",modestr);
  304. #else
  305.             string_print(NIL_PTR, "%s ",modestr);
  306. #endif
  307.             sprintf(stbuf,"%3d/%3d %8ld %s %s",
  308.                 (int) convert(header.member.m_uid, INT_TYPE),
  309.                 (int) convert(header.member.m_gid, INT_TYPE),
  310.                       convert(header.member.m_size,LONG_TYPE),
  311.                       atime(convert(header.member.m_time,LONG_TYPE)),
  312.                       header.member.m_name);
  313. #ifdef OSK
  314.             printf("%s",stbuf);
  315.         }
  316.         printf("\n");
  317. #else
  318.             print(stbuf);
  319.         }
  320.         print("\r\l");
  321. #endif
  322.         skip_entry();
  323.     }
  324.     flush();
  325.   }
  326. }
  327.  
  328. skip_entry()
  329. {
  330.   register int blocks = block_size();
  331.  
  332.     if (opts.sg_class == 1) {
  333.         long pos;
  334.  
  335.         pos = ((long) blocks) * BLOCK_SIZE;
  336.         lseek(tar_fd,pos,1);
  337.     }
  338.     else {
  339.         while (blocks--)
  340.             read(tar_fd, io_buffer, BLOCK_SIZE);
  341.     }
  342. }
  343.  
  344. extract(file)
  345. register char *file;
  346. {
  347.   register int fd;
  348.  
  349.   if (header.member.m_linked == '1') {
  350. #ifdef OSK
  351.     fprintf(stderr,"Cannot link %s (symbolic links not supportet)\n",header.member.m_link);
  352. #else
  353.     string_print(NIL_PTR,"Cannot link %s\r\l",header.member.m_link);
  354. #endif
  355.     skip_entry();
  356.     return;
  357.   }
  358.  
  359.   if ((fd = creat(file, S_IREAD | S_IWRITE)) < 0) {
  360. /* create missing directories (08/06/89) stp */
  361. register char *s,*pp;
  362.  
  363.     /* convert - to _ */
  364.     for(s = file; s = index(s,'-');) {
  365.         *s++ = '_';
  366.     }
  367.     pp = file;
  368.     while (s = index(pp,'/')) {
  369.       pp = (char *) malloc(s-file+1);
  370.       strncpy(pp,file,s-file);
  371.       pp[s-file] = '\0';
  372.       mkdir(pp);
  373.       free(pp);
  374.       pp = s+1;
  375.     }
  376.     if ((fd = creat(file, S_IREAD | S_IWRITE)) < 0) {
  377. #ifdef OSK
  378.       fprintf(stderr, "Cannot create %s : ", file); fflush(stderr);
  379.       prerr(0,errno);
  380. #else
  381.       string_print(NIL_PTR, "Cannot create %s\r\l", file);
  382. #endif
  383.       skip_entry();
  384.       return;
  385.     }
  386.   }
  387.  
  388.   copy(file, tar_fd, fd, convert(header.member.m_size, LONG_TYPE));
  389.  
  390.     _ss_attr(fd, u29mode((int) convert(header.member.m_mode, INT_TYPE)));
  391.  
  392.     if (!modtime_fl)
  393. #ifdef OSK
  394.         if (_gs_gfd(fd,&ofdbuf,sizeof(ofdbuf)) != -1) {
  395. #else
  396.         if (_gs_gfd(fd,&ofdbuf,sizeof(ofdbuf)) != ERROR) {
  397. #endif
  398.  
  399.             struct tm     *utm;
  400.             struct sgtbuf otm;
  401.             long clock;
  402.  
  403.             clock = convert(header.member.m_time,LONG_TYPE);
  404.             utm = localtime(&clock);
  405.             u2otime(&otm,utm);
  406.             _strass(&ofdbuf.fd_date[0], &otm, 5);
  407.             _ss_pfd(fd,&ofdbuf);
  408.         }
  409.  
  410.     close(fd);
  411.     flush();
  412. }
  413.  
  414. copy(file, from, to, bytes)
  415. char *file;
  416. int from, to;
  417. register long bytes;
  418. {
  419.   register int rest;
  420.   int blocks = (int) ((bytes + (long) BLOCK_SIZE - 1) / (long) BLOCK_SIZE);
  421.  
  422.   if (verbose_fl) {
  423.      if (to == tar_fd)
  424. #ifdef OSK
  425.         printf("a %s, %d tape blocks\n",file,blocks);
  426. #else
  427.         sprintf(stbuf,"a %s, %d tape blocks\r\l",file,blocks);
  428. #endif
  429.      else
  430. #ifdef OSK
  431.         printf("x %s, %ld bytes, %d tape blocks\n",file,bytes,blocks);
  432. #else
  433.         sprintf(stbuf,"x %s, %ld bytes, %d tape blocks\r\l",file,bytes,blocks);
  434.      print(stbuf);
  435.      flush();
  436. #endif
  437.   }
  438.  
  439.   while (blocks--) {
  440.     read(from, io_buffer, BLOCK_SIZE);
  441.     rest = (bytes > (long) BLOCK_SIZE) ? BLOCK_SIZE : (int) bytes;
  442.     mwrite(to, io_buffer, (to == tar_fd) ? BLOCK_SIZE : rest);
  443.     bytes -= (long) rest;
  444.   }
  445. }
  446.  
  447. long convert(str, type)
  448. char str[];
  449. int type;
  450. {
  451.   register long ac = 0L;
  452.   register int i;
  453.  
  454.   for (i = 0; i < type; i++) {
  455.     if (str[i] >= '0' && str[i] <= '7') {
  456.         ac <<= 3;
  457.         ac += (long) (str[i] - '0');
  458.     }
  459.   }
  460.  
  461.   return ac;
  462. }
  463.  
  464. mkdir(dir_name)
  465. char *dir_name;
  466. {
  467.   if (mknod(dir_name,S_IFDIR | S_IREAD | S_IWRITE) < 0) {
  468.      return;
  469.   }
  470.   else {
  471.     int fd;
  472.     if ((fd = open(dir_name,S_IFDIR | S_IREAD | S_IWRITE)) > 0) {
  473.         _ss_attr(fd, S_IFDIR | S_IWRITE | u29mode((int) convert(header.member.m_mode, INT_TYPE)));
  474.         close(fd);
  475.     }
  476.   }
  477. }
  478.  
  479. checksum()
  480. {
  481.   register char *ptr = header.member.m_checksum;
  482.   register int ac = 0;
  483.  
  484.   while (ptr < &header.member.m_checksum[INT_TYPE])
  485.     *ptr++ = ' ';
  486.  
  487.   ptr = header.hdr_block;
  488.   while (ptr < &header.hdr_block[BLOCK_SIZE])
  489.     ac += *ptr++;
  490.  
  491.   return ac;
  492. }
  493.  
  494. is_dir(file)
  495. register char *file;
  496. {
  497.   while (*file++ != '\0') ;
  498.   return (*(file - 2) == '/');
  499. }
  500.  
  501. char path[NAME_SIZE];
  502.  
  503. char pathname[NAME_SIZE];
  504. char *path_name(file)
  505. register char *file;
  506. {
  507.  
  508.   string_print(pathname, "%s%s", path, file);
  509.   return pathname;
  510. }
  511.  
  512. add_path(name)
  513. register char *name;
  514. {
  515.   register char *path_ptr = path;
  516.  
  517.   while (*path_ptr)
  518.     path_ptr++;
  519.  
  520.   if (name == NIL_PTR) {
  521.     while (*path_ptr-- != '/')
  522.         ;
  523.     while (*path_ptr != '/' && path_ptr != path)
  524.         path_ptr--;
  525.     if (*path_ptr == '/')
  526.         path_ptr++;
  527.     *path_ptr = '\0';
  528.   }
  529.   else {
  530.     while (*name) {
  531.         if (path_ptr == &path[NAME_SIZE])
  532.             error("tar: Pathname too long", NIL_PTR);
  533.         *path_ptr++ = *name++;
  534.     }
  535.     *path_ptr++ = '/';
  536.     *path_ptr = '\0';
  537.   }
  538. }
  539.  
  540. add_file(file)
  541. register char *file;
  542. {
  543.   struct fildes st;
  544.   struct dirent dir;
  545.   register int fd;
  546. #ifdef OSK
  547.   unsigned long siz;
  548.   u_char *sip = (u_char*) st.fd_fsize;
  549. #endif
  550.  
  551.   if ((fd = open(file,0x81)) < 0)
  552.      if ((fd = open(file, 1)) < 0) {
  553. #ifdef OSK
  554.         fprintf(stderr, "Cannot open '%s' ", file); fflush(stderr);
  555.         prerr(0,errno);
  556. #else
  557.         string_print(NIL_PTR, "Cannot open %s\r\l", file);
  558. #endif
  559.         return;
  560.      }
  561.   if (_gs_gfd(fd,&st,sizeof(st)) < 0) {
  562. #ifdef OSK
  563.      fprintf(stderr, "Cannot get file descriptor for %s",file); fflush(stderr);
  564.      prerr(0,errno);
  565. #else
  566.      string_print(NIL_PTR, "Cannot get file descriptor for %s\r\l",file);
  567. #endif
  568.      close(fd);
  569.      return;
  570.   }
  571.   siz = (((((sip[0] << 8) + sip[1]) << 8) + sip[2]) << 8) + sip[3];
  572.  
  573.   make_header(path_name(file), &st);
  574.   mwrite(tar_fd, &header, sizeof(header));
  575.   if (!(st.fd_att & S_IFDIR))
  576. #ifdef OSK
  577.      copy(path_name(file), fd, tar_fd, siz);
  578. #else
  579.      copy(path_name(file), fd, tar_fd, st.fd_fsize);
  580. #endif
  581.   else if (st.fd_att & S_IFDIR) {
  582.     if (chdir(file) < 0)
  583.         string_print(NIL_PTR, "Cannot chdir to %s\n", file);
  584.     else {
  585.         add_path(file);
  586.         mread(fd, &dir, sizeof(dir));       /* "." */
  587.         mread(fd, &dir, sizeof(dir));       /* ".." */
  588.         while (read(fd, &dir, sizeof(dir)) == sizeof(dir)) {
  589. #ifdef OSK
  590.             if (dir.dir_addr) {
  591. #else
  592.             if (dir.dir_addr[0] || dir.dir_addr[1] || dir.dir_addr[2]) {
  593. #endif
  594.                 strhcpy(dir.dir_name,dir.dir_name);
  595.                 if (*dir.dir_name)
  596.                   add_file(dir.dir_name);
  597.             }
  598.         }
  599.         chdir("..");
  600.         add_path(NIL_PTR);
  601.     }
  602.   }
  603.   else
  604. #ifdef OSK
  605.     _errmsg("unknown file type. Not added. ",0);
  606. #else
  607.     print("tar: unknown file type. Not added.\r\l");
  608. #endif
  609.  
  610.   close(fd);
  611. }
  612.  
  613. make_header(file, st)
  614. char *file;
  615. register struct fildes *st;
  616. {
  617.   register char *ptr = header.member.m_name;
  618.   char tbuf[6];
  619. #ifdef OSK
  620.   u_char *sip = (u_char*) st->fd_fsize;
  621.   unsigned long siz = (((((sip[0] << 8) + sip[1]) << 8) +
  622.                          sip[2]) << 8) + sip[3];
  623.   u_char *owp = (u_char*) st->fd_own;
  624.   unsigned short own = owp[1];
  625.   unsigned short group = owp[0];
  626. #endif
  627.  
  628.   clear_header();
  629.  
  630.   while (*ptr++ = *file++)
  631.     ;
  632.  
  633.   if (st->fd_att &  S_IFDIR) {
  634.     *(ptr - 1) = '/';
  635. #ifdef OSK
  636.     siz = 0;
  637. #else
  638.     st->fd_fsize = 0L;
  639. #endif
  640.   }
  641.  
  642.   _strass(tbuf,st->fd_date,5);
  643.   tbuf[5] = 0;
  644.   string_print(header.member.m_mode, "%I ", o2umode(st->fd_att));
  645. #ifdef OSK
  646.   string_print(header.member.m_uid,  "%I ", own);
  647.   string_print(header.member.m_gid,  "%I ", group);
  648.   string_print(header.member.m_size, "%L ", siz);
  649. #else
  650.   string_print(header.member.m_uid,  "%I ", st->fd_own);
  651.   string_print(header.member.m_gid,  "%I ", 101);
  652.   string_print(header.member.m_size, "%L ", st->fd_fsize);
  653. #endif
  654.   string_print(header.member.m_time, "%L ", o2utime(tbuf));
  655.   header.member.m_linked = ' ';
  656.   string_print(header.member.m_checksum, "%I", checksum());
  657. }
  658.  
  659. clear_header()
  660. {
  661.   register char *ptr = header.hdr_block;
  662.  
  663.   while (ptr < &header.hdr_block[BLOCK_SIZE])
  664.     *ptr++ = '\0';
  665. }
  666.  
  667. adjust_boundary()
  668. {
  669.   clear_header();
  670.   mwrite(tar_fd, &header, sizeof(header));
  671.  
  672.   while (total_blocks++ < BLOCK_BOUNDARY)
  673.     mwrite(tar_fd, &header, sizeof(header));
  674.   close(tar_fd);
  675. }
  676.  
  677. mread(fd, address, bytes)
  678. int fd, bytes;
  679. char *address;
  680. {
  681. register int r;
  682.  
  683.   if ((r = read(fd, address, bytes)) != bytes) {
  684. #ifdef OSK
  685.     if (r == 0)
  686.       errno = E_EOF;
  687.     exit(_errmsg(errno,"read error. "));
  688. #else
  689.     error("tar: read error.", NIL_PTR);
  690. #endif
  691.   }
  692. }
  693.  
  694. mwrite(fd, address, bytes)
  695. int fd, bytes;
  696. char *address;
  697. {
  698.   if (write(fd, address, bytes) != bytes) {
  699. #ifdef OSK
  700.     exit(_errmsg(errno,"write error. "));
  701. #else
  702.     error("tar: write error.", NIL_PTR);
  703. #endif
  704.   }
  705.   total_blocks++;
  706. }
  707.  
  708. char output[BLOCK_SIZE];
  709. print(str)
  710. register char *str;
  711. {
  712.   static int index = 0;
  713.  
  714.   if (str == NIL_PTR) {
  715.     write(2, output, index);
  716.     index = 0;
  717.     return;
  718.   }
  719.  
  720.   while (*str) {
  721.     output[index++] = *str++;
  722.     if (index == BLOCK_SIZE) {
  723.         write(2, output, BLOCK_SIZE);
  724.         index = 0;
  725.     }
  726.   }
  727. }
  728.  
  729. char *num_out(number)
  730. register long number;
  731. {
  732.   static char num_buf[13];
  733.   char temp[13];
  734.   register int i;
  735.  
  736.   for (i = 0; i < 11; i++) {
  737.     temp[i] = (number & 07) + '0';
  738.     number >>= 3;
  739.   }
  740.  
  741.   for (i = 0; i < 11; i++)
  742.     num_buf[i] = temp[10 - i];
  743.  
  744.   return num_buf;
  745. }
  746.  
  747. /* VARARGS */
  748. string_print(buffer, fmt, args)
  749. char *buffer;
  750. register char *fmt;
  751. int args;
  752. {
  753.   register char *buf_ptr;
  754.   char *scan_ptr;
  755.   char buf[NAME_SIZE];
  756.   int *argptr = &args;
  757.   BOOL pr_fl, i;
  758.  
  759.   if (pr_fl = (buffer == NIL_PTR))
  760.     buffer = buf;
  761.  
  762.   buf_ptr = buffer;
  763.   while (*fmt) {
  764.     if (*fmt == '%') {
  765.         fmt++;
  766.         switch (*fmt++) {
  767.             case 's':
  768.                 scan_ptr = (char *) *argptr;
  769.                 break;
  770.             case 'I':
  771.                 scan_ptr = num_out((long) *argptr) + 5;
  772. /*                for (i = 0; i < 5; i++)
  773.                     scan_ptr++; */
  774.                 break;
  775.             case 'L':
  776.                 scan_ptr = num_out(*((long *) argptr));
  777.                 argptr++;
  778.                 break;
  779.             default:
  780.                 scan_ptr = "";
  781.         }
  782.         while (*buf_ptr++ = *scan_ptr++)
  783.             ;
  784.         buf_ptr--;
  785.         argptr++;
  786.     }
  787.     else
  788.         *buf_ptr++ = *fmt++;
  789.   }
  790.   *buf_ptr = '\0';
  791.  
  792.   if (pr_fl)
  793.     print(buffer);
  794. }
  795.  
  796.  o2umode(mode)
  797.     char mode;
  798. {
  799.     int ret_mode=0;
  800.  
  801.     if (mode & S_IFDIR)
  802.         ret_mode |= 040000;
  803.     if (mode & S_IREAD)
  804.         ret_mode |= 0400;
  805.     if (mode & S_IWRITE)
  806.         ret_mode |= 0200;
  807.     if (mode & S_IEXEC)
  808.         ret_mode |= 0100;
  809.     if (mode & S_IOREAD)
  810.         ret_mode |= 04;
  811.     if (mode & S_IOWRITE)
  812.         ret_mode |= 02;
  813.     if (mode & S_IOEXEC)
  814.         ret_mode |= 01;
  815.  
  816.     return(ret_mode);
  817. }
  818.  
  819.  u29mode(mode)
  820.     int mode;
  821. {
  822.     int ret_mode=0;
  823.  
  824.     strcpy(modestr,"-----------");
  825.  
  826.     if (mode & 040000) {
  827.         ret_mode  |= S_IFDIR;
  828.         modestr[0] = 'd';
  829.     }
  830.  
  831.     if (mode & 0400) {
  832.         ret_mode  |= S_IREAD;
  833.         modestr[1] = 'r';
  834.     }
  835.  
  836.     if (mode & 0200) {
  837.         ret_mode  |= S_IWRITE;
  838.         modestr[2] = 'w';
  839.     }
  840.  
  841.     if (mode & 0100) {
  842.         ret_mode  |= S_IEXEC;
  843.         modestr[3] = 'x';
  844.     }
  845.  
  846.     if (mode & 04) {
  847.         ret_mode  |= S_IOREAD;
  848.         modestr[7] = 'r';
  849.     }
  850.  
  851.     if (mode & 02) {
  852.         ret_mode  |= S_IOWRITE;
  853.         modestr[8] = 'w';
  854.     }
  855.  
  856.     if (mode & 01) {
  857.         ret_mode  |= S_IOEXEC;
  858.         modestr[9] = 'x';
  859.     }
  860.  
  861.     return(ret_mode);
  862. }
  863.  
  864. char *atime(clock)
  865.     long clock;
  866. {
  867.     static char buf[26];
  868.     int i;
  869.  
  870.     strcpy(buf,ctime(&clock));
  871.  
  872.     for (i=4; i< 16; i++)
  873.         buf[i-4] = buf[i];
  874.     buf[12] = ' ';
  875.  
  876.     for (i=20; i<24; i++)
  877.         buf[i-7] = buf[i];
  878.     buf[17] = 0;
  879.  
  880.     return(buf);
  881. }
  882.  
  883. char **match(p,name)
  884.     char **p, *name;
  885. {
  886. char **q = p;
  887.  
  888.   while (*q) {
  889. #ifdef OSK
  890.     if (!_cmpnam(name,*q,strlen(*q))) {
  891. #else
  892.     if (patmatch(*q,name,1)) {
  893. #endif
  894.        return(q);
  895.     }
  896.     q++;
  897.   }
  898.   return(NULL);
  899. }
  900.  
  901. #ifdef OSK
  902. u2otime(om,um)
  903. struct sgtbuf *om;
  904. struct tm     *um;
  905. {
  906.   om->t_year = um->tm_year;
  907.   om->t_month = um->tm_mon+1;
  908.   om->t_day = um->tm_mday;
  909.   om->t_hour = um->tm_hour;
  910.   om->t_minute = um->tm_min;
  911.   om->t_second = um->tm_sec;
  912. }
  913.  
  914. long o2utime(om)
  915. struct sgtbuf *om;
  916. {
  917. struct tm um;
  918.  
  919.   um.tm_year = om->t_year;
  920.   um.tm_mon = om->t_month-1;
  921.   um.tm_mday = om->t_day;
  922.   um.tm_hour = om->t_hour;
  923.   um.tm_min = om->t_minute;
  924.   um.tm_sec = om->t_second;
  925.   return mktime(&um);
  926. }
  927. #endif
  928.