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