1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)chgrp.c 5.9 (Berkeley) 12/21/87"; 9 #endif not lint 10 11 /* 12 * chgrp -fR gid file ... 13 */ 14 15 #include <stdio.h> 16 #include <ctype.h> 17 #include <sys/types.h> 18 #include <sys/stat.h> 19 #include <grp.h> 20 #include <pwd.h> 21 #include <sys/dir.h> 22 23 struct group *gr, *getgrnam(), *getgrgid(); 24 struct passwd *getpwuid(), *pwd; 25 struct stat stbuf; 26 int gid, uid; 27 int status; 28 int fflag, rflag; 29 /* VARARGS */ 30 int fprintf(); 31 32 main(argc, argv) 33 int argc; 34 char *argv[]; 35 { 36 register c, i; 37 register char *cp; 38 39 argc--, argv++; 40 while (argc > 0 && argv[0][0] == '-') { 41 for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { 42 43 case 'f': 44 fflag++; 45 break; 46 47 case 'R': 48 rflag++; 49 break; 50 51 default: 52 fatal(255, "unknown option: %c", *cp); 53 /*NOTREACHED*/ 54 } 55 argv++, argc--; 56 } 57 if (argc < 2) { 58 fprintf(stderr, "usage: chgrp [-fR] gid file ...\n"); 59 exit(255); 60 } 61 uid = getuid(); 62 if (isnumber(argv[0])) { 63 gid = atoi(argv[0]); 64 gr = getgrgid(gid); 65 if (uid && gr == NULL) 66 fatal(255, "%s: unknown group", argv[0]); 67 } else { 68 gr = getgrnam(argv[0]); 69 if (gr == NULL) 70 fatal(255, "%s: unknown group", argv[0]); 71 gid = gr->gr_gid; 72 } 73 pwd = getpwuid(uid); 74 if (pwd == NULL) 75 fatal(255, "Who are you?"); 76 if (uid && pwd->pw_gid != gid) { 77 for (i=0; gr->gr_mem[i]; i++) 78 if (!(strcmp(pwd->pw_name, gr->gr_mem[i]))) 79 goto ok; 80 if (fflag) 81 exit(0); 82 fatal(255, "You are not a member of the %s group", argv[0]); 83 } 84 ok: 85 for (c = 1; c < argc; c++) { 86 /* do stat for directory arguments */ 87 if (lstat(argv[c], &stbuf)) { 88 status += Perror(argv[c]); 89 continue; 90 } 91 if (uid && uid != stbuf.st_uid) { 92 status += error("You are not the owner of %s", argv[c]); 93 continue; 94 } 95 if (rflag && ((stbuf.st_mode & S_IFMT) == S_IFDIR)) { 96 status += chownr(argv[c]); 97 continue; 98 } 99 if (chown(argv[c], -1, gid)) { 100 status += Perror(argv[c]); 101 continue; 102 } 103 } 104 exit(status); 105 } 106 107 isnumber(s) 108 char *s; 109 { 110 register int c; 111 112 while (c = *s++) 113 if (!isdigit(c)) 114 return (0); 115 return (1); 116 } 117 118 chownr(dir) 119 char *dir; 120 { 121 register DIR *dirp; 122 register struct direct *dp; 123 struct stat st; 124 char savedir[1024]; 125 int ecode; 126 127 if (getwd(savedir) == 0) 128 fatal(255, "%s", savedir); 129 /* 130 * Change what we are given before doing its contents. 131 */ 132 if (chown(dir, -1, gid) < 0 && Perror(dir)) 133 return (1); 134 if (chdir(dir) < 0) { 135 Perror(dir); 136 return (1); 137 } 138 if ((dirp = opendir(".")) == NULL) { 139 Perror(dir); 140 return (1); 141 } 142 dp = readdir(dirp); 143 dp = readdir(dirp); /* read "." and ".." */ 144 ecode = 0; 145 for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { 146 if (lstat(dp->d_name, &st) < 0) { 147 ecode = Perror(dp->d_name); 148 if (ecode) 149 break; 150 continue; 151 } 152 if (uid && uid != st.st_uid) { 153 ecode = error("You are not the owner of %s", 154 dp->d_name); 155 continue; 156 } 157 if ((st.st_mode & S_IFMT) == S_IFDIR) { 158 ecode = chownr(dp->d_name); 159 if (ecode) 160 break; 161 continue; 162 } 163 if (chown(dp->d_name, -1, gid) < 0 && 164 (ecode = Perror(dp->d_name))) 165 break; 166 } 167 closedir(dirp); 168 if (chdir(savedir) < 0) 169 fatal(255, "can't change back to %s", savedir); 170 return (ecode); 171 } 172 173 error(fmt, a) 174 char *fmt, *a; 175 { 176 177 if (!fflag) { 178 fprintf(stderr, "chgrp: "); 179 fprintf(stderr, fmt, a); 180 putc('\n', stderr); 181 } 182 return (!fflag); 183 } 184 185 fatal(status, fmt, a) 186 int status; 187 char *fmt, *a; 188 { 189 190 fflag = 0; 191 (void) error(fmt, a); 192 exit(status); 193 } 194 195 Perror(s) 196 char *s; 197 { 198 199 if (!fflag) { 200 fprintf(stderr, "chgrp: "); 201 perror(s); 202 } 203 return (!fflag); 204 } 205