|
|
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 ! 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) 6/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.