home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3884 / apply.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-22  |  5.0 KB  |  229 lines

  1. /*
  2.     apply -- apply a command to a set of arguments
  3.  
  4.     last edit:    85/10/20    D A Gwyn
  5.  
  6. Usage:
  7.     $ apply[ -a<c>][ -<n>][ -v][ -w] <command> <args ...>
  8.  
  9.     Runs the named <command> repeatedly, <n> (default 1) successive
  10.     arguments from <args ...> passed to <command> each time.
  11.  
  12.     Special case:  If <n> is 0, runs <command> as if <n> were 1, but
  13.     does not pass any arguments to the <command>.
  14.  
  15.     Special kludge:  If <command> contains <c> (default %) followed
  16.     by a digit from 1 through 9, <n> is ignored and the <c><digit>
  17.     pairs are replaced by the corresponding remaining unused <args>,
  18.     consuming as many <args> as the largest <digit> in <command>.
  19.  
  20.     Added by DAG:  The -v (verbose) option prints each constructed
  21.     command before executing it.  If -w is specified, commands that
  22.     return nonzero exit status will cause a warning message.
  23.  
  24. Credit:
  25.     This is a public domain implementation of the 8th Edition UNIX
  26.     command of the same name, working entirely from the manual spec.
  27. */
  28. #ifndef    lint
  29. static char    sccsid[] = "@(#)apply.c    1.1";
  30. #endif
  31.  
  32. #include    <ctype.h>
  33. #include    <stdio.h>
  34. #include    <string.h>
  35.  
  36. extern void    exit();
  37. extern int    atoi();
  38.  
  39. #define    MAX_CMD_LEN    BUFSIZ        /* allowed command size */
  40.  
  41. static int    verbose = 0;        /* set for command printout */
  42. static int    warn = 0;        /* set for failure warnings */
  43. static char    c = '%';        /* magic substitution prefix */
  44. static int    n = 1;            /* real arguments per command */
  45. static int    inc = 1;        /* args consumed per command */
  46. static char    *command;        /* command template */
  47. static char    buf[MAX_CMD_LEN+1];    /* shell command built here */
  48. static int    errors = 0;        /* 1 if any execution errors */
  49.  
  50. #define    ToDigit( c )    ((c) - '0')    /* convert char to int digit */
  51.  
  52. static void    LeftOver(), PutBuf(), Usage();
  53.  
  54.  
  55. main( argc, argv )
  56.     int    argc;
  57.     char    *argv[];
  58.     {
  59.     /* process options */
  60.  
  61.     while ( --argc > 0 && (*++argv)[0] == '-' )
  62.         if ( (*argv)[1] == 'v' && (*argv)[2] == '\0' )
  63.             verbose = 1;        /* "-v" */
  64.         else if ( (*argv)[1] == 'w' && (*argv)[2] == '\0' )
  65.             warn = 1;        /* "-w" */
  66.         else if ( (*argv)[1] == 'a' )    /* "-a<c>" */
  67.             {
  68.             /* wish we could use getopt() here */
  69.  
  70.             if ( (c = (*argv)[2]) != '\0'
  71.                && (*argv)[3] != '\0'
  72.               || (c == '\0'
  73.                && (--argc <= 0
  74.                 || (c = (*++argv)[0]) == '\0'
  75.                 || (*argv)[1] != '\0'
  76.                   )
  77.                  )
  78.                )    {
  79.                 (void)fprintf( stderr,
  80.                            "apply: bad -a value\n"
  81.                          );
  82.                 Usage();
  83.                 }
  84.             }
  85.         else if ( isdigit( (*argv)[1] ) )    /* "-<n>" */
  86.             {
  87.             if ( (n = atoi( &(*argv)[1] )) > 0 )
  88.                 inc = n;
  89.             /* else inc = 1; */
  90.             }
  91.         else    {
  92.             (void)fprintf( stderr,
  93.                        "apply: unknown option \"%s\"\n",
  94.                        *argv
  95.                      );
  96.             Usage();
  97.             }
  98.  
  99.     /* save command template */
  100.  
  101.     if ( --argc < 0 )
  102.         {
  103.         (void)fprintf( stderr, "apply: missing command\n" );
  104.         Usage();
  105.         }
  106.  
  107.     command = *argv++;
  108.  
  109.     /* execute constructed command repeatedly */
  110.  
  111.     while ( argc > 0 )        /* unconsumed <args> remain */
  112.         {
  113.         register char    *cp;    /* -> <command> template */
  114.         register char    *bp;    /* -> construction buffer */
  115.         register int    max = 0;    /* maximum <digit> */
  116.  
  117.         /* copy <command> template into construction buffer,
  118.            looking for and performing <c><digit> substitution */
  119.  
  120.         for ( bp = buf, cp = command; *cp != '\0'; ++cp )
  121.             if ( *cp == c    /* <c> matched, try <digit> */
  122.               && isdigit( cp[1] ) && cp[1] != '0'
  123.                )    {
  124.                 register char    *ap;    /* -> arg[.] */
  125.                 register int    digit;    /* arg # */
  126.  
  127.                 ++cp;    /* -> <digit> */
  128.  
  129.                 if ( (digit = ToDigit( *cp )) > max )
  130.                     max = digit;
  131.  
  132.                 if ( digit > argc )
  133.                     LeftOver( argc );
  134.  
  135.                 for ( ap = argv[digit - 1];
  136.                       *ap != '\0';
  137.                       ++ap
  138.                     )
  139.                     PutBuf( bp++, *ap );
  140.                 }
  141.             else
  142.                 PutBuf( bp++, *cp );
  143.  
  144.         if ( max > 0 )        /* substitution performed */
  145.             {
  146.             argc -= max;
  147.             argv += max;
  148.             }
  149.         else    {
  150.             register char    *ap;    /* -> arg[.] */
  151.             register int    i;    /* arg # - 1 */
  152.  
  153.             if ( inc > argc )
  154.                 LeftOver( argc );
  155.  
  156.             /* append <n> arguments separated by spaces */
  157.  
  158.             for ( i = 0; i < n; ++i )
  159.                 {
  160.                 PutBuf( bp++, ' ' );
  161.  
  162.                 for ( ap = argv[i]; *ap != '\0'; ++ap )
  163.                     PutBuf( bp++, *ap );
  164.                 }
  165.  
  166.             argc -= inc;
  167.             argv += inc;
  168.             }
  169.  
  170.         PutBuf( bp, '\0' );    /* terminate string */
  171.  
  172.         /* execute constructed command */
  173.  
  174.         if ( verbose )
  175.             (void)fprintf( stderr, "apply: %s\n", buf );
  176.  
  177.         if ( system( buf ) != 0 )
  178.             {
  179.             errors = 1;
  180.         
  181.             if ( warn )
  182.                 (void)fprintf( stderr,
  183.                            "apply: \"%s\" failed\n",
  184.                            buf
  185.                          );
  186.             }
  187.         }
  188.  
  189.     return errors;
  190.     }
  191.  
  192.  
  193. static void
  194. PutBuf( bp, ch )            /* store character in buf[] */
  195.     register char    *bp;        /* -> buf[.] */
  196.     int        ch;        /* character to be stored */
  197.     {
  198.     if ( bp > &buf[MAX_CMD_LEN] )
  199.         {
  200.         (void)fprintf( stderr, "apply: command too long\n" );
  201.         exit( 1 );
  202.         }
  203.  
  204.     *bp = ch;
  205.     }
  206.  
  207.  
  208. static void
  209. LeftOver( argc )            /* warn about LeftOver args */
  210.     int    argc;            /* how many left over */
  211.     {
  212.     (void)fprintf( stderr,
  213.                "apply: %d arg%s left over\n",
  214.                argc,
  215.                argc == 1 ? "" : "s"
  216.              );
  217.     exit( 1 );
  218.     }
  219.  
  220.  
  221. static void
  222. Usage()                    /* print usage message */
  223.     {
  224.     (void)fprintf( stderr,
  225.     "Usage:\tapply [-a<c>] [-<n>] [-v] [-w] <command> <args ...>\n"
  226.              );
  227.     exit( 2 );
  228.     }
  229.