+Tue Dec 25 13:53:07 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added silc_getopt to lib/silcutil/silcgetopt.[ch].
+
Sat Dec 22 19:55:28 EET 2007 Pekka Riikonen <priikone@silcnet.org>
* Added SILC errno API to lib/silcutil/silcerrno.[ch]. Added
o Add directory opening/traversing functions
- o silc_getopt routines
-
- o Add silc_stream_get_root and add get_root stream operation. It
- returns the root of the stream or NULL if stream doesn't have root.
-
- o Change some stream routines (like socket stream API) to accept ANY
- stream and use silc_stream_get_root to get the socket stream from the
- given stream. This will make various stream APIs more easier to use
- when user doesn't have to dig up the correct stream.
+ o silc_getopt routines (***DONE)
o The SILC Event signals. Asynchronous events that can be created,
connected to and signalled. Either own event routines or glued into
o Thread pool API. Add this to lib/silcutil/silcthread.[ch]. (***DONE)
- o Fast mutex implementation. Fast rwlock implementation. Mutex and
- rwlock implementation using atomic operations.
-
- o Compression routines are missing. The protocol supports packet
- compression thus it must be implemented. SILC Zip API must be
- defined.
-
o Add new functions to SilcStack API in lib/silcutil/silcstack.[ch]. Add
silc_stack_[set|get]_alignment. It defines the default alignment used
when allocating memory from stack. It can be used to specify special
o Generic SilcResult that includes all possible status and
error conditions and generic errno API. (***DONE)
+ (o Change some stream routines (like socket stream API) to accept ANY
+ stream and use silc_stream_get_root to get the socket stream from the
+ given stream. This will make various stream APIs more easier to use
+ when user doesn't have to dig up the correct stream.
+
+ Add silc_stream_get_root and add get_root stream operation. It
+ returns the root of the stream or NULL if stream doesn't have root.) maybe
+
+ (o Compression routines are missing. The protocol supports packet
+ compression thus it must be implemented. SILC Zip API must be
+ defined.) maybe
+
(o SilcIpAddr abstraction. Ipv4 and Ipv6 support to the abstaction.)
maybe
to all send(), recv(), sendto() etc. Bad thing is that we'd have to
define all socket options, sockaddrs, etc.) maybe
+ (o Fast mutex implementation. Fast rwlock implementation. Mutex and
+ rwlock implementation using atomic operations.) not for now.
+
(o mmap) maybe
#include "silcversion.h"
/* SILC util library includes */
+#include "silcgetopt.h"
#include "silclist.h"
#include "silcstack.h"
#include "silcmemory.h"
silcenv.c \
silcbase64.c \
silcbitops.c \
- silcerrno.c
+ silcerrno.c \
+ silcgetopt.c
#ifdef SILC_DIST_TOOLKIT
include_HEADERS = \
silcenv.h \
silcbase64.h \
silcbitops.h \
- silcerrno.h
+ silcerrno.h \
+ silcgetopt.h
SILC_EXTRA_DIST = tests
#endif SILC_DIST_TOOLKIT
--- /dev/null
+/*
+
+ silcgetopt.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2007 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#include "silc.h"
+
+/* Getopt, like getopt(3). */
+
+int silc_getopt(int argc, char **argv, const char *optstring, SilcGetOpt op)
+{
+ register int c;
+ register char *cp;
+ SilcBool optional = FALSE, optional_found = FALSE;
+
+ SILC_VERIFY(op);
+
+ op->opt_arg = NULL;
+
+ if (op->opt_sp == 1) {
+ if (op->opt_index >= argc ||
+ argv[op->opt_index][0] != '-' || argv[op->opt_index][1] == '\0') {
+ return -1;
+ } else if (strcmp(argv[op->opt_index], "--") == 0) {
+ op->opt_index++;
+ return -1;
+ }
+ }
+ op->opt_option = c = argv[op->opt_index][op->opt_sp];
+
+ if (c == ':' || (cp = strchr(optstring, c)) == NULL) {
+ if (op->opt_error)
+ fprintf(stderr, "%s: illegal option -- %c\n", argv[0], c);
+ if (argv[op->opt_index][++op->opt_sp] == '\0') {
+ op->opt_index++;
+ op->opt_sp = 1;
+ }
+ return '?';
+ }
+
+ if (*++cp == ':') {
+ /* Check for optional argument (::), must be written -oarg, not -o arg. */
+ if (strlen(cp) && *(cp + 1) == ':') {
+ optional = TRUE;
+ if (argv[op->opt_index][op->opt_sp + 1] != '\0')
+ optional_found = TRUE;
+ }
+
+ if (argv[op->opt_index][op->opt_sp + 1] != '\0')
+ op->opt_arg = &argv[op->opt_index++][op->opt_sp + 1];
+ else if (++op->opt_index >= argc) {
+ if (!optional && !optional_found) {
+ if (op->opt_error)
+ fprintf(stderr, "%s: option requires an argument -- %c\n",
+ argv[0], c);
+ op->opt_sp = 1;
+ return ':';
+ }
+ } else if (!optional || optional_found)
+ op->opt_arg = argv[op->opt_index++];
+ op->opt_sp = 1;
+ } else {
+ if (argv[op->opt_index][++op->opt_sp] == '\0') {
+ op->opt_sp = 1;
+ op->opt_index++;
+ }
+ op->opt_arg = NULL;
+ }
+
+ return c;
+}
--- /dev/null
+/*
+
+ silcgetopt.h
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2007 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#ifndef SILCGETOPT_H
+#define SILCGETOPT_H
+
+/****s* silcutil/SilcGetOptAPI/SilcGetOpt
+ *
+ * NAME
+ *
+ * typedef struct SilcGetOptObject { ... } *SilcGetOpt, SilcGetOptStruct;
+ *
+ * DESCRIPTION
+ *
+ * Command line option parsers structure given to silc_getopt as argument.
+ * It contains the current parsed command line option data.
+ *
+ * SOURCE
+ */
+typedef struct SilcGetOptObject {
+ int opt_index; /* Current option index in argv[] array */
+ int opt_option; /* Current option character */
+ char *opt_arg; /* Current parsed option argument */
+ SilcBool opt_error; /* Set this to TRUE to make silc_getopt print
+ errors or FALSE to suppress them. */
+
+ SilcUInt16 opt_sp; /* Internal parser index */
+} *SilcGetOpt, SilcGetOptStruct;
+/***/
+
+/****d* silcutil/SilcGetOptAPI/SILC_GETOPT_INIT
+ *
+ * NAME
+ *
+ * #define SILC_GETOPT_INIT ...
+ *
+ * DESCRIPTION
+ *
+ * Macro used to initialize SilcGetOptStruct before calling silc_getopt.
+ *
+ * EXAMPLE
+ *
+ * SilcGetOptStruct op = SILC_GETOPT_INIT;
+ *
+ ***/
+#define SILC_GETOPT_INIT { 1, 0, NULL, TRUE, 1 }
+
+/****f* silcutil/SilcGetOptAPI/silc_getopt
+ *
+ * SYNOPSIS
+ *
+ * int silc_getopt(int argc, char **argv, const char *optstring,
+ * SilcGetOpt op)
+ *
+ * DESCRIPTION
+ *
+ * Parses comand line options. This function is equivalent to getopt(3).
+ * Returns the current parsed option, '?' if option was unknown, ':' if
+ * required argument was missing or -1 after all options have been parsed.
+ * If options require arguments they are available from the `op' structure,
+ * to where the options are parsed. The parsing is stopped immediately
+ * when first non-option character, which is not an argument for an option,
+ * is encountered.
+ *
+ * The `optstring' contains the supported option characters. One character
+ * per option is required. If colon (':') follows option character the
+ * option requires an argument. If two colons ('::') follows option
+ * character the argument is optional. In that case the argument must
+ * follow the option in command line, for example -oarg, instead of -o arg.
+ *
+ * EXAMPLE
+ *
+ * int main(int argc, char **argv)
+ * {
+ * SilcGetOptStruct op = SILC_GETOPT_INIT;
+ *
+ * while ((option = silc_getopt(argc, argv, "ab:t::", &op)) != -1) {
+ * switch (option) {
+ * case 'a':
+ * ...
+ * break;
+ * case 'b':
+ * argument = silc_strdup(op.opt_arg);
+ * break;
+ * case 't':
+ * if (op.opt_arg)
+ * optional_argument = silc_strdup(op.opt_arg);
+ * break;
+ * default:
+ * exit(1);
+ * break;
+ * }
+ * }
+ * }
+ *
+ ***/
+int silc_getopt(int argc, char **argv, const char *optstring, SilcGetOpt op);
+
+#endif /* SILCGETOPT_H */
int main(int argc, char **argv)
{
SilcBool success = FALSE;
+ SilcGetOptStruct op = SILC_GETOPT_INIT;
+ int opt;
int i;
- if (argc > 1 && !strcmp(argv[1], "-d")) {
- silc_log_debug(TRUE);
- silc_log_debug_hexdump(TRUE);
- silc_log_quick(TRUE);
- silc_log_set_debug_string("*table*,*errno*");
- }
-
- if (argc > 1 && !strcmp(argv[1], "-D")) {
- silc_log_debug(TRUE);
- dump = TRUE;
- silc_log_set_debug_string("*table*,*errno*");
+ while ((opt = silc_getopt(argc, argv, "de::D", &op)) != -1) {
+ switch (opt) {
+ case 'd':
+ silc_log_debug(TRUE);
+ silc_log_debug_hexdump(TRUE);
+ silc_log_quick(TRUE);
+ silc_log_set_debug_string("*table*,*errno*");
+ break;
+
+ case 'D':
+ silc_log_debug(TRUE);
+ dump = TRUE;
+ silc_log_set_debug_string("*table*,*errno*");
+ break;
+
+ case 'e':
+ silc_log_debug(TRUE);
+ fprintf(stderr, "%s\n", op.opt_arg);
+ if (op.opt_arg) {
+ dump = TRUE;
+ silc_log_set_debug_string(op.opt_arg);
+ }
+ break;
+
+ default:
+ exit(1);
+ break;
+ }
}
if (!alloc_table())