1 /* 2 * Copyright (c) 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1988 Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)chown.c 5.15 (Berkeley) 06/01/90"; 16 #endif /* not lint */ 17 18 #include <sys/param.h> 19 #include <sys/stat.h> 20 #include <sys/errno.h> 21 #include <dirent.h> 22 #include <pwd.h> 23 #include <grp.h> 24 #include <stdio.h> 25 #include <ctype.h> 26 27 int ischown, uid, gid, fflag, rflag, retval; 28 char *gname, *myname; 29 30 main(argc, argv) 31 int argc; 32 char **argv; 33 { 34 extern char *optarg; 35 extern int optind; 36 register char *cp; 37 int ch; 38 char curpath[MAXPATHLEN], *reset, *index(), *rindex(); 39 40 myname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv; 41 ischown = myname[2] == 'o'; 42 43 while ((ch = getopt(argc, argv, "Rf")) != EOF) 44 switch((char)ch) { 45 case 'R': 46 rflag++; 47 break; 48 case 'f': 49 fflag++; 50 break; 51 case '?': 52 default: 53 usage(); 54 } 55 argv += optind; 56 argc -= optind; 57 58 if (argc < 2) 59 usage(); 60 61 if (ischown) { 62 if (cp = index(*argv, '.')) { 63 *cp++ = '\0'; 64 setgid(cp); 65 } 66 else 67 gid = -1; 68 setuid(*argv); 69 } 70 else { 71 uid = -1; 72 setgid(*argv); 73 } 74 75 while (*++argv) { 76 if (reset = index(*argv, '/')) 77 (void)getwd(curpath); 78 change(*argv); 79 if (reset && chdir(curpath)) { 80 if (fflag) 81 exit(0); 82 err(curpath); 83 exit(-1); 84 } 85 } 86 exit(retval); 87 } 88 89 setgid(s) 90 register char *s; 91 { 92 struct group *gr, *getgrnam(); 93 94 if (!*s) { 95 gid = -1; /* argument was "uid." */ 96 return; 97 } 98 for (gname = s; *s && isdigit(*s); ++s); 99 if (!*s) 100 gid = atoi(gname); 101 else { 102 if (!(gr = getgrnam(gname))) { 103 if (fflag) 104 exit(0); 105 (void)fprintf(stderr, "%s: unknown group id: %s\n", 106 myname, gname); 107 exit(-1); 108 } 109 gid = gr->gr_gid; 110 } 111 } 112 113 setuid(s) 114 register char *s; 115 { 116 struct passwd *pwd, *getpwnam(); 117 char *beg; 118 119 if (!*s) { 120 uid = -1; /* argument was ".gid" */ 121 return; 122 } 123 for (beg = s; *s && isdigit(*s); ++s); 124 if (!*s) 125 uid = atoi(beg); 126 else { 127 if (!(pwd = getpwnam(beg))) { 128 if (fflag) 129 exit(0); 130 (void)fprintf(stderr, 131 "chown: unknown user id: %s\n", beg); 132 exit(-1); 133 } 134 uid = pwd->pw_uid; 135 } 136 } 137 138 change(file) 139 char *file; 140 { 141 register DIR *dirp; 142 register struct dirent *dp; 143 struct stat buf; 144 145 if (chown(file, uid, gid)) { 146 chownerr(file); 147 return; 148 } 149 if (!rflag) 150 return; 151 if (lstat(file, &buf)) { 152 err(file); 153 return; 154 } 155 if ((buf.st_mode & S_IFMT) == S_IFDIR) { 156 if (chdir(file) < 0 || !(dirp = opendir("."))) { 157 err(file); 158 return; 159 } 160 for (dp = readdir(dirp); dp; dp = readdir(dirp)) { 161 if (dp->d_name[0] == '.' && (!dp->d_name[1] || 162 dp->d_name[1] == '.' && !dp->d_name[2])) 163 continue; 164 change(dp->d_name); 165 } 166 closedir(dirp); 167 if (chdir("..")) { 168 err(".."); 169 exit(fflag ? 0 : -1); 170 } 171 } 172 } 173 174 chownerr(file) 175 char *file; 176 { 177 extern int errno; 178 static int euid = -1, ngroups = -1; 179 180 /* check for chown without being root */ 181 if (errno != EPERM || uid != -1 && euid == -1 && (euid = geteuid())) { 182 if (fflag) 183 exit(0); 184 err(file); 185 exit(-1); 186 } 187 /* check group membership; kernel just returns EPERM */ 188 if (gid != -1 && ngroups == -1) { 189 int groups[NGROUPS]; 190 191 ngroups = getgroups(NGROUPS, groups); 192 while (--ngroups >= 0 && gid != groups[ngroups]); 193 if (ngroups < 0) { 194 if (fflag) 195 exit(0); 196 (void)fprintf(stderr, 197 "%s: you are not a member of group %s.\n", 198 myname, gname); 199 exit(-1); 200 } 201 } 202 err(file); 203 } 204 205 err(s) 206 char *s; 207 { 208 extern int errno; 209 char *strerror(); 210 211 if (fflag) 212 return; 213 (void)fprintf(stderr, "%s: %s: %s\n", myname, s, strerror(errno)); 214 retval = -1; 215 } 216 217 usage() 218 { 219 (void)fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname, 220 ischown ? "owner[.group]" : "group"); 221 exit(-1); 222 } 223