|
|
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.