119840Sdist /* 2*66445Sbostic * Copyright (c) 1989, 1993, 1994 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[] = 10*66445Sbostic "@(#) Copyright (c) 1989, 1993, 1994\n\ 1163597Sbostic The Regents of the University of California. All rights reserved.\n"; 1234043Sbostic #endif /* not lint */ 1319840Sdist 1434043Sbostic #ifndef lint 15*66445Sbostic static char sccsid[] = "@(#)chmod.c 8.3 (Berkeley) 03/25/94"; 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; 46*66445Sbostic while ((ch = getopt(argc, argv, "HRXfghorstuwx")) != EOF) 47*66445Sbostic switch (ch) { 4853782Selan case 'H': 4953782Selan Hflag = 1; 5053782Selan fts_options |= FTS_COMFOLLOW; 5153782Selan break; 5224503Ssam case 'R': 5347072Sbostic rflag = 1; 5424503Ssam break; 55*66445Sbostic case 'f': /* XXX: 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; 6365163Sbostic /* 64*66445Sbostic * XXX 6565163Sbostic * "-[rwx]" are valid mode commands. If they are the entire 6665163Sbostic * argument, getopt has moved past them, so decrement optind. 6765163Sbostic * Regardless, we're done argument processing. 6865163Sbostic */ 69*66445Sbostic case 'g': case 'o': case 'r': case 's': 70*66445Sbostic case 't': case 'u': case 'w': case 'X': case 'x': 71*66445Sbostic if (argv[optind - 1][0] == '-' && 72*66445Sbostic argv[optind - 1][1] == ch && 73*66445Sbostic argv[optind - 1][2] == '\0') 7465163Sbostic --optind; 7565163Sbostic goto done; 7634043Sbostic case '?': 7724503Ssam default: 7839829Sbostic usage(); 7923482Smckusick } 8034043Sbostic done: argv += optind; 8134043Sbostic argc -= optind; 8234043Sbostic 8339829Sbostic if (argc < 2) 8439829Sbostic usage(); 8539829Sbostic 8639829Sbostic mode = *argv; 8739829Sbostic if (*mode >= '0' && *mode <= '7') { 8852070Sbostic omode = (int)strtol(mode, &ep, 8); 8952070Sbostic if (omode < 0 || *ep) 9058142Sbostic errx(1, "invalid file mode: %s", mode); 9139829Sbostic oct = 1; 9239829Sbostic } else { 9358142Sbostic if ((set = setmode(mode)) == NULL) 9458142Sbostic errx(1, "invalid file mode: %s", mode); 9539829Sbostic oct = 0; 9616242Slayer } 9734043Sbostic 9839829Sbostic retval = 0; 9953782Selan if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL) 10063596Sbostic err(1, ""); 101*66445Sbostic while ((p = fts_read(ftsp)) != NULL) 102*66445Sbostic switch (p->fts_info) { 10353782Selan case FTS_D: 10453782Selan if (!rflag) 10553782Selan fts_set(ftsp, p, FTS_SKIP); 10663596Sbostic case FTS_SL: 10763596Sbostic case FTS_SLNONE: 10853782Selan break; 10953782Selan case FTS_DNR: 11053782Selan case FTS_ERR: 11153782Selan case FTS_NS: 11258142Sbostic err(1, "%s", p->fts_path); 11353782Selan default: 11463596Sbostic if (p->fts_info == FTS_SL && !(hflag || 11553782Selan (Hflag && p->fts_level == FTS_ROOTLEVEL))) 11653782Selan continue; 11753782Selan if (chmod(p->fts_accpath, oct ? omode : 11858142Sbostic getmode(set, p->fts_statp->st_mode)) && !fflag) { 11958142Sbostic warn(p->fts_path); 12058142Sbostic retval = 1; 12158142Sbostic } 12253782Selan break; 12353782Selan } 12439829Sbostic exit(retval); 12516242Slayer } 12616242Slayer 12752070Sbostic void 12839829Sbostic usage() 12916242Slayer { 13053782Selan (void)fprintf(stderr, "usage: chmod [-HRh] mode file ...\n"); 13139829Sbostic exit(1); 13216242Slayer } 133