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