119840Sdist /* 263597Sbostic * Copyright (c) 1989, 1993 363597Sbostic * The Regents of the University of California. All rights reserved. 439829Sbostic * 542527Sbostic * %sccs.include.redist.c% 619840Sdist */ 716242Slayer 819840Sdist #ifndef lint 963597Sbostic static char copyright[] = 1063597Sbostic "@(#) Copyright (c) 1989, 1993\n\ 1163597Sbostic The Regents of the University of California. All rights reserved.\n"; 1234043Sbostic #endif /* not lint */ 1319840Sdist 1434043Sbostic #ifndef lint 15*65163Sbostic static char sccsid[] = "@(#)chmod.c 8.2 (Berkeley) 12/16/93"; 1634043Sbostic #endif /* not lint */ 1734043Sbostic 1816242Slayer #include <sys/types.h> 1916242Slayer #include <sys/stat.h> 2058142Sbostic 2158142Sbostic #include <err.h> 2252070Sbostic #include <errno.h> 2339829Sbostic #include <fts.h> 2439829Sbostic #include <stdio.h> 2552070Sbostic #include <stdlib.h> 2642010Sbostic #include <string.h> 2758142Sbostic #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; 4158142Sbostic 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; 63*65163Sbostic /* 64*65163Sbostic * "-[rwx]" are valid mode commands. If they are the entire 65*65163Sbostic * argument, getopt has moved past them, so decrement optind. 66*65163Sbostic * Regardless, we're done argument processing. 67*65163Sbostic */ 68*65163Sbostic case 'r': 69*65163Sbostic if (!strcmp(argv[optind - 1], "-r")) 70*65163Sbostic --optind; 71*65163Sbostic goto done; 7239829Sbostic case 'w': 73*65163Sbostic if (!strcmp(argv[optind - 1], "-w")) 74*65163Sbostic --optind; 75*65163Sbostic goto done; 7639829Sbostic case 'x': 77*65163Sbostic if (!strcmp(argv[optind - 1], "-x")) 78*65163Sbostic --optind; 7939829Sbostic goto done; 8034043Sbostic case '?': 8124503Ssam default: 8239829Sbostic usage(); 8323482Smckusick } 8434043Sbostic done: argv += optind; 8534043Sbostic argc -= optind; 8634043Sbostic 8739829Sbostic if (argc < 2) 8839829Sbostic usage(); 8939829Sbostic 9039829Sbostic mode = *argv; 9139829Sbostic if (*mode >= '0' && *mode <= '7') { 9252070Sbostic omode = (int)strtol(mode, &ep, 8); 9352070Sbostic if (omode < 0 || *ep) 9458142Sbostic errx(1, "invalid file mode: %s", mode); 9539829Sbostic oct = 1; 9639829Sbostic } else { 9758142Sbostic if ((set = setmode(mode)) == NULL) 9858142Sbostic errx(1, "invalid file mode: %s", mode); 9939829Sbostic oct = 0; 10016242Slayer } 10134043Sbostic 10239829Sbostic retval = 0; 10353782Selan if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL) 10463596Sbostic err(1, ""); 10553782Selan while (p = fts_read(ftsp)) 10653782Selan switch(p->fts_info) { 10753782Selan case FTS_D: 10853782Selan if (!rflag) 10953782Selan fts_set(ftsp, p, FTS_SKIP); 11063596Sbostic case FTS_SL: 11163596Sbostic case FTS_SLNONE: 11253782Selan break; 11353782Selan case FTS_DNR: 11453782Selan case FTS_ERR: 11553782Selan case FTS_NS: 11658142Sbostic err(1, "%s", p->fts_path); 11753782Selan default: 11863596Sbostic if (p->fts_info == FTS_SL && !(hflag || 11953782Selan (Hflag && p->fts_level == FTS_ROOTLEVEL))) 12053782Selan continue; 12153782Selan if (chmod(p->fts_accpath, oct ? omode : 12258142Sbostic getmode(set, p->fts_statp->st_mode)) && !fflag) { 12358142Sbostic warn(p->fts_path); 12458142Sbostic retval = 1; 12558142Sbostic } 12653782Selan break; 12753782Selan } 12839829Sbostic exit(retval); 12916242Slayer } 13016242Slayer 13152070Sbostic void 13239829Sbostic usage() 13316242Slayer { 13453782Selan (void)fprintf(stderr, "usage: chmod [-HRh] mode file ...\n"); 13539829Sbostic exit(1); 13616242Slayer } 137