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*58142Sbostic static char sccsid[] = "@(#)chmod.c 5.23 (Berkeley) 02/21/93"; 1634043Sbostic #endif /* not lint */ 1734043Sbostic 1816242Slayer #include <sys/types.h> 1916242Slayer #include <sys/stat.h> 20*58142Sbostic 21*58142Sbostic #include <err.h> 2252070Sbostic #include <errno.h> 2339829Sbostic #include <fts.h> 2439829Sbostic #include <stdio.h> 2552070Sbostic #include <stdlib.h> 2642010Sbostic #include <string.h> 27*58142Sbostic #include <unistd.h> 2816242Slayer 2952070Sbostic void usage __P((void)); 3052070Sbostic 3152070Sbostic int 3224503Ssam main(argc, argv) 3334043Sbostic int argc; 3452070Sbostic char *argv[]; 3516242Slayer { 3653782Selan register FTS *ftsp; 3739829Sbostic register FTSENT *p; 3839829Sbostic register int oct, omode; 3952070Sbostic mode_t *set; 4053782Selan int ch, fflag, rflag, hflag, Hflag; 41*58142Sbostic int fts_options, retval; 4252070Sbostic char *ep, *mode; 4316242Slayer 4453782Selan fts_options = FTS_PHYSICAL; 4553782Selan fflag = rflag = hflag = Hflag = 0; 4653782Selan while ((ch = getopt(argc, argv, "HRfhrwx")) != EOF) 4734043Sbostic switch((char)ch) { 4853782Selan case 'H': 4953782Selan Hflag = 1; 5053782Selan fts_options |= FTS_COMFOLLOW; 5153782Selan break; 5224503Ssam case 'R': 5347072Sbostic rflag = 1; 5424503Ssam break; 5547072Sbostic case 'f': /* no longer documented */ 5647072Sbostic fflag = 1; 5724503Ssam break; 5853782Selan case 'h': 5953782Selan hflag = 1; 6053782Selan fts_options &= ~FTS_PHYSICAL; 6153782Selan fts_options |= FTS_LOGICAL; 6253782Selan break; 6347072Sbostic case 'r': /* "-[rwx]" are valid file modes */ 6439829Sbostic case 'w': 6539829Sbostic case 'x': 6639829Sbostic --optind; 6739829Sbostic goto done; 6834043Sbostic case '?': 6924503Ssam default: 7039829Sbostic usage(); 7123482Smckusick } 7234043Sbostic done: argv += optind; 7334043Sbostic argc -= optind; 7434043Sbostic 7539829Sbostic if (argc < 2) 7639829Sbostic usage(); 7739829Sbostic 7839829Sbostic mode = *argv; 7939829Sbostic if (*mode >= '0' && *mode <= '7') { 8052070Sbostic omode = (int)strtol(mode, &ep, 8); 8152070Sbostic if (omode < 0 || *ep) 82*58142Sbostic errx(1, "invalid file mode: %s", mode); 8339829Sbostic oct = 1; 8439829Sbostic } else { 85*58142Sbostic if ((set = setmode(mode)) == NULL) 86*58142Sbostic errx(1, "invalid file mode: %s", mode); 8739829Sbostic oct = 0; 8816242Slayer } 8934043Sbostic 9039829Sbostic retval = 0; 9153782Selan if (oct) 9253782Selan fts_options |= FTS_NOSTAT; 9353782Selan if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL) 94*58142Sbostic err(1, ""); 9553782Selan while (p = fts_read(ftsp)) 9653782Selan switch(p->fts_info) { 9753782Selan case FTS_D: 9853782Selan if (!rflag) 9953782Selan fts_set(ftsp, p, FTS_SKIP); 10053782Selan break; 10153782Selan case FTS_DNR: 10253782Selan case FTS_ERR: 10353782Selan case FTS_NS: 104*58142Sbostic err(1, "%s", p->fts_path); 10553782Selan default: 10653782Selan if (p->fts_info == FTS_SL && 10753782Selan !(hflag || 10853782Selan (Hflag && p->fts_level == FTS_ROOTLEVEL))) 10953782Selan continue; 11053782Selan if (chmod(p->fts_accpath, oct ? omode : 111*58142Sbostic getmode(set, p->fts_statp->st_mode)) && !fflag) { 112*58142Sbostic warn(p->fts_path); 113*58142Sbostic retval = 1; 114*58142Sbostic } 11553782Selan break; 11653782Selan } 11739829Sbostic exit(retval); 11816242Slayer } 11916242Slayer 12052070Sbostic void 12139829Sbostic usage() 12216242Slayer { 12353782Selan (void)fprintf(stderr, "usage: chmod [-HRh] mode file ...\n"); 12439829Sbostic exit(1); 12516242Slayer } 126