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