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.18 (Berkeley) 03/09/91"; 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 <fts.h> 23 #include <pwd.h> 24 #include <grp.h> 25 #include <unistd.h> 26 #include <stdio.h> 27 #include <ctype.h> 28 #include <stdlib.h> 29 #include <string.h> 30 31 int ischown, uid, gid, fflag, rflag, retval; 32 char *gname, *myname; 33 34 main(argc, argv) 35 int argc; 36 char **argv; 37 { 38 extern int optind; 39 register FTS *fts; 40 register FTSENT *p; 41 register char *cp; 42 int ch; 43 44 myname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv; 45 ischown = myname[2] == 'o'; 46 47 while ((ch = getopt(argc, argv, "Rf")) != EOF) 48 switch((char)ch) { 49 case 'R': 50 rflag = 1; 51 break; 52 case 'f': 53 fflag = 1; 54 break; 55 case '?': 56 default: 57 usage(); 58 } 59 argv += optind; 60 argc -= optind; 61 62 if (argc < 2) 63 usage(); 64 65 uid = gid = -1; 66 if (ischown) { 67 #ifdef SUPPORT_DOT 68 if (cp = index(*argv, '.')) { 69 *cp++ = '\0'; 70 a_gid(cp); 71 } else 72 #endif 73 if (cp = index(*argv, ':')) { 74 *cp++ = '\0'; 75 a_gid(cp); 76 } 77 a_uid(*argv); 78 } 79 else 80 a_gid(*argv); 81 82 if (rflag) { 83 if (!(fts = fts_open(++argv, FTS_NOSTAT|FTS_PHYSICAL, 0))) { 84 (void)fprintf(stderr, 85 "%s: %s.\n", myname, strerror(errno)); 86 exit(1); 87 } 88 while (p = fts_read(fts)) { 89 if (p->fts_info == FTS_D) 90 continue; 91 if (p->fts_info == FTS_ERR) { 92 error(p->fts_path); 93 continue; 94 } 95 if (chown(p->fts_accpath, uid, gid) && !fflag) 96 chownerr(p->fts_path); 97 } 98 exit(retval); 99 } 100 while (*++argv) 101 if (chown(*argv, uid, gid) && !fflag) 102 chownerr(*argv); 103 exit(retval); 104 } 105 106 a_gid(s) 107 register char *s; 108 { 109 struct group *gr; 110 111 if (!*s) { 112 gid = -1; /* argument was "uid." */ 113 return; 114 } 115 gname = s; 116 if (gr = getgrnam(s)) 117 gid = gr->gr_gid; 118 else { 119 for (; *s && isdigit(*s); ++s); 120 if (!*s) 121 gid = atoi(gname); 122 else { 123 (void)fprintf(stderr, "%s: unknown group id: %s\n", 124 myname, gname); 125 exit(1); 126 } 127 } 128 } 129 130 a_uid(s) 131 register char *s; 132 { 133 struct passwd *pw; 134 char *uname; 135 136 if (!*s) { 137 uid = -1; /* argument was ".gid" */ 138 return; 139 } 140 if (pw = getpwnam(s)) 141 uid = pw->pw_uid; 142 else { 143 for (uname = s; *s && isdigit(*s); ++s); 144 if (!*s) 145 uid = atoi(uname); 146 else { 147 (void)fprintf(stderr, 148 "chown: unknown user id: %s\n", uname); 149 exit(1); 150 } 151 } 152 } 153 154 chownerr(file) 155 char *file; 156 { 157 static int euid = -1, ngroups = -1; 158 159 /* check for chown without being root */ 160 if (errno != EPERM || uid != -1 && euid == -1 && (euid = geteuid())) { 161 if (fflag) 162 exit(0); 163 error(file); 164 exit(1); 165 } 166 /* check group membership; kernel just returns EPERM */ 167 if (gid != -1 && ngroups == -1) { 168 int groups[NGROUPS]; 169 170 ngroups = getgroups(NGROUPS, groups); 171 while (--ngroups >= 0 && gid != groups[ngroups]); 172 if (ngroups < 0) { 173 if (fflag) 174 exit(0); 175 (void)fprintf(stderr, 176 "%s: you are not a member of group %s.\n", 177 myname, gname); 178 exit(1); 179 } 180 } 181 if (!fflag) 182 error(file); 183 } 184 185 error(name) 186 char *name; 187 { 188 (void)fprintf(stderr, "%s: %s: %s\n", myname, name, strerror(errno)); 189 retval = 1; 190 } 191 192 usage() 193 { 194 (void)fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname, 195 ischown ? "[owner][:group]" : "group"); 196 exit(1); 197 } 198