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