source: trunk/src/sh_getopt.c@ 169

Last change on this file since 169 was 169, checked in by katerina, 17 years ago

Fixes for tickes #93 to #104 (yes, big commit, bad, bad,...).

File size: 23.2 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_("list-file"),
228 '-',
229 N_("Modify -d to list content of a single file"),
230 HAS_ARG_YES,
231 set_list_file},
232 { N_("full-detail"),
233 'a',
234 N_("Modify -d to list full details"),
235 HAS_ARG_NO,
236 set_full_detail},
237 { N_("delimited"),
238 '-',
239 N_("Modify -d to list full details, comma delimited"),
240 HAS_ARG_NO,
241 set_list_delimited},
242 { N_("list-database"),
243 'd',
244 N_("List database content (like ls -l)"),
245 HAS_ARG_YES,
246 sh_hash_list_db},
247 { N_("init2stdout"),
248 '-',
249 N_("Write database to stdout on init"),
250 HAS_ARG_NO,
251 sh_hash_pushdata_stdout},
252#endif
253 { N_("trace-logfile"),
254 '-',
255 N_("Logfile for trace"),
256 HAS_ARG_YES,
257 sl_trace_file },
258 { N_("trace-enable"),
259 '-',
260 N_("Enable tracing"),
261 HAS_ARG_NO,
262 sl_trace_use },
263 { N_("copyright"),
264 'c',
265 N_("Print copyright information"),
266 HAS_ARG_NO,
267 sh_getopt_copyright },
268 { N_("help"),
269 'h',
270 N_("Print usage information"),
271 HAS_ARG_NO,
272 sh_getopt_usage },
273 { N_("version"),
274 'v',
275 N_("Show version and compiled-in options"),
276 HAS_ARG_NO,
277 sh_getopt_version },
278#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
279 /* need to skip over these */
280 { N_("prelude"),
281 '-',
282 N_("Prelude generic options"),
283 HAS_ARG_NO,
284 NULL },
285 { N_("profile"),
286 '-',
287 N_("Profile to use for this analyzer"),
288 HAS_ARG_YES,
289 NULL },
290 { N_("heartbeat-interval"),
291 '-',
292 N_("Number of seconds between two heartbeats"),
293 HAS_ARG_YES,
294 NULL },
295 { N_("server-addr"),
296 '-',
297 N_("Address where this sensor should report to"),
298 HAS_ARG_YES,
299 NULL },
300 { N_("analyzer-name"),
301 '-',
302 N_("Name for this analyzer"),
303 HAS_ARG_YES,
304 NULL },
305#endif
306 /* last entry -- required !! -- */
307 { NULL,
308 '\0',
309 NULL,
310 HAS_ARG_NO,
311 NULL }
312};
313
314
315static void sh_getopt_print_log_facilities ()
316{
317 fputs (_("Compiled-in log facilities:"), stdout);
318
319#ifndef DEFAULT_CONSOLE
320 printf (_(" console (/dev/console)"));
321#else
322 if (0 == strcmp (DEFAULT_CONSOLE, _("NULL")))
323 printf (_(" console (/dev/console)"));
324 else
325 printf (_(" console (%s)"), DEFAULT_CONSOLE);
326#endif
327 fputs (_(", syslog"), stdout);
328 printf (_(", logfile (%s)"), DEFAULT_ERRFILE);
329
330#if defined(WITH_EXTERNAL)
331 fputs (_(", external program"), stdout);
332#endif
333
334#if defined(WITH_MESSAGE_QUEUE)
335 fputs (_(", message queue"), stdout);
336#endif
337
338#if defined(WITH_DATABASE)
339 fputs (_(", database"), stdout);
340#ifdef WITH_ODBC
341 fputs (_(" (odbc)"), stdout);
342#endif
343#ifdef WITH_ORACLE
344 fputs (_(" (Oracle)"), stdout);
345#endif
346#ifdef WITH_POSTGRES
347 fputs (_(" (PostgreSQL)"), stdout);
348#endif
349#ifdef WITH_MYSQL
350 fputs (_(" (MySQL)"), stdout);
351#endif
352#endif
353
354#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
355 fputs (_(", server"), stdout);
356#endif
357
358#if defined(SH_WITH_MAIL)
359 fputs (_(", email"), stdout);
360#endif
361
362#ifdef HAVE_LIBPRELUDE
363#ifdef HAVE_LIBPRELUDE_8
364 fputs (_(", prelude (0.8)"), stdout);
365#else
366 fputs (_(", prelude (0.9+)"), stdout);
367#endif
368#endif
369
370 fputc ('\n', stdout);
371 return;
372}
373
374static void sh_getopt_print_options ()
375{
376 int num = 0;
377
378
379#if defined(SH_STANDALONE)
380 if (num > 0) fputc ('\n', stdout);
381 fputs (_("Standalone executable"), stdout); ++num;
382#endif
383#if defined(SH_WITH_CLIENT)
384 if (num > 0) fputc ('\n', stdout);
385 printf (_("Client executable (port %d)"), SH_DEFAULT_PORT); ++num;
386#endif
387#if defined(SH_WITH_CLIENT)
388 if (num > 0) fputc ('\n', stdout);
389 printf (_("Server executable (port %d, user %s)"),
390 SH_DEFAULT_PORT, DEFAULT_IDENT);
391 ++num;
392#endif
393
394 fputs (_(", compiled-in options:"), stdout);
395
396#if defined(HAVE_EGD_RANDOM)
397 if (num > 0) fputc ('\n', stdout);
398 printf (_(" use entropy gathering daemon (%s)"), EGD_SOCKET_NAME); ++num;
399#endif
400#if defined(HAVE_UNIX_RANDOM)
401 if (num > 0) fputc ('\n', stdout);
402 fputs (_(" use unix entropy gatherer"), stdout); ++num;
403#endif
404#if defined(HAVE_URANDOM)
405 if (num > 0) fputc ('\n', stdout);
406 printf (_(" use entropy device (%s)"), NAME_OF_DEV_RANDOM); ++num;
407#endif
408
409#ifdef WITH_GPG
410 if (num > 0) fputc ('\n', stdout);
411 printf (_(" GnuPG signatures (%s)"), DEFAULT_GPG_PATH); ++num;
412#ifdef HAVE_GPG_CHECKSUM
413 if (num > 0) fputc ('\n', stdout);
414 printf (_(" -- GnuPG checksum: %s"), GPG_HASH); ++num;
415#endif
416#ifdef USE_FINGERPRINT
417 if (num > 0) fputc ('\n', stdout);
418 printf (_(" -- Key fingerprint: %s"), SH_GPG_FP); ++num;
419#endif
420#endif
421
422#if defined(SL_DEBUG)
423 if (num > 0) fputc ('\n', stdout);
424 fputs (_(" debug build (don't use for production)"), stdout); ++num;
425#endif
426#if defined(SCREW_IT_UP)
427 if (num > 0) fputc ('\n', stdout);
428 fputs (_(" anti-debugger"), stdout); ++num;
429#endif
430#if defined(SH_USE_XML)
431 if (num > 0) fputc ('\n', stdout);
432 fputs (_(" xml log format"), stdout); ++num;
433#endif
434#if defined(HAVE_NTIME)
435 if (num > 0) fputc ('\n', stdout);
436 fputs (_(" use time server"), stdout); ++num;
437#endif
438
439#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
440#if defined(HAVE_LIBZ)
441 if (num > 0) fputc ('\n', stdout);
442 fputs (_(" optionally store full text for files"), stdout); ++num;
443#endif
444#if defined(USE_XATTR)
445 if (num > 0) fputc ('\n', stdout);
446 fputs (_(" check SELinux attributes"), stdout); ++num;
447#endif
448#if defined(USE_ACL)
449 if (num > 0) fputc ('\n', stdout);
450 fputs (_(" check Posix ACLs"), stdout); ++num;
451#endif
452#if defined(RELOAD_DATABASE)
453 if (num > 0) fputc ('\n', stdout);
454 fputs (_(" fetch database on reload"), stdout); ++num;
455#endif
456#endif
457
458#if defined(SH_WITH_SERVER)
459
460#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && !defined(HAVE_STRUCT_CMSGCRED) && !defined(HAVE_STRUCT_FCRED) && !(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
461 if (num > 0) fputc ('\n', stdout);
462 fputs (_(" command socket authentication: use SetSocketPassword"), stdout);
463 ++num;
464#else
465 if (num > 0) fputc ('\n', stdout);
466 fputs (_(" command socket authentication: use SetSocketAllowUID"), stdout);
467 ++num;
468#endif
469
470#if defined(SH_USE_LIBWRAP)
471 if (num > 0) fputc ('\n', stdout);
472 fputs (_(" support tcp wrapper"), stdout); ++num;
473#endif
474#if defined(INET_SYSLOG)
475 if (num > 0) fputc ('\n', stdout);
476 fputs (_(" support listening on 514/udp (syslog)"), stdout); ++num;
477#endif
478#endif
479
480 if (num == 0)
481 fputs (_(" none"), stdout);
482 fputc ('\n', stdout);
483 return;
484}
485
486static void sh_getopt_print_modules ()
487{
488#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
489 int num = 0;
490
491 fputs (_("Compiled-in modules:"), stdout);
492#ifdef SH_USE_UTMP
493 if (num > 0) fputc (',', stdout);
494 fputs (_(" login/logout"), stdout); ++num;
495#endif
496#ifdef SH_USE_MOUNTS
497 if (num > 0) fputc (',', stdout);
498 fputs (_(" mount options"), stdout); ++num;
499#endif
500#ifdef SH_USE_USERFILES
501 if (num > 0) fputc (',', stdout);
502 fputs (_(" userfiles"), stdout); ++num;
503#endif
504#ifdef SH_USE_KERN
505 if (num > 0) fputc (',', stdout);
506 fputs (_(" kernel"), stdout); ++num;
507#endif
508#ifdef SH_USE_SUIDCHK
509 if (num > 0) fputc (',', stdout);
510 fputs (_(" suid"), stdout); ++num;
511#endif
512#ifdef SH_USE_PROCESSCHECK
513 if (num > 0) fputc (',', stdout);
514 fputs (_(" processes"), stdout); ++num;
515#endif
516#ifdef SH_USE_PORTCHECK
517 if (num > 0) fputc (',', stdout);
518 fputs (_(" ports"), stdout); ++num;
519#endif
520 if (num == 0)
521 fputs (_(" none"), stdout);
522 fputc ('\n', stdout);
523#endif
524 return;
525}
526
527static int sh_getopt_version (const char * dummy)
528{
529 (void) dummy;
530 fprintf (stdout,
531 _("This is samhain (%s), "\
532 "(c) 1999-2008 Rainer Wichmann (http://la-samhna.de).\n"),
533 VERSION);
534 fprintf (stdout, _("This software comes with ABSOLUTELY NO WARRANTY. "));
535 fprintf (stdout, _("Use at own risk.\n\n"));
536
537 sh_getopt_print_log_facilities ();
538 sh_getopt_print_modules ();
539 sh_getopt_print_options ();
540
541 _exit (EXIT_SUCCESS);
542 /*@notreached@*/
543 return 0; /* make compilers happy */
544}
545static int sh_getopt_copyright (const char * dummy)
546{
547 fprintf (stdout,
548 _("Copyright (C) 1999-2008 Rainer Wichmann"\
549 " (http://la-samhna.de).\n\n"));
550
551 fprintf (stdout,
552 _("This program is free software; "\
553 "you can redistribute it and/or modify\n"));
554 fprintf (stdout, _("it under the terms of the GNU General "\
555 "Public License as published by\n"));
556 fprintf (stdout, _("the Free Software Foundation; either version 2 "\
557 "of the License, or\n"));
558 fprintf (stdout, _("(at your option) any later version.\n\n"));
559
560 fprintf (stdout, _("This program is distributed in the hope "\
561 "that it will be useful,\n"));
562 fprintf (stdout, _("but WITHOUT ANY WARRANTY; "\
563 "without even the implied warranty of\n"));
564 fprintf (stdout, _("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."\
565 " See the\n"));
566 fprintf (stdout, _("GNU General Public License for more details.\n\n"));
567
568 fprintf (stdout, _("You should have received a copy of the "\
569 "GNU General Public License\n"));
570 fprintf (stdout, _("along with this program; "\
571 "if not, write to the Free Software\n"));
572 fprintf (stdout, _("Foundation, Inc., 59 Temple Place - Suite 330, "\
573 "Boston, MA 02111-1307, USA.\n\n"));
574
575 fprintf (stdout, _("This product makes use of the reference implementation "\
576 "of the TIGER message\n"));
577 fprintf (stdout, _("digest algorithm. This code is copyright Eli Biham "\
578 "(biham@cs.technion.ac.il)\n"));
579 fprintf (stdout, _("and Ross Anderson (rja14@cl.cam.ac.uk). It can be used "\
580 "freely without any\n"));
581 fprintf (stdout, _("restrictions.\n"));
582#if defined(USE_SRP_PROTOCOL) && !defined(SH_STANDALONE)
583#if (!defined(HAVE_LIBGMP) || !defined(HAVE_GMP_H))
584 fprintf (stdout, _("This product makes use of the 'bignum' library by "\
585 "Henrik Johansson\n"));
586 fprintf (stdout, _("(Henrik.Johansson@Nexus.Comm.SE). If you are including "\
587 "this library in a\n"));
588 fprintf (stdout, _("commercial product, be sure to distribute ALL of"\
589 " it with the product.\n"));
590#endif
591 fprintf (stdout, _("This product uses the 'Secure Remote Password' "\
592 "cryptographic\n"));
593 fprintf (stdout, _("authentication system developed by Tom Wu "\
594 "(tjw@CS.Stanford.EDU).\n"));
595#endif
596 fprintf (stdout, _("\nPlease refer to the file COPYING in the source "\
597 "distribution for a"));
598 fprintf (stdout, _("\nfull list of incorporated code and associated "\
599 "licenses.\n"));
600
601 if (dummy)
602 _exit (EXIT_SUCCESS);
603 else
604 _exit (EXIT_SUCCESS);
605 /*@notreached@*/
606 return 0; /* make compilers happy */
607}
608
609/*@noreturn@*/
610static int sh_getopt_usage (const char * dummy)
611{
612 int i;
613 char fmt[64];
614
615 char opts[64];
616
617 for (i = 0; i < 64; ++i) /* splint does not grok char opts[64] = { '\0' }; */
618 opts[i] = '\0';
619
620 fprintf (stdout,
621 _("This is samhain (%s), "\
622 "(c) 1999-2006 Rainer Wichmann (http://la-samhna.de).\n"),
623 VERSION);
624 fprintf (stdout, _("This software comes with ABSOLUTELY NO WARRANTY. "));
625 fprintf (stdout, _("Use at own risk.\n"));
626
627 fprintf (stdout, _("Usage:\n\n"));
628
629 for (i = 0; op_table[i].longopt != NULL; ++i) {
630
631 if (i == 63)
632 break;
633
634 if (op_table[i].shortopt != '-' &&
635 strchr(opts, op_table[i].shortopt) != NULL)
636 fprintf (stdout, _("Short option char collision !\n"));
637 opts[i] = op_table[i].shortopt;
638
639
640 if (op_table[i].hasArg == HAS_ARG_NO) {
641 if (sl_strlen(op_table[i].longopt) < 10)
642 sl_strlcpy(fmt,_("%c%c%c --%-s,\t\t\t %s\n"), sizeof(fmt));
643 else if (sl_strlen(op_table[i].longopt) < 17)
644 sl_strlcpy(fmt, _("%c%c%c --%-s,\t\t %s\n"), sizeof(fmt));
645 else
646 sl_strlcpy(fmt, _("%c%c%c --%-s,\t %s\n"), sizeof(fmt));
647 /* flawfinder: ignore */
648 fprintf (stdout, fmt,
649 (op_table[i].shortopt == '-') ? ' ' : '-',
650 (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
651 (op_table[i].shortopt == '-') ? ' ' : ',',
652 _(op_table[i].longopt),
653 _(op_table[i].usage));
654 } else {
655 if (sl_strlen(op_table[i].longopt) < 12)
656 sl_strlcpy(fmt, _("%c%c %s --%-s=<arg>,\t\t %s\n"), sizeof(fmt));
657 else
658 sl_strlcpy(fmt, _("%c%c %s --%-s=<arg>,\t %s\n"), sizeof(fmt));
659 /* flawfinder: ignore */
660 fprintf (stdout, fmt,
661 (op_table[i].shortopt == '-') ? ' ' : '-',
662 (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
663 (op_table[i].shortopt == '-') ? _(" ") : _("<arg>,"),
664 _(op_table[i].longopt),
665 _(op_table[i].usage));
666 }
667 }
668
669 fprintf (stdout,
670 _("\nPlease report bugs to support@la-samhna.de.\n"));
671
672 (void) fflush(stdout);
673
674 if ( dummy != NULL)
675 {
676 if (sl_strcmp( dummy, _("fail")) == 0 )
677 _exit (EXIT_FAILURE);
678 }
679
680 _exit (EXIT_SUCCESS);
681 /*@notreached@*/
682 return 0; /* make compilers happy */
683}
684
685#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
686static int sh_getopt_forever (const char * dummy)
687{
688 dummy = (void *) dummy;
689 SL_ENTER(_("sh_getopt_forever"));
690 sh.flag.loop = S_TRUE;
691 SL_RETURN(0, _("sh_getopt_forever"));
692}
693#endif
694
695int sh_getopt_get (int argc, char * argv[])
696{
697 int count = 0;
698 size_t len = 0;
699 int foundit = 0;
700 int i;
701 size_t k;
702 char * theequal;
703
704 SL_ENTER(_("sh_getopt_get"));
705
706 /* -- Return if no args. --
707 */
708 if (argc < 2)
709 SL_RETURN(0, _("sh_getopt_get"));
710
711 while (argc > 1 && argv[1][0] == '-')
712 {
713
714 /* Initialize
715 */
716 foundit = 0;
717 len = sl_strlen (argv[1]);
718
719 /* a '-' with no argument: error
720 */
721 if (len == 1)
722 (void) sh_getopt_usage(_("fail"));
723
724 /* a '--' with no argument: stop argument processing
725 */
726 if (len == 2 && argv[1][1] == '-')
727 SL_RETURN( count, _("sh_getopt_get"));
728
729 /* a short option: process it
730 */
731 if (len >= 2 && argv[1][1] != '-')
732 {
733 for (k = 1; k < len; ++k)
734 {
735 for (i = 0; op_table[i].shortopt != '\0'; ++i)
736 {
737
738 if ( op_table[i].shortopt == argv[1][k] )
739 {
740 foundit = 1;
741 if ( op_table[i].hasArg == HAS_ARG_YES )
742 {
743 if (k != (len - 1))
744 {
745 /* not last option
746 */
747 fprintf (stderr,
748 _("Error: short option with argument is not last in option string\n"));
749 (void) sh_getopt_usage(_("fail"));
750 }
751 if (argc < 3)
752 {
753 /* argument required, but no avail
754 */
755 fprintf (stderr, _("Error: missing argument\n"));
756 (void) sh_getopt_usage(_("fail"));
757 }
758 else
759 {
760 /* call function with argument */
761 --argc; ++argv;
762 if (NULL != op_table[i].func &&
763 0 != (* op_table[i].func )(argv[1]))
764 fprintf (stderr,
765 _("Error processing option -%c\n"),
766 op_table[i].shortopt);
767 break;
768 }
769 }
770 else
771 {
772 if (NULL != op_table[i].func &&
773 0 != (* op_table[i].func )(NULL))
774 fprintf (stderr,
775 _("Error processing option -%c\n"),
776 op_table[i].shortopt);
777 break;
778 }
779 }
780 }
781 }
782
783 /* 'break' should get here
784 */
785 if (foundit == 1)
786 {
787 --argc; ++argv;
788 continue;
789 }
790 else
791 {
792 /* unrecognized short option */
793 fprintf (stderr, _("Error: unrecognized short option\n"));
794 (void) sh_getopt_usage(_("fail"));
795 }
796 }
797
798 /* a long option: process it
799 */
800 if (len > 2)
801 {
802
803 for (i = 0; op_table[i].longopt != NULL; ++i)
804 {
805
806 if (sl_strncmp(_(op_table[i].longopt),
807 &argv[1][2],
808 sl_strlen(op_table[i].longopt)) == 0 )
809 {
810 foundit = 1;
811 if ( op_table[i].hasArg == HAS_ARG_YES )
812 {
813 theequal = strchr(argv[1], '=');
814 if (theequal == NULL)
815 {
816 if (argc < 3)
817 {
818 /* argument required, but no avail
819 */
820 fprintf (stderr, _("Error: missing argument\n"));
821 (void) sh_getopt_usage(_("fail"));
822 }
823 else
824 {
825 /* call function with argument */
826 --argc; ++argv;
827 if (NULL != op_table[i].func &&
828 0 != (* op_table[i].func )(argv[1]))
829 fprintf (stderr,
830 _("Error processing option -%s\n"),
831 op_table[i].longopt);
832 break;
833 }
834 }
835 else
836 {
837 if (sl_strlen (theequal) > 1)
838 {
839 ++theequal;
840 /* call function with argument */
841 if (NULL != op_table[i].func &&
842 0 != (* op_table[i].func )(theequal))
843 fprintf (stderr,
844 _("Error processing option -%s\n"),
845 op_table[i].longopt);
846 break;
847 }
848 else
849 {
850 fprintf (stderr, _("Error: invalid argument\n"));
851 /* argument required, but no avail */
852 (void) sh_getopt_usage(_("fail"));
853 }
854 }
855 }
856 else
857 {
858 if (NULL != op_table[i].func &&
859 0 != (* op_table[i].func )(NULL))
860 fprintf (stderr,
861 _("Error processing option -%s\n"),
862 op_table[i].longopt);
863 break;
864 }
865 }
866 }
867
868 /* 'break' should get here */
869 if (foundit == 1)
870 {
871 ++count;
872 --argc;
873 ++argv;
874 continue;
875 }
876 else
877 {
878 /* unrecognized long option */
879 fprintf (stderr, _("Error: unrecognized long option\n"));
880 (void) sh_getopt_usage(_("fail"));
881 }
882 }
883 }
884
885 SL_RETURN( count, _("sh_getopt_get"));
886}
Note: See TracBrowser for help on using the repository browser.