From 4f7b9c661b0b2fb672d2c465e68092f4885db534 Mon Sep 17 00:00:00 2001 From: Sami Kerola Date: Sat, 4 Jun 2011 18:56:08 +0200 Subject: [PATCH] pwdx.c: new usage & fix coding style Coding style fixed and new help output. Signed-off-by: Sami Kerola --- pwdx.c | 193 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 95 insertions(+), 98 deletions(-) diff --git a/pwdx.c b/pwdx.c index 755c1780..8edf8fb2 100644 --- a/pwdx.c +++ b/pwdx.c @@ -1,108 +1,105 @@ -// Copyright 2004 Nicholas Miell -// -// This file may be used subject to the terms and conditions of the -// GNU Library General Public License Version 2 as published by the -// Free Software Foundation.This program is distributed in the hope -// that it will be useful, but WITHOUT ANY WARRANTY; without even the -// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the GNU Library General Public License for more -// details. +/* + * Copyright 2004 Nicholas Miell + * + * This file may be used subject to the terms and conditions of the + * GNU Library General Public License Version 2 as published by the + * Free Software Foundation.This program is distributed in the hope + * that it will be useful, but WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Library General Public License for more + * details. + */ -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include #include "proc/version.h" -static void die(const char *msg) NORETURN; -static void die(const char *msg) +static void __attribute__ ((__noreturn__)) usage(FILE * out) { - fputs(msg, stderr); - exit(1); + fprintf(out, "\nUsage:\n" + " %s [options] pid...\n", program_invocation_short_name); + fprintf(out, + "\nOptions:\n" + " -V, --version output version information and exit\n" + " -h, --help output help screen and exit\n\n"); + + exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } -static void version(void) NORETURN; -static void version(void) +int main(int argc, char *argv[]) { - printf("pwdx (%s)\n", procps_version); - exit(0); -} - -int main(int argc, char* argv[]) -{ - regex_t re; - int i; - - if (argc < 2) - die("Usage: pwdx pid...\n"); - - // Allowed on the command line: - // - // --version - // -V - // /proc/nnnn - // nnnn - // - // where nnnn is any number that doesn't begin with 0. - // - // If --version or -V are present, further arguments are ignored - // completely. - - regcomp(&re, "^((/proc/+)?[1-9][0-9]*|-V|--version)$", - REG_EXTENDED|REG_NOSUB); - - for (i = 1; i < argc; i++) { - if (regexec(&re, argv[i], 0, NULL, 0) != 0) { - /* Constant 27 is the length of the error string "pwdx: ... " */ - char buf[27 + strlen (argv[i]) + 1]; - snprintf(buf, sizeof buf, "pwdx: invalid process id: %s\n", argv[i]); - buf[sizeof(buf)-1] = '\0'; - die(buf); - } - if (!strcmp("-V", argv[i]) || !strcmp("--version", argv[i])) - version(); - } - - regfree(&re); - - int alloclen = 128; - char *pathbuf = malloc(alloclen); - - for (i = 1; i < argc; i++) { - char * s; - int len; - /* Constant 10 is the length of strings "/proc/" + "/cwd" + 1 */ - char buf[10 + strlen(argv[i]) + 1]; - - // At this point, all arguments are in the form /proc/nnnn - // or nnnn, so a simple check based on the first char is - // possible - if (argv[i][0] != '/') - snprintf(buf, sizeof buf, "/proc/%s/cwd", argv[i]); - else - snprintf(buf, sizeof buf, "%s/cwd", argv[i]); - - // buf contains /proc/nnnn/cwd symlink name on entry, the - // target of that symlink on return - while ((len = readlink(buf, pathbuf, alloclen)) == alloclen) { - alloclen *= 2; - pathbuf = realloc(pathbuf, alloclen); - } - - if (len < 0) { - s = strerror(errno == ENOENT ? ESRCH : errno); - } else { - pathbuf[len] = 0; - s = pathbuf; - } - - printf("%s: %s\n", argv[i], s); - } - - return 0; + char ch; + int retval = 0, i; + int alloclen = 128; + char *pathbuf; + + static const struct option longopts[] = { + {"version", no_argument, 0, 'V'}, + {"help", no_argument, 0, 'h'}, + {NULL, 0, 0, 0} + }; + + while ((ch = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1) + switch (ch) { + case 'V': + display_version(); + return EXIT_SUCCESS; + case 'h': + usage(stdout); + default: + usage(stderr); + } + + argc -= optind; + argv += optind; + + if (argc == 0) + usage(stderr); + + pathbuf = malloc(alloclen); + + for (i = 0; i < argc; i++) { + char *s; + ssize_t len; + /* Constant 10 is the length of strings "/proc/" + "/cwd" + 1 */ + char buf[10 + strlen(argv[i]) + 1]; + + /* + * At this point, all arguments are in the form + * /proc/NNNN or NNNN, so a simple check based on + * the first char is possible + */ + if (argv[i][0] != '/') + snprintf(buf, sizeof buf, "/proc/%s/cwd", argv[i]); + else + snprintf(buf, sizeof buf, "%s/cwd", argv[i]); + + /* + * buf contains /proc/NNNN/cwd symlink name + * on entry, the target of that symlink on return + */ + while ((len = readlink(buf, pathbuf, alloclen)) == alloclen) { + alloclen *= 2; + pathbuf = realloc(pathbuf, alloclen); + } + + if (len < 0) { + s = strerror(errno == ENOENT ? ESRCH : errno); + retval = 1; + } else { + pathbuf[len] = 0; + s = pathbuf; + } + + printf("%s: %s\n", argv[i], s); + } + + return retval; }