1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 
  26 #include <stdio.h>
  27 #include <stdlib.h>
  28 #include <strings.h>
  29 #include <sys/param.h>
  30 #include <fcntl.h>
  31 #include <sys/errno.h>
  32 #include <sys/types.h>
  33 #include <sys/uio.h>
  34 #include <unistd.h>
  35 #include <sys/stat.h>
  36 #include <errno.h>
  37 #include <libgen.h>
  38 #include "stdusers.h"
  39 
  40 
  41 #define FILE_BUFF       40960
  42 
  43 static int suppress = 0;
  44 
  45 static void usage(void);
  46 static void file_copy(char *src_file, char *dest_file);
  47 static void chown_file(const char *file, const char *group, const char *owner);
  48 static char *find_basename(const char *str);
  49 static int creatdir(char *fn);
  50 
  51 
  52 void
  53 usage(void)
  54 {
  55         (void) fprintf(stderr,
  56             "usage: install [-sd][-m mode][-g group][-u owner] "
  57             "-f dir file ...\n");
  58 }
  59 
  60 void
  61 file_copy(char *src_file, char *dest_file)
  62 {
  63         int     src_fd;
  64         int     dest_fd;
  65         int     count;
  66         static char file_buff[FILE_BUFF];
  67 
  68         if ((src_fd = open(src_file, O_RDONLY))  == -1) {
  69                 (void) fprintf(stderr, "install:file_copy: %s failed "
  70                     "(%d): %s\n", src_file, errno, strerror(errno));
  71                 exit(1);
  72         }
  73 
  74         if ((dest_fd = open(dest_file, O_CREAT|O_WRONLY|O_TRUNC, 0755)) == -1) {
  75                 (void) fprintf(stderr, "install:file_copy: %s failed "
  76                     "(%d): %s\n", dest_file, errno, strerror(errno));
  77                 exit(1);
  78         }
  79 
  80         while ((count = read(src_fd, file_buff, FILE_BUFF)) > 0) {
  81                 (void) write(dest_fd, file_buff, count);
  82         }
  83 
  84         if (count == -1) {
  85                 (void) fprintf(stderr, "install:file_copy:read failed "
  86                     "(%d): %s\n", errno, strerror(errno));
  87                 exit(1);
  88         }
  89 
  90         if (!suppress)
  91                 (void) printf("%s installed as %s\n", src_file, dest_file);
  92 
  93         (void) close(src_fd);
  94         (void) close(dest_fd);
  95 }
  96 
  97 
  98 void
  99 chown_file(const char *file, const char *group, const char *owner)
 100 {
 101         gid_t   grp = (gid_t)-1;
 102         uid_t   own = (uid_t)-1;
 103 
 104         if (group) {
 105                 grp = stdfind(group, groupnames);
 106                 if (grp < 0)
 107                         (void) fprintf(stderr, "unknown group(%s)\n", group);
 108         }
 109 
 110         if (owner) {
 111                 own = stdfind(owner, usernames);
 112                 if (own < 0) {
 113                         (void) fprintf(stderr, "unknown owner(%s)\n", owner);
 114                         exit(1);
 115                 }
 116 
 117         }
 118 
 119         if (chown(file, own, grp) == -1) {
 120                 (void) fprintf(stderr, "install:chown_file: failed "
 121                     "(%d): %s\n", errno, strerror(errno));
 122                 exit(1);
 123         }
 124 }
 125 
 126 
 127 char *
 128 find_basename(const char *str)
 129 {
 130         int     i;
 131         int     len;
 132 
 133         len = strlen(str);
 134 
 135         for (i = len-1; i >= 0; i--)
 136                 if (str[i] == '/')
 137                         return ((char *)(str + i + 1));
 138         return ((char *)str);
 139 }
 140 
 141 int
 142 creatdir(char *fn) {
 143 
 144         errno = 0;
 145 
 146         if (mkdirp(fn, 0755) == -1) {
 147                 if (errno != EEXIST)
 148                         return (errno);
 149         } else if (!suppress) {
 150                 (void) printf("directory %s created\n", fn);
 151         }
 152         return (0);
 153 }
 154 
 155 
 156 int
 157 main(int argc, char **argv)
 158 {
 159         int     c;
 160         int     errflg = 0;
 161         int     dirflg = 0;
 162         char    *group = NULL;
 163         char    *owner = NULL;
 164         char    *dirb = NULL;
 165         char    *ins_file = NULL;
 166         int     mode = -1;
 167         char    dest_file[MAXPATHLEN];
 168         int     rv = 0;
 169 
 170         while ((c = getopt(argc, argv, "f:sm:du:g:")) != EOF) {
 171                 switch (c) {
 172                 case 'f':
 173                         dirb = optarg;
 174                         break;
 175                 case 'g':
 176                         group = optarg;
 177                         break;
 178                 case 'u':
 179                         owner = optarg;
 180                         break;
 181                 case 'd':
 182                         dirflg = 1;
 183                         break;
 184                 case 'm':
 185                         mode = strtol(optarg, NULL, 8);
 186                         break;
 187                 case 's':
 188                         suppress = 1;
 189                         break;
 190                 case '?':
 191                         errflg++;
 192                         break;
 193                 }
 194         }
 195 
 196         if (errflg) {
 197                 usage();
 198                 return (1);
 199         }
 200 
 201         if (argc == optind) {
 202                 usage();
 203                 return (1);
 204         }
 205 
 206         if (!dirflg && (dirb == NULL)) {
 207                 (void) fprintf(stderr,
 208                     "install: no destination directory specified.\n");
 209                 return (1);
 210         }
 211 
 212         for (c = optind; c < argc; c++) {
 213                 ins_file = argv[c];
 214 
 215                 if (dirflg) {
 216                         rv = creatdir(ins_file);
 217                         if (rv) {
 218                                 (void) fprintf(stderr,
 219                                     "install: creatdir %s (%d): %s\n",
 220                                     ins_file, errno, strerror(errno));
 221                                 return (rv);
 222                         }
 223                         (void) strlcpy(dest_file, ins_file, MAXPATHLEN);
 224 
 225                 } else {
 226                         (void) strcat(strcat(strcpy(dest_file, dirb), "/"),
 227                             find_basename(ins_file));
 228                         file_copy(ins_file, dest_file);
 229                 }
 230 
 231                 if (group || owner)
 232                         chown_file(dest_file, group, owner);
 233 
 234                 if (mode != -1) {
 235                         (void) umask(0);
 236                         if (chmod(dest_file, mode) == -1) {
 237                                 (void) fprintf(stderr,
 238                                     "install: chmod of %s to mode %o failed "
 239                                     "(%d): %s\n",
 240                                     dest_file, mode, errno, strerror(errno));
 241                                 return (1);
 242                         }
 243                 }
 244         }
 245         return (0);
 246 }