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*28349Smckusick static char sccsid[] = "@(#)chown.c 5.4 (Berkeley) 05/22/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 } 6627611Sbloom 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; 7427611Sbloom (void) endgrent(); 7527611Sbloom } 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 */ 86*28349Smckusick if (lstat(argv[c], &stbuf) < 0) { 87*28349Smckusick status += Perror(argv[c]); 8824505Ssam continue; 8918450Smckusick } 9024505Ssam if (rflag && stbuf.st_mode&S_IFDIR) { 9127611Sbloom status += chownr(argv[c], uid, gid); 9224505Ssam continue; 93975Sbill } 9424505Ssam if (chown(argv[c], uid, gid)) { 95*28349Smckusick status += Perror(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 11327611Sbloom chownr(dir, uid, gid) 11424505Ssam char *dir; 11518450Smckusick { 11624505Ssam register DIR *dirp; 11724505Ssam register struct direct *dp; 11827611Sbloom struct stat st; 11924505Ssam char savedir[1024]; 12027611Sbloom int ecode; 12127611Sbloom extern char *getwd(); 12218450Smckusick 12327611Sbloom if (getwd(savedir) == (char *)0) 12424505Ssam fatal(255, "%s", savedir); 12524505Ssam /* 12624505Ssam * Change what we are given before doing it's contents. 12724505Ssam */ 128*28349Smckusick if (chown(dir, uid, gid) < 0 && Perror(dir)) 12924505Ssam return (1); 130*28349Smckusick if (chdir(dir) < 0) { 131*28349Smckusick Perror(dir); 132*28349Smckusick return (1); 133*28349Smckusick } 134*28349Smckusick if ((dirp = opendir(".")) == NULL) { 135*28349Smckusick Perror(dir); 136*28349Smckusick return (1); 137*28349Smckusick } 13818450Smckusick dp = readdir(dirp); 13918450Smckusick dp = readdir(dirp); /* read "." and ".." */ 14024505Ssam ecode = 0; 14118450Smckusick for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { 142*28349Smckusick if (lstat(dp->d_name, &st) < 0) { 143*28349Smckusick ecode = Perror(dp->d_name); 14424505Ssam if (ecode) 14524505Ssam break; 14624505Ssam continue; 14718450Smckusick } 14824505Ssam if (st.st_mode&S_IFDIR) { 14927611Sbloom ecode = chownr(dp->d_name, uid, gid); 15024505Ssam if (ecode) 15124505Ssam break; 15224505Ssam continue; 15324505Ssam } 15424505Ssam if (chown(dp->d_name, uid, gid) < 0 && 155*28349Smckusick (ecode = Perror(dp->d_name))) 15624505Ssam break; 15718450Smckusick } 15818450Smckusick closedir(dirp); 15924505Ssam if (chdir(savedir) < 0) 16024505Ssam fatal(255, "can't change back to %s", savedir); 16124505Ssam return (ecode); 16218450Smckusick } 16324505Ssam 16424505Ssam error(fmt, a) 16524505Ssam char *fmt, *a; 16624505Ssam { 16724505Ssam 16824505Ssam if (!fflag) { 16924505Ssam fprintf(stderr, "chown: "); 17024505Ssam fprintf(stderr, fmt, a); 17124505Ssam putc('\n', stderr); 17224505Ssam } 17324505Ssam return (!fflag); 17424505Ssam } 17524505Ssam 17624505Ssam fatal(status, fmt, a) 17724505Ssam int status; 17824505Ssam char *fmt, *a; 17924505Ssam { 18024505Ssam 18124505Ssam fflag = 0; 18224505Ssam (void) error(fmt, a); 18324505Ssam exit(status); 18424505Ssam } 18524505Ssam 18624505Ssam Perror(s) 18724505Ssam char *s; 18824505Ssam { 18924505Ssam 190*28349Smckusick if (!fflag) { 191*28349Smckusick fprintf(stderr, "chown: "); 192*28349Smckusick perror(s); 193*28349Smckusick } 194*28349Smckusick return (!fflag); 19524505Ssam } 196