|
|
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.