1: /*
   2:  * Copyright (c) 1987, 1993
   3:  *	The Regents of the University of California.  All rights reserved.
   4:  *
   5:  * Redistribution and use in source and binary forms, with or without
   6:  * modification, are permitted provided that the following conditions
   7:  * are met:
   8:  * 1. Redistributions of source code must retain the above copyright
   9:  *    notice, this list of conditions and the following disclaimer.
  10:  * 2. Redistributions in binary form must reproduce the above copyright
  11:  *    notice, this list of conditions and the following disclaimer in the
  12:  *    documentation and/or other materials provided with the distribution.
  13:  * 3. All advertising materials mentioning features or use of this software
  14:  *    must display the following acknowledgement:
  15:  *	This product includes software developed by the University of
  16:  *	California, Berkeley and its contributors.
  17:  * 4. Neither the name of the University nor the names of its contributors
  18:  *    may be used to endorse or promote products derived from this software
  19:  *    without specific prior written permission.
  20:  *
  21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31:  * SUCH DAMAGE.
  32:  */
  33: 
  34: #if !defined(lint) && defined(DOSCCS)
  35: static char copyright[] =
  36: "@(#) Copyright (c) 1987, 1993\n\
  37: 	The Regents of the University of California.  All rights reserved.\n";
  38: 
  39: static char sccsid[] = "@(#)xinstall.c	8.1.1 (2.11BSD) 1996/2/21";
  40: #endif /* not lint */
  41: 
  42: #include <sys/param.h>
  43: #include <sys/wait.h>
  44: #include <sys/stat.h>
  45: 
  46: #include <ctype.h>
  47: #include <errno.h>
  48: #include <fcntl.h>
  49: #include <grp.h>
  50: #include <paths.h>
  51: #include <pwd.h>
  52: #include <stdio.h>
  53: #include <stdlib.h>
  54: #include <string.h>
  55: #include <unistd.h>
  56: 
  57: #include "pathnames.h"
  58: 
  59: struct passwd *pp;
  60: struct group *gp;
  61: int docopy, dostrip;
  62: int mode = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
  63: char *group, *owner, pathbuf[MAXPATHLEN];
  64: 
  65: #define DIRECTORY   0x01        /* Tell install it's a directory. */
  66: #define SETFLAGS    0x02        /* Tell install to set flags. */
  67: 
  68: void    copy();
  69: void    err();
  70: void    install();
  71: u_short string_to_flags();
  72: void    strip();
  73: void    usage();
  74: 
  75: int
  76: main(argc, argv)
  77:     int argc;
  78:     register char *argv[];
  79: {
  80:     struct stat from_sb, to_sb;
  81:     mode_t *set;
  82:     u_short fset;
  83:     u_int iflags;
  84:     int ch, no_target;
  85:     char *flags, *to_name;
  86: 
  87:     iflags = 0;
  88:     while ((ch = getopt(argc, argv, "cf:g:m:o:s")) != EOF)
  89:         switch((char)ch) {
  90:         case 'c':
  91:             docopy = 1;
  92:             break;
  93:         case 'f':
  94:             flags = optarg;
  95:             if (string_to_flags(&flags, &fset, NULL))
  96:                 err("%s: invalid flag", flags);
  97:             iflags |= SETFLAGS;
  98:             break;
  99:         case 'g':
 100:             group = optarg;
 101:             break;
 102:         case 'm':
 103:             if (!(set = (mode_t *)setmode(optarg)))
 104:                 err("%s: invalid file mode", optarg);
 105:             mode = getmode(set, 0);
 106:             break;
 107:         case 'o':
 108:             owner = optarg;
 109:             break;
 110:         case 's':
 111:             dostrip = 1;
 112:             break;
 113:         case '?':
 114:         default:
 115:             usage();
 116:         }
 117:     argc -= optind;
 118:     argv += optind;
 119:     if (argc < 2)
 120:         usage();
 121: 
 122:     /* get group and owner id's */
 123:     if (group && !(gp = getgrnam(group)))
 124:         err("unknown group %s", group);
 125:     if (owner && !(pp = getpwnam(owner)))
 126:         err("unknown user %s", owner);
 127: 
 128:     no_target = stat(to_name = argv[argc - 1], &to_sb);
 129:     if (!no_target && (to_sb.st_mode & S_IFMT) == S_IFDIR) {
 130:         for (; *argv != to_name; ++argv)
 131:             install(*argv, to_name, fset, iflags | DIRECTORY);
 132:         exit(0);
 133:     }
 134: 
 135:     /* can't do file1 file2 directory/file */
 136:     if (argc != 2)
 137:         usage();
 138: 
 139:     if (!no_target) {
 140:         if (stat(*argv, &from_sb))
 141:             err("%s: %s", *argv, strerror(errno));
 142:         if ((to_sb.st_mode & S_IFMT) != S_IFREG)
 143:             err("%s: %s", to_name, strerror(EFTYPE));
 144:         if (to_sb.st_dev == from_sb.st_dev &&
 145:             to_sb.st_ino == from_sb.st_ino)
 146:             err("%s and %s are the same file", *argv, to_name);
 147:         /*
 148: 		 * Unlink now... avoid ETXTBSY errors later.  Try and turn
 149: 		 * off the append/immutable bits -- if we fail, go ahead,
 150: 		 * it might work.
 151: 		 */
 152: #define NOCHANGEBITS    (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND)
 153:         if (to_sb.st_flags & NOCHANGEBITS)
 154:             (void)chflags(to_name,
 155:                 to_sb.st_flags & ~(NOCHANGEBITS));
 156:         (void)unlink(to_name);
 157:     }
 158:     install(*argv, to_name, fset, iflags);
 159:     exit(0);
 160: }
 161: 
 162: /*
 163:  * install --
 164:  *	build a path name and install the file
 165:  */
 166: void
 167: install(from_name, to_name, fset, flags)
 168:     register char *from_name, *to_name;
 169:     u_short fset;
 170:     u_int flags;
 171: {
 172:     struct stat from_sb, to_sb;
 173:     int devnull, from_fd, to_fd, serrno;
 174:     register char *p;
 175: 
 176:     /* If try to install NULL file to a directory, fails. */
 177:     if (flags & DIRECTORY || strcmp(from_name, _PATH_DEVNULL)) {
 178:         if (stat(from_name, &from_sb))
 179:             err("%s: %s", from_name, strerror(errno));
 180:         if ((from_sb.st_mode & S_IFMT) != S_IFREG)
 181:             err("%s: %s", from_name, strerror(EFTYPE));
 182:         /* Build the target path. */
 183:         if (flags & DIRECTORY) {
 184:             (void)sprintf(pathbuf, "%s/%s", to_name,
 185:                 (p = rindex(from_name, '/')) ? ++p : from_name);
 186:             to_name = pathbuf;
 187:         }
 188:         devnull = 0;
 189:     } else {
 190:         from_sb.st_flags = 0;   /* XXX */
 191:         devnull = 1;
 192:     }
 193: 
 194:     /*
 195: 	 * Unlink now... avoid ETXTBSY errors later.  Try and turn
 196: 	 * off the append/immutable bits -- if we fail, go ahead,
 197: 	 * it might work.
 198: 	 */
 199:     if (stat(to_name, &to_sb) == 0 &&
 200:         to_sb.st_flags & (NOCHANGEBITS))
 201:         (void)chflags(to_name, to_sb.st_flags & ~(NOCHANGEBITS));
 202:     (void)unlink(to_name);
 203: 
 204:     /* Create target. */
 205:     if ((to_fd = open(to_name,
 206:         O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR)) < 0)
 207:         err("%s: %s", to_name, strerror(errno));
 208:     if (!devnull) {
 209:         if ((from_fd = open(from_name, O_RDONLY, 0)) < 0) {
 210:             (void)unlink(to_name);
 211:             err("%s: %s", from_name, strerror(errno));
 212:         }
 213:         copy(from_fd, from_name, to_fd, to_name, from_sb.st_size);
 214:         (void)close(from_fd);
 215:     }
 216:     if (dostrip)
 217:         strip(to_name);
 218:     /*
 219: 	 * Set owner, group, mode for target; do the chown first,
 220: 	 * chown may lose the setuid bits.
 221: 	 */
 222:     if ((group || owner) &&
 223:         fchown(to_fd, owner ? pp->pw_uid : -1, group ? gp->gr_gid : -1)) {
 224:         serrno = errno;
 225:         (void)unlink(to_name);
 226:         err("%s: chown/chgrp: %s", to_name, strerror(serrno));
 227:     }
 228:     if (fchmod(to_fd, mode)) {
 229:         serrno = errno;
 230:         (void)unlink(to_name);
 231:         err("%s: chmod: %s", to_name, strerror(serrno));
 232:     }
 233: 
 234:     /*
 235: 	 * If provided a set of flags, set them, otherwise, preserve the
 236: 	 * flags, except for the dump flag.
 237: 	 */
 238:     if (fchflags(to_fd,
 239:         flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) {
 240:         serrno = errno;
 241:         (void)unlink(to_name);
 242:         err("%s: chflags: %s", to_name, strerror(serrno));
 243:     }
 244: 
 245:     (void)close(to_fd);
 246:     if (!docopy && !devnull && unlink(from_name))
 247:         err("%s: %s", from_name, strerror(errno));
 248: }
 249: 
 250: /*
 251:  * copy --
 252:  *	copy from one file to another
 253:  */
 254: void
 255: copy(from_fd, from_name, to_fd, to_name, size)
 256:     register int from_fd, to_fd;
 257:     char *from_name, *to_name;
 258:     off_t size;
 259: {
 260:     register int nr, nw;
 261:     int serrno;
 262:     char buf[MAXBSIZE];
 263: 
 264:     while ((nr = read(from_fd, buf, sizeof(buf))) > 0)
 265:         if ((nw = write(to_fd, buf, nr)) != nr) {
 266:             serrno = errno;
 267:             (void)unlink(to_name);
 268:             err("%s: %s",
 269:                 to_name, strerror(nw > 0 ? EIO : serrno));
 270:         }
 271:     if (nr != 0) {
 272:         serrno = errno;
 273:         (void)unlink(to_name);
 274:         err("%s: %s", from_name, strerror(serrno));
 275:     }
 276: }
 277: 
 278: /*
 279:  * strip --
 280:  *	use strip(1) to strip the target file
 281:  */
 282: void
 283: strip(to_name)
 284:     register char *to_name;
 285: {
 286:     register int serrno;
 287:     int status;
 288: 
 289:     switch (vfork()) {
 290:     case -1:
 291:         serrno = errno;
 292:         (void)unlink(to_name);
 293:         err("forks: %s", strerror(errno));
 294:     case 0:
 295:         execl(_PATH_STRIP, "strip", to_name, NULL);
 296:         err("%s: %s", _PATH_STRIP, strerror(errno));
 297:     default:
 298:         if (wait(&status) == -1 || status)
 299:             (void)unlink(to_name);
 300:     }
 301: }
 302: 
 303: /*
 304:  * usage --
 305:  *	print a usage message and die
 306:  */
 307: void
 308: usage()
 309: {
 310:     (void)fprintf(stderr,
 311: "usage: install [-cs] [-f flags] [-g group] [-m mode] [-o owner] file1 file2;\n\tor file1 ... fileN directory\n");
 312:     exit(1);
 313: }
 314: 
 315: #if __STDC__
 316: #include <stdarg.h>
 317: #else
 318: #include <varargs.h>
 319: #endif
 320: 
 321: void
 322: #if __STDC__
 323: err(const char *fmt, ...)
 324: #else
 325: err(fmt, va_alist)
 326:     char *fmt;
 327:         va_dcl
 328: #endif
 329: {
 330:     va_list ap;
 331: #if __STDC__
 332:     va_start(ap, fmt);
 333: #else
 334:     va_start(ap);
 335: #endif
 336:     (void)fprintf(stderr, "install: ");
 337:     (void)vfprintf(stderr, fmt, ap);
 338:     va_end(ap);
 339:     (void)fprintf(stderr, "\n");
 340:     exit(1);
 341:     /* NOTREACHED */
 342: }

Defined functions

copy defined in line 254; used 2 times
err defined in line 321; used 20 times
install defined in line 166; used 3 times
main defined in line 75; never used
strip defined in line 282; used 2 times
usage defined in line 307; used 4 times

Defined variables

copyright defined in line 35; never used
docopy defined in line 61; used 2 times
dostrip defined in line 61; used 2 times
gp defined in line 60; used 2 times
group defined in line 63; used 6 times
mode defined in line 62; used 2 times
owner defined in line 63; used 6 times
pathbuf defined in line 63; used 2 times
pp defined in line 59; used 2 times
sccsid defined in line 39; never used

Defined macros

DIRECTORY defined in line 65; used 3 times
NOCHANGEBITS defined in line 152; used 4 times
SETFLAGS defined in line 66; used 2 times
Last modified: 1996-02-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4220
Valid CSS Valid XHTML 1.0 Strict