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