sbase

suckless unix tools
git clone git://git.2f30.org/sbase.git
Log | Files | Refs | README | LICENSE

commit aea256c288d1eca5d0fce0225a89952690eda544
parent d9fa4b3ae7af2f5e0a3cc66ba90265afe720139c
Author: FRIGN <dev@frign.de>
Date:   Thu,  5 Mar 2015 19:08:28 +0100

Audit chmod(1)

1) Update manpage, refactor the HLP-section and other wordings.
2) BUGFIX: If chmod() fails, don't recurse.
3) Rewrite the arg-loop, fixing several issues:
   BUGFIX: Handle multi-flags (e.g. -RH)
   BUGFIX: Properly handle the termination flag --, error on e.g. --x
   BUGFIX: Error out on an empty flag -.
4) Refactor logic after the arg-loop, which is now simpler thanks
   to argv-incremention.

Diffstat:
README | 2+-
chmod.1 | 19+++++++++++--------
chmod.c | 60+++++++++++++++++++++++++++++++++++-------------------------
3 files changed, 47 insertions(+), 34 deletions(-)

diff --git a/README b/README @@ -13,7 +13,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support, =* cal yes none =*| cat yes none =* chgrp yes none -=* chmod yes none +=*| chmod yes none =* chown yes none =*| chroot non-posix none =* cksum yes none diff --git a/chmod.1 b/chmod.1 @@ -1,9 +1,9 @@ -.Dd January 17, 2015 +.Dd March 5, 2015 .Dt CHMOD 1 .Os sbase .Sh NAME .Nm chmod -.Nd change file mode +.Nd change file modes .Sh SYNOPSIS .Nm .Oo @@ -14,8 +14,10 @@ .Ar file ... .Sh DESCRIPTION .Nm -changes the file mode of the given -.Ar files . +changes the file mode of each +.Ar file +to +.Ar mode . .Pp If .Ar mode @@ -59,12 +61,13 @@ read | write | execute | setuid and setgid | sticky .It Fl R Change modes recursively. .It Fl H -Only dereference symbolic links that are passed as command line arguments when -recursively traversing directories. +Dereference +.Ar file +if it is a symbolic link. .It Fl L -Always dereference symbolic links while recursively traversing directories. +Dereference all symbolic links. .It Fl P -Don't dereference symbolic links (default). +Preserve symbolic links. This is the default. .El .Sh SEE ALSO .Xr chgrp 1 , diff --git a/chmod.c b/chmod.c @@ -24,8 +24,7 @@ chmodr(const char *path, int depth) if (chmod(path, m) < 0) { weprintf("chmod %s:", path); ret = 1; - } - if (Rflag) + } else if (Rflag) recurse(path, chmodr, depth); } @@ -40,37 +39,48 @@ main(int argc, char *argv[]) { size_t i; - argv0 = argv[0]; - for (i = 1; i < argc && argv[i][0] == '-'; i++) { - switch (argv[i][1]) { - case 'R': - Rflag = 1; - break; - case 'H': - case 'L': - case 'P': - recurse_follow = argv[i][1]; - break; - case 'r': case 'w': case 'x': case 's': case 't': - /* - * -[rwxst] are valid modes so do not interpret - * them as options - in any case we are done if - * we hit this case - */ - goto done; - default: + argv0 = *(argv++); + argc--; + for (; *argv && (*argv)[0] == '-'; argc--, argv++) { + if (!(*argv)[1]) usage(); + for (i = 1; (*argv)[i]; i++) { + switch ((*argv)[i]) { + case 'R': + Rflag = 1; + break; + case 'H': + case 'L': + case 'P': + recurse_follow = (*argv)[i]; + break; + case 'r': case 'w': case 'x': case 's': case 't': + /* -[rwxst] are valid modes, so we're done */ + if (i == 1) + goto done; + /* fallthrough */ + case '-': + /* -- terminator */ + if (i == 1 && !(*argv)[i + 1]) { + argv++; + argc--; + goto done; + } + /* fallthrough */ + default: + usage(); + } } } done: mask = getumask(); - modestr = argv[i]; + modestr = *argv; - if (argc - i - 1 < 1) + if (argc < 2) usage(); - for (++i; i < argc; i++) - chmodr(argv[i], 0); + for (--argc, ++argv; *argv; argc--, argv++) + chmodr(*argv, 0); return ret; }