122488Sdist /* 222488Sdist * Copyright (c) 1980 Regents of the University of California. 322488Sdist * All rights reserved. The Berkeley software License Agreement 422488Sdist * specifies the terms and conditions for redistribution. 522488Sdist */ 618450Smckusick 722488Sdist #ifndef lint 822488Sdist char copyright[] = 922488Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1022488Sdist All rights reserved.\n"; 1124505Ssam #endif 1222488Sdist 1322488Sdist #ifndef lint 14*27611Sbloom static char sccsid[] = "@(#)chown.c 5.3 (Berkeley) 04/29/86"; 1524505Ssam #endif 1622488Sdist 17975Sbill /* 1818474Smckusick * chown [-fR] uid[.gid] file ... 19975Sbill */ 20975Sbill 21975Sbill #include <stdio.h> 22975Sbill #include <ctype.h> 23975Sbill #include <sys/types.h> 24975Sbill #include <sys/stat.h> 25975Sbill #include <pwd.h> 2618450Smckusick #include <sys/dir.h> 2718450Smckusick #include <grp.h> 2824505Ssam #include <strings.h> 29975Sbill 3024505Ssam struct passwd *pwd; 3124505Ssam struct passwd *getpwnam(); 3224505Ssam struct stat stbuf; 33975Sbill int uid; 34975Sbill int status; 3524505Ssam int fflag; 3624505Ssam int rflag; 37975Sbill 38975Sbill main(argc, argv) 3924505Ssam char *argv[]; 40975Sbill { 4118450Smckusick register int c, gid; 4224505Ssam register char *cp, *group; 4318450Smckusick struct group *grp; 44975Sbill 4524505Ssam argc--, argv++; 4624505Ssam while (argc > 0 && argv[0][0] == '-') { 4724505Ssam for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { 4824505Ssam 4924505Ssam case 'f': 5024505Ssam fflag++; 5124505Ssam break; 5224505Ssam 5324505Ssam case 'R': 5424505Ssam rflag++; 5524505Ssam break; 5624505Ssam 5724505Ssam default: 5824505Ssam fatal(255, "unknown option: %c", *cp); 5924505Ssam } 6024505Ssam argv++, argc--; 6124505Ssam } 6224505Ssam if (argc < 2) { 6318474Smckusick fprintf(stderr, "usage: chown [-fR] owner[.group] file ...\n"); 6418450Smckusick exit(-1); 65975Sbill } 66*27611Sbloom gid = -1; 6724505Ssam group = index(argv[0], '.'); 6824505Ssam if (group != NULL) { 6924505Ssam *group++ = '\0'; 7024505Ssam if (!isnumber(group)) { 7124505Ssam if ((grp = getgrnam(group)) == NULL) 7224505Ssam fatal(255, "unknown group: %s",group); 7324505Ssam gid = grp -> gr_gid; 74*27611Sbloom (void) endgrent(); 75*27611Sbloom } else if (*group != '\0') 7624505Ssam gid = atoi(group); 7711442Smckusick } 7824505Ssam if (!isnumber(argv[0])) { 7924505Ssam if ((pwd = getpwnam(argv[0])) == NULL) 8024505Ssam fatal(255, "unknown user id: %s",argv[0]); 8118450Smckusick uid = pwd->pw_uid; 8224505Ssam } else 8324505Ssam uid = atoi(argv[0]); 8424505Ssam for (c = 1; c < argc; c++) { 8524505Ssam /* do stat for directory arguments */ 8624505Ssam if (stat(argv[c], &stbuf) < 0) { 8724505Ssam status += error("couldn't access %s", argv[c]); 8824505Ssam continue; 8918450Smckusick } 9024505Ssam if (rflag && stbuf.st_mode&S_IFDIR) { 91*27611Sbloom status += chownr(argv[c], uid, gid); 9224505Ssam continue; 93975Sbill } 9424505Ssam if (chown(argv[c], uid, gid)) { 9524505Ssam status += error("couldn't change %s", argv[c]); 9624505Ssam continue; 9724505Ssam } 98975Sbill } 99975Sbill exit(status); 100975Sbill } 101975Sbill 102975Sbill isnumber(s) 10324505Ssam char *s; 104975Sbill { 105975Sbill register c; 106975Sbill 107975Sbill while(c = *s++) 10824505Ssam if (!isdigit(c)) 10924505Ssam return (0); 11024505Ssam return (1); 111975Sbill } 11218450Smckusick 113*27611Sbloom chownr(dir, uid, gid) 11424505Ssam char *dir; 11518450Smckusick { 11624505Ssam register DIR *dirp; 11724505Ssam register struct direct *dp; 118*27611Sbloom struct stat st; 11924505Ssam char savedir[1024]; 120*27611Sbloom int ecode; 121*27611Sbloom extern char *getwd(); 12218450Smckusick 123*27611Sbloom if (getwd(savedir) == (char *)0) 12424505Ssam fatal(255, "%s", savedir); 12524505Ssam /* 12624505Ssam * Change what we are given before doing it's contents. 12724505Ssam */ 128*27611Sbloom if (chown(dir, uid, gid) < 0 && error("can't change %s", dir)) 12924505Ssam return (1); 13024505Ssam if (chdir(dir) < 0) 13124505Ssam return (Perror(dir)); 13224505Ssam if ((dirp = opendir(".")) == NULL) 13324505Ssam return (Perror(dir)); 13418450Smckusick dp = readdir(dirp); 13518450Smckusick dp = readdir(dirp); /* read "." and ".." */ 13624505Ssam ecode = 0; 13718450Smckusick for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { 13824505Ssam if (stat(dp->d_name, &st) < 0) { 13924505Ssam ecode = error("can't access %s", dp->d_name); 14024505Ssam if (ecode) 14124505Ssam break; 14224505Ssam continue; 14318450Smckusick } 14424505Ssam if (st.st_mode&S_IFDIR) { 145*27611Sbloom ecode = chownr(dp->d_name, uid, gid); 14624505Ssam if (ecode) 14724505Ssam break; 14824505Ssam continue; 14924505Ssam } 15024505Ssam if (chown(dp->d_name, uid, gid) < 0 && 15124505Ssam (ecode = error("can't change %s", dp->d_name))) 15224505Ssam break; 15318450Smckusick } 15418450Smckusick closedir(dirp); 15524505Ssam if (chdir(savedir) < 0) 15624505Ssam fatal(255, "can't change back to %s", savedir); 15724505Ssam return (ecode); 15818450Smckusick } 15924505Ssam 16024505Ssam error(fmt, a) 16124505Ssam char *fmt, *a; 16224505Ssam { 16324505Ssam 16424505Ssam if (!fflag) { 16524505Ssam fprintf(stderr, "chown: "); 16624505Ssam fprintf(stderr, fmt, a); 16724505Ssam putc('\n', stderr); 16824505Ssam } 16924505Ssam return (!fflag); 17024505Ssam } 17124505Ssam 17224505Ssam fatal(status, fmt, a) 17324505Ssam int status; 17424505Ssam char *fmt, *a; 17524505Ssam { 17624505Ssam 17724505Ssam fflag = 0; 17824505Ssam (void) error(fmt, a); 17924505Ssam exit(status); 18024505Ssam } 18124505Ssam 18224505Ssam Perror(s) 18324505Ssam char *s; 18424505Ssam { 18524505Ssam 18624505Ssam fprintf(stderr, "chown: "); 18724505Ssam perror(s); 18824505Ssam return (1); 18924505Ssam } 190