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