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"; 11*24505Ssam #endif 1222488Sdist 1322488Sdist #ifndef lint 14*24505Ssam static char sccsid[] = "@(#)chown.c 5.2 (Berkeley) 08/31/85"; 15*24505Ssam #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> 28*24505Ssam #include <strings.h> 29975Sbill 30*24505Ssam struct passwd *pwd; 31*24505Ssam struct passwd *getpwnam(); 32*24505Ssam struct stat stbuf; 33975Sbill int uid; 34975Sbill int status; 35*24505Ssam int fflag; 36*24505Ssam int rflag; 37975Sbill 38975Sbill main(argc, argv) 39*24505Ssam char *argv[]; 40975Sbill { 4118450Smckusick register int c, gid; 42*24505Ssam register char *cp, *group; 4318450Smckusick struct group *grp; 44975Sbill 45*24505Ssam argc--, argv++; 46*24505Ssam while (argc > 0 && argv[0][0] == '-') { 47*24505Ssam for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { 48*24505Ssam 49*24505Ssam case 'f': 50*24505Ssam fflag++; 51*24505Ssam break; 52*24505Ssam 53*24505Ssam case 'R': 54*24505Ssam rflag++; 55*24505Ssam break; 56*24505Ssam 57*24505Ssam default: 58*24505Ssam fatal(255, "unknown option: %c", *cp); 59*24505Ssam } 60*24505Ssam argv++, argc--; 61*24505Ssam } 62*24505Ssam if (argc < 2) { 6318474Smckusick fprintf(stderr, "usage: chown [-fR] owner[.group] file ...\n"); 6418450Smckusick exit(-1); 65975Sbill } 66*24505Ssam group = index(argv[0], '.'); 67*24505Ssam if (group != NULL) { 68*24505Ssam *group++ = '\0'; 69*24505Ssam if (!isnumber(group)) { 70*24505Ssam if ((grp = getgrnam(group)) == NULL) 71*24505Ssam fatal(255, "unknown group: %s",group); 72*24505Ssam gid = grp -> gr_gid; 73*24505Ssam endgrent(); 74*24505Ssam } else 75*24505Ssam gid = atoi(group); 7611442Smckusick } 77*24505Ssam if (!isnumber(argv[0])) { 78*24505Ssam if ((pwd = getpwnam(argv[0])) == NULL) 79*24505Ssam fatal(255, "unknown user id: %s",argv[0]); 8018450Smckusick uid = pwd->pw_uid; 81*24505Ssam } else 82*24505Ssam uid = atoi(argv[0]); 83*24505Ssam for (c = 1; c < argc; c++) { 84*24505Ssam /* do stat for directory arguments */ 85*24505Ssam if (stat(argv[c], &stbuf) < 0) { 86*24505Ssam status += error("couldn't access %s", argv[c]); 87*24505Ssam continue; 8818450Smckusick } 8918450Smckusick if (group == NULL) 9018450Smckusick gid = stbuf.st_gid; 91*24505Ssam if (rflag && stbuf.st_mode&S_IFDIR) { 92*24505Ssam status += chownr(argv[c], group != NULL, uid, gid); 93*24505Ssam continue; 94975Sbill } 95*24505Ssam if (chown(argv[c], uid, gid)) { 96*24505Ssam status += error("couldn't change %s", argv[c]); 97*24505Ssam continue; 98*24505Ssam } 99975Sbill } 100975Sbill exit(status); 101975Sbill } 102975Sbill 103975Sbill isnumber(s) 104*24505Ssam char *s; 105975Sbill { 106975Sbill register c; 107975Sbill 108975Sbill while(c = *s++) 109*24505Ssam if (!isdigit(c)) 110*24505Ssam return (0); 111*24505Ssam return (1); 112975Sbill } 11318450Smckusick 114*24505Ssam chownr(dir, dogrp, uid, ogid) 115*24505Ssam char *dir; 11618450Smckusick { 117*24505Ssam register DIR *dirp; 118*24505Ssam register struct direct *dp; 119*24505Ssam register struct stat st; 120*24505Ssam char savedir[1024]; 121*24505Ssam int ecode, gid; 12218450Smckusick 123*24505Ssam if (getwd(savedir) == 0) 124*24505Ssam fatal(255, "%s", savedir); 125*24505Ssam /* 126*24505Ssam * Change what we are given before doing it's contents. 127*24505Ssam */ 128*24505Ssam if (chown(dir, uid, ogid) < 0 && error("can't change %s", dir)) 129*24505Ssam return (1); 130*24505Ssam if (chdir(dir) < 0) 131*24505Ssam return (Perror(dir)); 132*24505Ssam if ((dirp = opendir(".")) == NULL) 133*24505Ssam return (Perror(dir)); 13418450Smckusick dp = readdir(dirp); 13518450Smckusick dp = readdir(dirp); /* read "." and ".." */ 136*24505Ssam ecode = 0; 13718450Smckusick for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { 138*24505Ssam if (stat(dp->d_name, &st) < 0) { 139*24505Ssam ecode = error("can't access %s", dp->d_name); 140*24505Ssam if (ecode) 141*24505Ssam break; 142*24505Ssam continue; 14318450Smckusick } 14418450Smckusick if (dogrp) 145*24505Ssam gid = ogid; 14618450Smckusick else 14718450Smckusick gid = st.st_gid; 148*24505Ssam if (st.st_mode&S_IFDIR) { 149*24505Ssam ecode = chownr(dp->d_name, dogrp, uid, gid); 150*24505Ssam if (ecode) 151*24505Ssam break; 152*24505Ssam continue; 153*24505Ssam } 154*24505Ssam if (chown(dp->d_name, uid, gid) < 0 && 155*24505Ssam (ecode = error("can't change %s", dp->d_name))) 156*24505Ssam break; 15718450Smckusick } 15818450Smckusick closedir(dirp); 159*24505Ssam if (chdir(savedir) < 0) 160*24505Ssam fatal(255, "can't change back to %s", savedir); 161*24505Ssam return (ecode); 16218450Smckusick } 163*24505Ssam 164*24505Ssam error(fmt, a) 165*24505Ssam char *fmt, *a; 166*24505Ssam { 167*24505Ssam 168*24505Ssam if (!fflag) { 169*24505Ssam fprintf(stderr, "chown: "); 170*24505Ssam fprintf(stderr, fmt, a); 171*24505Ssam putc('\n', stderr); 172*24505Ssam } 173*24505Ssam return (!fflag); 174*24505Ssam } 175*24505Ssam 176*24505Ssam fatal(status, fmt, a) 177*24505Ssam int status; 178*24505Ssam char *fmt, *a; 179*24505Ssam { 180*24505Ssam 181*24505Ssam fflag = 0; 182*24505Ssam (void) error(fmt, a); 183*24505Ssam exit(status); 184*24505Ssam } 185*24505Ssam 186*24505Ssam Perror(s) 187*24505Ssam char *s; 188*24505Ssam { 189*24505Ssam 190*24505Ssam fprintf(stderr, "chown: "); 191*24505Ssam perror(s); 192*24505Ssam return (1); 193*24505Ssam } 194