|
|
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 provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: char copyright[] =
22: "@(#) Copyright (c) 1987 Regents of the University of California.\n\
23: All rights reserved.\n";
24: #endif /* not lint */
25:
26: #ifndef lint
27: static char sccsid[] = "@(#)xinstall.c 5.24 (Berkeley) 7/1/90";
28: #endif /* not lint */
29:
30: #include <sys/param.h>
31: #include <sys/stat.h>
32: #include <sys/file.h>
33: #include <grp.h>
34: #include <pwd.h>
35: #include <stdio.h>
36: #include <ctype.h>
37: #include <paths.h>
38: #include "pathnames.h"
39:
40: static struct passwd *pp;
41: static struct group *gp;
42: static int docopy, dostrip, mode = 0755;
43: static char *group, *owner, pathbuf[MAXPATHLEN];
44:
45: main(argc, argv)
46: int argc;
47: char **argv;
48: {
49: extern char *optarg;
50: extern int optind;
51: struct stat from_sb, to_sb;
52: mode_t *set, *setmode();
53: int ch, no_target;
54: char *to_name;
55:
56: while ((ch = getopt(argc, argv, "cg:m:o:s")) != EOF)
57: switch((char)ch) {
58: case 'c':
59: docopy = 1;
60: break;
61: case 'g':
62: group = optarg;
63: break;
64: case 'm':
65: if (!(set = setmode(optarg))) {
66: (void)fprintf(stderr,
67: "install: invalid file mode.\n");
68: exit(1);
69: }
70: mode = getmode(set, 0);
71: break;
72: case 'o':
73: owner = optarg;
74: break;
75: case 's':
76: dostrip = 1;
77: break;
78: case '?':
79: default:
80: usage();
81: }
82: argc -= optind;
83: argv += optind;
84: if (argc < 2)
85: usage();
86:
87: /* get group and owner id's */
88: if (group && !(gp = getgrnam(group))) {
89: fprintf(stderr, "install: unknown group %s.\n", group);
90: exit(1);
91: }
92: if (owner && !(pp = getpwnam(owner))) {
93: fprintf(stderr, "install: unknown user %s.\n", owner);
94: exit(1);
95: }
96:
97: no_target = stat(to_name = argv[argc - 1], &to_sb);
98: if (!no_target && (to_sb.st_mode & S_IFMT) == S_IFDIR) {
99: for (; *argv != to_name; ++argv)
100: install(*argv, to_name, 1);
101: exit(0);
102: }
103:
104: /* can't do file1 file2 directory/file */
105: if (argc != 2)
106: usage();
107:
108: if (!no_target) {
109: if (stat(*argv, &from_sb)) {
110: fprintf(stderr, "install: can't find %s.\n", *argv);
111: exit(1);
112: }
113: if ((to_sb.st_mode & S_IFMT) != S_IFREG) {
114: fprintf(stderr, "install: %s isn't a regular file.\n", to_name);
115: exit(1);
116: }
117: if (to_sb.st_dev == from_sb.st_dev && to_sb.st_ino == from_sb.st_ino) {
118: fprintf(stderr, "install: %s and %s are the same file.\n", *argv, to_name);
119: exit(1);
120: }
121: /* unlink now... avoid ETXTBSY errors later */
122: (void)unlink(to_name);
123: }
124: install(*argv, to_name, 0);
125: exit(0);
126: }
127:
128: /*
129: * install --
130: * build a path name and install the file
131: */
132: install(from_name, to_name, isdir)
133: char *from_name, *to_name;
134: int isdir;
135: {
136: struct stat from_sb;
137: int devnull, from_fd, to_fd;
138: char *C, *rindex();
139:
140: /* if try to install NULL file to a directory, fails */
141: if (isdir || strcmp(from_name, _PATH_DEVNULL)) {
142: if (stat(from_name, &from_sb)) {
143: fprintf(stderr, "install: can't find %s.\n", from_name);
144: exit(1);
145: }
146: if ((from_sb.st_mode & S_IFMT) != S_IFREG) {
147: fprintf(stderr, "install: %s isn't a regular file.\n", from_name);
148: exit(1);
149: }
150: /* build the target path */
151: if (isdir) {
152: (void)sprintf(pathbuf, "%s/%s", to_name, (C = rindex(from_name, '/')) ? ++C : from_name);
153: to_name = pathbuf;
154: }
155: devnull = 0;
156: } else
157: devnull = 1;
158:
159: /* unlink now... avoid ETXTBSY errors later */
160: (void)unlink(to_name);
161:
162: /* create target */
163: if ((to_fd = open(to_name, O_CREAT|O_WRONLY|O_TRUNC, 0600)) < 0) {
164: error(to_name);
165: exit(1);
166: }
167: if (!devnull) {
168: if ((from_fd = open(from_name, O_RDONLY, 0)) < 0) {
169: (void)unlink(to_name);
170: error(from_name);
171: exit(1);
172: }
173: copy(from_fd, from_name, to_fd, to_name);
174: (void)close(from_fd);
175: }
176: if (dostrip)
177: strip(to_name);
178: /*
179: * set owner, group, mode for target; do the chown first,
180: * chown may lose the setuid bits.
181: */
182: if ((group || owner) &&
183: fchown(to_fd, owner ? pp->pw_uid : -1, group ? gp->gr_gid : -1) ||
184: fchmod(to_fd, mode)) {
185: error(to_name);
186: bad(to_name);
187: }
188: (void)close(to_fd);
189: if (!docopy && !devnull && unlink(from_name)) {
190: error(from_name);
191: exit(1);
192: }
193: }
194:
195: /*
196: * copy --
197: * copy from one file to another
198: */
199: copy(from_fd, from_name, to_fd, to_name)
200: register int from_fd, to_fd;
201: char *from_name, *to_name;
202: {
203: register int n;
204: char buf[MAXBSIZE];
205:
206: while ((n = read(from_fd, buf, sizeof(buf))) > 0)
207: if (write(to_fd, buf, n) != n) {
208: error(to_name);
209: bad(to_name);
210: }
211: if (n == -1) {
212: error(from_name);
213: bad(to_name);
214: }
215: }
216:
217: /*
218: * strip --
219: * use strip(1) to strip the target file
220: */
221: strip(to_name)
222: char *to_name;
223: {
224: int status;
225:
226: switch (vfork()) {
227: case -1:
228: error("fork");
229: bad(to_name);
230: case 0:
231: execl(_PATH_STRIP, "strip", to_name, (char *)NULL);
232: error(_PATH_STRIP);
233: _exit(1);
234: default:
235: if (wait(&status) == -1 || status)
236: bad(to_name);
237: }
238: }
239:
240: /*
241: * error --
242: * print out an error message
243: */
244: error(s)
245: char *s;
246: {
247: extern int errno;
248: char *strerror();
249:
250: (void)fprintf(stderr, "install: %s: %s\n", s, strerror(errno));
251: }
252:
253: /*
254: * bad --
255: * remove created target and die
256: */
257: bad(fname)
258: char *fname;
259: {
260: (void)unlink(fname);
261: exit(1);
262: }
263:
264: /*
265: * usage --
266: * print a usage message and die
267: */
268: usage()
269: {
270: (void)fprintf(stderr,
271: "usage: install [-cs] [-g group] [-m mode] [-o owner] file1 file2;\n\tor file1 ... fileN directory\n");
272: exit(1);
273: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.