|
|
1.1 root 1: #include "asd.h"
2:
3: #define CHUNK 64
4:
5: /* type codes for installation subroutine */
6: #define BACKUP 0
7: #define INSTALL 1
8:
9: void readtemp();
10:
11: /*
12: * The following declarations and functions manipulate
13: * a list of directory names. This list is used to decide
14: * which files should be backed up and which have already been.
15: */
16:
17: struct list {
18: char *name;
19: struct list *next;
20: };
21:
22: static struct list *dirs;
23:
24: /* is the name given a subdirectory of the name on the list? */
25: static int
26: subsumed (name)
27: register char *name;
28: {
29: register struct list *item;
30: register char *p, *q;
31:
32: for (item = dirs; item; item = item->next) {
33: p = item->name;
34: q = name;
35: while (*p && *p == *q)
36: p++, q++;
37: if (*p == '\0' && (*q == '/' || *q == '\0'))
38: return 1;
39: }
40:
41: return 0;
42: }
43:
44: /* add the name given to the list */
45: static void
46: addlist (name)
47: register char *name;
48: {
49: register struct list *l;
50:
51: l = new (struct list);
52: l->next = dirs;
53: l->name = copy (name);
54: dirs = l;
55: }
56:
57: /* clear the entire list */
58: static void
59: clearlist()
60: {
61: register struct list *l;
62:
63: while (l = dirs) {
64: dirs = l->next;
65: free (l->name);
66: free ((char *) l);
67: }
68: }
69:
70: /*
71: * install the given file
72: */
73: process (file, fname)
74: FILE *file;
75: char *fname;
76: {
77: register int c, rc = 0;
78:
79: if (vflag)
80: fprintf (stderr, "%s:\n", fname);
81:
82: while ((c = getc (file)) != EOF) {
83: ungetc (c, file);
84: rc += doarch (file);
85: }
86:
87: return rc;
88: }
89:
90: main (argc, argv)
91: int argc;
92: char **argv;
93: {
94: static char errbuf[BUFSIZ];
95:
96: setbuf (stderr, errbuf);
97: umask (0);
98: return getargs (argc, argv, "nvbD:", process);
99: }
100:
101: static char tfname[TMPNAML];
102: void delete();
103:
104: /* process a single archive in a concatenation */
105: doarch (file)
106: register FILE *file;
107: {
108: register FILE *tf;
109: Sig_typ sigsav;
110: register long size;
111: register int c;
112: char armag[SARMAG];
113:
114: /* Make sure the file is an archive */
115: if (fread (armag, sizeof (*armag), SARMAG, file) != SARMAG) {
116: fprintf (stderr, "inspkg: unexpected EOF\n");
117: exit (1);
118: }
119: if (strncmp (armag, ARMAG, SARMAG) != 0) {
120: fprintf (stderr, "inspkg: input not a package\n");
121: exit (1);
122: }
123:
124: /* establish a temporary file */
125: (void) tmpname (tfname);
126: tf = fopen (tfname, "w");
127: sigsav = signal (SIGINT, SIG_IGN);
128: if (sigsav != SIG_IGN)
129: signal (SIGINT, delete);
130: chmod (tfname, 0600);
131:
132: /* copy the installation instructions to the temp file */
133: size = read_header (instr, file);
134: while (--size >= 0) {
135: c = getc (file);
136: if (c == EOF) {
137: fprintf (stderr, "inspkg: premature EOF\n");
138: exit (1);
139: }
140: if (putc (c, tf) == EOF) {
141: perror ("inspkg: Instructions");
142: exit (1);
143: }
144: }
145: if (fclose (tf) == EOF) {
146: perror ("inspkg: Instructions fclose");
147: exit (1);
148: }
149:
150: next_header (file);
151:
152: /* create the optional backup package */
153: if (bflag) {
154: pkgstart();
155: readtemp (BACKUP, file);
156: pkgend();
157: clearlist();
158: }
159:
160: /* do the actual work */
161: readtemp (INSTALL, file);
162:
163: /* delete the temporary file */
164: nchk (unlink (tfname));
165: signal (SIGINT, sigsav);
166:
167: return 0;
168: }
169:
170: /*
171: * Make a pass through the temp file.
172: */
173: static void
174: readtemp (code, file)
175: register int code;
176: register FILE *file;
177: {
178: register FILE *tf;
179: register int c;
180:
181: /* we're done writing the temp file, time to read it */
182: tf = fopen (tfname, "r");
183: schk ((char *) tf);
184:
185: /*
186: * The main loop -- one iteration per line
187: * We are careful in use and reuse of storage here;
188: * if you change this code make sure you understand
189: * the times at which getfield and transname
190: * recycle storage or strange things will happen.
191: */
192: while ((c = getc (tf)) != EOF) {
193: char *param, *path, *path2;
194: register FILE *outfd;
195: int uid, gid, mode, dmajor, dminor, dev;
196: register long size;
197: char component[MAXCOMP+1];
198:
199: switch (c) {
200:
201: /* special files */
202: case 'b':
203: case 'c':
204: /* read the parameters */
205: param = getfield (tf);
206: mode = cvlong (param, strlen (param), 8) |
207: (c == 'c'? S_IFCHR: S_IFBLK);
208: param = getfield (tf);
209: dmajor = cvlong (param, strlen (param), 10);
210: param = getfield (tf);
211: dminor = cvlong (param, strlen (param), 10);
212: dev = makedev (dmajor, dminor);
213: uid = numuid (getfield (tf));
214: gid = numgid (getfield (tf));
215: path = transname (getfield (tf));
216: geteol (tf);
217:
218: switch (code) {
219:
220: case BACKUP:
221: if (!subsumed (path)) {
222: pkgfile (path);
223: addlist (path);
224: }
225: break;
226:
227: case INSTALL:
228: if (vflag) {
229: fprintf (stderr, "special file ");
230: putpath (stderr, path);
231: fprintf (stderr, "\n");
232: }
233:
234: if (!nflag) {
235: rmall (path);
236: if (mknod (path, mode, dev) >= 0)
237: chown (path, uid, gid);
238: else
239: perror (path);
240: }
241: break;
242: }
243: break;
244:
245: /* directory */
246: case 'd':
247: /* read the parameters */
248: param = getfield (tf);
249: mode = cvlong (param, strlen (param), 8);
250: uid = numuid (getfield (tf));
251: gid = numgid (getfield (tf));
252: path = transname (getfield (tf));
253: geteol (tf);
254:
255: switch (code) {
256:
257: case BACKUP:
258: if (!subsumed (path)) {
259: pkgfile (path);
260: addlist (path);
261: }
262: break;
263:
264: case INSTALL:
265: /* make the directory */
266: if (vflag) {
267: fprintf (stderr, "directory ");
268: putpath (stderr, path);
269: putc ('\n', stderr);
270: }
271: if (!nflag) {
272: rmall (path);
273: mkdir (path);
274: chmod (path, mode);
275: chown (path, uid, gid);
276: chmod (path, mode);
277: }
278: break;
279: }
280:
281: break;
282:
283: /* file */
284: case 'f':
285: /* read parameters */
286: param = getfield (tf);
287: if (strlen (param) > MAXCOMP) {
288: fprintf (stderr,
289: "inspkg: impossibly long component name\n");
290: delete();
291: exit (1);
292: }
293: strcpy (component, param);
294: uid = numuid (getfield (tf));
295: gid = numgid (getfield (tf));
296: path = transname (getfield (tf));
297: geteol (tf);
298:
299: switch (code) {
300:
301: case BACKUP:
302: if (!subsumed (path))
303: pkgfile (path);
304: break;
305:
306: case INSTALL:
307: /* read the corresponding archive header */
308: size = read_header (component, file);
309:
310: if (vflag) {
311: fprintf (stderr, "file ");
312: putpath (stderr, path);
313: putc ('\n', stderr);
314: }
315:
316: /* create and open the file */
317: if (!nflag) {
318: rmall (path);
319: umask (077);
320: outfd = fopen (path, "w");
321: umask (0);
322: if (outfd == NULL) {
323: fprintf (stderr,
324: "inspkg: cannot create ");
325: putpath (stderr, path);
326: putc ('\n', stderr);
327: }
328: }
329: if (nflag || outfd == NULL) {
330: outfd = fopen ("/dev/null", "w");
331: schk ((char *) outfd);
332: }
333:
334: /* copy the file, advance input */
335: while (--size >= 0)
336: putc (getc (file), outfd);
337: next_header (file);
338:
339: /* check successful completion, close output */
340: fflush (outfd);
341: if (feof (file) || ferror (file) ||
342: ferror (outfd)) {
343: fprintf (stderr, "inspkg: can't write ");
344: putpath (stderr, path);
345: putc ('\n', stderr);
346: }
347: if (fclose (outfd) == EOF) {
348: fprintf (stderr, "inspkg: can't close ");
349: putpath (stderr, path);
350: fprintf (stderr, ": ");
351: perror ("");
352: }
353:
354: /*
355: * Update output modification times
356: * and change mode and owner.
357: * This is done here to cater to systems
358: * that allow people to give files away.
359: * The chmod is done twice because
360: * systems that let you give files away
361: * won't let you change the mode after
362: * you've done so, and some other systems
363: * turn off the setuid bit as a side
364: * effect of chown, so the second chmod
365: * will restore that bit.
366: */
367: if (!nflag) {
368: time_t timep[2];
369: timep[0] = timep[1] = hdr.date;
370: utime (path, timep);
371: chmod (path, hdr.mode & 07777);
372: chown (path, uid, gid);
373: chmod (path, hdr.mode & 07777);
374: }
375:
376: break;
377: }
378: break;
379:
380: /* symbolic link */
381: case 's':
382: /* read parameters */
383: path = copy (transname (getfield (tf)));
384: path2 = transname (getfield (tf));
385: geteol (tf);
386:
387: switch (code) {
388: case BACKUP:
389: if (!subsumed (path2))
390: pkgfile (path2);
391: break;
392:
393: case INSTALL:
394: /* log it if requested */
395: if (vflag) {
396: fprintf (stderr, "symlink ");
397: putpath (stderr, path2);
398: fprintf (stderr, " to ");
399: putpath (stderr, path);
400: putc ('\n', stderr);
401: }
402: #ifdef S_IFLNK
403:
404: /* make the link */
405: if (!nflag) {
406: rmall (path2);
407: if (symlink (path, path2) < 0)
408: perror (path2);
409: }
410: #else
411: fprintf(stderr, "This system does not support symbolic links\n");
412: #endif
413:
414: break;
415: }
416: free (path);
417: break;
418:
419: /* link */
420: case 'l':
421: /* read parameters */
422: path = copy (transname (getfield (tf)));
423: path2 = transname (getfield (tf));
424: geteol (tf);
425:
426: switch (code) {
427:
428: case BACKUP:
429: if (!subsumed (path2))
430: pkgfile (path2);
431: break;
432:
433: case INSTALL:
434: /* log it if requested */
435: if (vflag) {
436: fprintf (stderr, "link ");
437: putpath (stderr, path);
438: fprintf (stderr, " to ");
439: putpath (stderr, path2);
440: putc ('\n', stderr);
441: }
442:
443: /* make the link */
444: if (!nflag) {
445: struct stat sb, sb2;
446:
447: /* are we about to link x to x? */
448: if (stat (path, &sb) < 0
449: || stat (path2, &sb2) < 0
450: || sb.st_dev != sb2.st_dev
451: || sb.st_ino != sb2.st_ino) {
452: rmall (path2);
453: if (link (path, path2) < 0)
454: perror (path2);
455: }
456: }
457:
458: break;
459: }
460: free (path);
461: break;
462:
463: /* remove */
464: case 'r':
465: /* get parameters */
466: path = transname (getfield (tf));
467: geteol (tf);
468:
469: switch (code) {
470:
471: case BACKUP:
472: if (!subsumed (path))
473: pkgfile (path);
474: break;
475:
476: case INSTALL:
477: if (vflag) {
478: fprintf (stderr, "remove file ");
479: putpath (stderr, path);
480: putc ('\n', stderr);
481: }
482: if (!nflag)
483: rmall (path);
484: break;
485: }
486:
487: break;
488:
489: case 'x':
490: xstr = getfield (tf);
491: geteol (tf);
492: if (code == INSTALL) {
493: if (vflag) {
494: fprintf (stderr, "execute: ");
495: putpath (stderr, xstr);
496: fprintf (stderr, "\n");
497: }
498: if (!nflag) {
499: fflush (stderr);
500: system (xstr);
501: }
502: }
503: xstr = NULL;
504: break;
505:
506: case 'X':
507: Xstr = transname (getfield (tf));
508: geteol (tf);
509: if (code == INSTALL) {
510: if (vflag) {
511: fprintf (stderr, "exec file: ");
512: putpath (stderr, Xstr);
513: fprintf (stderr, "\n");
514: }
515: if (!nflag) {
516: int status, pid, w;
517: Sig_typ istat, qstat;
518:
519: fflush (stderr);
520: if ((pid = fork()) == 0) {
521: execl (Xstr, Xstr, (char *)0);
522: execl ("/bin/sh", "sh", Xstr, (char *) 0);
523: putpath (stderr, Xstr);
524: fprintf (stderr, ": ");
525: fflush (stderr);
526: perror ("");
527: _exit(127);
528: }
529: istat = signal (SIGINT, SIG_IGN);
530: qstat = signal (SIGQUIT, SIG_IGN);
531: while ((w=wait(&status)) != pid && w != -1)
532: ;
533: signal(SIGINT, istat);
534: signal(SIGQUIT, qstat);
535: }
536: }
537: Xstr = NULL;
538: break;
539:
540: default:
541: fprintf (stderr, "inspkg: invalid package\n");
542: delete();
543: exit (1);
544: }
545: }
546:
547: if (ferror (tf))
548: perror ("inspkg: internal temp file");
549:
550: fclose (tf);
551:
552: }
553:
554: static void
555: delete()
556: {
557: unlink (tfname);
558: exit (3);
559: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.