URI: 
       tMake invocation simpler and more robust - wendy - watch files/directories and run commands on any event
  HTML git clone git://z3bra.org/wendy
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 56b76a0bf99cdb6c1ec4d7564d9692352960ec02
   DIR parent 914fb4ad0fa9e4e14541ccd0baf749c582e6227a
  HTML Author: z3bra <willyatmailoodotorg>
       Date:   Sun, 31 Jan 2016 15:18:58 +0100
       
       Make invocation simpler and more robust
       
       * uses arg.h for argument parsing
       * removes -e argument. now everything passed beyond arguments
         is considered to be the command
       * makes IN_CLOSE_WRITE the default mask (aka, file modification)
       
       Diffstat:
         A arg.h                               |      65 +++++++++++++++++++++++++++++++
         M wendy.c                             |      59 ++++++++++++++++---------------
       
       2 files changed, 96 insertions(+), 28 deletions(-)
       ---
   DIR diff --git a/arg.h b/arg.h
       t@@ -0,0 +1,65 @@
       +/*
       + * Copy me if you can.
       + * by 20h
       + */
       +
       +#ifndef ARG_H__
       +#define ARG_H__
       +
       +extern char *argv0;
       +
       +/* use main(int argc, char *argv[]) */
       +#define ARGBEGIN        for (argv0 = *argv, argv++, argc--;\
       +                                        argv[0] && argv[0][1]\
       +                                        && argv[0][0] == '-';\
       +                                        argc--, argv++) {\
       +                                char argc_;\
       +                                char **argv_;\
       +                                int brk_;\
       +                                if (argv[0][1] == '-' && argv[0][2] == '\0') {\
       +                                        argv++;\
       +                                        argc--;\
       +                                        break;\
       +                                }\
       +                                for (brk_ = 0, argv[0]++, argv_ = argv;\
       +                                                argv[0][0] && !brk_;\
       +                                                argv[0]++) {\
       +                                        if (argv_ != argv)\
       +                                                break;\
       +                                        argc_ = argv[0][0];\
       +                                        switch (argc_)
       +
       +/* Handles obsolete -NUM syntax */
       +#define ARGNUM                                case '0':\
       +                                        case '1':\
       +                                        case '2':\
       +                                        case '3':\
       +                                        case '4':\
       +                                        case '5':\
       +                                        case '6':\
       +                                        case '7':\
       +                                        case '8':\
       +                                        case '9'
       +
       +#define ARGEND                        }\
       +                        }
       +
       +#define ARGC()                argc_
       +
       +#define ARGNUMF()        (brk_ = 1, estrtonum(argv[0], 0, INT_MAX))
       +
       +#define EARGF(x)        ((argv[0][1] == '\0' && argv[1] == NULL)?\
       +                                ((x), abort(), (char *)0) :\
       +                                (brk_ = 1, (argv[0][1] != '\0')?\
       +                                        (&argv[0][1]) :\
       +                                        (argc--, argv++, argv[0])))
       +
       +#define ARGF()                ((argv[0][1] == '\0' && argv[1] == NULL)?\
       +                                (char *)0 :\
       +                                (brk_ = 1, (argv[0][1] != '\0')?\
       +                                        (&argv[0][1]) :\
       +                                        (argc--, argv++, argv[0])))
       +
       +#define LNGARG()        &argv[0][0]
       +
       +#endif
   DIR diff --git a/wendy.c b/wendy.c
       t@@ -23,6 +23,8 @@
        #include <sys/inotify.h>
        #include <sys/wait.h>
        
       +#include "arg.h"
       +
        /* definitions, defaults, bla bla blah */
        #define EVENT_SIZE      (sizeof(struct inotify_event))
        /* maximum number of event * queuing at the same time */
       t@@ -42,17 +44,10 @@ int verbose = 0, nb = 0;
        struct node_t *head = NULL;
        
                void
       -usage()
       +usage(char *name)
        {
       -        fputs("usage: wendy [-m mask] [-l] [-f file] [-t timeout] [-q] "
       -                        "[-e command [args] ..]\n"
       -                        "\t-m mask      : set mask manually (see -l))\n"
       -                        "\t-l           : list events mask values\n"
       -                        "\t-f file      : file to watch (everything is a file)\n"
       -                        "\t-t timeout   : time between event check (in seconds)\n"
       -                        "\t-v           : talk to me, program\n"
       -                        "\t-e command   : command to launch (must be the last arg!)\n",
       -                        stdout);
       +        fprintf(stderr, "usage: %s [-lq] [-m mask] [-f file] [-t timeout] "
       +                        "[cmd [args..]]\n", name);
                exit(1);
        }
        
       t@@ -89,7 +84,6 @@ list_events()
                                IN_ALL_EVENTS,
                                IN_UNMOUNT
                                        );
       -        exit(0);
        }
        
                char *
       t@@ -177,33 +171,42 @@ watch_node(int fd, const char *path, uint32_t mask)
                int
        main (int argc, char **argv)
        {
       -        int  fd, len, i = 0, timeout = 0, ignore = 0;
       -        uint32_t mask = 0;
       +        int  fd, len, i = 0, timeout = 0;
       +        uint32_t mask = IN_CLOSE_WRITE;
                char buf[BUF_LEN];
       -        char *fn = NULL;
       +        char *fn = NULL, *argv0 = NULL;
                char **cmd = NULL;
                struct inotify_event *ev;
        
       -        if ((argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h')) usage();
       -
                /* get file descriptor */
                fd = inotify_init();
                if (fd < 0)
                        perror("inotify_init");
        
        
       -        /* parse option given. see usage() above */
       -        for(i = 1; (i < argc) && (argv[i][0] == '-') && !ignore; i++) {
       -                switch (argv[i][1]) {
       -                        case 'm': mask = atoi(argv[++i]); break;
       -                        case 'l': list_events(); break;
       -                        case 'v': verbose += 1; break;
       -                        case 'f': watch_node(fd, argv[++i], mask); break;
       -                        case 't': timeout = atoi(argv[++i]); break;
       -                        case 'e': cmd = &argv[++i]; ignore=1; break;
       -                        default: usage();
       -                }
       -        }
       +        ARGBEGIN{
       +        case 'm':
       +                mask = atoi(EARGF(usage(argv0)));
       +                break;
       +        case 'l':
       +                list_events();
       +                return 0;
       +                break; /* NOT REACHED */
       +        case 'v':
       +                verbose++;
       +                break;
       +        case 'f':
       +                watch_node(fd, EARGF(usage(argv0)), mask);
       +                break;
       +        case 't':
       +                timeout = atoi(EARGF(usage(argv0)));
       +                break;
       +        default:
       +                usage(argv0);
       +        }ARGEND;
       +
       +        if (argc > 0)
       +                cmd = argv;
        
                /* test given arguments */
                if (!timeout)   { timeout = DEFAULT_CHECK; }