Annotation of coherent/d/usr/bin/pax/public/part02.sh, revision 1.1

1.1     ! root        1: # This is a shell archive.  Remove anything before this line, then unpack
        !             2: # it by saving it into a file and typing "sh file".  To overwrite existing
        !             3: # files, type "sh file -c".  You can also feed this as standard input via
        !             4: # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
        !             5: # will see the following message at the end:
        !             6: #              "End of archive 2 (of 6)."
        !             7: # Contents:  cpio.1 create.c func.h link.c names.c replace.c ttyio.c
        !             8: #   warn.c
        !             9: # Wrapped by mark@jhereg on Tue Dec 27 19:37:38 1988
        !            10: PATH=/bin:/usr/bin:/usr/ucb ; export PATH
        !            11: if test -f cpio.1 -a "${1}" != "-c" ; then 
        !            12:   echo shar: Will not over-write existing file \"cpio.1\"
        !            13: else
        !            14: echo shar: Extracting \"cpio.1\" \(6231 characters\)
        !            15: sed "s/^X//" >cpio.1 <<'END_OF_cpio.1'
        !            16: X.\" $Id: cpio.1,v 1.1 88/12/23 18:02:04 mark Rel $
        !            17: X.TH CPIO 1 "USENIX Association" ""
        !            18: X.SH NAME
        !            19: Xcpio \- copy file archives in and out
        !            20: X.SH SYNOPSIS
        !            21: X.B cpio
        !            22: X.BR \-o [ Bacv ]
        !            23: X.br
        !            24: X.B cpio
        !            25: X.BR \-i [ Bcdfmrtuv ]
        !            26: X.RI [ pattern... ]
        !            27: X.br
        !            28: X.B cpio
        !            29: X.BR \-p [ adlmruv ]
        !            30: X.I directory
        !            31: X.SH DESCRIPTION
        !            32: XThe
        !            33: X.B cpio
        !            34: Xutility produces and reads files in the format specified by the
        !            35: X.B cpio
        !            36: X.B "Archive/Interchange File Format"
        !            37: Xspecified in
        !            38: X.IR "IEEE Std. 1003.1-1988" .
        !            39: X.PP
        !            40: XThe
        !            41: X.B "cpio -i"
        !            42: X(copy in) utility extracts files from the standard input, which is
        !            43: Xassumed to be the product of a previous
        !            44: X.B "cpio -o" .
        !            45: XOnly files with names that match
        !            46: X.I patterns
        !            47: Xare selected.
        !            48: XMultiple
        !            49: X.I patterns
        !            50: Xmay be specified and if no
        !            51: X.I patterns
        !            52: Xare specified, the default for
        !            53: X.I patterns
        !            54: Xis \*, selecting all files.
        !            55: XThe extracted files are conditionally created and copied into the
        !            56: Xcurrent directory, and possibly any levels below, based upon the
        !            57: Xoptions described below and the permissions of the files will be those
        !            58: Xof the previous
        !            59: X.B "cpio -o" .
        !            60: XThe owner and group of the files will be that of the current user
        !            61: Xunless the user has appropriate privileges, which causes
        !            62: X.B cpio
        !            63: Xto retains the owner and group of the files of the previous
        !            64: X.B "cpio -o" .
        !            65: X.PP
        !            66: XThe 
        !            67: X.B "cpio -p"
        !            68: X(pass) utility reads the standard input to obtain a list of path names
        !            69: Xof files that are conditionally created and copied into the
        !            70: Xdestination
        !            71: X.I directory 
        !            72: Xbased upon the options described below.
        !            73: X.PP
        !            74: XIf an error is detected, the cause is reported and the
        !            75: X.B cpio
        !            76: Xutility will continue to copy other files.
        !            77: X.B cpio
        !            78: Xwill skip over any unrecognized files which it encounters in the archive.
        !            79: X.PP
        !            80: XThe following restrictions apply to the 
        !            81: X.B cpio
        !            82: Xutility:
        !            83: X.IP 1 .25i
        !            84: XPathnames are restricted to 256 characters.
        !            85: X.IP 2 .25i
        !            86: XAppropriate privileges are required to copy special files.
        !            87: X.IP 3 .25i
        !            88: XBlocks are reported in 512-byte quantities.
        !            89: X.SS Options
        !            90: XThe following options are available:
        !            91: X.TP .5i
        !            92: X.B \-B
        !            93: XInput/output is to be blocked 5120 bytes to the record.
        !            94: XCan only be used with
        !            95: X.B "cpio -o" 
        !            96: Xor
        !            97: X.B "cpio -i"
        !            98: Xfor data that is directed to or from character special files.
        !            99: X.TP .5i
        !           100: X.B \-a
        !           101: XReset access times of input files after they have been copied.
        !           102: XWhen the
        !           103: X.B \-l
        !           104: Xoption is also specified, the linked files do not have their access
        !           105: Xtimes reset.
        !           106: XCan only be used with
        !           107: X.B "cpio -o"
        !           108: Xor
        !           109: X.B "cpio -i" .
        !           110: X.TP .5i
        !           111: X.B \-c
        !           112: XWrite header information in ASCII character for for portability.
        !           113: XCan only be used with
        !           114: X.B "cpio -i"
        !           115: Xor
        !           116: X.B "cpio -o" .
        !           117: XNote that this option should always be used to write portable files.
        !           118: X.TP .5i
        !           119: X.B \-d
        !           120: XCreates directories as needed.
        !           121: XCan only be used with 
        !           122: X.B "cpio -i" 
        !           123: Xor
        !           124: X.B "cpio -p" .
        !           125: X.TP .5i
        !           126: X.B \-f
        !           127: XCopy in all files except those in
        !           128: X.I patterns .
        !           129: XCan only be used with
        !           130: X.B "cpio -i" .
        !           131: X.TP .5i
        !           132: X.B \-l
        !           133: XWhenever possible, link files rather than copying them.
        !           134: XCan only be used with 
        !           135: X.B "cpio -p" .
        !           136: X.TP .5i
        !           137: X.B \-m
        !           138: XRetain previous modification times.
        !           139: XThis option is ineffective on directories that are being copied.
        !           140: XCan only be used with
        !           141: X.B "cpio -i" 
        !           142: Xor
        !           143: X.B "cpio -p" .
        !           144: X.TP .5i
        !           145: X.B \-r
        !           146: XInteractively rename files.
        !           147: XThe user is asked whether to rename
        !           148: X.I pattern
        !           149: Xeach invocation.
        !           150: XRead and write permissions for
        !           151: X.B "/dev/tty"
        !           152: Xare required for this option.
        !           153: XIf the user types a null line, the file is skipped.
        !           154: XShould only be used with
        !           155: X.B "cpio -i"
        !           156: Xor
        !           157: X.B "cpio -o" .
        !           158: X.TP .5i
        !           159: X.B \-t
        !           160: XPrint a table of contents of the input.
        !           161: XNo files are created.
        !           162: XCan only be used with
        !           163: X.B "cpio -i" .
        !           164: X.TP .5i
        !           165: X.B \-u
        !           166: XCopy files unconditionally; usually an older file will not replace a
        !           167: Xnew file with the same name.
        !           168: XCan only be used with
        !           169: X.B "cpio -i"
        !           170: Xor
        !           171: X.B "cpio -p" .
        !           172: X.TP .5i
        !           173: X.B \-v
        !           174: XVerbose: cause the names of the affected files to be printed.
        !           175: XCan only be used with
        !           176: X.B "cpio -i" .
        !           177: XProvides a detailed listing when used with the 
        !           178: X.B \-t
        !           179: Xoption.
        !           180: X.SS Operands
        !           181: XThe following operands are available:
        !           182: X.TP 1i
        !           183: X.I patterns
        !           184: XSimple regular expressions given in the name-generating notation of the
        !           185: Xshell.
        !           186: X.TP 1i
        !           187: X.I directory
        !           188: XThe destination directory.
        !           189: X.SS "Exit Status"
        !           190: XThe
        !           191: X.B cpio
        !           192: Xutility exits with one of the following values:
        !           193: X.TP .5i
        !           194: X0
        !           195: XAll input files were copied.
        !           196: X.TP .5i
        !           197: X2
        !           198: XThe utility encountered errors in copying or accessing files or
        !           199: Xdirectories.
        !           200: XAn error will be reported for nonexistent files or directories, or
        !           201: Xpermissions that do not allow the user to access the source or target
        !           202: Xfiles.
        !           203: X.SS
        !           204: XIt is important to use the
        !           205: X.B "-depth"
        !           206: Xoption of the
        !           207: X.B find
        !           208: Xutility to generate pathnames for 
        !           209: X.B cpio .
        !           210: XThis eliminates problems
        !           211: X.B cpio
        !           212: Xcould have trying to create files under read-only directories.
        !           213: X.PP
        !           214: XThe following command:
        !           215: X.RS
        !           216: Xls | cpio -o > ../newfile
        !           217: X.RE
        !           218: Xcopies out the files listed by the 
        !           219: X.B ls
        !           220: Xutility and redirects them to the file
        !           221: X.B newfile .
        !           222: X.PP
        !           223: XThe following command:
        !           224: X.RS
        !           225: Xcat newfile | cpio -id "memo/al" "memo/b*"
        !           226: X.RE
        !           227: Xuses the output file
        !           228: X.B newfile
        !           229: Xfrom the
        !           230: X.B "cpio -o"
        !           231: Xutility, takes those files that match the patterns
        !           232: X.B "memo/al"
        !           233: Xand
        !           234: X.B "memo/b*" ,
        !           235: Xcreates the directories below the current directory, and places the
        !           236: Xfiles in the appropriate directories.
        !           237: X.PP
        !           238: XThe command
        !           239: X.RS
        !           240: Xfind . -depth -print | cpio -pdlmv newdir
        !           241: X.RE
        !           242: Xtakes the file names piped to it from the
        !           243: X.B find
        !           244: Xutility and copies or links those files to another directory
        !           245: Xnamed
        !           246: X.B newdir ,
        !           247: Xwhile retaining the modification time.
        !           248: X.SH FILES
        !           249: X.TP 1i
        !           250: X/dev/tty
        !           251: Xused to prompt the user for information when the
        !           252: X.B \-i 
        !           253: Xor 
        !           254: X.B \-r
        !           255: Xoptions are specified.
        !           256: X.SH "SEE ALSO"
        !           257: Xfind(1), pax(1), tar(1), cpio(5), tar(5)
        !           258: X.SH COPYRIGHT
        !           259: XCopyright (c) 1989 Mark H. Colburn.  
        !           260: X.br
        !           261: XAll rights reserved.
        !           262: X.PP
        !           263: XRedistribution and use in source and binary forms are permitted
        !           264: Xprovided that the above copyright notice is duplicated in all such 
        !           265: Xforms and that any documentation, advertising materials, and other 
        !           266: Xmaterials related to such distribution and use acknowledge that the 
        !           267: Xsoftware was developed by Mark H. Colburn and sponsored by The 
        !           268: XUSENIX Association. 
        !           269: X.PP
        !           270: XTHE SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !           271: XIMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !           272: XWARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !           273: X.SH AUTHOR
        !           274: XMark H. Colburn
        !           275: X.br
        !           276: XNAPS International
        !           277: X.br
        !           278: X117 Mackubin Street, Suite 1
        !           279: X.br
        !           280: XSt. Paul, MN 55102
        !           281: X.br
        !           282: [email protected]
        !           283: X.sp 2
        !           284: XSponsored by
        !           285: X.B "The USENIX Association"
        !           286: Xfor public distribution.
        !           287: END_OF_cpio.1
        !           288: if test 6231 -ne `wc -c <cpio.1`; then
        !           289:     echo shar: \"cpio.1\" unpacked with wrong size!
        !           290: fi
        !           291: # end of overwriting check
        !           292: fi
        !           293: if test -f create.c -a "${1}" != "-c" ; then 
        !           294:   echo shar: Will not over-write existing file \"create.c\"
        !           295: else
        !           296: echo shar: Extracting \"create.c\" \(7830 characters\)
        !           297: sed "s/^X//" >create.c <<'END_OF_create.c'
        !           298: X/* $Source: /u/mark/src/pax/RCS/create.c,v $
        !           299: X *
        !           300: X * $Revision: 1.1 $
        !           301: X *
        !           302: X * create.c - Create a tape archive. 
        !           303: X *
        !           304: X * DESCRIPTION
        !           305: X *
        !           306: X *    These functions are used to create/write and archive from an set of
        !           307: X *    named files.
        !           308: X *
        !           309: X * AUTHOR
        !           310: X *
        !           311: X *            Mark H. Colburn, NAPS International ([email protected])
        !           312: X *
        !           313: X * Sponsored by The USENIX Association for public distribution. 
        !           314: X *
        !           315: X * Copyright (c) 1989 Mark H. Colburn.
        !           316: X * All rights reserved.
        !           317: X *
        !           318: X * Redistribution and use in source and binary forms are permitted
        !           319: X * provided that the above copyright notice is duplicated in all such 
        !           320: X * forms and that any documentation, advertising materials, and other 
        !           321: X * materials related to such distribution and use acknowledge that the 
        !           322: X * software was developed * by Mark H. Colburn and sponsored by The 
        !           323: X * USENIX Association. 
        !           324: X *
        !           325: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !           326: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !           327: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !           328: X *
        !           329: X * $Log:      create.c,v $
        !           330: X * Revision 1.1  88/12/23  18:02:06  mark
        !           331: X * Initial revision
        !           332: X * 
        !           333: X */
        !           334: X
        !           335: X#ifndef lint
        !           336: Xstatic char *ident = "$Id: create.c,v 1.1 88/12/23 18:02:06 mark Rel $";
        !           337: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
        !           338: X#endif /* ! lint */
        !           339: X
        !           340: X
        !           341: X/* Headers */
        !           342: X
        !           343: X#include "pax.h"
        !           344: X
        !           345: X
        !           346: X/* Function Prototypes */
        !           347: X
        !           348: X#ifdef __STDC__
        !           349: X
        !           350: Xstatic void writetar(char *, Stat *);
        !           351: Xstatic void writecpio(char *, Stat *);
        !           352: Xstatic char tartype(int);
        !           353: X
        !           354: X#else /* !__STDC__ */
        !           355: X
        !           356: Xstatic void writetar();
        !           357: Xstatic void writecpio();
        !           358: Xstatic char tartype();
        !           359: X
        !           360: X#endif /* __STDC__ */
        !           361: X
        !           362: X
        !           363: X/* create_archive - create a tar archive.
        !           364: X *
        !           365: X * DESCRIPTION
        !           366: X *
        !           367: X *    Create_archive is used as an entry point to both create and append
        !           368: X *    archives.  Create archive goes through the files specified by the
        !           369: X *    user and writes each one to the archive if it can.  Create_archive
        !           370: X *    knows how to write both cpio and tar headers and the padding which
        !           371: X *    is needed for each type of archive.
        !           372: X *
        !           373: X * RETURNS
        !           374: X *
        !           375: X *    Always returns 0
        !           376: X */
        !           377: X
        !           378: X#ifdef __STDC__
        !           379: X
        !           380: Xint create_archive(void)
        !           381: X
        !           382: X#else
        !           383: X
        !           384: Xint create_archive()
        !           385: X
        !           386: X#endif
        !           387: X{
        !           388: X    char            name[PATH_MAX + 1];
        !           389: X    Stat            sb;
        !           390: X    int             fd;
        !           391: X
        !           392: X    while (name_next(name, &sb) != -1) {
        !           393: X      if ((fd = openi(name, &sb)) < 0) {
        !           394: X          /* FIXME: pax wants to exit here??? */
        !           395: X          continue;
        !           396: X      }
        !           397: X
        !           398: X      if (rplhead != NULL) {
        !           399: X          rpl_name(name);
        !           400: X          if (strlen(name) == 0) {
        !           401: X              continue;
        !           402: X          }
        !           403: X      }
        !           404: X      if (get_disposition("add", name) || get_newname(name, sizeof(name))) {
        !           405: X          /* skip file... */
        !           406: X          if (fd) {
        !           407: X              close(fd);
        !           408: X          }
        !           409: X          continue;
        !           410: X      } 
        !           411: X
        !           412: X      if (!f_link && sb.sb_nlink > 1) {
        !           413: X          if (islink(name, &sb)) {
        !           414: X              sb.sb_size = 0;
        !           415: X          }
        !           416: X          linkto(name, &sb);
        !           417: X      }
        !           418: X      if (ar_format == TAR) {
        !           419: X          writetar(name, &sb);
        !           420: X      } else {
        !           421: X          writecpio(name, &sb);
        !           422: X      }
        !           423: X      if (fd) {
        !           424: X          outdata(fd, name, sb.sb_size);
        !           425: X      }
        !           426: X      if (f_verbose) {
        !           427: X          print_entry(name, &sb);
        !           428: X      }
        !           429: X    }
        !           430: X
        !           431: X    write_eot();
        !           432: X    close_archive();
        !           433: X    return (0);
        !           434: X}
        !           435: X
        !           436: X
        !           437: X/* writetar - write a header block for a tar file
        !           438: X *
        !           439: X * DESCRIPTION
        !           440: X *
        !           441: X *    Make a header block for the file name whose stat info is in st.  
        !           442: X *    Return header pointer for success, NULL if the name is too long.
        !           443: X *
        !           444: X *    The tar header block is structured as follows:
        !           445: X *
        !           446: X *            FIELD NAME      OFFSET          SIZE
        !           447: X *            -------------|---------------|------
        !           448: X *            name              0             100
        !           449: X *            mode            100               8
        !           450: X *            uid             108               8
        !           451: X *            gid             116               8
        !           452: X *            size            124              12
        !           453: X *            mtime           136              12
        !           454: X *            chksum          148               8
        !           455: X *            typeflag        156               1
        !           456: X *            linkname        157             100
        !           457: X *            magic           257               6
        !           458: X *            version         263               2
        !           459: X *            uname           265              32
        !           460: X *            gname           297              32
        !           461: X *            devmajor        329               8
        !           462: X *            devminor        337               8
        !           463: X *            prefix          345             155
        !           464: X *
        !           465: X * PARAMETERS
        !           466: X *
        !           467: X *    char    *name   - name of file to create a header block for
        !           468: X *    Stat    *asb    - pointer to the stat structure for the named file
        !           469: X *
        !           470: X */
        !           471: X
        !           472: X#ifdef __STDC__
        !           473: X
        !           474: Xstatic void writetar(char *name, Stat *asb)
        !           475: X
        !           476: X#else
        !           477: X    
        !           478: Xstatic void writetar(name, asb)
        !           479: Xchar           *name;
        !           480: XStat           *asb;
        !           481: X
        !           482: X#endif
        !           483: X{
        !           484: X    char         *p;
        !           485: X    char           *prefix = NULL;
        !           486: X    int             i;
        !           487: X    int             sum;
        !           488: X    char            hdr[BLOCKSIZE];
        !           489: X    Link           *from;
        !           490: X
        !           491: X    memset(hdr, 0, BLOCKSIZE);
        !           492: X    if (strlen(name) > 255) {
        !           493: X      warn(name, "name too long");
        !           494: X      return;
        !           495: X    }
        !           496: X
        !           497: X    /* 
        !           498: X     * If the pathname is longer than TNAMLEN, but less than 255, then
        !           499: X     * we can split it up into the prefix and the filename.
        !           500: X     */
        !           501: X    if (strlen(name) > 100) {
        !           502: X      prefix = name;
        !           503: X      name += 155;
        !           504: X      while (name > prefix && *name != '/') {
        !           505: X          name--;
        !           506: X      }
        !           507: X
        !           508: X      /* no slash found....hmmm.... */
        !           509: X      if (name == prefix) {
        !           510: X          warn(prefix, "Name too long");
        !           511: X          return;
        !           512: X      }
        !           513: X      *name++ = '\0';
        !           514: X    }
        !           515: X
        !           516: X#ifdef S_IFLNK
        !           517: X    if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
        !           518: X      strcpy(&hdr[157], asb->sb_link);
        !           519: X      asb->sb_size = 0;
        !           520: X    }
        !           521: X#endif
        !           522: X    strcpy(hdr, name);
        !           523: X    sprintf(&hdr[100], "%06o \0", asb->sb_mode & ~S_IFMT);
        !           524: X    sprintf(&hdr[108], "%06o \0", asb->sb_uid);
        !           525: X    sprintf(&hdr[116], "%06o \0", asb->sb_gid);
        !           526: X    sprintf(&hdr[124], "%011lo ", (long) asb->sb_size);
        !           527: X    sprintf(&hdr[136], "%011lo ", (long) asb->sb_mtime);
        !           528: X    strncpy(&hdr[148], "        ", 8);
        !           529: X    hdr[156] = tartype(asb->sb_mode);
        !           530: X    if (asb->sb_nlink > 1 && (from = linkfrom(name, asb)) != NULL) {
        !           531: X      strcpy(&hdr[157], from->l_name);
        !           532: X      hdr[156] = LNKTYPE;
        !           533: X    }
        !           534: X    strcpy(&hdr[257], TMAGIC);
        !           535: X    strncpy(&hdr[263], TVERSION, 2);
        !           536: X    strcpy(&hdr[265], finduname((int) asb->sb_uid));
        !           537: X    strcpy(&hdr[297], findgname((int) asb->sb_gid));
        !           538: X    sprintf(&hdr[329], "%06o \0", major(asb->sb_rdev));
        !           539: X    sprintf(&hdr[337], "%06o \0", minor(asb->sb_rdev));
        !           540: X    if (prefix != NULL) {
        !           541: X      strncpy(&hdr[345], prefix, 155);
        !           542: X    }
        !           543: X
        !           544: X    /* Calculate the checksum */
        !           545: X
        !           546: X    sum = 0;
        !           547: X    p = hdr;
        !           548: X    for (i = 0; i < 500; i++) {
        !           549: X      sum += 0xFF & *p++;
        !           550: X    }
        !           551: X
        !           552: X    /* Fill in the checksum field. */
        !           553: X
        !           554: X    sprintf(&hdr[148], "%06o \0", sum);
        !           555: X
        !           556: X    outwrite(hdr, BLOCKSIZE);
        !           557: X}
        !           558: X
        !           559: X
        !           560: X/* tartype - return tar file type from file mode
        !           561: X *
        !           562: X * DESCRIPTION
        !           563: X *
        !           564: X *    tartype returns the character which represents the type of file
        !           565: X *    indicated by "mode". 
        !           566: X *
        !           567: X * PARAMETERS
        !           568: X *
        !           569: X *    int     mode    - file mode from a stat block
        !           570: X *
        !           571: X * RETURNS
        !           572: X *
        !           573: X *    The character which represents the particular file type in the 
        !           574: X *    ustar standard headers.
        !           575: X */
        !           576: X
        !           577: X#ifdef __STDC__
        !           578: X
        !           579: Xstatic char tartype(int mode)
        !           580: X
        !           581: X#else
        !           582: X    
        !           583: Xstatic char tartype(mode)
        !           584: Xint       mode;
        !           585: X
        !           586: X#endif
        !           587: X{
        !           588: X    switch (mode & S_IFMT) {
        !           589: X
        !           590: X#ifdef S_IFCTG
        !           591: X    case S_IFCTG:
        !           592: X      return(CONTTYPE);
        !           593: X#endif
        !           594: X
        !           595: X    case S_IFDIR:
        !           596: X      return (DIRTYPE);
        !           597: X
        !           598: X#ifdef S_IFLNK
        !           599: X    case S_IFLNK:
        !           600: X      return (SYMTYPE);
        !           601: X#endif
        !           602: X
        !           603: X#ifdef S_IFFIFO
        !           604: X    case S_IFIFO:
        !           605: X      return (FIFOTYPE);
        !           606: X#endif
        !           607: X
        !           608: X#ifdef S_IFCHR
        !           609: X    case S_IFCHR:
        !           610: X      return (CHRTYPE);
        !           611: X#endif
        !           612: X
        !           613: X#ifdef S_IFBLK
        !           614: X    case S_IFBLK:
        !           615: X      return (BLKTYPE);
        !           616: X#endif
        !           617: X
        !           618: X    default:
        !           619: X      return (REGTYPE);
        !           620: X    }
        !           621: X}
        !           622: X
        !           623: X
        !           624: X/* writecpio - write a cpio archive header
        !           625: X *
        !           626: X * DESCRIPTION
        !           627: X *
        !           628: X *    Writes a new CPIO style archive header for the file specified.
        !           629: X *
        !           630: X * PARAMETERS
        !           631: X *
        !           632: X *    char    *name   - name of file to create a header block for
        !           633: X *    Stat    *asb    - pointer to the stat structure for the named file
        !           634: X */
        !           635: X
        !           636: X#ifdef __STDC__
        !           637: X
        !           638: Xstatic void writecpio(char *name, Stat *asb)
        !           639: X
        !           640: X#else
        !           641: X    
        !           642: Xstatic void writecpio(name, asb)
        !           643: Xchar           *name;
        !           644: XStat           *asb;
        !           645: X
        !           646: X#endif
        !           647: X{
        !           648: X    uint            namelen;
        !           649: X    char            header[M_STRLEN + H_STRLEN + 1];
        !           650: X
        !           651: X    namelen = (uint) strlen(name) + 1;
        !           652: X    strcpy(header, M_ASCII);
        !           653: X    sprintf(header + M_STRLEN, "%06o%06o%06o%06o%06o",
        !           654: X          USH(asb->sb_dev), USH(asb->sb_ino), USH(asb->sb_mode), 
        !           655: X          USH(asb->sb_uid), USH(asb->sb_gid));
        !           656: X    sprintf(header + M_STRLEN + 30, "%06o%06o%011lo%06o%011lo",
        !           657: X          USH(asb->sb_nlink), USH(asb->sb_rdev),
        !           658: X          f_modification_time ? asb->sb_mtime : time((time_t *) 0),
        !           659: X          namelen, asb->sb_size);
        !           660: X    outwrite(header, M_STRLEN + H_STRLEN);
        !           661: X    outwrite(name, namelen);
        !           662: X#ifdef        S_IFLNK
        !           663: X    if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
        !           664: X      outwrite(asb->sb_link, (uint) asb->sb_size);
        !           665: X    }
        !           666: X#endif        /* S_IFLNK */
        !           667: X}
        !           668: END_OF_create.c
        !           669: if test 7830 -ne `wc -c <create.c`; then
        !           670:     echo shar: \"create.c\" unpacked with wrong size!
        !           671: fi
        !           672: # end of overwriting check
        !           673: fi
        !           674: if test -f func.h -a "${1}" != "-c" ; then 
        !           675:   echo shar: Will not over-write existing file \"func.h\"
        !           676: else
        !           677: echo shar: Extracting \"func.h\" \(5047 characters\)
        !           678: sed "s/^X//" >func.h <<'END_OF_func.h'
        !           679: X/* $Source: /u/mark/src/pax/RCS/func.h,v $
        !           680: X *
        !           681: X * $Revision: 1.1 $
        !           682: X *
        !           683: X * func.h - function type and argument declarations
        !           684: X *
        !           685: X * DESCRIPTION
        !           686: X *
        !           687: X *    This file contains function delcarations in both ANSI style
        !           688: X *    (function prototypes) and traditional style. 
        !           689: X *
        !           690: X * AUTHOR
        !           691: X *
        !           692: X *     Mark H. Colburn, NAPS International ([email protected])
        !           693: X *
        !           694: X * Sponsored by The USENIX Association for public distribution. 
        !           695: X *
        !           696: X * Copyright (c) 1989 Mark H. Colburn.
        !           697: X * All rights reserved.
        !           698: X *
        !           699: X * Redistribution and use in source and binary forms are permitted
        !           700: X * provided that the above copyright notice and this paragraph are
        !           701: X * duplicated in all such forms and that any documentation,
        !           702: X * advertising materials, and other materials related to such
        !           703: X * distribution and use acknowledge that the software was developed
        !           704: X * by Mark H. Colburn and sponsored by The USENIX Association. 
        !           705: X *
        !           706: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !           707: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !           708: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !           709: X */
        !           710: X
        !           711: X#ifndef _PAX_FUNC_H
        !           712: X#define _PAX_FUNC_H
        !           713: X
        !           714: X/* Function Prototypes */
        !           715: X
        !           716: X#ifdef __STDC__
        !           717: X
        !           718: Xextern Link                  *linkfrom(char *, Stat *);
        !           719: Xextern Link                  *linkto(char *, Stat *);
        !           720: Xextern char                  *mem_get(uint);
        !           721: Xextern char                  *mem_str(char *);
        !           722: Xextern char                  *syserr(void);
        !           723: Xextern int            ar_read(void);
        !           724: Xextern int            buf_read(char *, uint);
        !           725: Xextern int            buf_skip(OFFSET);
        !           726: Xextern int            create_archive(void);
        !           727: Xextern int            dirneed(char *);
        !           728: Xextern int            read_archive(void);
        !           729: Xextern int            inentry(char *, Stat *);
        !           730: Xextern int            lineget(FILE *, char *);
        !           731: Xextern int            name_match(char *);
        !           732: Xextern int            name_next(char *, Stat *);
        !           733: Xextern int            nameopt(char *);
        !           734: Xextern int            open_archive(int);
        !           735: Xextern int            open_tty(void);
        !           736: Xextern int            openi(char *, Stat *);
        !           737: Xextern int            openo(char *, Stat *, Link *, int);
        !           738: Xextern int            pass(char *);
        !           739: Xextern int            passitem(char *, Stat *, int, char *);
        !           740: Xextern int            read_header(char *, Stat *);
        !           741: Xextern int            wildmat(char *, char *);
        !           742: Xextern void           buf_allocate(OFFSET);
        !           743: Xextern void           close_archive(void);
        !           744: Xextern void           fatal(char *);
        !           745: Xextern void           name_gather(void);
        !           746: Xextern void           name_init(int, char **);
        !           747: Xextern void           names_notfound(void);
        !           748: Xextern void           next(int);
        !           749: Xextern int            nextask(char *, char *, int);
        !           750: Xextern void           outdata(int, char *, OFFSET);
        !           751: Xextern void           outwrite(char *, uint);
        !           752: Xextern void           passdata(char *, int, char *, int);
        !           753: Xextern void           print_entry(char *, Stat *);
        !           754: Xextern void           warn();
        !           755: Xextern void           warnarch(char *, OFFSET);
        !           756: Xextern void           write_eot(void);
        !           757: Xextern void           get_archive_type(void);
        !           758: Xextern struct group    *getgrgid();
        !           759: Xextern struct group    *getgrnam();
        !           760: Xextern struct passwd   *getpwuid();
        !           761: Xextern char                  *getenv(char *);
        !           762: Xextern SIG_T                (*signal())();
        !           763: Xextern Link            *islink(char *, Stat *);
        !           764: Xextern char            *finduname(int);
        !           765: Xextern char            *findgname(int);
        !           766: Xextern int            findgid(char *gname);
        !           767: X
        !           768: X#else /* !__STDC__ */
        !           769: X
        !           770: Xextern Link                  *linkfrom();
        !           771: Xextern Link                  *linkto();
        !           772: Xextern char                  *mem_get();
        !           773: Xextern char                  *mem_str();
        !           774: Xextern char                  *syserr();
        !           775: Xextern int            ar_read();
        !           776: Xextern int            buf_read();
        !           777: Xextern int            buf_skip();
        !           778: Xextern int            create_archive();
        !           779: Xextern int            dirneed();
        !           780: Xextern int            read_archive();
        !           781: Xextern int            inentry();
        !           782: Xextern int            lineget();
        !           783: Xextern int            name_match();
        !           784: Xextern int            name_next();
        !           785: Xextern int            nameopt();
        !           786: Xextern int            open_archive();
        !           787: Xextern int            open_tty();
        !           788: Xextern int            openi();
        !           789: Xextern int            openo();
        !           790: Xextern int            pass();
        !           791: Xextern int            passitem();
        !           792: Xextern int                    read_header();
        !           793: Xextern int            wildmat();
        !           794: Xextern void           buf_allocate();
        !           795: Xextern void           close_archive();
        !           796: Xextern void           fatal();
        !           797: Xextern void           name_gather();
        !           798: Xextern void           name_init();
        !           799: Xextern void           names_notfound();
        !           800: Xextern void           next();
        !           801: Xextern int            nextask();
        !           802: Xextern void           outdata();
        !           803: Xextern void           outwrite();
        !           804: Xextern void           passdata();
        !           805: Xextern void           print_entry();
        !           806: Xextern void           warn();
        !           807: Xextern void           warnarch();
        !           808: Xextern void           write_eot();
        !           809: Xextern void           get_archive_type();
        !           810: Xextern char                  *getenv();
        !           811: Xextern char                  *malloc();
        !           812: Xextern char                  *strcat();
        !           813: Xextern char                  *strcpy();
        !           814: Xextern char                  *strncpy();
        !           815: Xextern SIG_T                (*signal())();
        !           816: Xextern OFFSET         lseek();
        !           817: Xextern struct group    *getgrgid();
        !           818: Xextern struct group    *getgrnam();
        !           819: Xextern struct passwd   *getpwuid();
        !           820: Xextern struct tm       *localtime();
        !           821: Xextern time_t                 time();
        !           822: Xextern uint                   sleep();
        !           823: Xextern void                   _exit();
        !           824: Xextern void                   exit();
        !           825: Xextern void                   free();
        !           826: Xextern Link            *islink();
        !           827: Xextern char            *finduname();
        !           828: Xextern char            *findgname();
        !           829: Xextern int            findgid();
        !           830: X
        !           831: X#endif /* __STDC__ */
        !           832: X#endif /* _PAX_FUNC_H */
        !           833: END_OF_func.h
        !           834: if test 5047 -ne `wc -c <func.h`; then
        !           835:     echo shar: \"func.h\" unpacked with wrong size!
        !           836: fi
        !           837: # end of overwriting check
        !           838: fi
        !           839: if test -f link.c -a "${1}" != "-c" ; then 
        !           840:   echo shar: Will not over-write existing file \"link.c\"
        !           841: else
        !           842: echo shar: Extracting \"link.c\" \(7575 characters\)
        !           843: sed "s/^X//" >link.c <<'END_OF_link.c'
        !           844: X/* $Source: /u/mark/src/pax/RCS/link.c,v $
        !           845: X *
        !           846: X * $Revision: 1.1 $
        !           847: X *
        !           848: X * link.c - functions for handling multiple file links 
        !           849: X *
        !           850: X * DESCRIPTION
        !           851: X *
        !           852: X *    These function manage the link chains which are used to keep track
        !           853: X *    of outstanding links during archive reading and writing.
        !           854: X *
        !           855: X * AUTHOR
        !           856: X *
        !           857: X *    Mark H. Colburn, NAPS International ([email protected])
        !           858: X *
        !           859: X * Sponsored by The USENIX Association for public distribution. 
        !           860: X *
        !           861: X * Copyright (c) 1989 Mark H. Colburn.
        !           862: X * All rights reserved.
        !           863: X *
        !           864: X * Redistribution and use in source and binary forms are permitted
        !           865: X * provided that the above copyright notice is duplicated in all such 
        !           866: X * forms and that any documentation, advertising materials, and other 
        !           867: X * materials related to such distribution and use acknowledge that the 
        !           868: X * software was developed * by Mark H. Colburn and sponsored by The 
        !           869: X * USENIX Association. 
        !           870: X *
        !           871: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !           872: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !           873: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !           874: X *
        !           875: X * $Log:      link.c,v $
        !           876: X * Revision 1.1  88/12/23  18:02:12  mark
        !           877: X * Initial revision
        !           878: X * 
        !           879: X */
        !           880: X
        !           881: X#ifndef lint
        !           882: Xstatic char *ident = "$Id: link.c,v 1.1 88/12/23 18:02:12 mark Rel $";
        !           883: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
        !           884: X#endif /* ! lint */
        !           885: X
        !           886: X
        !           887: X/* Headers */
        !           888: X
        !           889: X#include "pax.h"
        !           890: X
        !           891: X
        !           892: X/* Defines */
        !           893: X
        !           894: X/*
        !           895: X * Address link information base. 
        !           896: X */
        !           897: X#define       LINKHASH(ino)   (linkbase + (ino) % NEL(linkbase))
        !           898: X
        !           899: X/*
        !           900: X * Number of array elements. 
        !           901: X */
        !           902: X#define       NEL(a)          (sizeof(a) / sizeof(*(a)))
        !           903: X
        !           904: X
        !           905: X
        !           906: X/* Internal Identifiers */
        !           907: X
        !           908: Xstatic Link    *linkbase[256];        /* Unresolved link information */
        !           909: X
        !           910: X
        !           911: X/* linkfrom - find a file to link from 
        !           912: X *
        !           913: X * DESCRIPTION
        !           914: X *
        !           915: X *    Linkfrom searches the link chain to see if there is a file in the
        !           916: X *    link chain which has the same inode number as the file specified
        !           917: X *    by the stat block pointed at by asb.  If a file is found, the
        !           918: X *    name is returned to the caller, otherwise a NULL is returned.
        !           919: X *
        !           920: X * PARAMETERS
        !           921: X *
        !           922: X *    char    *name   - name of the file which we are attempting
        !           923: X *                        to find a link for
        !           924: X *    Stat    *asb    - stat structure of file to find a link to
        !           925: X *
        !           926: X * RETURNS
        !           927: X *
        !           928: X *    Returns a pointer to a link structure, or NULL if unsuccessful. 
        !           929: X *
        !           930: X */
        !           931: X
        !           932: X#ifdef __STDC__
        !           933: X
        !           934: XLink *linkfrom(char *name, Stat *asb)
        !           935: X
        !           936: X#else
        !           937: X    
        !           938: XLink *linkfrom(name, asb)
        !           939: Xchar           *name;
        !           940: XStat           *asb;
        !           941: X
        !           942: X#endif
        !           943: X{
        !           944: X    Link           *linkp;
        !           945: X    Link           *linknext;
        !           946: X    Path           *path;
        !           947: X    Path           *pathnext;
        !           948: X    Link          **abase;
        !           949: X
        !           950: X    for (linkp = *(abase = LINKHASH(asb->sb_ino)); linkp; linkp = linknext) {
        !           951: X      if (linkp->l_nlink == 0) {
        !           952: X          if (linkp->l_name) {
        !           953: X              free((char *) linkp->l_name);
        !           954: X          }
        !           955: X          if (linknext = linkp->l_forw) {
        !           956: X              linknext->l_back = linkp->l_back;
        !           957: X          }
        !           958: X          if (linkp->l_back) {
        !           959: X              linkp->l_back->l_forw = linkp->l_forw;
        !           960: X          }
        !           961: X          free((char *) linkp);
        !           962: X          *abase = (Link *) NULL;
        !           963: X      } else if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
        !           964: X          /* 
        !           965: X           * check to see if a file with the name "name" exists in the 
        !           966: X           * chain of files which we have for this particular link
        !           967: X           */
        !           968: X          for (path = linkp->l_path; path; path = pathnext) {
        !           969: X              if (strcmp(path->p_name, name) == 0) {
        !           970: X                  --linkp->l_nlink;
        !           971: X                  if (path->p_name) {
        !           972: X                      free(path->p_name);
        !           973: X                  }
        !           974: X                  if (pathnext = path->p_forw) {
        !           975: X                      pathnext->p_back = path->p_back;
        !           976: X                  }
        !           977: X                  if (path->p_back) {
        !           978: X                      path->p_back->p_forw = pathnext;
        !           979: X                  }
        !           980: X                  if (linkp->l_path == path) {
        !           981: X                      linkp->l_path = pathnext;
        !           982: X                  }
        !           983: X                  free(path);
        !           984: X                  return (linkp);
        !           985: X              }
        !           986: X              pathnext = path->p_forw;
        !           987: X          }
        !           988: X          return((Link *)NULL);
        !           989: X      } else {
        !           990: X          linknext = linkp->l_forw;
        !           991: X      }
        !           992: X    }
        !           993: X    return ((Link *)NULL);
        !           994: X}
        !           995: X
        !           996: X
        !           997: X
        !           998: X/* islink - determine whether a given file really a link
        !           999: X *
        !          1000: X * DESCRIPTION
        !          1001: X *
        !          1002: X *    Islink searches the link chain to see if there is a file in the
        !          1003: X *    link chain which has the same inode number as the file specified
        !          1004: X *    by the stat block pointed at by asb.  If a file is found, a
        !          1005: X *    non-zero value is returned to the caller, otherwise a 0 is
        !          1006: X *    returned.
        !          1007: X *
        !          1008: X * PARAMETERS
        !          1009: X *
        !          1010: X *    char    *name   - name of file to check to see if it is link.
        !          1011: X *    Stat    *asb    - stat structure of file to find a link to
        !          1012: X *
        !          1013: X * RETURNS
        !          1014: X *
        !          1015: X *    Returns a pointer to a link structure, or NULL if unsuccessful. 
        !          1016: X *
        !          1017: X */
        !          1018: X
        !          1019: X#ifdef __STDC__
        !          1020: X
        !          1021: XLink *islink(char *name, Stat *asb)
        !          1022: X
        !          1023: X#else
        !          1024: X    
        !          1025: XLink *islink(name, asb)
        !          1026: Xchar           *name;
        !          1027: XStat           *asb;
        !          1028: X
        !          1029: X#endif
        !          1030: X{
        !          1031: X    Link           *linkp;
        !          1032: X    Link           *linknext;
        !          1033: X
        !          1034: X    for (linkp = *(LINKHASH(asb->sb_ino)); linkp; linkp = linknext) {
        !          1035: X      if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
        !          1036: X          if (strcmp(name, linkp->l_name) == 0) {
        !          1037: X              return ((Link *) NULL);
        !          1038: X          } 
        !          1039: X          return (linkp);
        !          1040: X      } else {
        !          1041: X          linknext = linkp->l_forw;
        !          1042: X      }
        !          1043: X    }
        !          1044: X    return ((Link *)NULL);
        !          1045: X}
        !          1046: X
        !          1047: X
        !          1048: X/* linkto  - remember a file with outstanding links 
        !          1049: X *
        !          1050: X * DESCRIPTION
        !          1051: X *
        !          1052: X *    Linkto adds the specified file to the link chain.  Any subsequent
        !          1053: X *    calls to linkfrom which have the same inode will match the file
        !          1054: X *    just entered.  If not enough space is available to make the link
        !          1055: X *    then the item is not added to the link chain, and a NULL is
        !          1056: X *    returned to the calling function.
        !          1057: X *
        !          1058: X * PARAMETERS
        !          1059: X *
        !          1060: X *    char    *name   - name of file to remember
        !          1061: X *    Stat    *asb    - pointer to stat structure of file to remember
        !          1062: X *
        !          1063: X * RETURNS
        !          1064: X *
        !          1065: X *    Returns a pointer to the associated link structure, or NULL when 
        !          1066: X *    linking is not possible. 
        !          1067: X *
        !          1068: X */
        !          1069: X
        !          1070: X#ifdef __STDC__
        !          1071: X
        !          1072: XLink *linkto(char *name, Stat *asb)
        !          1073: X
        !          1074: X#else
        !          1075: X    
        !          1076: XLink *linkto(name, asb)
        !          1077: Xchar           *name;
        !          1078: XStat           *asb;
        !          1079: X
        !          1080: X#endif
        !          1081: X{
        !          1082: X    Link           *linkp;
        !          1083: X    Link           *linknext;
        !          1084: X    Path           *path;
        !          1085: X    Link          **abase;
        !          1086: X
        !          1087: X    for (linkp = *(LINKHASH(asb->sb_ino)); linkp; linkp = linknext) {
        !          1088: X      if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
        !          1089: X          if ((path = (Path *) mem_get(sizeof(Path))) == (Path *) NULL || 
        !          1090: X              (path->p_name = mem_str(name)) == (char *) NULL) {
        !          1091: X              return((Link *) NULL);
        !          1092: X          }
        !          1093: X          if (path->p_forw = linkp->l_path) {
        !          1094: X              if (linkp->l_path->p_forw) {
        !          1095: X                  linkp->l_path->p_forw->p_back = path;
        !          1096: X              }
        !          1097: X          } else {
        !          1098: X              linkp->l_path = path;
        !          1099: X          }
        !          1100: X          path->p_back = (Path *) NULL;
        !          1101: X          return(linkp);
        !          1102: X      } else {
        !          1103: X          linknext = linkp->l_forw;
        !          1104: X      }
        !          1105: X    }
        !          1106: X    /*
        !          1107: X     * This is a brand new link, for which there is no other information
        !          1108: X     */
        !          1109: X
        !          1110: X    if ((asb->sb_mode & S_IFMT) == S_IFDIR
        !          1111: X      || (linkp = (Link *) mem_get(sizeof(Link))) == NULL
        !          1112: X      || (linkp->l_name = mem_str(name)) == NULL) {
        !          1113: X      return ((Link *) NULL);
        !          1114: X    }
        !          1115: X    linkp->l_dev = asb->sb_dev;
        !          1116: X    linkp->l_ino = asb->sb_ino;
        !          1117: X    linkp->l_nlink = asb->sb_nlink - 1;
        !          1118: X    linkp->l_size = asb->sb_size;
        !          1119: X    linkp->l_path = (Path *) NULL;
        !          1120: X    if (linkp->l_forw = *(abase = LINKHASH(asb->sb_ino))) {
        !          1121: X      linkp->l_forw->l_back = linkp;
        !          1122: X    } else {
        !          1123: X      *abase = linkp;
        !          1124: X    }
        !          1125: X    linkp->l_back = NULL;
        !          1126: X    return (linkp);
        !          1127: X}
        !          1128: X
        !          1129: X
        !          1130: X/* linkleft - complain about files with unseen links 
        !          1131: X *
        !          1132: X * DESCRIPTION
        !          1133: X *
        !          1134: X *    Linksleft scans through the link chain to see if there were any
        !          1135: X *    files which have outstanding links that were not processed by the
        !          1136: X *    archive.  For each file in the link chain for which there was not
        !          1137: X *    a file,  and error message is printed.
        !          1138: X */
        !          1139: X
        !          1140: X#ifdef __STDC__
        !          1141: X
        !          1142: Xvoid linkleft(void)
        !          1143: X
        !          1144: X#else
        !          1145: X    
        !          1146: Xvoid linkleft()
        !          1147: X
        !          1148: X#endif
        !          1149: X{
        !          1150: X    Link           *lp;
        !          1151: X    Link          **base;
        !          1152: X
        !          1153: X    for (base = linkbase; base < linkbase + NEL(linkbase); ++base) {
        !          1154: X      for (lp = *base; lp; lp = lp->l_forw) {
        !          1155: X          if (lp->l_nlink) {
        !          1156: X              warn(lp->l_path->p_name, "Unseen link(s)");
        !          1157: X          }
        !          1158: X      }
        !          1159: X    }
        !          1160: X}
        !          1161: END_OF_link.c
        !          1162: if test 7575 -ne `wc -c <link.c`; then
        !          1163:     echo shar: \"link.c\" unpacked with wrong size!
        !          1164: fi
        !          1165: # end of overwriting check
        !          1166: fi
        !          1167: if test -f names.c -a "${1}" != "-c" ; then 
        !          1168:   echo shar: Will not over-write existing file \"names.c\"
        !          1169: else
        !          1170: echo shar: Extracting \"names.c\" \(5005 characters\)
        !          1171: sed "s/^X//" >names.c <<'END_OF_names.c'
        !          1172: X/* $Source: /u/mark/src/pax/RCS/names.c,v $
        !          1173: X *
        !          1174: X * $Revision: 1.1 $
        !          1175: X *
        !          1176: X * names.c - Look up user and/or group names. 
        !          1177: X *
        !          1178: X * DESCRIPTION
        !          1179: X *
        !          1180: X *    These functions support UID and GID name lookup.  The results are
        !          1181: X *    cached to improve performance.
        !          1182: X *
        !          1183: X * AUTHOR
        !          1184: X *
        !          1185: X *    Mark H. Colburn, NAPS International ([email protected])
        !          1186: X *
        !          1187: X * Sponsored by The USENIX Association for public distribution. 
        !          1188: X *
        !          1189: X * Copyright (c) 1989 Mark H. Colburn.
        !          1190: X * All rights reserved.
        !          1191: X *
        !          1192: X * Redistribution and use in source and binary forms are permitted
        !          1193: X * provided that the above copyright notice is duplicated in all such 
        !          1194: X * forms and that any documentation, advertising materials, and other 
        !          1195: X * materials related to such distribution and use acknowledge that the 
        !          1196: X * software was developed * by Mark H. Colburn and sponsored by The 
        !          1197: X * USENIX Association. 
        !          1198: X *
        !          1199: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !          1200: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !          1201: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !          1202: X *
        !          1203: X * $Log:      names.c,v $
        !          1204: X * Revision 1.1  88/12/23  18:02:19  mark
        !          1205: X * Initial revision
        !          1206: X * 
        !          1207: X */
        !          1208: X
        !          1209: X#ifndef lint
        !          1210: Xstatic char *ident = "$Id: names.c,v 1.1 88/12/23 18:02:19 mark Rel $";
        !          1211: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
        !          1212: X#endif /* ! lint */
        !          1213: X
        !          1214: X
        !          1215: X/* Headers */
        !          1216: X
        !          1217: X#include "pax.h"
        !          1218: X
        !          1219: X
        !          1220: X/* Defines */
        !          1221: X
        !          1222: X#define myuid ( my_uid < 0? (my_uid = getuid()): my_uid )
        !          1223: X#define       mygid   ( my_gid < 0? (my_gid = getgid()): my_gid )
        !          1224: X
        !          1225: X
        !          1226: X/* Internal Identifiers */
        !          1227: X
        !          1228: Xstatic int      saveuid = -993;
        !          1229: Xstatic char     saveuname[TUNMLEN];
        !          1230: Xstatic int      my_uid = -993;
        !          1231: X
        !          1232: Xstatic int      savegid = -993;
        !          1233: Xstatic char     savegname[TGNMLEN];
        !          1234: Xstatic int      my_gid = -993;
        !          1235: X
        !          1236: X
        !          1237: X/* finduname - find a user or group name from a uid or gid
        !          1238: X *
        !          1239: X * DESCRIPTION
        !          1240: X *
        !          1241: X *    Look up a user name from a uid/gid, maintaining a cache. 
        !          1242: X *
        !          1243: X * PARAMETERS
        !          1244: X *
        !          1245: X *    char    uname[]         - name (to be returned to user)
        !          1246: X *    int     uuid            - id of name to find
        !          1247: X *
        !          1248: X *
        !          1249: X * RETURNS
        !          1250: X *
        !          1251: X *    Returns a name which is associated with the user id given.  If there
        !          1252: X *    is not name which corresponds to the user-id given, then a pointer
        !          1253: X *    to a string of zero length is returned.
        !          1254: X *    
        !          1255: X * FIXME
        !          1256: X *
        !          1257: X *    1. for now it's a one-entry cache. 
        !          1258: X *    2. The "-993" is to reduce the chance of a hit on the first lookup. 
        !          1259: X */
        !          1260: X
        !          1261: X#ifdef __STDC__
        !          1262: X
        !          1263: Xchar *finduname(int uuid)
        !          1264: X
        !          1265: X#else
        !          1266: X    
        !          1267: Xchar *finduname(uuid)
        !          1268: Xint             uuid;
        !          1269: X
        !          1270: X#endif
        !          1271: X{
        !          1272: X    struct passwd  *pw;
        !          1273: X
        !          1274: X    if (uuid != saveuid) {
        !          1275: X      saveuid = uuid;
        !          1276: X      saveuname[0] = '\0';
        !          1277: X      pw = getpwuid(uuid);
        !          1278: X      if (pw) {
        !          1279: X          strncpy(saveuname, pw->pw_name, TUNMLEN);
        !          1280: X      }
        !          1281: X    }
        !          1282: X    return(saveuname);
        !          1283: X}
        !          1284: X
        !          1285: X
        !          1286: X/* finduid - get the uid for a given user name
        !          1287: X *
        !          1288: X * DESCRIPTION
        !          1289: X *
        !          1290: X *    This does just the opposit of finduname.  Given a user name it
        !          1291: X *    finds the corresponding UID for that name.
        !          1292: X *
        !          1293: X * PARAMETERS
        !          1294: X *
        !          1295: X *    char    uname[]         - username to find a UID for
        !          1296: X *
        !          1297: X * RETURNS
        !          1298: X *
        !          1299: X *    The UID which corresponds to the uname given, if any.  If no UID
        !          1300: X *    could be found, then the UID which corrsponds the user running the
        !          1301: X *    program is returned.
        !          1302: X *
        !          1303: X */
        !          1304: X
        !          1305: X#ifdef __STDC__
        !          1306: X
        !          1307: Xint finduid(char *uname)
        !          1308: X
        !          1309: X#else
        !          1310: X    
        !          1311: Xint finduid(uname)
        !          1312: Xchar            *uname;
        !          1313: X
        !          1314: X#endif
        !          1315: X{
        !          1316: X    struct passwd  *pw;
        !          1317: X    extern struct passwd *getpwnam();
        !          1318: X
        !          1319: X    if (uname[0] != saveuname[0]/* Quick test w/o proc call */
        !          1320: X      ||0 != strncmp(uname, saveuname, TUNMLEN)) {
        !          1321: X      strncpy(saveuname, uname, TUNMLEN);
        !          1322: X      pw = getpwnam(uname);
        !          1323: X      if (pw) {
        !          1324: X          saveuid = pw->pw_uid;
        !          1325: X      } else {
        !          1326: X          saveuid = myuid;
        !          1327: X      }
        !          1328: X    }
        !          1329: X    return (saveuid);
        !          1330: X}
        !          1331: X
        !          1332: X
        !          1333: X/* findgname - look up a group name from a gid
        !          1334: X *
        !          1335: X * DESCRIPTION
        !          1336: X *
        !          1337: X *    Look up a group name from a gid, maintaining a cache.
        !          1338: X *    
        !          1339: X *
        !          1340: X * PARAMETERS
        !          1341: X *
        !          1342: X *    int     ggid            - goupid of group to find
        !          1343: X *
        !          1344: X * RETURNS
        !          1345: X *
        !          1346: X *    A string which is associated with the group ID given.  If no name
        !          1347: X *    can be found, a string of zero length is returned.
        !          1348: X */
        !          1349: X
        !          1350: X#ifdef __STDC__
        !          1351: X
        !          1352: Xchar *findgname(int ggid)
        !          1353: X
        !          1354: X#else
        !          1355: X    
        !          1356: Xchar *findgname(ggid)
        !          1357: Xint             ggid;
        !          1358: X
        !          1359: X#endif
        !          1360: X{
        !          1361: X    struct group   *gr;
        !          1362: X
        !          1363: X    if (ggid != savegid) {
        !          1364: X      savegid = ggid;
        !          1365: X      savegname[0] = '\0';
        !          1366: X      setgrent();
        !          1367: X      gr = getgrgid(ggid);
        !          1368: X      if (gr) {
        !          1369: X          strncpy(savegname, gr->gr_name, TGNMLEN);
        !          1370: X      }
        !          1371: X    }
        !          1372: X    return(savegname);
        !          1373: X}
        !          1374: X
        !          1375: X
        !          1376: X
        !          1377: X/* findgid - get the gid for a given group name
        !          1378: X *
        !          1379: X * DESCRIPTION
        !          1380: X *
        !          1381: X *    This does just the opposit of finduname.  Given a group name it
        !          1382: X *    finds the corresponding GID for that name.
        !          1383: X *
        !          1384: X * PARAMETERS
        !          1385: X *
        !          1386: X *    char    uname[]         - groupname to find a GID for
        !          1387: X *
        !          1388: X * RETURNS
        !          1389: X *
        !          1390: X *    The GID which corresponds to the uname given, if any.  If no GID
        !          1391: X *    could be found, then the GID which corrsponds the group running the
        !          1392: X *    program is returned.
        !          1393: X *
        !          1394: X */
        !          1395: X
        !          1396: X#ifdef __STDC__
        !          1397: X
        !          1398: Xint findgid(char *gname)
        !          1399: X
        !          1400: X#else
        !          1401: X    
        !          1402: Xint findgid(gname)
        !          1403: Xchar           *gname;
        !          1404: X
        !          1405: X#endif
        !          1406: X{
        !          1407: X    struct group   *gr;
        !          1408: X
        !          1409: X    /* Quick test w/o proc call */
        !          1410: X    if (gname[0] != savegname[0] || strncmp(gname, savegname, TUNMLEN) != 0) {
        !          1411: X      strncpy(savegname, gname, TUNMLEN);
        !          1412: X      gr = getgrnam(gname);
        !          1413: X      if (gr) {
        !          1414: X          savegid = gr->gr_gid;
        !          1415: X      } else {
        !          1416: X          savegid = mygid;
        !          1417: X      }
        !          1418: X    }
        !          1419: X    return (savegid);
        !          1420: X}
        !          1421: END_OF_names.c
        !          1422: if test 5005 -ne `wc -c <names.c`; then
        !          1423:     echo shar: \"names.c\" unpacked with wrong size!
        !          1424: fi
        !          1425: # end of overwriting check
        !          1426: fi
        !          1427: if test -f replace.c -a "${1}" != "-c" ; then 
        !          1428:   echo shar: Will not over-write existing file \"replace.c\"
        !          1429: else
        !          1430: echo shar: Extracting \"replace.c\" \(6493 characters\)
        !          1431: sed "s/^X//" >replace.c <<'END_OF_replace.c'
        !          1432: X/* $Source: /u/mark/src/pax/RCS/replace.c,v $
        !          1433: X *
        !          1434: X * $Revision: 1.1 $
        !          1435: X *
        !          1436: X * replace.c - regular expression pattern replacement functions
        !          1437: X *
        !          1438: X * DESCRIPTION
        !          1439: X *
        !          1440: X *    These routines provide for regular expression file name replacement
        !          1441: X *    as required by pax.
        !          1442: X *
        !          1443: X * AUTHORS
        !          1444: X *
        !          1445: X *    Mark H. Colburn, NAPS International
        !          1446: X *
        !          1447: X * Sponsored by The USENIX Association for public distribution. 
        !          1448: X *
        !          1449: X * Copyright (c) 1989 Mark H. Colburn.
        !          1450: X * All rights reserved.
        !          1451: X *
        !          1452: X * Redistribution and use in source and binary forms are permitted
        !          1453: X * provided that the above copyright notice is duplicated in all such 
        !          1454: X * forms and that any documentation, advertising materials, and other 
        !          1455: X * materials related to such distribution and use acknowledge that the 
        !          1456: X * software was developed * by Mark H. Colburn and sponsored by The 
        !          1457: X * USENIX Association. 
        !          1458: X *
        !          1459: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !          1460: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !          1461: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !          1462: X *
        !          1463: X * $Log:      replace.c,v $
        !          1464: X * Revision 1.1  88/12/23  18:02:36  mark
        !          1465: X * Initial revision
        !          1466: X * 
        !          1467: X */
        !          1468: X
        !          1469: X#ifndef lint
        !          1470: Xstatic char *ident = "$Id: replace.c,v 1.1 88/12/23 18:02:36 mark Rel $";
        !          1471: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
        !          1472: X#endif /* not lint */
        !          1473: X
        !          1474: X/* Headers */
        !          1475: X
        !          1476: X#include "pax.h"
        !          1477: X
        !          1478: X
        !          1479: X/* add_replstr - add a replacement string to the replacement string list
        !          1480: X *
        !          1481: X * DESCRIPTION
        !          1482: X *
        !          1483: X *    Add_replstr adds a replacement string to the replacement string
        !          1484: X *    list which is applied each time a file is about to be processed.
        !          1485: X *
        !          1486: X * PARAMETERS
        !          1487: X *
        !          1488: X *    char    *pattern        - A regular expression which is to be parsed
        !          1489: X */
        !          1490: X
        !          1491: X#ifdef __STDC__
        !          1492: X
        !          1493: Xvoid add_replstr(char *pattern)
        !          1494: X
        !          1495: X#else
        !          1496: X
        !          1497: Xvoid add_replstr(pattern)
        !          1498: Xchar           *pattern;
        !          1499: X
        !          1500: X#endif
        !          1501: X{
        !          1502: X    char           *p;
        !          1503: X    char            sep;
        !          1504: X    Replstr        *rptr;
        !          1505: X    int             len;
        !          1506: X
        !          1507: X    if ((len = strlen(pattern)) < 4) {
        !          1508: X      warn("Replacement string not added",
        !          1509: X               "Malformed substitution syntax");
        !          1510: X      return;
        !          1511: X    }
        !          1512: X    if ((rptr = (Replstr *) malloc(sizeof(Replstr))) == NULL) {
        !          1513: X      warn("Replacement string not added", "No space");
        !          1514: X      return;
        !          1515: X    }
        !          1516: X
        !          1517: X    /* First character is the delimeter... */
        !          1518: X    sep = *pattern;
        !          1519: X
        !          1520: X    /* Get trailing g and/or p */
        !          1521: X    p = pattern + len - 1;
        !          1522: X    while (*p != sep) {
        !          1523: X      if (*p == 'g') {
        !          1524: X            rptr->global = 1;
        !          1525: X      } else if (*p == 'p') {
        !          1526: X          rptr->print = 1;
        !          1527: X      } else {
        !          1528: X          warn(p, "Invalid RE modifier");
        !          1529: X      }
        !          1530: X      p--;
        !          1531: X    }
        !          1532: X
        !          1533: X    if (*p != sep) {
        !          1534: X      warn("Replacement string not added", "Bad delimeters");
        !          1535: X      free(rptr);
        !          1536: X      return;
        !          1537: X    }
        !          1538: X    /* strip off leading and trailing delimeter */
        !          1539: X    *p = '\0';
        !          1540: X    pattern++;
        !          1541: X
        !          1542: X    /* find the separating '/' in the pattern */
        !          1543: X    p = pattern;
        !          1544: X    while (*p) {
        !          1545: X      if (*p == sep) {
        !          1546: X          break;
        !          1547: X      }
        !          1548: X      if (*p == '\\' && *(p + 1) != '\0') {
        !          1549: X          p++;
        !          1550: X      }
        !          1551: X      p++;
        !          1552: X    }
        !          1553: X    if (*p != sep) {
        !          1554: X      warn("Replacement string not added", "Bad delimeters");
        !          1555: X      free(rptr);
        !          1556: X      return;
        !          1557: X    }
        !          1558: X    *p++ = '\0';
        !          1559: X
        !          1560: X    /*
        !          1561: X     * Now pattern points to 'old' and p points to 'new' and both are '\0'
        !          1562: X     * terminated 
        !          1563: X     */
        !          1564: X    if ((rptr->comp = regcomp(pattern)) == NULL) {
        !          1565: X      warn("Replacement string not added", "Invalid RE");
        !          1566: X      free(rptr);
        !          1567: X      return;
        !          1568: X    }
        !          1569: X    rptr->replace = p;
        !          1570: X    rptr->next = NULL;
        !          1571: X    if (rplhead == NULL) {
        !          1572: X      rplhead = rptr;
        !          1573: X      rpltail = rptr;
        !          1574: X    } else {
        !          1575: X      rpltail->next = rptr;
        !          1576: X      rpltail = rptr;
        !          1577: X    }
        !          1578: X}
        !          1579: X
        !          1580: X
        !          1581: X
        !          1582: X/* rpl_name - possibly replace a name with a regular expression
        !          1583: X *
        !          1584: X * DESCRIPTION
        !          1585: X *
        !          1586: X *    The string name is searched for in the list of regular expression
        !          1587: X *    substituions.  If the string matches any of the regular expressions
        !          1588: X *    then the string is modified as specified by the user.
        !          1589: X *
        !          1590: X * PARAMETERS
        !          1591: X *
        !          1592: X *    char    *name   - name to search for and possibly modify
        !          1593: X */
        !          1594: X
        !          1595: X#ifdef __STDC__
        !          1596: X
        !          1597: Xvoid rpl_name(char *name)
        !          1598: X
        !          1599: X#else
        !          1600: X
        !          1601: Xvoid rpl_name(name)
        !          1602: Xchar           *name;
        !          1603: X
        !          1604: X#endif
        !          1605: X{
        !          1606: X    int             found = 0;
        !          1607: X    int             ret;
        !          1608: X    Replstr        *rptr;
        !          1609: X    char            buff[PATH_MAX + 1];
        !          1610: X    char            buff1[PATH_MAX + 1];
        !          1611: X    char            buff2[PATH_MAX + 1];
        !          1612: X    char           *p;
        !          1613: X    char           *b;
        !          1614: X
        !          1615: X    strcpy(buff, name);
        !          1616: X    for (rptr = rplhead; !found && rptr != NULL; rptr = rptr->next) {
        !          1617: X      do {
        !          1618: X          if ((ret = regexec(rptr->comp, buff)) != 0) {
        !          1619: X              p = buff;
        !          1620: X              b = buff1;
        !          1621: X              while (p < rptr->comp->startp[0]) {
        !          1622: X                  *b++ = *p++;
        !          1623: X              }
        !          1624: X              p = rptr->replace;
        !          1625: X              while (*p) {
        !          1626: X                  *b++ = *p++;
        !          1627: X              }
        !          1628: X              strcpy(b, rptr->comp->endp[0]);
        !          1629: X              found = 1;
        !          1630: X              regsub(rptr->comp, buff1, buff2);
        !          1631: X              strcpy(buff, buff2);
        !          1632: X          }
        !          1633: X      } while (ret && rptr->global);
        !          1634: X      if (found) {
        !          1635: X          if (rptr->print) {
        !          1636: X              fprintf(stderr, "%s >> %s\n", name, buff);
        !          1637: X          }
        !          1638: X          strcpy(name, buff);
        !          1639: X      }
        !          1640: X    }
        !          1641: X}
        !          1642: X
        !          1643: X
        !          1644: X/* get_disposition - get a file disposition
        !          1645: X *
        !          1646: X * DESCRIPTION
        !          1647: X *
        !          1648: X *    Get a file disposition from the user.  If the user enters 'y'
        !          1649: X *    the the file is processed, anything else and the file is ignored.
        !          1650: X *    If the user enters EOF, then the PAX exits with a non-zero return
        !          1651: X *    status.
        !          1652: X *
        !          1653: X * PARAMETERS
        !          1654: X *
        !          1655: X *    char    *mode   - string signifying the action to be taken on file
        !          1656: X *    char    *name   - the name of the file
        !          1657: X *
        !          1658: X * RETURNS
        !          1659: X *
        !          1660: X *    Returns 1 if the file should be processed, 0 if it should not.
        !          1661: X */
        !          1662: X
        !          1663: X#ifdef __STDC__
        !          1664: X
        !          1665: Xint get_disposition(char *mode, char *name)
        !          1666: X
        !          1667: X#else
        !          1668: X
        !          1669: Xint get_disposition(mode, name)
        !          1670: Xchar  *mode;
        !          1671: Xchar  *name;
        !          1672: X
        !          1673: X#endif
        !          1674: X{
        !          1675: X    char      ans[2];
        !          1676: X    char      buf[PATH_MAX + 10];
        !          1677: X
        !          1678: X    if (f_disposition) {
        !          1679: X      sprintf(buf, "%s %s? ", mode, name);
        !          1680: X      if (nextask(buf, ans, sizeof(ans)) == -1 || ans[0] == 'q') {
        !          1681: X          exit(0);
        !          1682: X      }
        !          1683: X      if (strlen(ans) == 0 || ans[0] != 'y') {
        !          1684: X          return(1);
        !          1685: X      } 
        !          1686: X    } 
        !          1687: X    return(0);
        !          1688: X}
        !          1689: X
        !          1690: X
        !          1691: X/* get_newname - prompt the user for a new filename
        !          1692: X *
        !          1693: X * DESCRIPTION
        !          1694: X *
        !          1695: X *    The user is prompted with the name of the file which is currently
        !          1696: X *    being processed.  The user may choose to rename the file by
        !          1697: X *    entering the new file name after the prompt; the user may press
        !          1698: X *    carriage-return/newline, which will skip the file or the user may
        !          1699: X *    type an 'EOF' character, which will cause the program to stop.
        !          1700: X *
        !          1701: X * PARAMETERS
        !          1702: X *
        !          1703: X *    char    *name           - filename, possibly modified by user
        !          1704: X *    int     size            - size of allowable new filename
        !          1705: X *
        !          1706: X * RETURNS
        !          1707: X *
        !          1708: X *    Returns 0 if successfull, or -1 if an error occurred.
        !          1709: X *
        !          1710: X */
        !          1711: X
        !          1712: X#ifdef __STDC__
        !          1713: X
        !          1714: Xint get_newname(char *name, int size)
        !          1715: X
        !          1716: X#else
        !          1717: X
        !          1718: Xint get_newname(name, size)
        !          1719: Xchar  *name;
        !          1720: Xint   size;
        !          1721: X
        !          1722: X#endif
        !          1723: X{
        !          1724: X    char      buf[PATH_MAX + 10];
        !          1725: X
        !          1726: X    if (f_interactive) {
        !          1727: X      sprintf(buf, "rename %s? ", name);
        !          1728: X      if (nextask(buf, name, size) == -1) {
        !          1729: X          exit(0);
        !          1730: X      }
        !          1731: X      if (strlen(name) == 0) {
        !          1732: X          return(1);
        !          1733: X      }
        !          1734: X    }
        !          1735: X    return(0);
        !          1736: X}
        !          1737: END_OF_replace.c
        !          1738: if test 6493 -ne `wc -c <replace.c`; then
        !          1739:     echo shar: \"replace.c\" unpacked with wrong size!
        !          1740: fi
        !          1741: # end of overwriting check
        !          1742: fi
        !          1743: if test -f ttyio.c -a "${1}" != "-c" ; then 
        !          1744:   echo shar: Will not over-write existing file \"ttyio.c\"
        !          1745: else
        !          1746: echo shar: Extracting \"ttyio.c\" \(6321 characters\)
        !          1747: sed "s/^X//" >ttyio.c <<'END_OF_ttyio.c'
        !          1748: X/* $Source: /u/mark/src/pax/RCS/ttyio.c,v $
        !          1749: X *
        !          1750: X * $Revision: 1.1 $
        !          1751: X *
        !          1752: X * ttyio.c - Terminal/Console I/O functions for all archive interfaces
        !          1753: X *
        !          1754: X * DESCRIPTION
        !          1755: X *
        !          1756: X *    These routines provide a consistent, general purpose interface to
        !          1757: X *    the user via the users terminal, if it is available to the
        !          1758: X *    process.
        !          1759: X *
        !          1760: X * AUTHOR
        !          1761: X *
        !          1762: X *     Mark H. Colburn, NAPS International ([email protected])
        !          1763: X *
        !          1764: X * Sponsored by The USENIX Association for public distribution. 
        !          1765: X *
        !          1766: X * Copyright (c) 1989 Mark H. Colburn.
        !          1767: X * All rights reserved.
        !          1768: X *
        !          1769: X * Redistribution and use in source and binary forms are permitted
        !          1770: X * provided that the above copyright notice is duplicated in all such 
        !          1771: X * forms and that any documentation, advertising materials, and other 
        !          1772: X * materials related to such distribution and use acknowledge that the 
        !          1773: X * software was developed * by Mark H. Colburn and sponsored by The 
        !          1774: X * USENIX Association. 
        !          1775: X *
        !          1776: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !          1777: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !          1778: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !          1779: X *
        !          1780: X * $Log:      ttyio.c,v $
        !          1781: X * Revision 1.1  88/12/23  18:02:39  mark
        !          1782: X * Initial revision
        !          1783: X * 
        !          1784: X */
        !          1785: X
        !          1786: X#ifndef lint
        !          1787: Xstatic char *ident = "$Id: ttyio.c,v 1.1 88/12/23 18:02:39 mark Rel $";
        !          1788: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
        !          1789: X#endif /* ! lint */
        !          1790: X
        !          1791: X
        !          1792: X/* Headers */
        !          1793: X
        !          1794: X#include "pax.h"
        !          1795: X
        !          1796: X
        !          1797: X/* open_tty - open the terminal for interactive queries
        !          1798: X *
        !          1799: X * DESCRIPTION
        !          1800: X *
        !          1801: X *    Assumes that background processes ignore interrupts and that the
        !          1802: X *    open() or the isatty() will fail for processes which are not
        !          1803: X *    attached to terminals. Returns a file descriptor or -1 if
        !          1804: X *    unsuccessful. 
        !          1805: X *
        !          1806: X * RETURNS
        !          1807: X *
        !          1808: X *    Returns a file descriptor which can be used to read and write
        !          1809: X *    directly to the user's terminal, or -1 on failure.  
        !          1810: X *
        !          1811: X * ERRORS
        !          1812: X *
        !          1813: X *    If SIGINT cannot be ignored, or the open fails, or the newly opened
        !          1814: X *    terminal device is not a tty, then open_tty will return a -1 to the
        !          1815: X *    caller.
        !          1816: X */
        !          1817: X
        !          1818: X#ifdef __STDC__
        !          1819: X
        !          1820: Xint open_tty(void)
        !          1821: X
        !          1822: X#else
        !          1823: X
        !          1824: Xint open_tty()
        !          1825: X
        !          1826: X#endif
        !          1827: X{
        !          1828: X    int             fd;               /* file descriptor for terminal */
        !          1829: X    SIG_T         (*intr)();  /* used to restore interupts if signal fails */
        !          1830: X
        !          1831: X    if ((intr = signal(SIGINT, SIG_IGN)) == SIG_IGN) {
        !          1832: X      return (-1);
        !          1833: X    }
        !          1834: X    signal(SIGINT, intr);
        !          1835: X    if ((fd = open(TTY, O_RDWR)) < 0) {
        !          1836: X      return (-1);
        !          1837: X    }
        !          1838: X    if (isatty(fd)) {
        !          1839: X      return (fd);
        !          1840: X    }
        !          1841: X    close(fd);
        !          1842: X    return (-1);
        !          1843: X}
        !          1844: X
        !          1845: X
        !          1846: X/* nextask - ask a question and get a response
        !          1847: X *
        !          1848: X * DESCRIPTION
        !          1849: X *
        !          1850: X *    Give the user a prompt and wait for their response.  The prompt,
        !          1851: X *    located in "msg" is printed, then the user is allowed to type
        !          1852: X *    a response to the message.  The first "limit" characters of the
        !          1853: X *    user response is stored in "answer".
        !          1854: X *
        !          1855: X *    Nextask ignores spaces and tabs. 
        !          1856: X *
        !          1857: X * PARAMETERS
        !          1858: X *
        !          1859: X *    char *msg       - Message to display for user 
        !          1860: X *    char *answer    - Pointer to user's response to question 
        !          1861: X *    int limit       - Limit of length for user's response
        !          1862: X *
        !          1863: X * RETURNS
        !          1864: X *
        !          1865: X *    Returns the number of characters in the user response to the 
        !          1866: X *    calling function.  If an EOF was encountered, a -1 is returned to
        !          1867: X *    the calling function.  If an error occured which causes the read
        !          1868: X *    to return with a value of -1, then the function will return a
        !          1869: X *    non-zero return status to the calling process, and abort
        !          1870: X *    execution.
        !          1871: X */
        !          1872: X
        !          1873: X#ifdef __STDC__
        !          1874: X
        !          1875: Xint nextask(char *msg, char *answer, int limit)
        !          1876: X
        !          1877: X#else
        !          1878: X
        !          1879: Xint nextask(msg, answer, limit)
        !          1880: Xchar           *msg;          /* message to display for user */
        !          1881: Xchar           *answer;               /* pointer to user's response to question */
        !          1882: Xint             limit;                /* limit of length for user's response */
        !          1883: X
        !          1884: X#endif
        !          1885: X{
        !          1886: X    int             idx;      /* index into answer for character input */
        !          1887: X    int             got;      /* number of characters read */
        !          1888: X    char            c;                /* character read */
        !          1889: X
        !          1890: X    if (ttyf < 0) {
        !          1891: X      fatal("/dev/tty Unavailable");
        !          1892: X    }
        !          1893: X    write(ttyf, msg, (uint) strlen(msg));
        !          1894: X    idx = 0;
        !          1895: X    while ((got = read(ttyf, &c, 1)) == 1) {
        !          1896: X      if (c == '\n') {
        !          1897: X          break;
        !          1898: X      } else if (c == ' ' || c == '\t') {
        !          1899: X          continue;
        !          1900: X      } else if (idx < limit - 1) {
        !          1901: X          answer[idx++] = c;
        !          1902: X      }
        !          1903: X    }
        !          1904: X    if (got == 0) {           /* got an EOF */
        !          1905: X        return(-1);
        !          1906: X    }
        !          1907: X    if (got < 0) {
        !          1908: X      fatal(syserr());
        !          1909: X    }
        !          1910: X    answer[idx] = '\0';
        !          1911: X    return(0);
        !          1912: X}
        !          1913: X
        !          1914: X
        !          1915: X/* lineget - get a line from a given stream
        !          1916: X *
        !          1917: X * DESCRIPTION
        !          1918: X * 
        !          1919: X *    Get a line of input for the stream named by "stream".  The data on
        !          1920: X *    the stream is put into the buffer "buf".
        !          1921: X *
        !          1922: X * PARAMETERS
        !          1923: X *
        !          1924: X *    FILE *stream            - Stream to get input from 
        !          1925: X *    char *buf               - Buffer to put input into
        !          1926: X *
        !          1927: X * RETURNS
        !          1928: X *
        !          1929: X *    Returns 0 if successful, -1 at EOF. 
        !          1930: X */
        !          1931: X
        !          1932: X#ifdef __STDC__
        !          1933: X
        !          1934: Xint lineget(FILE *stream, char *buf)
        !          1935: X
        !          1936: X#else
        !          1937: X
        !          1938: Xint lineget(stream, buf)
        !          1939: XFILE           *stream;               /* stream to get input from */
        !          1940: Xchar           *buf;          /* buffer to put input into */
        !          1941: X
        !          1942: X#endif
        !          1943: X{
        !          1944: X    int             c;
        !          1945: X
        !          1946: X    for (;;) {
        !          1947: X      if ((c = getc(stream)) == EOF) {
        !          1948: X          return (-1);
        !          1949: X      }
        !          1950: X      if (c == '\n') {
        !          1951: X          break;
        !          1952: X      }
        !          1953: X      *buf++ = c;
        !          1954: X    }
        !          1955: X    *buf = '\0';
        !          1956: X    return (0);
        !          1957: X}
        !          1958: X
        !          1959: X
        !          1960: X/* next - Advance to the next archive volume. 
        !          1961: X *
        !          1962: X * DESCRIPTION
        !          1963: X *
        !          1964: X *    Prompts the user to replace the backup medium with a new volume
        !          1965: X *    when the old one is full.  There are some cases, such as when
        !          1966: X *    archiving to a file on a hard disk, that the message can be a
        !          1967: X *    little surprising.  Assumes that background processes ignore
        !          1968: X *    interrupts and that the open() or the isatty() will fail for
        !          1969: X *    processes which are not attached to terminals. Returns a file
        !          1970: X *    descriptor or -1 if unsuccessful. 
        !          1971: X *
        !          1972: X * PARAMETERS
        !          1973: X *
        !          1974: X *    int mode        - mode of archive (READ, WRITE, PASS) 
        !          1975: X */
        !          1976: X
        !          1977: X#ifdef __STDC__
        !          1978: X
        !          1979: Xvoid next(int mode)
        !          1980: X
        !          1981: X#else
        !          1982: X
        !          1983: Xvoid next(mode)
        !          1984: Xint             mode;         /* mode of archive (READ, WRITE, PASS) */
        !          1985: X
        !          1986: X#endif
        !          1987: X{
        !          1988: X    char            msg[200]; /* buffer for message display */ 
        !          1989: X    char            answer[20];       /* buffer for user's answer */
        !          1990: X    int             ret;
        !          1991: X
        !          1992: X    close_archive();
        !          1993: X
        !          1994: X    sprintf(msg, "\
        !          1995: X%s: Ready for volume %u\n\
        !          1996: X%s: Type \"go\" when ready to proceed (or \"quit\" to abort): \07",
        !          1997: X                 myname, arvolume + 1, myname);
        !          1998: X    for (;;) {
        !          1999: X      ret = nextask(msg, answer, sizeof(answer));
        !          2000: X      if (ret == -1 || strcmp(answer, "quit") == 0) {
        !          2001: X          fatal("Aborted");
        !          2002: X      }
        !          2003: X      if (strcmp(answer, "go") == 0 && open_archive(mode) == 0) {
        !          2004: X          break;
        !          2005: X      }
        !          2006: X    }
        !          2007: X    warnarch("Continuing", (OFFSET) 0);
        !          2008: X}
        !          2009: END_OF_ttyio.c
        !          2010: if test 6321 -ne `wc -c <ttyio.c`; then
        !          2011:     echo shar: \"ttyio.c\" unpacked with wrong size!
        !          2012: fi
        !          2013: # end of overwriting check
        !          2014: fi
        !          2015: if test -f warn.c -a "${1}" != "-c" ; then 
        !          2016:   echo shar: Will not over-write existing file \"warn.c\"
        !          2017: else
        !          2018: echo shar: Extracting \"warn.c\" \(5446 characters\)
        !          2019: sed "s/^X//" >warn.c <<'END_OF_warn.c'
        !          2020: X/* $Source: /u/mark/src/pax/RCS/warn.c,v $
        !          2021: X *
        !          2022: X * $Revision: 1.1 $
        !          2023: X *
        !          2024: X * warn.c - miscellaneous user warning routines 
        !          2025: X *
        !          2026: X * DESCRIPTION
        !          2027: X *
        !          2028: X *    These routines provide the user with various forms of warning
        !          2029: X *    and informational messages.
        !          2030: X *
        !          2031: X * AUTHOR
        !          2032: X *
        !          2033: X *     Mark H. Colburn, NAPS International ([email protected])
        !          2034: X *
        !          2035: X * Sponsored by The USENIX Association for public distribution. 
        !          2036: X *
        !          2037: X * Copyright (c) 1989 Mark H. Colburn.
        !          2038: X * All rights reserved.
        !          2039: X *
        !          2040: X * Redistribution and use in source and binary forms are permitted
        !          2041: X * provided that the above copyright notice is duplicated in all such 
        !          2042: X * forms and that any documentation, advertising materials, and other 
        !          2043: X * materials related to such distribution and use acknowledge that the 
        !          2044: X * software was developed * by Mark H. Colburn and sponsored by The 
        !          2045: X * USENIX Association. 
        !          2046: X *
        !          2047: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !          2048: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !          2049: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !          2050: X *
        !          2051: X * $Log:      warn.c,v $
        !          2052: X * Revision 1.1  88/12/23  18:02:40  mark
        !          2053: X * Initial revision
        !          2054: X * 
        !          2055: X */
        !          2056: X
        !          2057: X#ifndef lint
        !          2058: Xstatic char *ident = "$Id: warn.c,v 1.1 88/12/23 18:02:40 mark Rel $";
        !          2059: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
        !          2060: X#endif /* ! lint */
        !          2061: X
        !          2062: X
        !          2063: X/* Headers */
        !          2064: X
        !          2065: X#include "pax.h"
        !          2066: X
        !          2067: X
        !          2068: X/* Function Prototypes */
        !          2069: X
        !          2070: X#ifdef __STDC__
        !          2071: X
        !          2072: Xstatic void prsize(FILE *, OFFSET);
        !          2073: X
        !          2074: X#else /* !__STDC__ */
        !          2075: X
        !          2076: Xstatic void prsize();
        !          2077: X
        !          2078: X#endif /* __STDC__ */
        !          2079: X
        !          2080: X
        !          2081: X/* warnarch - print an archive-related warning message and offset
        !          2082: X *
        !          2083: X * DESCRIPTION
        !          2084: X *
        !          2085: X *    Present the user with an error message and an archive offset at
        !          2086: X *    which the error occured.   This can be useful for diagnosing or
        !          2087: X *    fixing damaged archives.
        !          2088: X *
        !          2089: X * PARAMETERS
        !          2090: X *
        !          2091: X *    char    *msg    - A message string to be printed for the user.
        !          2092: X *    OFFSET  adjust  - An adjustment which is added to the current 
        !          2093: X *                      archive position to tell the user exactly where 
        !          2094: X *                      the error occurred.
        !          2095: X */
        !          2096: X
        !          2097: X#ifdef __STDC__
        !          2098: X
        !          2099: Xvoid warnarch(char *msg, OFFSET adjust)
        !          2100: X
        !          2101: X#else 
        !          2102: X
        !          2103: Xvoid warnarch(msg, adjust)
        !          2104: Xchar           *msg;
        !          2105: XOFFSET          adjust;
        !          2106: X
        !          2107: X#endif
        !          2108: X{
        !          2109: X    fprintf(stderr, "%s: [offset ", myname);
        !          2110: X    prsize(stderr, total - adjust);
        !          2111: X    fprintf(stderr, "]: %s\n", msg);
        !          2112: X}
        !          2113: X
        !          2114: X
        !          2115: X/* syserr - return pointer to appropriate system error message
        !          2116: X *
        !          2117: X * DESCRIPTION
        !          2118: X *
        !          2119: X *    Get an error message string which is appropriate for the setting
        !          2120: X *    of the errno variable.
        !          2121: X *
        !          2122: X * RETURNS
        !          2123: X *
        !          2124: X *    Returns a pointer to a string which has an appropriate error
        !          2125: X *    message for the present value of errno.  The error message
        !          2126: X *    strings are taken from sys_errlist[] where appropriate.  If an
        !          2127: X *    appropriate message is not available in sys_errlist, then a
        !          2128: X *    pointer to the string "Unknown error (errno <errvalue>)" is 
        !          2129: X *    returned instead.
        !          2130: X */
        !          2131: X
        !          2132: X#ifdef __STDC__
        !          2133: X
        !          2134: Xchar *syserr(void)
        !          2135: X
        !          2136: X#else
        !          2137: X
        !          2138: Xchar *syserr()
        !          2139: X
        !          2140: X#endif
        !          2141: X{
        !          2142: X    static char     msg[40];          /* used for "Unknown error" messages */
        !          2143: X
        !          2144: X    if (errno > 0 && errno < sys_nerr) {
        !          2145: X      return (sys_errlist[errno]);
        !          2146: X    }
        !          2147: X    sprintf(msg, "Unknown error (errno %d)", errno);
        !          2148: X    return (msg);
        !          2149: X}
        !          2150: X
        !          2151: X
        !          2152: X/* prsize - print a file offset on a file stream
        !          2153: X *
        !          2154: X * DESCRIPTION
        !          2155: X *
        !          2156: X *    Prints a file offset to a specific file stream.  The file offset is
        !          2157: X *    of the form "%dm+%dk+%d", where the number preceeding the "m" and
        !          2158: X *    the "k" stand for the number of Megabytes and the number of
        !          2159: X *    Kilobytes, respectivley, which have been processed so far.
        !          2160: X *
        !          2161: X * PARAMETERS
        !          2162: X *
        !          2163: X *    FILE  *stream   - Stream which is to be used for output 
        !          2164: X *    OFFSET size     - Current archive position to be printed on the output 
        !          2165: X *                      stream in the form: "%dm+%dk+%d".
        !          2166: X *
        !          2167: X */
        !          2168: X
        !          2169: X#ifdef __STDC__
        !          2170: X
        !          2171: Xstatic void prsize(FILE *stream, OFFSET size)
        !          2172: X
        !          2173: X#else
        !          2174: X
        !          2175: Xstatic void prsize(stream, size)
        !          2176: XFILE           *stream;               /* stream which is used for output */
        !          2177: XOFFSET          size;         /* current archive position to be printed */
        !          2178: X
        !          2179: X#endif
        !          2180: X
        !          2181: X{
        !          2182: X    OFFSET          n;
        !          2183: X
        !          2184: X    if (n = (size / (1024 * 1024))) {
        !          2185: X      fprintf(stream, "%ldm+", n);
        !          2186: X      size -= n * 1024 * 1024;
        !          2187: X    }
        !          2188: X    if (n = (size / 1024)) {
        !          2189: X      fprintf(stream, "%ldk+", n);
        !          2190: X      size -= n * 1024;
        !          2191: X    }
        !          2192: X    fprintf(stream, "%ld", size);
        !          2193: X}
        !          2194: X
        !          2195: X
        !          2196: X/* fatal - print fatal message and exit
        !          2197: X *
        !          2198: X * DESCRIPTION
        !          2199: X *
        !          2200: X *    Fatal prints the program's name along with an error message, then
        !          2201: X *    exits the program with a non-zero return code.
        !          2202: X *
        !          2203: X * PARAMETERS
        !          2204: X *
        !          2205: X *    char    *why    - description of reason for termination 
        !          2206: X *            
        !          2207: X * RETURNS
        !          2208: X *
        !          2209: X *    Returns an exit code of 1 to the parent process.
        !          2210: X */
        !          2211: X
        !          2212: X#ifdef __STDC__
        !          2213: X
        !          2214: Xvoid fatal(char *why)
        !          2215: X
        !          2216: X#else
        !          2217: X
        !          2218: Xvoid fatal(why)
        !          2219: Xchar           *why;          /* description of reason for termination */
        !          2220: X
        !          2221: X#endif
        !          2222: X{
        !          2223: X    fprintf(stderr, "%s: %s\n", myname, why);
        !          2224: X    exit(1);
        !          2225: X}
        !          2226: X
        !          2227: X
        !          2228: X
        !          2229: X/* warn - print a warning message
        !          2230: X *
        !          2231: X * DESCRIPTION
        !          2232: X *
        !          2233: X *    Print an error message listing the program name, the actual error
        !          2234: X *    which occurred and an informational message as to why the error
        !          2235: X *    occurred on the standard error device.  The standard error is
        !          2236: X *    flushed after the error is printed to assure that the user gets
        !          2237: X *    the message in a timely fasion.
        !          2238: X *
        !          2239: X * PARAMETERS
        !          2240: X *
        !          2241: X *    char *what      - Pointer to string describing what failed.
        !          2242: X *    char *why       - Pointer to string describing why did it failed.
        !          2243: X */
        !          2244: X
        !          2245: X#ifdef __STDC__
        !          2246: X
        !          2247: Xvoid warn(char *what, char *why)
        !          2248: X
        !          2249: X#else
        !          2250: X
        !          2251: Xvoid warn(what, why)
        !          2252: Xchar           *what;         /* message as to what the error was */
        !          2253: Xchar           *why;          /* explanation why the error occurred */
        !          2254: X
        !          2255: X#endif
        !          2256: X{
        !          2257: X    fprintf(stderr, "%s: %s : %s\n", myname, what, why);
        !          2258: X    fflush(stderr);
        !          2259: X}
        !          2260: END_OF_warn.c
        !          2261: if test 5446 -ne `wc -c <warn.c`; then
        !          2262:     echo shar: \"warn.c\" unpacked with wrong size!
        !          2263: fi
        !          2264: # end of overwriting check
        !          2265: fi
        !          2266: echo shar: End of archive 2 \(of 6\).
        !          2267: cp /dev/null ark2isdone
        !          2268: MISSING=""
        !          2269: for I in 1 2 3 4 5 6 ; do
        !          2270:     if test ! -f ark${I}isdone ; then
        !          2271:        MISSING="${MISSING} ${I}"
        !          2272:     fi
        !          2273: done
        !          2274: if test "${MISSING}" = "" ; then
        !          2275:     echo You have unpacked all 6 archives.
        !          2276:     rm -f ark[1-9]isdone
        !          2277: else
        !          2278:     echo You still need to unpack the following archives:
        !          2279:     echo "        " ${MISSING}
        !          2280: fi
        !          2281: ##  End of shell archive.
        !          2282: exit 0
        !          2283: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.