# 2.11BSD#431 - /usr/src/usr.bin/xinstall/xinstall.c

##### Functions

    copy              X
    err               X
    install           X
    main              X
    strip             X
    usage             X

##### Variables

    docopy            X
    dostrip           X
    gp                X
    group             X
    mode              X
    owner             X
    pathbuf           X
    pp                X

##### Macros

    DIRECTORY         X
    NOCHANGEBITS      X
    SETFLAGS          X

       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

- in line 68, 213

err defined in line 321; used 20 times

- in line 69, 96, 104, 124-126(2), 141-146(3), 179-181(2), 207-211(2), 226-231(2), 242-247(2), 268, 274, 293-296(2)

install defined in line 166; used 3 times

- in line 70, 131, 158

main defined in line 75; never used
strip defined in line 282; used 2 times

- in line 72, 217

usage defined in line 307; used 4 times

- in line 73, 115-120(2), 137

#### Defined variables

copyright defined in line 35; never used
docopy defined in line 61; used 2 times

- in line 91, 246

dostrip defined in line 61; used 2 times

- in line 111, 216

gp defined in line 60; used 2 times

- in line 123, 223

group defined in line 63; used 6 times

- in line 100, 123-124(3), 222-223(2)

mode defined in line 62; used 2 times

- in line 105, 228

owner defined in line 63; used 6 times

- in line 108, 125-126(3), 222-223(2)

pathbuf defined in line 63; used 2 times

- in line 184-186(2)

pp defined in line 59; used 2 times

- in line 125, 223

sccsid defined in line 39; never used

#### Defined macros

DIRECTORY defined in line 65; used 3 times

- in line 131, 177, 183

NOCHANGEBITS defined in line 152; used 4 times

- in line 153-155(2), 200-201(2)

SETFLAGS defined in line 66; used 2 times

- in line 97, 239

Last modified: 1996-02-21 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1980 |