|
|
1.1 root 1: /*
2: * Copyright (c) 1987 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: */
17:
18: #ifndef lint
19: char copyright[] =
20: "@(#) Copyright (c) 1987 Regents of the University of California.\n\
21: All rights reserved.\n";
22: #endif /* not lint */
23:
24: #ifndef lint
25: static char sccsid[] = "@(#)install.c 5.12 (Berkeley) 7/6/88";
26: #endif /* not lint */
27:
28: #include <sys/param.h>
29: #include <sys/stat.h>
30: #include <sys/file.h>
31: #include <a.out.h>
32: #include <grp.h>
33: #include <pwd.h>
34: #include <stdio.h>
35: #include <ctype.h>
36:
37: #define YES 1 /* yes/true */
38: #define NO 0 /* no/false */
39:
40: #define PERROR(head, msg) { \
41: fputs(head, stderr); \
42: perror(msg); \
43: }
44:
45: static struct passwd *pp;
46: static struct group *gp;
47: static int docopy, dostrip,
48: mode = 0755;
49: static char *group, *owner,
50: pathbuf[MAXPATHLEN];
51:
52: main(argc, argv)
53: int argc;
54: char **argv;
55: {
56: extern char *optarg;
57: extern int optind;
58: struct stat from_sb, to_sb;
59: int ch, no_target;
60: char *to_name;
61:
62: while ((ch = getopt(argc, argv, "cg:m:o:s")) != EOF)
63: switch((char)ch) {
64: case 'c':
65: docopy = YES;
66: break;
67: case 'g':
68: group = optarg;
69: break;
70: case 'm':
71: mode = atoo(optarg);
72: break;
73: case 'o':
74: owner = optarg;
75: break;
76: case 's':
77: dostrip = YES;
78: break;
79: case '?':
80: default:
81: usage();
82: }
83: argc -= optind;
84: argv += optind;
85: if (argc < 2)
86: usage();
87:
88: /* get group and owner id's */
89: if (group && !(gp = getgrnam(group))) {
90: fprintf(stderr, "install: unknown group %s.\n", group);
91: exit(1);
92: }
93: if (owner && !(pp = getpwnam(owner))) {
94: fprintf(stderr, "install: unknown user %s.\n", owner);
95: exit(1);
96: }
97:
98: no_target = stat(to_name = argv[argc - 1], &to_sb);
99: if (!no_target && (to_sb.st_mode & S_IFMT) == S_IFDIR) {
100: for (; *argv != to_name; ++argv)
101: install(*argv, to_name, YES);
102: exit(0);
103: }
104:
105: /* can't do file1 file2 directory/file */
106: if (argc != 2)
107: usage();
108:
109: if (!no_target) {
110: if (stat(*argv, &from_sb)) {
111: fprintf(stderr, "install: can't find %s.\n", *argv);
112: exit(1);
113: }
114: if ((to_sb.st_mode & S_IFMT) != S_IFREG) {
115: fprintf(stderr, "install: %s isn't a regular file.\n", to_name);
116: exit(1);
117: }
118: if (to_sb.st_dev == from_sb.st_dev && to_sb.st_ino == from_sb.st_ino) {
119: fprintf(stderr, "install: %s and %s are the same file.\n", *argv, to_name);
120: exit(1);
121: }
122: /* unlink now... avoid ETXTBSY errors later */
123: (void)unlink(to_name);
124: }
125: install(*argv, to_name, NO);
126: exit(0);
127: }
128:
129: /*
130: * install --
131: * build a path name and install the file
132: */
133: static
134: install(from_name, to_name, isdir)
135: char *from_name, *to_name;
136: int isdir;
137: {
138: struct stat from_sb;
139: int devnull, from_fd, to_fd;
140: char *C, *rindex();
141:
142: /* if try to install "/dev/null" to a directory, fails */
143: if (isdir || strcmp(from_name, "/dev/null")) {
144: if (stat(from_name, &from_sb)) {
145: fprintf(stderr, "install: can't find %s.\n", from_name);
146: exit(1);
147: }
148: if ((from_sb.st_mode & S_IFMT) != S_IFREG) {
149: fprintf(stderr, "install: %s isn't a regular file.\n", from_name);
150: exit(1);
151: }
152: /* build the target path */
153: if (isdir) {
154: (void)sprintf(pathbuf, "%s/%s", to_name, (C = rindex(from_name, '/')) ? ++C : from_name);
155: to_name = pathbuf;
156: }
157: devnull = NO;
158: }
159: else
160: devnull = YES;
161:
162: /* unlink now... avoid ETXTBSY errors later */
163: (void)unlink(to_name);
164:
165: /* create target */
166: if ((to_fd = open(to_name, O_CREAT|O_WRONLY|O_TRUNC, 0)) < 0) {
167: PERROR("install: ", to_name);
168: exit(1);
169: }
170: if (!devnull) {
171: if ((from_fd = open(from_name, O_RDONLY, 0)) < 0) {
172: (void)unlink(to_name);
173: PERROR("install: open: ", from_name);
174: exit(1);
175: }
176: if (dostrip)
177: strip(from_fd, from_name, to_fd, to_name);
178: else
179: copy(from_fd, from_name, to_fd, to_name);
180: (void)close(from_fd);
181: if (!docopy)
182: (void)unlink(from_name);
183: }
184: /* set owner, group, mode for target */
185: if (fchmod(to_fd, mode)) {
186: PERROR("install: fchmod: ", to_name);
187: bad();
188: }
189: if ((group || owner) && fchown(to_fd, owner ? pp->pw_uid : -1,
190: group ? gp->gr_gid : -1)) {
191: PERROR("install: fchown: ", to_name);
192: bad();
193: }
194: (void)close(to_fd);
195: }
196:
197: /*
198: * strip --
199: * copy file, strip(1)'ing it at the same time
200: */
201: static
202: strip(from_fd, from_name, to_fd, to_name)
203: register int from_fd, to_fd;
204: char *from_name, *to_name;
205: {
206: typedef struct exec EXEC;
207: register long size;
208: register int n;
209: EXEC head;
210: char buf[MAXBSIZE];
211: off_t lseek();
212:
213: if (read(from_fd, (char *)&head, sizeof(head)) < 0 || N_BADMAG(head)) {
214: fprintf(stderr, "install: %s not in a.out format.\n", from_name);
215: bad();
216: }
217: if (head.a_syms || head.a_trsize || head.a_drsize) {
218: size = (long)head.a_text + head.a_data;
219: head.a_syms = head.a_trsize = head.a_drsize = 0;
220: if (head.a_magic == ZMAGIC)
221: size += getpagesize() - sizeof(EXEC);
222: if (write(to_fd, (char *)&head, sizeof(EXEC)) != sizeof(EXEC)) {
223: PERROR("install: write: ", to_name);
224: bad();
225: }
226: for (; size; size -= n)
227: /* sizeof(buf) guaranteed to fit in an int */
228: if ((n = read(from_fd, buf, (int)MIN(size, sizeof(buf)))) <= 0)
229: break;
230: else if (write(to_fd, buf, n) != n) {
231: PERROR("install: write: ", to_name);
232: bad();
233: }
234: if (size) {
235: fprintf(stderr, "install: read: %s: premature EOF.\n", from_name);
236: bad();
237: }
238: if (n == -1) {
239: PERROR("install: read: ", from_name);
240: bad();
241: }
242: }
243: else {
244: (void)lseek(from_fd, 0L, L_SET);
245: copy(from_fd, from_name, to_fd, to_name);
246: }
247: }
248:
249: /*
250: * copy --
251: * copy from one file to another
252: */
253: static
254: copy(from_fd, from_name, to_fd, to_name)
255: register int from_fd, to_fd;
256: char *from_name, *to_name;
257: {
258: register int n;
259: char buf[MAXBSIZE];
260:
261: while ((n = read(from_fd, buf, sizeof(buf))) > 0)
262: if (write(to_fd, buf, n) != n) {
263: PERROR("install: write: ", to_name);
264: bad();
265: }
266: if (n == -1) {
267: PERROR("install: read: ", from_name);
268: bad();
269: }
270: }
271:
272: /*
273: * atoo --
274: * octal string to int
275: */
276: static
277: atoo(str)
278: register char *str;
279: {
280: register int val;
281:
282: for (val = 0; isdigit(*str); ++str)
283: val = val * 8 + *str - '0';
284: return(val);
285: }
286:
287: /*
288: * bad --
289: * remove created target and die
290: */
291: static
292: bad()
293: {
294: (void)unlink(pathbuf);
295: exit(1);
296: }
297:
298: /*
299: * usage --
300: * print a usage message and die
301: */
302: static
303: usage()
304: {
305: fputs("usage: install [-cs] [-g group] [-m mode] [-o owner] file1 file2;\n\tor file1 ... fileN directory\n", stderr);
306: exit(1);
307: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.