Commit | Line | Data |
---|---|---|
9daf6813 KB |
1 | /* |
2 | * Copyright (c) 1987 Regents of the University of California. | |
a541407a KB |
3 | * All rights reserved. |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
5e8b0e60 KB |
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. | |
9daf6813 KB |
16 | */ |
17 | ||
18 | #ifndef lint | |
19 | char copyright[] = | |
20 | "@(#) Copyright (c) 1987 Regents of the University of California.\n\ | |
21 | All rights reserved.\n"; | |
a541407a | 22 | #endif /* not lint */ |
9daf6813 KB |
23 | |
24 | #ifndef lint | |
57d64e93 | 25 | static char sccsid[] = "@(#)xinstall.c 5.13 (Berkeley) %G%"; |
a541407a | 26 | #endif /* not lint */ |
9daf6813 KB |
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 | ||
a541407a KB |
37 | #define YES 1 /* yes/true */ |
38 | #define NO 0 /* no/false */ | |
9daf6813 | 39 | |
75e0e63a KB |
40 | #define PERROR(head, msg) { \ |
41 | fputs(head, stderr); \ | |
42 | perror(msg); \ | |
43 | } | |
9daf6813 | 44 | |
57d64e93 KB |
45 | static struct passwd *pp; |
46 | static struct group *gp; | |
47 | static int docopy, dostrip, mode = 0755; | |
48 | static char *group, *owner, pathbuf[MAXPATHLEN]; | |
6544b76d | 49 | |
9daf6813 | 50 | main(argc, argv) |
f31e9bdc KB |
51 | int argc; |
52 | char **argv; | |
9daf6813 | 53 | { |
f31e9bdc KB |
54 | extern char *optarg; |
55 | extern int optind; | |
56 | struct stat from_sb, to_sb; | |
57 | int ch, no_target; | |
58 | char *to_name; | |
9daf6813 KB |
59 | |
60 | while ((ch = getopt(argc, argv, "cg:m:o:s")) != EOF) | |
61 | switch((char)ch) { | |
62 | case 'c': | |
63 | docopy = YES; | |
64 | break; | |
65 | case 'g': | |
66 | group = optarg; | |
67 | break; | |
68 | case 'm': | |
69 | mode = atoo(optarg); | |
70 | break; | |
71 | case 'o': | |
72 | owner = optarg; | |
73 | break; | |
74 | case 's': | |
75 | dostrip = YES; | |
76 | break; | |
77 | case '?': | |
78 | default: | |
79 | usage(); | |
80 | } | |
81 | argc -= optind; | |
82 | argv += optind; | |
6544b76d | 83 | if (argc < 2) |
9daf6813 KB |
84 | usage(); |
85 | ||
5f10a190 | 86 | /* get group and owner id's */ |
cd03af1a | 87 | if (group && !(gp = getgrnam(group))) { |
5f10a190 KB |
88 | fprintf(stderr, "install: unknown group %s.\n", group); |
89 | exit(1); | |
90 | } | |
cd03af1a | 91 | if (owner && !(pp = getpwnam(owner))) { |
5f10a190 KB |
92 | fprintf(stderr, "install: unknown user %s.\n", owner); |
93 | exit(1); | |
94 | } | |
95 | ||
6544b76d | 96 | no_target = stat(to_name = argv[argc - 1], &to_sb); |
20264d07 | 97 | if (!no_target && (to_sb.st_mode & S_IFMT) == S_IFDIR) { |
6544b76d KB |
98 | for (; *argv != to_name; ++argv) |
99 | install(*argv, to_name, YES); | |
100 | exit(0); | |
9daf6813 KB |
101 | } |
102 | ||
6544b76d KB |
103 | /* can't do file1 file2 directory/file */ |
104 | if (argc != 2) | |
105 | usage(); | |
426871e1 | 106 | |
6544b76d KB |
107 | if (!no_target) { |
108 | if (stat(*argv, &from_sb)) { | |
109 | fprintf(stderr, "install: can't find %s.\n", *argv); | |
110 | exit(1); | |
426871e1 | 111 | } |
20264d07 | 112 | if ((to_sb.st_mode & S_IFMT) != S_IFREG) { |
6544b76d | 113 | fprintf(stderr, "install: %s isn't a regular file.\n", to_name); |
426871e1 | 114 | exit(1); |
9daf6813 KB |
115 | } |
116 | if (to_sb.st_dev == from_sb.st_dev && to_sb.st_ino == from_sb.st_ino) { | |
6544b76d | 117 | fprintf(stderr, "install: %s and %s are the same file.\n", *argv, to_name); |
9daf6813 KB |
118 | exit(1); |
119 | } | |
120 | /* unlink now... avoid ETXTBSY errors later */ | |
6544b76d KB |
121 | (void)unlink(to_name); |
122 | } | |
123 | install(*argv, to_name, NO); | |
124 | exit(0); | |
125 | } | |
126 | ||
127 | /* | |
128 | * install -- | |
129 | * build a path name and install the file | |
130 | */ | |
6544b76d | 131 | install(from_name, to_name, isdir) |
f31e9bdc KB |
132 | char *from_name, *to_name; |
133 | int isdir; | |
6544b76d | 134 | { |
f31e9bdc KB |
135 | struct stat from_sb; |
136 | int devnull, from_fd, to_fd; | |
137 | char *C, *rindex(); | |
6544b76d KB |
138 | |
139 | /* if try to install "/dev/null" to a directory, fails */ | |
a541407a KB |
140 | if (isdir || strcmp(from_name, "/dev/null")) { |
141 | if (stat(from_name, &from_sb)) { | |
6544b76d KB |
142 | fprintf(stderr, "install: can't find %s.\n", from_name); |
143 | exit(1); | |
144 | } | |
20264d07 | 145 | if ((from_sb.st_mode & S_IFMT) != S_IFREG) { |
6544b76d KB |
146 | fprintf(stderr, "install: %s isn't a regular file.\n", from_name); |
147 | exit(1); | |
148 | } | |
a541407a KB |
149 | /* build the target path */ |
150 | if (isdir) { | |
151 | (void)sprintf(pathbuf, "%s/%s", to_name, (C = rindex(from_name, '/')) ? ++C : from_name); | |
152 | to_name = pathbuf; | |
153 | } | |
154 | devnull = NO; | |
9daf6813 | 155 | } |
a541407a KB |
156 | else |
157 | devnull = YES; | |
6544b76d KB |
158 | |
159 | /* unlink now... avoid ETXTBSY errors later */ | |
160 | (void)unlink(to_name); | |
161 | ||
a541407a | 162 | /* create target */ |
6544b76d | 163 | if ((to_fd = open(to_name, O_CREAT|O_WRONLY|O_TRUNC, 0)) < 0) { |
75e0e63a | 164 | PERROR("install: ", to_name); |
9daf6813 KB |
165 | exit(1); |
166 | } | |
a541407a KB |
167 | if (!devnull) { |
168 | if ((from_fd = open(from_name, O_RDONLY, 0)) < 0) { | |
169 | (void)unlink(to_name); | |
170 | PERROR("install: open: ", from_name); | |
171 | exit(1); | |
172 | } | |
173 | if (dostrip) | |
174 | strip(from_fd, from_name, to_fd, to_name); | |
175 | else | |
176 | copy(from_fd, from_name, to_fd, to_name); | |
177 | (void)close(from_fd); | |
178 | if (!docopy) | |
179 | (void)unlink(from_name); | |
180 | } | |
181 | /* set owner, group, mode for target */ | |
9daf6813 | 182 | if (fchmod(to_fd, mode)) { |
75e0e63a | 183 | PERROR("install: fchmod: ", to_name); |
5f10a190 | 184 | bad(); |
9daf6813 | 185 | } |
a541407a KB |
186 | if ((group || owner) && fchown(to_fd, owner ? pp->pw_uid : -1, |
187 | group ? gp->gr_gid : -1)) { | |
75e0e63a | 188 | PERROR("install: fchown: ", to_name); |
5f10a190 | 189 | bad(); |
9daf6813 | 190 | } |
6544b76d | 191 | (void)close(to_fd); |
9daf6813 KB |
192 | } |
193 | ||
194 | /* | |
195 | * strip -- | |
196 | * copy file, strip(1)'ing it at the same time | |
197 | */ | |
6544b76d | 198 | strip(from_fd, from_name, to_fd, to_name) |
f31e9bdc KB |
199 | register int from_fd, to_fd; |
200 | char *from_name, *to_name; | |
9daf6813 | 201 | { |
f31e9bdc KB |
202 | typedef struct exec EXEC; |
203 | register long size; | |
204 | register int n; | |
205 | EXEC head; | |
206 | char buf[MAXBSIZE]; | |
207 | off_t lseek(); | |
9daf6813 | 208 | |
9daf6813 KB |
209 | if (read(from_fd, (char *)&head, sizeof(head)) < 0 || N_BADMAG(head)) { |
210 | fprintf(stderr, "install: %s not in a.out format.\n", from_name); | |
5f10a190 | 211 | bad(); |
9daf6813 KB |
212 | } |
213 | if (head.a_syms || head.a_trsize || head.a_drsize) { | |
214 | size = (long)head.a_text + head.a_data; | |
215 | head.a_syms = head.a_trsize = head.a_drsize = 0; | |
216 | if (head.a_magic == ZMAGIC) | |
217 | size += getpagesize() - sizeof(EXEC); | |
218 | if (write(to_fd, (char *)&head, sizeof(EXEC)) != sizeof(EXEC)) { | |
75e0e63a | 219 | PERROR("install: write: ", to_name); |
5f10a190 | 220 | bad(); |
9daf6813 KB |
221 | } |
222 | for (; size; size -= n) | |
a541407a | 223 | /* sizeof(buf) guaranteed to fit in an int */ |
9daf6813 KB |
224 | if ((n = read(from_fd, buf, (int)MIN(size, sizeof(buf)))) <= 0) |
225 | break; | |
226 | else if (write(to_fd, buf, n) != n) { | |
75e0e63a | 227 | PERROR("install: write: ", to_name); |
5f10a190 | 228 | bad(); |
9daf6813 | 229 | } |
5f10a190 KB |
230 | if (size) { |
231 | fprintf(stderr, "install: read: %s: premature EOF.\n", from_name); | |
232 | bad(); | |
233 | } | |
9daf6813 | 234 | if (n == -1) { |
75e0e63a | 235 | PERROR("install: read: ", from_name); |
5f10a190 | 236 | bad(); |
9daf6813 KB |
237 | } |
238 | } | |
6544b76d | 239 | else { |
cd03af1a | 240 | (void)lseek(from_fd, 0L, L_SET); |
6544b76d KB |
241 | copy(from_fd, from_name, to_fd, to_name); |
242 | } | |
243 | } | |
244 | ||
245 | /* | |
246 | * copy -- | |
247 | * copy from one file to another | |
248 | */ | |
6544b76d | 249 | copy(from_fd, from_name, to_fd, to_name) |
f31e9bdc KB |
250 | register int from_fd, to_fd; |
251 | char *from_name, *to_name; | |
6544b76d | 252 | { |
f31e9bdc KB |
253 | register int n; |
254 | char buf[MAXBSIZE]; | |
6544b76d KB |
255 | |
256 | while ((n = read(from_fd, buf, sizeof(buf))) > 0) | |
257 | if (write(to_fd, buf, n) != n) { | |
75e0e63a | 258 | PERROR("install: write: ", to_name); |
6544b76d KB |
259 | bad(); |
260 | } | |
261 | if (n == -1) { | |
75e0e63a | 262 | PERROR("install: read: ", from_name); |
6544b76d KB |
263 | bad(); |
264 | } | |
9daf6813 KB |
265 | } |
266 | ||
267 | /* | |
268 | * atoo -- | |
269 | * octal string to int | |
270 | */ | |
5f10a190 | 271 | atoo(str) |
f31e9bdc | 272 | register char *str; |
9daf6813 | 273 | { |
f31e9bdc | 274 | register int val; |
9daf6813 | 275 | |
5f10a190 KB |
276 | for (val = 0; isdigit(*str); ++str) |
277 | val = val * 8 + *str - '0'; | |
9daf6813 KB |
278 | return(val); |
279 | } | |
280 | ||
281 | /* | |
6544b76d KB |
282 | * bad -- |
283 | * remove created target and die | |
9daf6813 | 284 | */ |
6544b76d | 285 | bad() |
9daf6813 | 286 | { |
6544b76d | 287 | (void)unlink(pathbuf); |
9daf6813 KB |
288 | exit(1); |
289 | } | |
5f10a190 KB |
290 | |
291 | /* | |
6544b76d KB |
292 | * usage -- |
293 | * print a usage message and die | |
5f10a190 | 294 | */ |
6544b76d | 295 | usage() |
5f10a190 | 296 | { |
75e0e63a | 297 | fputs("usage: install [-cs] [-g group] [-m mode] [-o owner] file1 file2;\n\tor file1 ... fileN directory\n", stderr); |
5f10a190 KB |
298 | exit(1); |
299 | } |