122488Sdist /* 234039Sbostic * Copyright (c) 1988 Regents of the University of California. 334039Sbostic * All rights reserved. 434039Sbostic * 542792Sbostic * %sccs.include.redist.c% 622488Sdist */ 718450Smckusick 822488Sdist #ifndef lint 922488Sdist char copyright[] = 1034039Sbostic "@(#) Copyright (c) 1988 Regents of the University of California.\n\ 1122488Sdist All rights reserved.\n"; 1234039Sbostic #endif /* not lint */ 1322488Sdist 1422488Sdist #ifndef lint 15*45426Sbostic static char sccsid[] = "@(#)chown.c 5.16 (Berkeley) 10/26/90"; 1634039Sbostic #endif /* not lint */ 1722488Sdist 1834039Sbostic #include <sys/param.h> 19975Sbill #include <sys/stat.h> 2038427Sbostic #include <sys/errno.h> 2138427Sbostic #include <dirent.h> 22*45426Sbostic #include <fts.h> 23975Sbill #include <pwd.h> 2418450Smckusick #include <grp.h> 2534039Sbostic #include <stdio.h> 2634039Sbostic #include <ctype.h> 27*45426Sbostic #include <string.h> 28975Sbill 2941090Smarc int ischown, uid, gid, fflag, rflag, retval; 3041090Smarc char *gname, *myname; 31975Sbill 32975Sbill main(argc, argv) 3334039Sbostic int argc; 3434039Sbostic char **argv; 35975Sbill { 3634039Sbostic extern int optind; 37*45426Sbostic register FTS *fts; 38*45426Sbostic register FTSENT *p; 3934039Sbostic register char *cp; 4034039Sbostic int ch; 41975Sbill 4234039Sbostic myname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv; 4334039Sbostic ischown = myname[2] == 'o'; 4424505Ssam 4534039Sbostic while ((ch = getopt(argc, argv, "Rf")) != EOF) 4634039Sbostic switch((char)ch) { 4734039Sbostic case 'R': 48*45426Sbostic rflag = 1; 4934039Sbostic break; 5024505Ssam case 'f': 51*45426Sbostic fflag = 1; 5224505Ssam break; 5334039Sbostic case '?': 5434039Sbostic default: 5534039Sbostic usage(); 5634039Sbostic } 5734039Sbostic argv += optind; 5834039Sbostic argc -= optind; 5924505Ssam 6034039Sbostic if (argc < 2) 6134039Sbostic usage(); 6224505Ssam 63*45426Sbostic uid = gid = -1; 6434039Sbostic if (ischown) { 65*45426Sbostic #ifdef SUPPORT_DOT 6634039Sbostic if (cp = index(*argv, '.')) { 6734039Sbostic *cp++ = '\0'; 6834039Sbostic setgid(cp); 69*45426Sbostic } else 70*45426Sbostic #endif 71*45426Sbostic if (cp = index(*argv, ':')) { 72*45426Sbostic *cp++ = '\0'; 73*45426Sbostic setgid(cp); 74*45426Sbostic } 7534039Sbostic setuid(*argv); 7624505Ssam } 77*45426Sbostic else 7834039Sbostic setgid(*argv); 7934039Sbostic 80*45426Sbostic if (rflag) { 81*45426Sbostic if (!(fts = ftsopen(++argv, FTS_NOSTAT|FTS_PHYSICAL, 0))) { 82*45426Sbostic (void)fprintf(stderr, 83*45426Sbostic "%s: %s.\n", myname, strerror(errno)); 84*45426Sbostic exit(1); 8536959Sbostic } 86*45426Sbostic while (p = ftsread(fts)) { 87*45426Sbostic if (p->fts_info == FTS_D) 88*45426Sbostic continue; 89*45426Sbostic if (p->fts_info == FTS_ERR) { 90*45426Sbostic error(p->fts_path); 91*45426Sbostic continue; 92*45426Sbostic } 93*45426Sbostic if (chown(p->fts_accpath, uid, gid) && !fflag) 94*45426Sbostic chownerr(p->fts_path); 95*45426Sbostic } 96*45426Sbostic exit(retval); 9736959Sbostic } 98*45426Sbostic while (*++argv) 99*45426Sbostic if (chown(*argv, uid, gid) && !fflag) 100*45426Sbostic chownerr(*argv); 10134039Sbostic exit(retval); 10234039Sbostic } 10334039Sbostic 10434039Sbostic setgid(s) 10534039Sbostic register char *s; 10634039Sbostic { 10734039Sbostic struct group *gr, *getgrnam(); 10834039Sbostic 10934039Sbostic if (!*s) { 11034039Sbostic gid = -1; /* argument was "uid." */ 11134039Sbostic return; 11211442Smckusick } 11334056Sbostic for (gname = s; *s && isdigit(*s); ++s); 11434039Sbostic if (!*s) 11534056Sbostic gid = atoi(gname); 11634039Sbostic else { 11734056Sbostic if (!(gr = getgrnam(gname))) { 11838427Sbostic (void)fprintf(stderr, "%s: unknown group id: %s\n", 11934056Sbostic myname, gname); 120*45426Sbostic exit(1); 12118450Smckusick } 12234039Sbostic gid = gr->gr_gid; 123975Sbill } 124975Sbill } 125975Sbill 12634039Sbostic setuid(s) 12734039Sbostic register char *s; 128975Sbill { 12934039Sbostic struct passwd *pwd, *getpwnam(); 13034039Sbostic char *beg; 131975Sbill 13234039Sbostic if (!*s) { 13334039Sbostic uid = -1; /* argument was ".gid" */ 13434039Sbostic return; 13534039Sbostic } 13634039Sbostic for (beg = s; *s && isdigit(*s); ++s); 13734039Sbostic if (!*s) 13834039Sbostic uid = atoi(beg); 13934039Sbostic else { 14034039Sbostic if (!(pwd = getpwnam(beg))) { 14138427Sbostic (void)fprintf(stderr, 14238427Sbostic "chown: unknown user id: %s\n", beg); 143*45426Sbostic exit(1); 14434039Sbostic } 14534039Sbostic uid = pwd->pw_uid; 14634039Sbostic } 147975Sbill } 14818450Smckusick 14934069Sbostic chownerr(file) 15034069Sbostic char *file; 15134069Sbostic { 15234069Sbostic static int euid = -1, ngroups = -1; 15334069Sbostic 15434069Sbostic /* check for chown without being root */ 15538427Sbostic if (errno != EPERM || uid != -1 && euid == -1 && (euid = geteuid())) { 15634069Sbostic if (fflag) 15734069Sbostic exit(0); 158*45426Sbostic error(file); 159*45426Sbostic exit(1); 16034069Sbostic } 16134069Sbostic /* check group membership; kernel just returns EPERM */ 16234069Sbostic if (gid != -1 && ngroups == -1) { 16334069Sbostic int groups[NGROUPS]; 16434069Sbostic 16534069Sbostic ngroups = getgroups(NGROUPS, groups); 16634069Sbostic while (--ngroups >= 0 && gid != groups[ngroups]); 16734069Sbostic if (ngroups < 0) { 16834069Sbostic if (fflag) 16934069Sbostic exit(0); 17038427Sbostic (void)fprintf(stderr, 17134069Sbostic "%s: you are not a member of group %s.\n", 17234069Sbostic myname, gname); 173*45426Sbostic exit(1); 17434069Sbostic } 17534069Sbostic } 176*45426Sbostic if (!fflag) 177*45426Sbostic error(file); 17834069Sbostic } 17934069Sbostic 180*45426Sbostic error(name) 181*45426Sbostic char *name; 18224505Ssam { 183*45426Sbostic (void)fprintf(stderr, "%s: %s: %s\n", myname, name, strerror(errno)); 184*45426Sbostic retval = 1; 18524505Ssam } 18624505Ssam 18734039Sbostic usage() 18824505Ssam { 18938427Sbostic (void)fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname, 190*45426Sbostic ischown ? "[owner][:group]" : "group"); 191*45426Sbostic exit(1); 19224505Ssam } 193