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.11 (Berkeley) 06/18/88"; 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 *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 change(*argv); 86 exit(retval); 87 } 88 89 static 90 setgid(s) 91 register char *s; 92 { 93 struct group *gr, *getgrnam(); 94 95 if (!*s) { 96 gid = -1; /* argument was "uid." */ 97 return; 98 } 99 for (gname = s; *s && isdigit(*s); ++s); 100 if (!*s) 101 gid = atoi(gname); 102 else { 103 if (!(gr = getgrnam(gname))) { 104 if (fflag) 105 exit(0); 106 fprintf(stderr, "%s: unknown group id: %s\n", 107 myname, gname); 108 exit(-1); 109 } 110 gid = gr->gr_gid; 111 } 112 } 113 114 static 115 setuid(s) 116 register char *s; 117 { 118 struct passwd *pwd, *getpwnam(); 119 char *beg; 120 121 if (!*s) { 122 uid = -1; /* argument was ".gid" */ 123 return; 124 } 125 for (beg = s; *s && isdigit(*s); ++s); 126 if (!*s) 127 uid = atoi(beg); 128 else { 129 if (!(pwd = getpwnam(beg))) { 130 if (fflag) 131 exit(0); 132 fprintf(stderr, "chown: unknown user id: %s\n", beg); 133 exit(-1); 134 } 135 uid = pwd->pw_uid; 136 } 137 } 138 139 static 140 change(file) 141 char *file; 142 { 143 register DIR *dirp; 144 register struct direct *dp; 145 struct stat buf; 146 147 if (chown(file, uid, gid)) { 148 chownerr(file); 149 return; 150 } 151 if (!rflag) 152 return; 153 if (lstat(file, &buf)) { 154 err(file); 155 return; 156 } 157 if ((buf.st_mode & S_IFMT) == S_IFDIR) { 158 if (chdir(file) < 0 || !(dirp = opendir("."))) { 159 err(file); 160 return; 161 } 162 for (dp = readdir(dirp); dp; dp = readdir(dirp)) { 163 if (dp->d_name[0] == '.' && (!dp->d_name[1] || 164 dp->d_name[1] == '.' && !dp->d_name[2])) 165 continue; 166 change(dp->d_name); 167 } 168 closedir(dirp); 169 if (chdir("..")) { 170 err(".."); 171 exit(fflag ? 0 : -1); 172 } 173 } 174 } 175 176 static 177 chownerr(file) 178 char *file; 179 { 180 static int euid = -1, ngroups = -1; 181 182 /* check for chown without being root */ 183 if (uid != -1 && euid == -1 && (euid = geteuid())) { 184 if (fflag) 185 exit(0); 186 err(file); 187 exit(-1); 188 } 189 /* check group membership; kernel just returns EPERM */ 190 if (gid != -1 && ngroups == -1) { 191 int groups[NGROUPS]; 192 193 ngroups = getgroups(NGROUPS, groups); 194 while (--ngroups >= 0 && gid != groups[ngroups]); 195 if (ngroups < 0) { 196 if (fflag) 197 exit(0); 198 fprintf(stderr, 199 "%s: you are not a member of group %s.\n", 200 myname, gname); 201 exit(-1); 202 } 203 } 204 err(file); 205 } 206 207 static 208 err(s) 209 char *s; 210 { 211 if (fflag) 212 return; 213 fprintf(stderr, "%s: ", myname); 214 perror(s); 215 retval = -1; 216 } 217 218 static 219 usage() 220 { 221 fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname, 222 ischown ? "owner[.group]" : "group"); 223 exit(-1); 224 } 225