Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/util-linux/getopt.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 532 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 22  Line 22 
22   * Version 1.0.6: Tue Jun 27 2000   * Version 1.0.6: Tue Jun 27 2000
23   *   No important changes   *   No important changes
24   * Version 1.1.0: Tue Jun 30 2000   * Version 1.1.0: Tue Jun 30 2000
25   *   Added NLS support (partly written by Arkadiusz Mi<B6>kiewicz   *   Added NLS support (partly written by Arkadiusz Mickiewicz
26   *     <misiek@misiek.eu.org>)   *     <misiek@misiek.eu.org>)
27   * Ported to Busybox - Alfred M. Szmidt <ams@trillian.itslinux.org>   * Ported to Busybox - Alfred M. Szmidt <ams@trillian.itslinux.org>
28   *  Removed --version/-V and --help/-h in   *  Removed --version/-V and --help/-h in
# Line 31  Line 31 
31   *   *
32   */   */
33    
 #include "busybox.h"  
34  #include <getopt.h>  #include <getopt.h>
35    #include "libbb.h"
36    
37  /* NON_OPT is the code that is returned when a non-option is found in '+'  /* NON_OPT is the code that is returned when a non-option is found in '+'
38     mode */     mode */
39  enum {  enum {
40   NON_OPT = 1,   NON_OPT = 1,
41    #if ENABLE_GETOPT_LONG
42  /* LONG_OPT is the code that is returned when a long option is found. */  /* LONG_OPT is the code that is returned when a long option is found. */
43   LONG_OPT = 2   LONG_OPT = 2
44    #endif
45  };  };
46    
47  /* The shells recognized. */  /* For finding activated option flags. Must match getopt32 call! */
48  typedef enum {BASH,TCSH} shell_t;  enum {
49     OPT_o = 0x1, // -o
50     OPT_n = 0x2, // -n
51     OPT_q = 0x4, // -q
52     OPT_Q = 0x8, // -Q
53     OPT_s = 0x10, // -s
54     OPT_T = 0x20, // -T
55     OPT_u = 0x40, // -u
56    #if ENABLE_GETOPT_LONG
57     OPT_a = 0x80, // -a
58     OPT_l = 0x100, // -l
59    #endif
60     SHELL_IS_TCSH = 0x8000, /* hijack this bit for other purposes */
61    };
62    
63  /* Some global variables that tells us how to parse. */  /* 0 is getopt_long, 1 is getopt_long_only */
64  static shell_t shell=BASH; /* The shell we generate output for. */  #define alternative  (option_mask32 & OPT_a)
 static int quiet_errors; /* 0 is not quiet. */  
 static int quiet_output; /* 0 is not quiet. */  
 static int quote=1; /* 1 is do quote. */  
 static int alternative; /* 0 is getopt_long, 1 is getopt_long_only */  
   
 /* Function prototypes */  
 static const char *normalize(const char *arg);  
 static int generate_output(char * argv[],int argc,const char *optstr,  
  const struct option *longopts);  
 static void add_long_options(char *options);  
 static void add_longopt(const char *name,int has_arg);  
 static void set_shell(const char *new_shell);  
65    
66    #define quiet_errors (option_mask32 & OPT_q)
67    #define quiet_output (option_mask32 & OPT_Q)
68    #define quote        (!(option_mask32 & OPT_u))
69    #define shell_TCSH   (option_mask32 & SHELL_IS_TCSH)
70    
71  /*  /*
72   * This function 'normalizes' a single argument: it puts single quotes around   * This function 'normalizes' a single argument: it puts single quotes around
# Line 71  static void set_shell(const char *new_sh Line 77  static void set_shell(const char *new_sh
77   * This function returns a pointer to a buffer that is overwritten by   * This function returns a pointer to a buffer that is overwritten by
78   * each call.   * each call.
79   */   */
80  const char *normalize(const char *arg)  static const char *normalize(const char *arg)
81  {  {
  static char *BUFFER=NULL;  
  const char *argptr=arg;  
82   char *bufptr;   char *bufptr;
83    #if ENABLE_FEATURE_CLEAN_UP
84     static char *BUFFER = NULL;
85   free(BUFFER);   free(BUFFER);
86    #else
87     char *BUFFER;
88    #endif
89    
90   if (!quote) { /* Just copy arg */   if (!quote) { /* Just copy arg */
91   BUFFER=xstrdup(arg);   BUFFER = xstrdup(arg);
92   return BUFFER;   return BUFFER;
93   }   }
94    
# Line 88  const char *normalize(const char *arg) Line 96  const char *normalize(const char *arg)
96     For a quote we need a closing quote, a backslash, a quote and an     For a quote we need a closing quote, a backslash, a quote and an
97     opening quote! We need also the global opening and closing quote,     opening quote! We need also the global opening and closing quote,
98     and one extra character for '\0'. */     and one extra character for '\0'. */
99   BUFFER=xmalloc(strlen(arg)*4+3);   BUFFER = xmalloc(strlen(arg)*4 + 3);
100    
101   bufptr=BUFFER;   bufptr = BUFFER;
102   *bufptr++='\'';   *bufptr ++= '\'';
103    
104   while (*argptr) {   while (*arg) {
105   if (*argptr == '\'') {   if (*arg == '\'') {
106   /* Quote: replace it with: '\'' */   /* Quote: replace it with: '\'' */
107   *bufptr++='\'';   *bufptr ++= '\'';
108   *bufptr++='\\';   *bufptr ++= '\\';
109   *bufptr++='\'';   *bufptr ++= '\'';
110   *bufptr++='\'';   *bufptr ++= '\'';
111   } else if (shell==TCSH && *argptr=='!') {   } else if (shell_TCSH && *arg == '!') {
112   /* Exclamation mark: replace it with: \! */   /* Exclamation mark: replace it with: \! */
113   *bufptr++='\'';   *bufptr ++= '\'';
114   *bufptr++='\\';   *bufptr ++= '\\';
115   *bufptr++='!';   *bufptr ++= '!';
116   *bufptr++='\'';   *bufptr ++= '\'';
117   } else if (shell==TCSH && *argptr=='\n') {   } else if (shell_TCSH && *arg == '\n') {
118   /* Newline: replace it with: \n */   /* Newline: replace it with: \n */
119   *bufptr++='\\';   *bufptr ++= '\\';
120   *bufptr++='n';   *bufptr ++= 'n';
121   } else if (shell==TCSH && isspace(*argptr)) {   } else if (shell_TCSH && isspace(*arg)) {
122   /* Non-newline whitespace: replace it with \<ws> */   /* Non-newline whitespace: replace it with \<ws> */
123   *bufptr++='\'';   *bufptr ++= '\'';
124   *bufptr++='\\';   *bufptr ++= '\\';
125   *bufptr++=*argptr;   *bufptr ++= *arg;
126   *bufptr++='\'';   *bufptr ++= '\'';
127   } else   } else
128   /* Just copy */   /* Just copy */
129   *bufptr++=*argptr;   *bufptr ++= *arg;
130   argptr++;   arg++;
131   }   }
132   *bufptr++='\'';   *bufptr ++= '\'';
133   *bufptr++='\0';   *bufptr ++= '\0';
134   return BUFFER;   return BUFFER;
135  }  }
136    
# Line 133  const char *normalize(const char *arg) Line 141  const char *normalize(const char *arg)
141   * optstr must contain the short options, and longopts the long options.   * optstr must contain the short options, and longopts the long options.
142   * Other settings are found in global variables.   * Other settings are found in global variables.
143   */   */
144  int generate_output(char * argv[],int argc,const char *optstr,  #if !ENABLE_GETOPT_LONG
145   const struct option *longopts)  #define generate_output(argv,argc,optstr,longopts) \
146     generate_output(argv,argc,optstr)
147    #endif
148    static int generate_output(char **argv, int argc, const char *optstr, const struct option *longopts)
149  {  {
150   int exit_code = 0; /* We assume everything will be OK */   int exit_code = 0; /* We assume everything will be OK */
151   int opt;   int opt;
152    #if ENABLE_GETOPT_LONG
153   int longindex;   int longindex;
154    #endif
155   const char *charptr;   const char *charptr;
156    
157   if (quiet_errors) /* No error reporting from getopt(3) */   if (quiet_errors) /* No error reporting from getopt(3) */
158   opterr=0;   opterr = 0;
  optind=0; /* Reset getopt(3) */  
159    
160   while ((opt = (alternative?   /* We used it already in main() in getopt32(),
161   getopt_long_only(argc,argv,optstr,longopts,&longindex):   * we *must* reset getopt(3): */
162   getopt_long(argc,argv,optstr,longopts,&longindex)))  #ifdef __GLIBC__
163         != EOF)   optind = 0;
164    #else /* BSD style */
165     optind = 1;
166     /* optreset = 1; */
167    #endif
168    
169     while (1) {
170     opt =
171    #if ENABLE_GETOPT_LONG
172     alternative ?
173     getopt_long_only(argc, argv, optstr, longopts, &longindex) :
174     getopt_long(argc, argv, optstr, longopts, &longindex);
175    #else
176     getopt(argc, argv, optstr);
177    #endif
178     if (opt == -1)
179     break;
180   if (opt == '?' || opt == ':' )   if (opt == '?' || opt == ':' )
181   exit_code = 1;   exit_code = 1;
182   else if (!quiet_output) {   else if (!quiet_output) {
183    #if ENABLE_GETOPT_LONG
184   if (opt == LONG_OPT) {   if (opt == LONG_OPT) {
185   printf(" --%s",longopts[longindex].name);   printf(" --%s", longopts[longindex].name);
186   if (longopts[longindex].has_arg)   if (longopts[longindex].has_arg)
187   printf(" %s",   printf(" %s",
188   normalize(optarg?optarg:""));   normalize(optarg ? optarg : ""));
189   } else if (opt == NON_OPT)   } else
190   printf(" %s",normalize(optarg));  #endif
191     if (opt == NON_OPT)
192     printf(" %s", normalize(optarg));
193   else {   else {
194   printf(" -%c",opt);   printf(" -%c", opt);
195   charptr = strchr(optstr,opt);   charptr = strchr(optstr, opt);
196   if (charptr != NULL && *++charptr == ':')   if (charptr != NULL && *++charptr == ':')
197   printf(" %s",   printf(" %s",
198   normalize(optarg?optarg:""));   normalize(optarg ? optarg : ""));
199   }   }
200   }   }
201     }
202    
203   if (! quiet_output) {   if (!quiet_output) {
204   printf(" --");   printf(" --");
205   while (optind < argc)   while (optind < argc)
206   printf(" %s",normalize(argv[optind++]));   printf(" %s", normalize(argv[optind++]));
207   puts("");   bb_putchar('\n');
208   }   }
209   return exit_code;   return exit_code;
210  }  }
211    
212  static struct option *long_options;  #if ENABLE_GETOPT_LONG
 static int long_options_length; /* Length of array */  
 static int long_options_nr; /* Nr of used elements in array */  
 enum { LONG_OPTIONS_INCR = 10 };  
 #define init_longopt() add_longopt(NULL,0)  
   
 /* Register a long option. The contents of name is copied. */  
 void add_longopt(const char *name, int has_arg)  
 {  
  if (!name) { /* init */  
  free(long_options);  
  long_options=NULL;  
  long_options_length=0;  
  long_options_nr=0;  
  }  
   
  if (long_options_nr == long_options_length) {  
  long_options_length += LONG_OPTIONS_INCR;  
  long_options=xrealloc(long_options,  
  sizeof(struct option) *  
  long_options_length);  
  }  
   
  long_options[long_options_nr].name=NULL;  
  long_options[long_options_nr].has_arg=0;  
  long_options[long_options_nr].flag=NULL;  
  long_options[long_options_nr].val=0;  
   
  if (long_options_nr) { /* Not for init! */  
  long_options[long_options_nr-1].has_arg=has_arg;  
  long_options[long_options_nr-1].flag=NULL;  
  long_options[long_options_nr-1].val=LONG_OPT;  
  long_options[long_options_nr-1].name=xstrdup(name);  
  }  
  long_options_nr++;  
 }  
   
   
213  /*  /*
214   * Register several long options. options is a string of long options,   * Register several long options. options is a string of long options,
215   * separated by commas or whitespace.   * separated by commas or whitespace.
216   * This nukes options!   * This nukes options!
217   */   */
218  void add_long_options(char *options)  static struct option *add_long_options(struct option *long_options, char *options)
219  {  {
220     int long_nr = 0;
221   int arg_opt, tlen;   int arg_opt, tlen;
222   char *tokptr=strtok(options,", \t\n");   char *tokptr = strtok(options, ", \t\n");
223    
224     if (long_options)
225     while (long_options[long_nr].name)
226     long_nr++;
227    
228   while (tokptr) {   while (tokptr) {
229   arg_opt=no_argument;   arg_opt = no_argument;
230   tlen=strlen(tokptr);   tlen = strlen(tokptr);
231   if (tlen > 0) {   if (tlen) {
232   if (tokptr[tlen-1] == ':') {   tlen--;
233   if (tlen > 1 && tokptr[tlen-2] == ':') {   if (tokptr[tlen] == ':') {
234   tokptr[tlen-2]='\0';   arg_opt = required_argument;
235   tlen -= 2;   if (tlen && tokptr[tlen-1] == ':') {
236   arg_opt=optional_argument;   tlen--;
237   } else {   arg_opt = optional_argument;
  tokptr[tlen-1]='\0';  
  tlen -= 1;  
  arg_opt=required_argument;  
238   }   }
239     tokptr[tlen] = '\0';
240   if (tlen == 0)   if (tlen == 0)
241   bb_error_msg("empty long option after -l or --long argument");   bb_error_msg_and_die("empty long option specified");
242   }   }
243   add_longopt(tokptr,arg_opt);   long_options = xrealloc_vector(long_options, 4, long_nr);
244     long_options[long_nr].has_arg = arg_opt;
245     /*long_options[long_nr].flag = NULL; - xrealloc_vector did it */
246     long_options[long_nr].val = LONG_OPT;
247     long_options[long_nr].name = xstrdup(tokptr);
248     long_nr++;
249     /*memset(&long_options[long_nr], 0, sizeof(long_options[0])); - xrealloc_vector did it */
250   }   }
251   tokptr=strtok(NULL,", \t\n");   tokptr = strtok(NULL, ", \t\n");
252   }   }
253     return long_options;
254  }  }
255    #endif
256    
257  void set_shell(const char *new_shell)  static void set_shell(const char *new_shell)
258  {  {
259   if (!strcmp(new_shell,"bash"))   if (!strcmp(new_shell, "bash") || !strcmp(new_shell, "sh"))
260   shell=BASH;   return;
261   else if (!strcmp(new_shell,"tcsh"))   if (!strcmp(new_shell, "tcsh") || !strcmp(new_shell, "csh"))
262   shell=TCSH;   option_mask32 |= SHELL_IS_TCSH;
  else if (!strcmp(new_shell,"sh"))  
  shell=BASH;  
  else if (!strcmp(new_shell,"csh"))  
  shell=TCSH;  
263   else   else
264   bb_error_msg("unknown shell after -s or --shell argument");   bb_error_msg("unknown shell '%s', assuming bash", new_shell);
265  }  }
266    
267    
# Line 270  void set_shell(const char *new_shell) Line 273  void set_shell(const char *new_shell)
273   *   4) Returned for -T   *   4) Returned for -T
274   */   */
275    
276  static const struct option longopts[]=  #if ENABLE_GETOPT_LONG
277  {  static const char getopt_longopts[] ALIGN1 =
278   {"options",required_argument,NULL,'o'},   "options\0"      Required_argument "o"
279   {"longoptions",required_argument,NULL,'l'},   "longoptions\0"  Required_argument "l"
280   {"quiet",no_argument,NULL,'q'},   "quiet\0"        No_argument       "q"
281   {"quiet-output",no_argument,NULL,'Q'},   "quiet-output\0" No_argument       "Q"
282   {"shell",required_argument,NULL,'s'},   "shell\0"        Required_argument "s"
283   {"test",no_argument,NULL,'T'},   "test\0"         No_argument       "T"
284   {"unquoted",no_argument,NULL,'u'},   "unquoted\0"     No_argument       "u"
285   {"alternative",no_argument,NULL,'a'},   "alternative\0"  No_argument       "a"
286   {"name",required_argument,NULL,'n'},   "name\0"         Required_argument "n"
287   {NULL,0,NULL,0}   ;
288  };  #endif
   
 /* Stop scanning as soon as a non-option argument is found! */  
 static const char shortopts[]="+ao:l:n:qQs:Tu";  
   
289    
290  int getopt_main(int argc, char *argv[])  int getopt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
291    int getopt_main(int argc, char **argv)
292  {  {
293   const char *optstr = NULL;   char *optstr = NULL;
294   char *name = NULL;   char *name = NULL;
295   int opt;   unsigned opt;
296   int compatible=0;   const char *compatible;
297     char *s_arg;
298   init_longopt();  #if ENABLE_GETOPT_LONG
299     struct option *long_options = NULL;
300     llist_t *l_arg = NULL;
301    #endif
302    
303   if (getenv("GETOPT_COMPATIBLE"))   compatible = getenv("GETOPT_COMPATIBLE"); /* used as yes/no flag */
  compatible=1;  
304    
305   if (argc == 1) {   if (argc == 1) {
306   if (compatible) {   if (compatible) {
# Line 306  int getopt_main(int argc, char *argv[]) Line 308  int getopt_main(int argc, char *argv[])
308     when there were no arguments. */     when there were no arguments. */
309   printf(" --\n");   printf(" --\n");
310   return 0;   return 0;
311   } else   }
312   bb_error_msg_and_die("missing optstring argument");   bb_error_msg_and_die("missing optstring argument");
313   }   }
314    
315   if (argv[1][0] != '-' || compatible) {   if (argv[1][0] != '-' || compatible) {
316   char *s;   char *s;
317    
318   quote=0;   option_mask32 |= OPT_u; /* quoting off */
319   s=xmalloc(strlen(argv[1])+1);   s = xstrdup(argv[1] + strspn(argv[1], "-+"));
320   strcpy(s,argv[1]+strspn(argv[1],"-+"));   argv[1] = argv[0];
321   argv[1]=argv[0];   return generate_output(argv+1, argc-1, s, long_options);
  return generate_output(argv+1,argc-1,s,long_options);  
322   }   }
323    
324   while ((opt = getopt_long(argc,argv,shortopts,longopts,NULL)) != EOF)  #if !ENABLE_GETOPT_LONG
325   switch (opt) {   opt = getopt32(argv, "+o:n:qQs:Tu", &optstr, &name, &s_arg);
326   case 'a':  #else
327   alternative=1;   applet_long_options = getopt_longopts;
328   break;   opt_complementary = "l::";
329   case 'o':   opt = getopt32(argv, "+o:n:qQs:Tual:",
330   optstr = optarg;   &optstr, &name, &s_arg, &l_arg);
331   break;   /* Effectuate the read options for the applet itself */
332   case 'l':   while (l_arg) {
333   add_long_options(optarg);   long_options = add_long_options(long_options, llist_pop(&l_arg));
334   break;   }
335   case 'n':  #endif
336   name = optarg;  
337   break;   if (opt & OPT_s) {
338   case 'q':   set_shell(s_arg);
339   quiet_errors=1;   }
  break;  
  case 'Q':  
  quiet_output=1;  
  break;  
  case 's':  
  set_shell(optarg);  
  break;  
  case 'T':  
  return 4;  
  case 'u':  
  quote=0;  
  break;  
  default:  
  bb_show_usage();  
  }  
340    
341     if (opt & OPT_T) {
342     return 4;
343     }
344    
345     /* All options controlling the applet have now been parsed */
346   if (!optstr) {   if (!optstr) {
347   if (optind >= argc)   if (optind >= argc)
348   bb_error_msg_and_die("missing optstring argument");   bb_error_msg_and_die("missing optstring argument");
349   else optstr=argv[optind++];   optstr = argv[optind++];
350   }   }
351   if (name)  
352   argv[optind-1]=name;   argv[optind-1] = name ? name : argv[0];
353   else   return generate_output(argv+optind-1, argc-optind+1, optstr, long_options);
  argv[optind-1]=argv[0];  
  return generate_output(argv+optind-1,argc-optind+1,optstr,long_options);  
354  }  }

Legend:
Removed from v.532  
changed lines
  Added in v.816