|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.