15 opt_HLP
; /* 0: do not follow symlinks; 1: only for cmd args; 2: all */
26 int add_visited(struct stat
*s
) {
28 if(!(v
=malloc(sizeof(struct visited
))))
42 struct visited
*v
= v_stack
->next
;
50 int is_visited(struct stat
*s
) {
51 struct visited
*v
=v_stack
;
53 if(v
->dev
==s
->st_dev
&& v
->ino
==s
->st_ino
)
60 /* chgrp everything in directory pointed to by path (and recurse, per opt_R and opt_HLP) */
61 int do_chgrp(char *path
) {
63 struct dirent
*cur_file
;
68 if(stat(path
,&f_stat
)) {
69 fprintf(stderr
,"%s: cannot stat %s: %s\n",g_nam
,path
,strerror(errno
));
73 fprintf(stderr
,"%s: cannot enter directory %s\n",g_nam
,path
);
76 if(add_visited(&f_stat
)) {
77 fprintf(stderr
,"%s: cannot add path to stack: %s\n",g_nam
,strerror(errno
));
80 if(!(cur
=opendir("."))) {
81 fprintf(stderr
,"%s: cannot open directory %s\n",g_nam
,path
);
85 while(cur_file
=readdir(cur
)) {
86 filename
=cur_file
->d_name
;
87 if(!strcmp(filename
,".") || !strcmp(filename
,".."))
89 if((opt_h
)?lchown(filename
,-1,new_gid
):chown(filename
,-1,new_gid
)) {
90 fprintf(stderr
,"%s: cannot change group of %s: %s\n",g_nam
,filename
,strerror(errno
));
95 if(lstat(filename
,&f_stat
)) {
97 fprintf(stderr
,"%s: cannot stat %s: %s\n",g_nam
,filename
,strerror(errno
));
101 switch(f_stat
.st_mode
&S_IFMT
) {
103 /* check if symlink points to directory... */
104 if(stat(filename
,&f_stat
))
106 if(f_stat
.st_mode
!=S_IFDIR
)
108 /* fall through and enter directory */
110 if(opt_HLP
<2 || is_visited(&f_stat
))
112 ret
|=do_chgrp(filename
);
123 fprintf(stderr
,"%s: cannot return to parent of %s: %s\n",g_nam
,path
,strerror(errno
));
129 int main(int argc
, char **argv
) {
131 struct group
*new_group
;
136 while((c
=getopt(argc
,argv
,"hHLPR"))!=-1) {
138 case 'h': /* chgrp symlink regular files and not its destination */
141 case 'H': /* enter only symlinked directories as args */
144 case 'L': /* enter all symlinked directories */
147 case 'P': /* do not enter symlinked directories */
150 case 'R': /* recurse */
154 fprintf(stderr
,"%s: invalid option %c\n",argv
[0],optopt
);
160 fprintf(stderr
,"usage: %s [-hR] group file ...\n %s -R [-H | -L | -P] group file ...\n",argv
[0],argv
[0]);
163 if(!isdigit(argv
[optind
][0])) {
164 if(!(new_group
=getgrnam(argv
[optind
++]))) {
165 fprintf(stderr
,"%s: invalid group %s\n",argv
[0],argv
[optind
-1]);
168 new_gid
=new_group
->gr_gid
;
170 new_gid
=atoi(argv
[optind
++]);
172 while(path
=argv
[optind
++]) { /* main chown loop */
173 if((opt_h
)?lchown(path
,-1,new_gid
):chown(path
,-1,new_gid
)) {
174 fprintf(stderr
,"%s: cannot change group of %s: %s\n",argv
[0],path
,strerror(errno
));
178 if(opt_R
) { /* recurse if a subdirectory */
179 if(lstat(path
,&f_stat
)) {
181 fprintf(stderr
,"%s: cannot stat %s: %s\n",argv
[0],path
,strerror(errno
));
185 switch(f_stat
.st_mode
&S_IFMT
) {
187 if(!opt_HLP
) /* do not follow any symlinks */
189 /* check if symlink points to directory... */
190 if(stat(path
,&f_stat
))
192 if(f_stat
.st_mode
!=S_IFDIR
)
194 /* fall through and enter directory */