source: trunk/src/sh_getopt.c@ 87

Last change on this file since 87 was 76, checked in by rainer, 18 years ago

Fix for ticket #38 (csv escaping) and #39 (building on cygwin). Also optimize a bit.

File size: 22.9 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <limits.h>
26#include <errno.h>
27
28
29#include "samhain.h"
30#include "sh_error.h"
31#include "sh_getopt.h"
32#include "sh_files.h"
33#include "sh_utils.h"
34#include "sh_mail.h"
35#include "sh_forward.h"
36#include "sh_hash.h"
37
38#if defined(WITH_EXTERNAL)
39#include "sh_extern.h"
40#endif
41
42extern int sh_calls_set_bind_addr (const char *);
43
44#undef FIL__
45#define FIL__ _("sh_getopt.c")
46
47#define HAS_ARG_NO 0
48#define HAS_ARG_YES 1
49#define DROP_PRIV_NO 0
50#define DROP_PRIV_YES 1
51
52
53typedef struct options {
54 char * longopt;
55 const char shortopt;
56 char * usage;
57 int hasArg;
58 int (*func)(const char * opt);
59} opttable_t;
60
61/*@noreturn@*/
62static int sh_getopt_usage (const char * dummy);
63#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
64static int sh_getopt_forever (const char * dummy);
65#endif
66static int sh_getopt_copyright (const char * dummy);
67static int sh_getopt_version (const char * dummy);
68
69static opttable_t op_table[] = {
70
71#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
72 { N_("set-checksum-test"),
73 't',
74 N_("Set checksum testing to 'init', 'update', or 'check'"),
75 HAS_ARG_YES,
76 sh_util_setchecksum },
77 { N_("interactive"),
78 'i',
79 N_("Run update in interactive mode"),
80 HAS_ARG_NO,
81 sh_util_set_interactive },
82#endif
83#if defined(SH_WITH_SERVER) || defined(SH_WITH_CLIENT)
84 { N_("server-port"),
85 '-',
86 N_("Set the server port to connect to"),
87 HAS_ARG_YES,
88 sh_forward_server_port },
89#endif
90#ifdef SH_WITH_SERVER
91 { N_("server"),
92 'S',
93 N_("Run as log server (obsolete)"),
94 HAS_ARG_NO,
95 sh_util_setserver },
96 { N_("qualified"),
97 'q',
98 N_("Log fully qualified name of client host"),
99 HAS_ARG_NO,
100 sh_forward_set_strip },
101 { N_("chroot"),
102 '-',
103 N_("Chroot to specified directory"),
104 HAS_ARG_YES,
105 sh_unix_set_chroot },
106#endif
107 { N_("daemon"),
108 'D',
109 N_("Run as daemon"),
110 HAS_ARG_NO,
111 sh_unix_setdeamon },
112 { N_("foreground"),
113 '-',
114 N_("Stay in the foreground"),
115 HAS_ARG_NO,
116 sh_unix_setnodeamon },
117 { N_("bind-address"),
118 '-',
119 N_("Bind to this address (interface) for outgoing connections"),
120 HAS_ARG_YES,
121 sh_calls_set_bind_addr },
122#if defined(SH_WITH_SERVER) || defined(SH_WITH_CLIENT)
123 { N_("set-export-severity"),
124 'e',
125 N_("Set severity threshold for export to remote log server"),
126 HAS_ARG_YES,
127 sh_error_setexport },
128#endif
129 { N_("set-syslog-severity"),
130 's',
131 N_("Set severity threshold for syslog"),
132 HAS_ARG_YES,
133 sh_error_set_syslog },
134#ifdef WITH_EXTERNAL
135 { N_("set-extern-severity"),
136 'x',
137 N_("Set severity threshold for logging by external program(s)"),
138 HAS_ARG_YES,
139 sh_error_set_external },
140#endif
141#ifdef HAVE_LIBPRELUDE
142 { N_("set-prelude-severity"),
143 '-',
144 N_("Set severity threshold for logging to prelude"),
145 HAS_ARG_YES,
146 sh_error_set_prelude },
147#endif
148#if defined(WITH_DATABASE)
149 { N_("set-database-severity"),
150 '-',
151 N_("Set severity threshold for logging to RDBMS"),
152 HAS_ARG_YES,
153 sh_error_set_database },
154#endif
155 { N_("set-log-severity"),
156 'l',
157 N_("Set severity threshold for logfile"),
158 HAS_ARG_YES,
159 sh_error_setlog },
160#if defined(SH_WITH_MAIL)
161 { N_("set-mail-severity"),
162 'm',
163 N_("Set severitythreshold for e-mail"),
164 HAS_ARG_YES,
165 sh_error_setseverity },
166#endif
167 { N_("set-print-severity"),
168 'p',
169 N_("Set the severity threshold for terminal/console log"),
170 HAS_ARG_YES,
171 sh_error_setprint },
172#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
173 { N_("recursion"),
174 'r',
175 N_("Set recursion level for directories"),
176 HAS_ARG_YES,
177 sh_files_setrecursion },
178#endif
179 { N_("verify-log"),
180 'L',
181 N_("Verify the audit trail"),
182 HAS_ARG_YES,
183 sh_error_logverify },
184 { N_("just-list"),
185 'j',
186 N_("Modify -L to just list the audit trail"),
187 HAS_ARG_NO,
188 sh_error_logverify_mod },
189#if defined(SH_WITH_MAIL)
190 { N_("verify-mail"),
191 'M',
192 N_("Verify the mailbox"),
193 HAS_ARG_YES,
194 sh_mail_sigverify
195 },
196#endif
197 { N_("add-key"),
198 'V',
199 N_("Add key for the mail/log signature"),
200 HAS_ARG_YES,
201 sh_util_set_newkey
202 },
203 { N_("hash-string"),
204 'H',
205 N_("Print the hash of a string"),
206 HAS_ARG_YES,
207 sh_error_verify },
208#if defined (SH_WITH_SERVER)
209 { N_("password"),
210 'P',
211 N_("Compute a client registry entry for password"),
212 HAS_ARG_YES,
213 sh_forward_make_client },
214 { N_("gen-password"),
215 'G',
216 N_("Generate a random password"),
217 HAS_ARG_NO,
218 sh_forward_create_password },
219#endif
220
221#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
222 { N_("forever"),
223 'f',
224 N_("Loop forever, even if not daemon"),
225 HAS_ARG_NO,
226 sh_getopt_forever},
227 { N_("full-detail"),
228 'a',
229 N_("Modify -d to list full details"),
230 HAS_ARG_NO,
231 set_full_detail},
232 { N_("delimited"),
233 '-',
234 N_("Modify -d to list full details, comma delimited"),
235 HAS_ARG_NO,
236 set_list_delimited},
237 { N_("list-database"),
238 'd',
239 N_("List database content (like ls -l)"),
240 HAS_ARG_YES,
241 sh_hash_list_db},
242 { N_("init2stdout"),
243 '-',
244 N_("Write database to stdout on init"),
245 HAS_ARG_NO,
246 sh_hash_pushdata_stdout},
247#endif
248 { N_("trace-logfile"),
249 '-',
250 N_("Logfile for trace"),
251 HAS_ARG_YES,
252 sl_trace_file },
253 { N_("trace-enable"),
254 '-',
255 N_("Enable tracing"),
256 HAS_ARG_NO,
257 sl_trace_use },
258 { N_("copyright"),
259 'c',
260 N_("Print copyright information"),
261 HAS_ARG_NO,
262 sh_getopt_copyright },
263 { N_("help"),
264 'h',
265 N_("Print usage information"),
266 HAS_ARG_NO,
267 sh_getopt_usage },
268 { N_("version"),
269 'v',
270 N_("Show version and compiled-in options"),
271 HAS_ARG_NO,
272 sh_getopt_version },
273#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
274 /* need to skip over these */
275 { N_("prelude"),
276 '-',
277 N_("Prelude generic options"),
278 HAS_ARG_NO,
279 NULL },
280 { N_("profile"),
281 '-',
282 N_("Profile to use for this analyzer"),
283 HAS_ARG_YES,
284 NULL },
285 { N_("heartbeat-interval"),
286 '-',
287 N_("Number of seconds between two heartbeats"),
288 HAS_ARG_YES,
289 NULL },
290 { N_("server-addr"),
291 '-',
292 N_("Address where this sensor should report to"),
293 HAS_ARG_YES,
294 NULL },
295 { N_("analyzer-name"),
296 '-',
297 N_("Name for this analyzer"),
298 HAS_ARG_YES,
299 NULL },
300#endif
301 /* last entry -- required !! -- */
302 { NULL,
303 '\0',
304 NULL,
305 HAS_ARG_NO,
306 NULL }
307};
308
309
310static void sh_getopt_print_log_facilities ()
311{
312 fputs (_("Compiled-in log facilities:"), stdout);
313
314#ifndef DEFAULT_CONSOLE
315 printf (_(" console (/dev/console)"));
316#else
317 if (0 == strcmp (DEFAULT_CONSOLE, _("NULL")))
318 printf (_(" console (/dev/console)"));
319 else
320 printf (_(" console (%s)"), DEFAULT_CONSOLE);
321#endif
322 fputs (_(", syslog"), stdout);
323 printf (_(", logfile (%s)"), DEFAULT_ERRFILE);
324
325#if defined(WITH_EXTERNAL)
326 fputs (_(", external program"), stdout);
327#endif
328
329#if defined(WITH_MESSAGE_QUEUE)
330 fputs (_(", message queue"), stdout);
331#endif
332
333#if defined(WITH_DATABASE)
334 fputs (_(", database"), stdout);
335#ifdef WITH_ODBC
336 fputs (_(" (odbc)"), stdout);
337#endif
338#ifdef WITH_ORACLE
339 fputs (_(" (Oracle)"), stdout);
340#endif
341#ifdef WITH_POSTGRES
342 fputs (_(" (PostgreSQL)"), stdout);
343#endif
344#ifdef WITH_MYSQL
345 fputs (_(" (MySQL)"), stdout);
346#endif
347#endif
348
349#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
350 fputs (_(", server"), stdout);
351#endif
352
353#if defined(SH_WITH_MAIL)
354 fputs (_(", email"), stdout);
355#endif
356
357#ifdef HAVE_LIBPRELUDE
358#ifdef HAVE_LIBPRELUDE_8
359 fputs (_(", prelude (0.8)"), stdout);
360#else
361 fputs (_(", prelude (0.9+)"), stdout);
362#endif
363#endif
364
365 fputc ('\n', stdout);
366 return;
367}
368
369static void sh_getopt_print_options ()
370{
371 int num = 0;
372
373
374#if defined(SH_STANDALONE)
375 if (num > 0) fputc ('\n', stdout);
376 fputs (_("Standalone executable"), stdout); ++num;
377#endif
378#if defined(SH_WITH_CLIENT)
379 if (num > 0) fputc ('\n', stdout);
380 printf (_("Client executable (port %d)"), SH_DEFAULT_PORT); ++num;
381#endif
382#if defined(SH_WITH_CLIENT)
383 if (num > 0) fputc ('\n', stdout);
384 printf (_("Server executable (port %d, user %s)"),
385 SH_DEFAULT_PORT, DEFAULT_IDENT);
386 ++num;
387#endif
388
389 fputs (_(", compiled-in options:"), stdout);
390
391#if defined(HAVE_EGD_RANDOM)
392 if (num > 0) fputc ('\n', stdout);
393 printf (_(" use entropy gathering daemon (%s)"), EGD_SOCKET_NAME); ++num;
394#endif
395#if defined(HAVE_UNIX_RANDOM)
396 if (num > 0) fputc ('\n', stdout);
397 fputs (_(" use unix entropy gatherer"), stdout); ++num;
398#endif
399#if defined(HAVE_URANDOM)
400 if (num > 0) fputc ('\n', stdout);
401 printf (_(" use entropy device (%s)"), NAME_OF_DEV_RANDOM); ++num;
402#endif
403
404#ifdef WITH_GPG
405 if (num > 0) fputc ('\n', stdout);
406 printf (_(" GnuPG signatures (%s)"), DEFAULT_GPG_PATH); ++num;
407#ifdef HAVE_GPG_CHECKSUM
408 if (num > 0) fputc ('\n', stdout);
409 printf (_(" -- GnuPG checksum: %s"), GPG_HASH); ++num;
410#endif
411#ifdef USE_FINGERPRINT
412 if (num > 0) fputc ('\n', stdout);
413 printf (_(" -- Key fingerprint: %s"), SH_GPG_FP); ++num;
414#endif
415#endif
416
417#if defined(SL_DEBUG)
418 if (num > 0) fputc ('\n', stdout);
419 fputs (_(" debug build"), stdout); ++num;
420#endif
421#if defined(SCREW_IT_UP)
422 if (num > 0) fputc ('\n', stdout);
423 fputs (_(" anti-debugger"), stdout); ++num;
424#endif
425#if defined(SH_USE_XML)
426 if (num > 0) fputc ('\n', stdout);
427 fputs (_(" xml log format"), stdout); ++num;
428#endif
429#if defined(HAVE_NTIME)
430 if (num > 0) fputc ('\n', stdout);
431 fputs (_(" use time server"), stdout); ++num;
432#endif
433
434#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
435#if defined(USE_XATTR)
436 if (num > 0) fputc ('\n', stdout);
437 fputs (_(" check SELinux attributes"), stdout); ++num;
438#endif
439#if defined(USE_ACL)
440 if (num > 0) fputc ('\n', stdout);
441 fputs (_(" check Posix ACLs"), stdout); ++num;
442#endif
443#if defined(RELOAD_DATABASE)
444 if (num > 0) fputc ('\n', stdout);
445 fputs (_(" fetch database on reload"), stdout); ++num;
446#endif
447#endif
448
449#if defined(SH_WITH_SERVER)
450
451#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && !defined(HAVE_STRUCT_CMSGCRED) && !defined(HAVE_STRUCT_FCRED) && !(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
452 if (num > 0) fputc ('\n', stdout);
453 fputs (_(" command socket authentication: use SetSocketPassword"), stdout);
454 ++num;
455#else
456 if (num > 0) fputc ('\n', stdout);
457 fputs (_(" command socket authentication: use SetSocketAllowUID"), stdout);
458 ++num;
459#endif
460
461#if defined(SH_USE_LIBWRAP)
462 if (num > 0) fputc ('\n', stdout);
463 fputs (_(" support tcp wrapper"), stdout); ++num;
464#endif
465#if defined(INET_SYSLOG)
466 if (num > 0) fputc ('\n', stdout);
467 fputs (_(" support listening on 514/udp (syslog)"), stdout); ++num;
468#endif
469#endif
470
471 if (num == 0)
472 fputs (_(" none"), stdout);
473 fputc ('\n', stdout);
474 return;
475}
476
477static void sh_getopt_print_modules ()
478{
479#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
480 int num = 0;
481
482 fputs (_("Compiled-in modules:"), stdout);
483#ifdef SH_USE_UTMP
484 if (num > 0) fputc (',', stdout);
485 fputs (_(" login/logout"), stdout); ++num;
486#endif
487#ifdef SH_USE_MOUNTS
488 if (num > 0) fputc (',', stdout);
489 fputs (_(" mount options"), stdout); ++num;
490#endif
491#ifdef SH_USE_USERFILES
492 if (num > 0) fputc (',', stdout);
493 fputs (_(" userfiles"), stdout); ++num;
494#endif
495#ifdef SH_USE_KERN
496 if (num > 0) fputc (',', stdout);
497 fputs (_(" kernel"), stdout); ++num;
498#endif
499#ifdef SH_USE_SUIDCHK
500 if (num > 0) fputc (',', stdout);
501 fputs (_(" suid"), stdout); ++num;
502#endif
503#ifdef SH_USE_PROCESSCHECK
504 if (num > 0) fputc (',', stdout);
505 fputs (_(" processes"), stdout); ++num;
506#endif
507#ifdef SH_USE_PORTCHECK
508 if (num > 0) fputc (',', stdout);
509 fputs (_(" ports"), stdout); ++num;
510#endif
511 if (num == 0)
512 fputs (_(" none"), stdout);
513 fputc ('\n', stdout);
514#endif
515 return;
516}
517
518static int sh_getopt_version (const char * dummy)
519{
520 (void) dummy;
521 fprintf (stdout,
522 _("This is samhain (%s), "\
523 "(c) 1999-2006 Rainer Wichmann (http://la-samhna.de).\n"),
524 VERSION);
525 fprintf (stdout, _("This software comes with ABSOLUTELY NO WARRANTY. "));
526 fprintf (stdout, _("Use at own risk.\n\n"));
527
528 sh_getopt_print_log_facilities ();
529 sh_getopt_print_modules ();
530 sh_getopt_print_options ();
531
532 _exit (EXIT_SUCCESS);
533 /*@notreached@*/
534 return 0; /* make compilers happy */
535}
536static int sh_getopt_copyright (const char * dummy)
537{
538 fprintf (stdout,
539 _("Copyright (C) 1999-2006 Rainer Wichmann"\
540 " (http://la-samhna.de).\n\n"));
541
542 fprintf (stdout,
543 _("This program is free software; "\
544 "you can redistribute it and/or modify\n"));
545 fprintf (stdout, _("it under the terms of the GNU General "\
546 "Public License as published by\n"));
547 fprintf (stdout, _("the Free Software Foundation; either version 2 "\
548 "of the License, or\n"));
549 fprintf (stdout, _("(at your option) any later version.\n\n"));
550
551 fprintf (stdout, _("This program is distributed in the hope "\
552 "that it will be useful,\n"));
553 fprintf (stdout, _("but WITHOUT ANY WARRANTY; "\
554 "without even the implied warranty of\n"));
555 fprintf (stdout, _("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."\
556 " See the\n"));
557 fprintf (stdout, _("GNU General Public License for more details.\n\n"));
558
559 fprintf (stdout, _("You should have received a copy of the "\
560 "GNU General Public License\n"));
561 fprintf (stdout, _("along with this program; "\
562 "if not, write to the Free Software\n"));
563 fprintf (stdout, _("Foundation, Inc., 59 Temple Place - Suite 330, "\
564 "Boston, MA 02111-1307, USA.\n\n"));
565
566 fprintf (stdout, _("This product makes use of the reference implementation "\
567 "of the TIGER message\n"));
568 fprintf (stdout, _("digest algorithm. This code is copyright Eli Biham "\
569 "(biham@cs.technion.ac.il)\n"));
570 fprintf (stdout, _("and Ross Anderson (rja14@cl.cam.ac.uk). It can be used "\
571 "freely without any\n"));
572 fprintf (stdout, _("restrictions.\n"));
573#if defined(USE_SRP_PROTOCOL) && !defined(SH_STANDALONE)
574#if (!defined(HAVE_LIBGMP) || !defined(HAVE_GMP_H))
575 fprintf (stdout, _("This product makes use of the 'bignum' library by "\
576 "Henrik Johansson\n"));
577 fprintf (stdout, _("(Henrik.Johansson@Nexus.Comm.SE). If you are including "\
578 "this library in a\n"));
579 fprintf (stdout, _("commercial product, be sure to distribute ALL of"\
580 " it with the product.\n"));
581#endif
582 fprintf (stdout, _("This product uses the 'Secure Remote Password' "\
583 "cryptographic\n"));
584 fprintf (stdout, _("authentication system developed by Tom Wu "\
585 "(tjw@CS.Stanford.EDU).\n"));
586#endif
587 fprintf (stdout, _("\nPlease refer to the file COPYING in the source "\
588 "distribution for a"));
589 fprintf (stdout, _("\nfull list of incorporated code and associated "\
590 "licenses.\n"));
591
592 if (dummy)
593 _exit (EXIT_SUCCESS);
594 else
595 _exit (EXIT_SUCCESS);
596 /*@notreached@*/
597 return 0; /* make compilers happy */
598}
599
600/*@noreturn@*/
601static int sh_getopt_usage (const char * dummy)
602{
603 int i;
604 char fmt[64];
605
606 char opts[64];
607
608 for (i = 0; i < 64; ++i) /* splint does not grok char opts[64] = { '\0' }; */
609 opts[i] = '\0';
610
611 fprintf (stdout,
612 _("This is samhain (%s), "\
613 "(c) 1999-2006 Rainer Wichmann (http://la-samhna.de).\n"),
614 VERSION);
615 fprintf (stdout, _("This software comes with ABSOLUTELY NO WARRANTY. "));
616 fprintf (stdout, _("Use at own risk.\n"));
617
618 fprintf (stdout, _("Usage:\n\n"));
619
620 for (i = 0; op_table[i].longopt != NULL; ++i) {
621
622 if (i == 63)
623 break;
624
625 if (op_table[i].shortopt != '-' &&
626 strchr(opts, op_table[i].shortopt) != NULL)
627 fprintf (stdout, _("Short option char collision !\n"));
628 opts[i] = op_table[i].shortopt;
629
630
631 if (op_table[i].hasArg == HAS_ARG_NO) {
632 if (sl_strlen(op_table[i].longopt) < 10)
633 sl_strlcpy(fmt,_("%c%c%c --%-s,\t\t\t %s\n"), sizeof(fmt));
634 else if (sl_strlen(op_table[i].longopt) < 17)
635 sl_strlcpy(fmt, _("%c%c%c --%-s,\t\t %s\n"), sizeof(fmt));
636 else
637 sl_strlcpy(fmt, _("%c%c%c --%-s,\t %s\n"), sizeof(fmt));
638 /* flawfinder: ignore */
639 fprintf (stdout, fmt,
640 (op_table[i].shortopt == '-') ? ' ' : '-',
641 (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
642 (op_table[i].shortopt == '-') ? ' ' : ',',
643 _(op_table[i].longopt),
644 _(op_table[i].usage));
645 } else {
646 if (sl_strlen(op_table[i].longopt) < 12)
647 sl_strlcpy(fmt, _("%c%c %s --%-s=<arg>,\t\t %s\n"), sizeof(fmt));
648 else
649 sl_strlcpy(fmt, _("%c%c %s --%-s=<arg>,\t %s\n"), sizeof(fmt));
650 /* flawfinder: ignore */
651 fprintf (stdout, fmt,
652 (op_table[i].shortopt == '-') ? ' ' : '-',
653 (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
654 (op_table[i].shortopt == '-') ? _(" ") : _("<arg>,"),
655 _(op_table[i].longopt),
656 _(op_table[i].usage));
657 }
658 }
659
660 fprintf (stdout,
661 _("\nPlease report bugs to support@la-samhna.de.\n"));
662
663 (void) fflush(stdout);
664
665 if ( dummy != NULL)
666 {
667 if (sl_strcmp( dummy, _("fail")) == 0 )
668 _exit (EXIT_FAILURE);
669 }
670
671 _exit (EXIT_SUCCESS);
672 /*@notreached@*/
673 return 0; /* make compilers happy */
674}
675
676#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
677static int sh_getopt_forever (const char * dummy)
678{
679 dummy = (void *) dummy;
680 SL_ENTER(_("sh_getopt_forever"));
681 sh.flag.loop = S_TRUE;
682 SL_RETURN(0, _("sh_getopt_forever"));
683}
684#endif
685
686int sh_getopt_get (int argc, char * argv[])
687{
688 int count = 0;
689 size_t len = 0;
690 int foundit = 0;
691 int i;
692 size_t k;
693 char * theequal;
694
695 SL_ENTER(_("sh_getopt_get"));
696
697 /* -- Return if no args. --
698 */
699 if (argc < 2)
700 SL_RETURN(0, _("sh_getopt_get"));
701
702 while (argc > 1 && argv[1][0] == '-')
703 {
704
705 /* Initialize
706 */
707 foundit = 0;
708 len = sl_strlen (argv[1]);
709
710 /* a '-' with no argument: error
711 */
712 if (len == 1)
713 (void) sh_getopt_usage(_("fail"));
714
715 /* a '--' with no argument: stop argument processing
716 */
717 if (len == 2 && argv[1][1] == '-')
718 SL_RETURN( count, _("sh_getopt_get"));
719
720 /* a short option: process it
721 */
722 if (len >= 2 && argv[1][1] != '-')
723 {
724 for (k = 1; k < len; ++k)
725 {
726 for (i = 0; op_table[i].shortopt != '\0'; ++i)
727 {
728
729 if ( op_table[i].shortopt == argv[1][k] )
730 {
731 foundit = 1;
732 if ( op_table[i].hasArg == HAS_ARG_YES )
733 {
734 if (k != (len - 1))
735 {
736 /* not last option
737 */
738 fprintf (stderr,
739 _("Error: short option with argument is not last in option string\n"));
740 (void) sh_getopt_usage(_("fail"));
741 }
742 if (argc < 3)
743 {
744 /* argument required, but no avail
745 */
746 fprintf (stderr, _("Error: missing argument\n"));
747 (void) sh_getopt_usage(_("fail"));
748 }
749 else
750 {
751 /* call function with argument */
752 --argc; ++argv;
753 if (NULL != op_table[i].func &&
754 0 != (* op_table[i].func )(argv[1]))
755 fprintf (stderr,
756 _("Error processing option -%c\n"),
757 op_table[i].shortopt);
758 break;
759 }
760 }
761 else
762 {
763 if (NULL != op_table[i].func &&
764 0 != (* op_table[i].func )(NULL))
765 fprintf (stderr,
766 _("Error processing option -%c\n"),
767 op_table[i].shortopt);
768 break;
769 }
770 }
771 }
772 }
773
774 /* 'break' should get here
775 */
776 if (foundit == 1)
777 {
778 --argc; ++argv;
779 continue;
780 }
781 else
782 {
783 /* unrecognized short option */
784 fprintf (stderr, _("Error: unrecognized short option\n"));
785 (void) sh_getopt_usage(_("fail"));
786 }
787 }
788
789 /* a long option: process it
790 */
791 if (len > 2)
792 {
793
794 for (i = 0; op_table[i].longopt != NULL; ++i)
795 {
796
797 if (sl_strncmp(_(op_table[i].longopt),
798 &argv[1][2],
799 sl_strlen(op_table[i].longopt)) == 0 )
800 {
801 foundit = 1;
802 if ( op_table[i].hasArg == HAS_ARG_YES )
803 {
804 theequal = strchr(argv[1], '=');
805 if (theequal == NULL)
806 {
807 if (argc < 3)
808 {
809 /* argument required, but no avail
810 */
811 fprintf (stderr, _("Error: missing argument\n"));
812 (void) sh_getopt_usage(_("fail"));
813 }
814 else
815 {
816 /* call function with argument */
817 --argc; ++argv;
818 if (NULL != op_table[i].func &&
819 0 != (* op_table[i].func )(argv[1]))
820 fprintf (stderr,
821 _("Error processing option -%s\n"),
822 op_table[i].longopt);
823 break;
824 }
825 }
826 else
827 {
828 if (sl_strlen (theequal) > 1)
829 {
830 ++theequal;
831 /* call function with argument */
832 if (NULL != op_table[i].func &&
833 0 != (* op_table[i].func )(theequal))
834 fprintf (stderr,
835 _("Error processing option -%s\n"),
836 op_table[i].longopt);
837 break;
838 }
839 else
840 {
841 fprintf (stderr, _("Error: invalid argument\n"));
842 /* argument required, but no avail */
843 (void) sh_getopt_usage(_("fail"));
844 }
845 }
846 }
847 else
848 {
849 if (NULL != op_table[i].func &&
850 0 != (* op_table[i].func )(NULL))
851 fprintf (stderr,
852 _("Error processing option -%s\n"),
853 op_table[i].longopt);
854 break;
855 }
856 }
857 }
858
859 /* 'break' should get here */
860 if (foundit == 1)
861 {
862 ++count;
863 --argc;
864 ++argv;
865 continue;
866 }
867 else
868 {
869 /* unrecognized long option */
870 fprintf (stderr, _("Error: unrecognized long option\n"));
871 (void) sh_getopt_usage(_("fail"));
872 }
873 }
874 }
875
876 SL_RETURN( count, _("sh_getopt_get"));
877}
Note: See TracBrowser for help on using the repository browser.