"Fossies" - the Fresh Open Source Software Archive

Member "e2fsprogs-1.45.4/lib/support/argv_parse.c" (23 Sep 2019, 3773 Bytes) of package /linux/misc/e2fsprogs-1.45.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "argv_parse.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * argv_parse.c --- utility function for parsing a string into a
    3  *  argc, argv array.
    4  *
    5  * This file defines a function argv_parse() which parsing a
    6  * passed-in string, handling double quotes and backslashes, and
    7  * creates an allocated argv vector which can be freed using the
    8  * argv_free() function.
    9  *
   10  * See argv_parse.h for the formal definition of the functions.
   11  *
   12  * Copyright 1999 by Theodore Ts'o.
   13  *
   14  * Permission to use, copy, modify, and distribute this software for
   15  * any purpose with or without fee is hereby granted, provided that
   16  * the above copyright notice and this permission notice appear in all
   17  * copies.  THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE
   18  * AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
   19  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
   21  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
   22  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
   23  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
   24  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  (Isn't
   25  * it sick that the U.S. culture of lawsuit-happy lawyers requires
   26  * this kind of disclaimer?)
   27  *
   28  * Version 1.1, modified 2/27/1999
   29  */
   30 
   31 #include "config.h"
   32 #ifdef HAVE_STDLIB_H
   33 #include <stdlib.h>
   34 #endif
   35 #include <ctype.h>
   36 #include <string.h>
   37 #include "argv_parse.h"
   38 
   39 #define STATE_WHITESPACE    1
   40 #define STATE_TOKEN     2
   41 #define STATE_QUOTED        3
   42 
   43 /*
   44  * Returns 0 on success, -1 on failure.
   45  */
   46 int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv)
   47 {
   48     int argc = 0, max_argc = 0;
   49     char    **argv, **new_argv, *buf, ch;
   50     char    *cp = 0, *outcp = 0;
   51     int state = STATE_WHITESPACE;
   52 
   53     buf = malloc(strlen(in_buf)+1);
   54     if (!buf)
   55         return -1;
   56 
   57     max_argc = 0; argc = 0; argv = 0;
   58     outcp = buf;
   59     for (cp = in_buf; (ch = *cp); cp++) {
   60         if (state == STATE_WHITESPACE) {
   61             if (isspace((int) ch))
   62                 continue;
   63             /* Not whitespace, so start a new token */
   64             state = STATE_TOKEN;
   65             if (argc >= max_argc) {
   66                 max_argc += 3;
   67                 new_argv = realloc(argv,
   68                           (max_argc+1)*sizeof(char *));
   69                 if (!new_argv) {
   70                     free(argv);
   71                     free(buf);
   72                     return -1;
   73                 }
   74                 argv = new_argv;
   75             }
   76             argv[argc++] = outcp;
   77         }
   78         if (state == STATE_QUOTED) {
   79             if (ch == '"')
   80                 state = STATE_TOKEN;
   81             else
   82                 *outcp++ = ch;
   83             continue;
   84         }
   85         /* Must be processing characters in a word */
   86         if (isspace((int) ch)) {
   87             /*
   88              * Terminate the current word and start
   89              * looking for the beginning of the next word.
   90              */
   91             *outcp++ = 0;
   92             state = STATE_WHITESPACE;
   93             continue;
   94         }
   95         if (ch == '"') {
   96             state = STATE_QUOTED;
   97             continue;
   98         }
   99         if (ch == '\\') {
  100             ch = *++cp;
  101             switch (ch) {
  102             case '\0':
  103                 ch = '\\'; cp--; break;
  104             case 'n':
  105                 ch = '\n'; break;
  106             case 't':
  107                 ch = '\t'; break;
  108             case 'b':
  109                 ch = '\b'; break;
  110             }
  111         }
  112         *outcp++ = ch;
  113     }
  114     if (state != STATE_WHITESPACE)
  115         *outcp++ = '\0';
  116     if (argv == 0) {
  117         argv = malloc(sizeof(char *));
  118         free(buf);
  119     }
  120     argv[argc] = 0;
  121     if (ret_argc)
  122         *ret_argc = argc;
  123     if (ret_argv)
  124         *ret_argv = argv;
  125     return 0;
  126 }
  127 
  128 void argv_free(char **argv)
  129 {
  130     free(*argv);
  131     free(argv);
  132 }
  133 
  134 #ifdef DEBUG
  135 /*
  136  * For debugging
  137  */
  138 
  139 #include <stdio.h>
  140 
  141 int main(int argc, char **argv)
  142 {
  143     int ac, ret;
  144     char    **av, **cpp;
  145     char    buf[256];
  146 
  147     while (!feof(stdin)) {
  148         if (fgets(buf, sizeof(buf), stdin) == NULL)
  149             break;
  150         ret = argv_parse(buf, &ac, &av);
  151         if (ret != 0) {
  152             printf("Argv_parse returned %d!\n", ret);
  153             continue;
  154         }
  155         printf("Argv_parse returned %d arguments...\n", ac);
  156         for (cpp = av; *cpp; cpp++) {
  157             if (cpp != av)
  158                 printf(", ");
  159             printf("'%s'", *cpp);
  160         }
  161         printf("\n");
  162         argv_free(av);
  163     }
  164     exit(0);
  165 }
  166 #endif /* DEBUG */