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