119840Sdist /* 239829Sbostic * Copyright (c) 1989 The Regents of the University of California. 339829Sbostic * All rights reserved. 439829Sbostic * 542527Sbostic * %sccs.include.redist.c% 619840Sdist */ 716242Slayer 819840Sdist #ifndef lint 934043Sbostic char copyright[] = 1039829Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 1134043Sbostic All rights reserved.\n"; 1234043Sbostic #endif /* not lint */ 1319840Sdist 1434043Sbostic #ifndef lint 15*53782Selan static char sccsid[] = "@(#)chmod.c 5.22 (Berkeley) 06/01/92"; 1634043Sbostic #endif /* not lint */ 1734043Sbostic 1816242Slayer #include <sys/types.h> 1916242Slayer #include <sys/stat.h> 2052070Sbostic #include <errno.h> 2139829Sbostic #include <fts.h> 2252070Sbostic #include <unistd.h> 2339829Sbostic #include <stdio.h> 2452070Sbostic #include <stdlib.h> 2542010Sbostic #include <string.h> 2616242Slayer 2739829Sbostic int retval; 2816242Slayer 2952070Sbostic void err __P((const char *, ...)); 3052070Sbostic void error __P((char *)); 3152070Sbostic void usage __P((void)); 3252070Sbostic 3352070Sbostic int 3424503Ssam main(argc, argv) 3534043Sbostic int argc; 3652070Sbostic char *argv[]; 3716242Slayer { 38*53782Selan register FTS *ftsp; 3939829Sbostic register FTSENT *p; 4039829Sbostic register int oct, omode; 4139829Sbostic struct stat sb; 4252070Sbostic mode_t *set; 43*53782Selan int ch, fflag, rflag, hflag, Hflag; 4452070Sbostic char *ep, *mode; 45*53782Selan int fts_options; 4616242Slayer 47*53782Selan fts_options = FTS_PHYSICAL; 48*53782Selan fflag = rflag = hflag = Hflag = 0; 49*53782Selan while ((ch = getopt(argc, argv, "HRfhrwx")) != EOF) 5034043Sbostic switch((char)ch) { 51*53782Selan case 'H': 52*53782Selan Hflag = 1; 53*53782Selan fts_options |= FTS_COMFOLLOW; 54*53782Selan break; 5524503Ssam case 'R': 5647072Sbostic rflag = 1; 5724503Ssam break; 5847072Sbostic case 'f': /* no longer documented */ 5947072Sbostic fflag = 1; 6024503Ssam break; 61*53782Selan case 'h': 62*53782Selan hflag = 1; 63*53782Selan fts_options &= ~FTS_PHYSICAL; 64*53782Selan fts_options |= FTS_LOGICAL; 65*53782Selan break; 6647072Sbostic case 'r': /* "-[rwx]" are valid file modes */ 6739829Sbostic case 'w': 6839829Sbostic case 'x': 6939829Sbostic --optind; 7039829Sbostic goto done; 7134043Sbostic case '?': 7224503Ssam default: 7339829Sbostic usage(); 7423482Smckusick } 7534043Sbostic done: argv += optind; 7634043Sbostic argc -= optind; 7734043Sbostic 7839829Sbostic if (argc < 2) 7939829Sbostic usage(); 8039829Sbostic 8139829Sbostic mode = *argv; 8239829Sbostic if (*mode >= '0' && *mode <= '7') { 8352070Sbostic omode = (int)strtol(mode, &ep, 8); 8452070Sbostic if (omode < 0 || *ep) 8552070Sbostic err("invalid file mode: %s", mode); 8639829Sbostic oct = 1; 8739829Sbostic } else { 8852070Sbostic if (!(set = setmode(mode))) 8952070Sbostic err("invalid file mode: %s", mode); 9039829Sbostic oct = 0; 9116242Slayer } 9234043Sbostic 9339829Sbostic retval = 0; 94*53782Selan if (oct) 95*53782Selan fts_options |= FTS_NOSTAT; 96*53782Selan if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL) 9752070Sbostic err("%s", strerror(errno)); 98*53782Selan while (p = fts_read(ftsp)) 99*53782Selan switch(p->fts_info) { 100*53782Selan case FTS_D: 101*53782Selan if (!rflag) 102*53782Selan fts_set(ftsp, p, FTS_SKIP); 103*53782Selan break; 104*53782Selan case FTS_DNR: 105*53782Selan case FTS_ERR: 106*53782Selan case FTS_NS: 107*53782Selan err("%s: %s", p->fts_path, strerror(errno)); 108*53782Selan default: 109*53782Selan if (p->fts_info == FTS_SL && 110*53782Selan !(hflag || 111*53782Selan (Hflag && p->fts_level == FTS_ROOTLEVEL))) 112*53782Selan continue; 113*53782Selan if (chmod(p->fts_accpath, oct ? omode : 114*53782Selan getmode(set, p->fts_statp->st_mode)) && 115*53782Selan !fflag) 116*53782Selan error(p->fts_path); 117*53782Selan break; 118*53782Selan } 11939829Sbostic exit(retval); 12016242Slayer } 12116242Slayer 12252070Sbostic void 12339829Sbostic error(name) 12439829Sbostic char *name; 12516242Slayer { 12652070Sbostic (void)fprintf(stderr, "chmod: %s: %s\n", name, strerror(errno)); 12739829Sbostic retval = 1; 12816242Slayer } 12916242Slayer 13052070Sbostic void 13139829Sbostic usage() 13216242Slayer { 133*53782Selan (void)fprintf(stderr, "usage: chmod [-HRh] mode file ...\n"); 13439829Sbostic exit(1); 13516242Slayer } 13652070Sbostic 13752070Sbostic #if __STDC__ 13852070Sbostic #include <stdarg.h> 13952070Sbostic #else 14052070Sbostic #include <varargs.h> 14152070Sbostic #endif 14252070Sbostic 14352070Sbostic void 14452070Sbostic #if __STDC__ 14552070Sbostic err(const char *fmt, ...) 14652070Sbostic #else 14752070Sbostic err(fmt, va_alist) 14852070Sbostic char *fmt; 14952070Sbostic va_dcl 15052070Sbostic #endif 15152070Sbostic { 15252070Sbostic va_list ap; 15352070Sbostic #if __STDC__ 15452070Sbostic va_start(ap, fmt); 15552070Sbostic #else 15652070Sbostic va_start(ap); 15752070Sbostic #endif 15852070Sbostic (void)fprintf(stderr, "chmod: "); 15952070Sbostic (void)vfprintf(stderr, fmt, ap); 16052070Sbostic va_end(ap); 16152070Sbostic (void)fprintf(stderr, "\n"); 16252070Sbostic exit(1); 16352070Sbostic /* NOTREACHED */ 16452070Sbostic } 165