X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/95f51977ddc18faa2e212f30c00a39540b39f325..ca67e7b465996afb3821d6a075c4dc6a7f0f5d52:/usr/src/etc/chown.c?ds=inline diff --git a/usr/src/etc/chown.c b/usr/src/etc/chown.c index 757b55abd5..e9233ce6e1 100644 --- a/usr/src/etc/chown.c +++ b/usr/src/etc/chown.c @@ -1,195 +1,224 @@ /* - * Copyright (c) 1980 Regents of the University of California. - * All rights reserved. The Berkeley software License Agreement - * specifies the terms and conditions for redistribution. + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint char copyright[] = -"@(#) Copyright (c) 1980 Regents of the University of California.\n\ +"@(#) Copyright (c) 1988 Regents of the University of California.\n\ All rights reserved.\n"; -#endif +#endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)chown.c 5.6 (Berkeley) 5/29/86"; -#endif +static char sccsid[] = "@(#)chown.c 5.11 (Berkeley) 6/18/88"; +#endif /* not lint */ -/* - * chown [-fR] uid[.gid] file ... - */ - -#include -#include -#include +#include #include -#include #include +#include #include -#include +#include +#include -struct passwd *pwd; -struct passwd *getpwnam(); -struct stat stbuf; -int uid; -int status; -int fflag; -int rflag; +static int ischown, uid, gid, fflag, rflag, retval; +static char *gname, *myname; main(argc, argv) - char *argv[]; + int argc; + char **argv; { - register int c, gid; - register char *cp, *group; - struct group *grp; + extern char *optarg; + extern int optind; + register char *cp; + int ch; + char *index(), *rindex(); - argc--, argv++; - while (argc > 0 && argv[0][0] == '-') { - for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { + myname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv; + ischown = myname[2] == 'o'; + while ((ch = getopt(argc, argv, "Rf")) != EOF) + switch((char)ch) { + case 'R': + rflag++; + break; case 'f': fflag++; break; + case '?': + default: + usage(); + } + argv += optind; + argc -= optind; - case 'R': - rflag++; - break; + if (argc < 2) + usage(); - default: - fatal(255, "unknown option: %c", *cp); + if (ischown) { + if (cp = index(*argv, '.')) { + *cp++ = '\0'; + setgid(cp); } - argv++, argc--; + else + gid = -1; + setuid(*argv); } - if (argc < 2) { - fprintf(stderr, "usage: chown [-fR] owner[.group] file ...\n"); - exit(-1); + else { + uid = -1; + setgid(*argv); } - gid = -1; - group = index(argv[0], '.'); - if (group != NULL) { - *group++ = '\0'; - if (!isnumber(group)) { - if ((grp = getgrnam(group)) == NULL) - fatal(255, "unknown group: %s",group); - gid = grp -> gr_gid; - (void) endgrent(); - } else if (*group != '\0') - gid = atoi(group); + + while (*++argv) + change(*argv); + exit(retval); +} + +static +setgid(s) + register char *s; +{ + struct group *gr, *getgrnam(); + + if (!*s) { + gid = -1; /* argument was "uid." */ + return; } - if (!isnumber(argv[0])) { - if ((pwd = getpwnam(argv[0])) == NULL) - fatal(255, "unknown user id: %s",argv[0]); - uid = pwd->pw_uid; - } else - uid = atoi(argv[0]); - for (c = 1; c < argc; c++) { - /* do stat for directory arguments */ - if (lstat(argv[c], &stbuf) < 0) { - status += Perror(argv[c]); - continue; - } - if (rflag && ((stbuf.st_mode&S_IFMT) == S_IFDIR)) { - status += chownr(argv[c], uid, gid); - continue; - } - if (chown(argv[c], uid, gid)) { - status += Perror(argv[c]); - continue; + for (gname = s; *s && isdigit(*s); ++s); + if (!*s) + gid = atoi(gname); + else { + if (!(gr = getgrnam(gname))) { + if (fflag) + exit(0); + fprintf(stderr, "%s: unknown group id: %s\n", + myname, gname); + exit(-1); } + gid = gr->gr_gid; } - exit(status); } -isnumber(s) - char *s; +static +setuid(s) + register char *s; { - register c; + struct passwd *pwd, *getpwnam(); + char *beg; - while(c = *s++) - if (!isdigit(c)) - return (0); - return (1); + if (!*s) { + uid = -1; /* argument was ".gid" */ + return; + } + for (beg = s; *s && isdigit(*s); ++s); + if (!*s) + uid = atoi(beg); + else { + if (!(pwd = getpwnam(beg))) { + if (fflag) + exit(0); + fprintf(stderr, "chown: unknown user id: %s\n", beg); + exit(-1); + } + uid = pwd->pw_uid; + } } -chownr(dir, uid, gid) - char *dir; +static +change(file) + char *file; { register DIR *dirp; register struct direct *dp; - struct stat st; - char savedir[1024]; - int ecode; - extern char *getwd(); - - if (getwd(savedir) == (char *)0) - fatal(255, "%s", savedir); - /* - * Change what we are given before doing it's contents. - */ - if (chown(dir, uid, gid) < 0 && Perror(dir)) - return (1); - if (chdir(dir) < 0) { - Perror(dir); - return (1); + struct stat buf; + + if (chown(file, uid, gid)) { + chownerr(file); + return; } - if ((dirp = opendir(".")) == NULL) { - Perror(dir); - return (1); + if (!rflag) + return; + if (lstat(file, &buf)) { + err(file); + return; } - dp = readdir(dirp); - dp = readdir(dirp); /* read "." and ".." */ - ecode = 0; - for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { - if (lstat(dp->d_name, &st) < 0) { - ecode = Perror(dp->d_name); - if (ecode) - break; - continue; + if ((buf.st_mode & S_IFMT) == S_IFDIR) { + if (chdir(file) < 0 || !(dirp = opendir("."))) { + err(file); + return; } - if ((st.st_mode&S_IFMT) == S_IFDIR) { - ecode = chownr(dp->d_name, uid, gid); - if (ecode) - break; - continue; + for (dp = readdir(dirp); dp; dp = readdir(dirp)) { + if (dp->d_name[0] == '.' && (!dp->d_name[1] || + dp->d_name[1] == '.' && !dp->d_name[2])) + continue; + change(dp->d_name); + } + closedir(dirp); + if (chdir("..")) { + err(".."); + exit(fflag ? 0 : -1); } - if (chown(dp->d_name, uid, gid) < 0 && - (ecode = Perror(dp->d_name))) - break; } - closedir(dirp); - if (chdir(savedir) < 0) - fatal(255, "can't change back to %s", savedir); - return (ecode); } -error(fmt, a) - char *fmt, *a; +static +chownerr(file) + char *file; { + static int euid = -1, ngroups = -1; - if (!fflag) { - fprintf(stderr, "chown: "); - fprintf(stderr, fmt, a); - putc('\n', stderr); + /* check for chown without being root */ + if (uid != -1 && euid == -1 && (euid = geteuid())) { + if (fflag) + exit(0); + err(file); + exit(-1); + } + /* check group membership; kernel just returns EPERM */ + if (gid != -1 && ngroups == -1) { + int groups[NGROUPS]; + + ngroups = getgroups(NGROUPS, groups); + while (--ngroups >= 0 && gid != groups[ngroups]); + if (ngroups < 0) { + if (fflag) + exit(0); + fprintf(stderr, + "%s: you are not a member of group %s.\n", + myname, gname); + exit(-1); + } } - return (!fflag); + err(file); } -fatal(status, fmt, a) - int status; - char *fmt, *a; +static +err(s) + char *s; { - - fflag = 0; - (void) error(fmt, a); - exit(status); + if (fflag) + return; + fprintf(stderr, "%s: ", myname); + perror(s); + retval = -1; } -Perror(s) - char *s; +static +usage() { - - if (!fflag) { - fprintf(stderr, "chown: "); - perror(s); - } - return (!fflag); + fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname, + ischown ? "owner[.group]" : "group"); + exit(-1); }