static void open_log_files(void) { int fd; char str[32]; if (interactive_mode) return; /* Open access log */ if (log_access) logbuf_open(); /* Open and write pid to pid file */ if ((fd = open(PID_FILE, O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0) err_sys_quit(errfd, "ERROR: can't open pid file: open"); sprintf(str, "%d\n", (int)getpid()); if (write(fd, str, strlen(str)) != strlen(str)) err_sys_quit(errfd, "ERROR: can't write to pid file: write"); close(fd); /* Open error log file */ if ((fd = open(ERRORS_FILE, O_CREAT | O_WRONLY | O_APPEND, 0644)) < 0) err_sys_quit(errfd, "ERROR: can't open error log file: open"); errfd = fd; err_report(errfd, "INFO: starting the server..."); }
static void start_threads(void) { long i, n; /* Create access log flushing thread */ if (log_access && st_thread_create(flush_acclog_buffer, NULL, 0, 0) == NULL) err_sys_quit(errfd, "ERROR: process %d (pid %d): can't create" " log flushing thread", my_index, my_pid); /* Create connections handling threads */ for (i = 0; i < sk_count; i++) { err_report(errfd, "INFO: process %d (pid %d): starting %d threads" " on %s:%u", my_index, my_pid, max_wait_threads, srv_socket[i].addr, srv_socket[i].port); WAIT_THREADS(i) = 0; BUSY_THREADS(i) = 0; RQST_COUNT(i) = 0; for (n = 0; n < max_wait_threads; n++) { if (st_thread_create(handle_connections, (void *)i, 0, 0) != NULL) WAIT_THREADS(i)++; else err_sys_report(errfd, "ERROR: process %d (pid %d): can't create" " thread", my_index, my_pid); } if (WAIT_THREADS(i) == 0) exit(1); } }
/* * Function: insert_data * * Description: This routine inserts the data into the table * */ void insert_data() { colp *colsptr; sword colindex; row_count = 0; while (row_count < numrows) { colsptr = cols; numinsert = numrows - row_count < MAX_ROWS_PER_INSERT ? numrows - row_count : MAX_ROWS_PER_INSERT; for (colindex = 0; colindex < NUMCOLS; colsptr++, colindex++) { initialize_data(colsptr->c_buf, colsptr->c_size, colsptr->c_rlen, numinsert); colsptr->c_curlen = numinsert; } /* using offset zero - we want all the rows right away */ if (oexec(&cda)) { err_report(&cda); do_exit(OCI_EXIT_FAILURE); } printf(" Number of rows processed so far is %d\n", retval); row_count += numinsert; } }
static void parse_arguments( int argc, char *argv[] ) { extern char *optarg; int opt; char* c = NULL; while (( opt = getopt( argc, argv, "b:p:l:h" ) ) != EOF ) { switch ( opt ) { case 'b': if (( c = strdup( optarg ) ) == NULL ) err_sys_quit( s_errfd, "ERROR: strdup" ); s_serverIP = c; break; case 'p': s_nListenPort = atoi( optarg ); if ( s_nListenPort < 1024 ) err_quit( s_errfd, "ERROR: invalid listening port: %s", optarg ); break; case 'l': s_logdir = optarg; break; case 'h': case '?': usage( argv[0] ); } } if ( s_logdir == NULL ) { err_report( s_errfd, "ERROR: logging directory is required\n" ); usage( argv[0] ); } }
int unsetenv_manager(t_manage *man, char *cmd) { int pos; char **d_cmd; char **d_all; int i; int nb_of_args; int j; i = -1; j = 1; d_all = my_str_to_wordtab(cmd, ' '); while (d_all[++i]) { pos = 0; if ((nb_of_args = wordtab_count(d_all)) == 1) { err_report(3, "NULL"); return (-1); } d_cmd = get_args(cmd); if ((pos = my_getenv(man->all_env->my_env, d_cmd[j])) == -1) return (-1); man->all_env->my_env = d_tab_unset_doc(man->all_env->my_env, pos - 1); j = j + 1; } return (0); }
static void wdog_sighandler(int signo) { int i, err; /* Save errno */ err = errno; /* Forward the signal to all children */ for (i = 0; i < vp_count; i++) { if (vp_pids[i] > 0) kill(vp_pids[i], signo); } /* * It is safe to do pretty much everything here because process is * sleeping in wait() which is async-safe. */ switch (signo) { case SIGHUP: err_report(errfd, "INFO: watchdog: caught SIGHUP"); /* Reopen log files - needed for log rotation */ if (log_access) { logbuf_close(); logbuf_open(); } close(errfd); if ((errfd = open(ERRORS_FILE, O_CREAT | O_WRONLY | O_APPEND, 0644)) < 0) err_sys_quit(STDERR_FILENO, "ERROR: watchdog: open"); break; case SIGTERM: /* Non-graceful termination */ err_report(errfd, "INFO: watchdog: caught SIGTERM, terminating"); unlink(PID_FILE); exit(0); case SIGUSR1: err_report(errfd, "INFO: watchdog: caught SIGUSR1"); break; default: err_report(errfd, "INFO: watchdog: caught signal %d", signo); } /* Restore errno */ errno = err; }
static void err_bad_res (const CLIF_option *optn, char c, const char *opt_arg, int n) { CLIF_option tmp = *optn; char *ss; const char *type; tmp.arg_name = NULL; if (c) { ss = show_short (&tmp); type = "option"; } else { ss = show_long (&tmp); type = is_keyword (optn) ? "keyword" : "option"; } if (optn->arg_name) err_report ("Cannot handle `%s' %s with arg `%s' (argc %d)", ss, type, opt_arg, n); else err_report ("Cannot handle `%s' %s (argc %d)", ss, type, n); }
int main(int argc, char *argv[]) { int fd; //file desciptor fd=open(argv[0],O_RDONLY); if(fd == -1) err_report("error in opening "); else printf("You have open a file successfully\r\n"); exit(0); }
static void change_user(void) { struct passwd *pw; if ((pw = getpwnam(username)) == NULL) err_quit(errfd, "ERROR: can't find user '%s': getpwnam failed", username); if (setgid(pw->pw_gid) < 0) err_sys_quit(errfd, "ERROR: can't change group id: setgid"); if (setuid(pw->pw_uid) < 0) err_sys_quit(errfd, "ERROR: can't change user id: setuid"); err_report(errfd, "INFO: changed process user id to '%s'", username); }
int check_cmd_in_list(t_list *list, t_manage *man) { while (list->next != NULL && list->num != -1) { if ((is_built_ins(list->cmd) == 0) && is_path_cmd(list, man) == 0) { err_report(0, list->cmd); return (0); } if (list->next != NULL && (list->num == 3 || list->num == 5)) list = list->next; if (list->next != NULL) list = list->next; } return (1); }
static void err_bad_excl (const CLIF_option *optn, char c, int n) { CLIF_option tmp = *optn; char *ss; char *excl = show_excl (curr.option_list, 0); /* Note: show_(short|long)() nested!!! */ tmp.arg_name = NULL; if (c) ss = show_short (&tmp); else ss = show_long (&tmp); err_report ("%s `%s' (argc %d): Only one of:\n %s\n" "may be specified.", (c || !is_keyword (optn)) ? "Option" : "Keyword", ss, n, excl); }
static void err_bad_arg (const CLIF_option *optn, char c, int n) { CLIF_option tmp = *optn; char ss[80]; char *s; tmp.arg_name = NULL; if (c) { s = show_short (&tmp); /* always without arg... */ strncpy (ss, s, sizeof (ss)); s = show_short (optn); } else { s = show_long (&tmp); /* always without arg... */ strncpy (ss, s, sizeof (ss)); s = show_long (optn); } err_report ("%s `%s' (argc %d) requires an argument: `%s'", (c || !is_keyword (optn)) ? "Option" : "Keyword", ss, n, s); }
/* * Configuration loading function stub. */ void load_configs(void) { err_report(errfd, "INFO: process %d (pid %d): configuration loaded", my_index, my_pid); }
cchobj cch_alloc(cch c, size_t size, cchobj *owner) { cchobj obj; bool wrapped_this_time; /* Allow for size of cchobj_str */ size += sizeof(struct cchobj_str); /* 4 byte align */ size = (size + 3) & ~3; if (size > c->size) { err_report("cch_alloc: %i > cache size of %i", size, c->size); return NULL; } /* If there is not size bytes after the rover, reset to the cache base */ wrapped_this_time = false; if (!c->rover) c->rover = c->base; else if (cch_free(c) < size) { wrapped_this_time = true; c->rover = c->base; } /* Collect and free objects until the rover block is large enough */ obj = c->rover; if (c->fast) { if(!globalGL.glTestFenceNV(c->rover->fence)) globalGL.glFinishFenceNV(c->rover->fence); globalGL.glDeleteFencesNV(1, &(c->rover->fence)); } if (c->rover->owner) *(c->rover->owner) = NULL; while (obj->size < size) { /* Free another object */ c->rover = c->rover->next; if (c->fast) { if(!globalGL.glTestFenceNV(c->rover->fence)) globalGL.glFinishFenceNV(c->rover->fence); globalGL.glDeleteFencesNV(1, &(c->rover->fence)); } if (c->rover->owner) *(c->rover->owner) = NULL; obj->size += c->rover->size; obj->next = c->rover->next; } /* Create a fragment out of any leftovers */ if (obj->size - size > 63) { c->rover = (cchobj)(((unsigned char*)obj) + size); c->rover->size = obj->size - size; c->rover->next = obj->next; c->rover->owner = NULL; obj->next = c->rover; obj->size = size; } else c->rover = obj->next; *owner = obj; obj->owner = owner; if (c->fast) globalGL.glGenFencesNV(1, &(obj->fence)); if (c->wrapped) { if (wrapped_this_time || (c->rover >= c->initRover)) c->thrashed = true; } else if (wrapped_this_time) c->wrapped = true; if (c->fast) obj->data = (((unsigned char*)(obj + 1)) - (unsigned char*)c->base) + c->fastBase; else obj->data = (unsigned char*)(obj + 1); return obj; }
/* * Function: setup * * Description: This routine does the necessary setup to execute the SQL * statement. Specifically, it does the open, parse, bind and * define phases as needed. * */ void setup() { colp *colsptr; /* temporary pointer */ sword colindex; if (oopen(&cda, &lda, (text *) 0, -1, -1, (text *) 0, -1)) /* open */ { err_report(&cda); do_exit(OCI_EXIT_FAILURE); } if (oparse(&cda, sqlstmt, (sb4) -1, DEFER_PARSE, /* parse */ (ub4) VERSION_7)) { err_report(&cda); do_exit(OCI_EXIT_FAILURE); } /* bind the scalar */ if (obndra(&cda, (text *)":numins", -1, (ub1 *)&numinsert, (sword)sizeof(numinsert), SQLT_INT, -1, (sb2 *) 0, (ub2 *)0, (ub2 *)0, (ub4)0, (ub4 *)0, (text *)0, -1, -1)) /* bind */ { err_report(&cda); do_exit(OCI_EXIT_FAILURE); } if (obndra(&cda, (text *)":retval", -1, (ub1 *)&retval, (sword)sizeof(retval), SQLT_INT, -1, (sb2 *) 0, (ub2 *)0, (ub2 *)0, (ub4)0, (ub4 *)0, (text *)0, -1, -1)) /* bind */ { err_report(&cda); do_exit(OCI_EXIT_FAILURE); } cols = malloc_col(NUMCOLS); colsptr = cols; for (colindex = 0; colindex < NUMCOLS; colindex++, colsptr++) { colsptr->c_size = coltable[colindex].size; colsptr->c_type = coltable[colindex].type; colsptr->c_indp = (sb2*)malloc((size_t)(MAX_ROWS_PER_INSERT*sizeof(sb2))); memset((dvoid *)colsptr->c_indp, 0, MAX_ROWS_PER_INSERT * sizeof(sb2)); colsptr->c_rlen = (ub2*)malloc((size_t)(MAX_ROWS_PER_INSERT*sizeof(ub2))); memset((dvoid *)colsptr->c_rlen, 0, MAX_ROWS_PER_INSERT * sizeof(ub2)); colsptr->c_rcode = (ub2*)malloc((size_t)(MAX_ROWS_PER_INSERT*sizeof(ub2))); memset((dvoid *)colsptr->c_rcode, 0, MAX_ROWS_PER_INSERT * sizeof(ub2)); colsptr->c_buf = (ub1 *)malloc((size_t)(MAX_ROWS_PER_INSERT*colsptr->c_size)); memset((dvoid *)colsptr->c_buf, 0, MAX_ROWS_PER_INSERT * colsptr->c_size); colsptr->c_curlen = 0; switch (colindex) { case(0) : /* GOTCHA!!! - need to pass in zeroes for mal and cal parameters when running a regular insert. Set it to non-zero when using plsql */ if (obndra(&cda, (text *)":col1", -1, colsptr->c_buf, colsptr->c_size, (sword)colsptr->c_type, (sword) -1, (sb2 *)colsptr->c_indp, colsptr->c_rlen, colsptr->c_rcode, (ub4)MAX_ROWS_PER_INSERT, (ub4 *)&(colsptr->c_curlen), (text *)0, -1, -1)) { err_report(&cda); do_exit(OCI_EXIT_FAILURE); } break; } } }
static void start_processes(void) { int i, status; pid_t pid; sigset_t mask, omask; if (interactive_mode) { my_index = 0; my_pid = getpid(); return; } for (i = 0; i < vp_count; i++) { if ((pid = fork()) < 0) { err_sys_report(errfd, "ERROR: can't create process: fork"); if (i == 0) exit(1); err_report(errfd, "WARN: started only %d processes out of %d", i, vp_count); vp_count = i; break; } if (pid == 0) { my_index = i; my_pid = getpid(); /* Child returns to continue in main() */ return; } vp_pids[i] = pid; } /* * Parent process becomes a "watchdog" and never returns to main(). */ /* Install signal handlers */ Signal(SIGTERM, wdog_sighandler); /* terminate */ Signal(SIGHUP, wdog_sighandler); /* restart */ Signal(SIGUSR1, wdog_sighandler); /* dump info */ /* Now go to sleep waiting for a child termination or a signal */ for ( ; ; ) { if ((pid = wait(&status)) < 0) { if (errno == EINTR) continue; err_sys_quit(errfd, "ERROR: watchdog: wait"); } /* Find index of the exited child */ for (i = 0; i < vp_count; i++) { if (vp_pids[i] == pid) break; } /* Block signals while printing and forking */ sigemptyset(&mask); sigaddset(&mask, SIGTERM); sigaddset(&mask, SIGHUP); sigaddset(&mask, SIGUSR1); sigprocmask(SIG_BLOCK, &mask, &omask); if (WIFEXITED(status)) err_report(errfd, "WARN: watchdog: process %d (pid %d) exited" " with status %d", i, pid, WEXITSTATUS(status)); else if (WIFSIGNALED(status)) err_report(errfd, "WARN: watchdog: process %d (pid %d) terminated" " by signal %d", i, pid, WTERMSIG(status)); else if (WIFSTOPPED(status)) err_report(errfd, "WARN: watchdog: process %d (pid %d) stopped" " by signal %d", i, pid, WSTOPSIG(status)); else err_report(errfd, "WARN: watchdog: process %d (pid %d) terminated:" " unknown termination reason", i, pid); /* Fork another VP */ if ((pid = fork()) < 0) { err_sys_report(errfd, "ERROR: watchdog: can't create process: fork"); } else if (pid == 0) { my_index = i; my_pid = getpid(); /* Child returns to continue in main() */ return; } vp_pids[i] = pid; /* Restore the signal mask */ sigprocmask(SIG_SETMASK, &omask, NULL); } }
bool str2userinfo (sfsauth_userinfo *ui, str s) { str name; vec<str> uv; if (split (&uv, colon, s, 12, true) != 11) return false; str2wstr (uv[7]); str2wstr (uv[8]); str fields[13] = { "name", "uid", "version", "gid", "owner", "pubkey", "privs", "srp", "privkey", "srvprivkey", // "refresh", "timeout", "audit" }; if (!namerx.match (uv[0])) { err_report ("<null>", 1, fields[0], uv[0]); return false; } name = uv[0]; for (int i = 1; i < 4; i++) { if (!decrx.match (uv[i])) { err_report (name, i+1, fields[i], uv[i]); return false; } } if (uv[4].len () && !namerx.match (uv[4])) { err_report (name, 5, fields[4], uv[4]); return false; } for (int i = 6; i < 10; i++) { if (badcharrx.search (uv[i])) { err_report (name, i+1, fields[i], uv[i]); return false; } } #if 0 for (int i = 10; i < 12; i++) { if (!decrx.match (uv[i])) { err_report (name, i+1, fields[i], uv[i]); return false; } } #endif str privkey = dearmor64 (uv[8]); if (!privkey) { err_report (name, 9, fields[8], "could not dearmor64"); return false; } str2wstr (privkey); ui->privkey.setsize (privkey.len ()); memcpy (ui->privkey.base (), privkey, ui->privkey.size ()); ui->name = uv[0]; if (!convertint (uv[1], &ui->id) || !convertint (uv[2], &ui->vers) || !convertint (uv[3], &ui->gid) // || !convertint (uv[10], &ui->refresh) // || !convertint (uv[11], &ui->timeout) ) return false; if (uv[4].len ()) *ui->owner.alloc () = uv[4]; else ui->owner.clear (); ptr<sfspub> pk = sfscrypt.alloc (uv[5]); if (!pk) return false; if (!pk->export_pubkey (&ui->pubkey)) { warn << "Cannot load keypair for " << uv[0] << "\n"; return false; } ui->privs = uv[6]; ui->pwauth = uv[7]; if (uv[9] && uv[9].len ()) { if (!sfs_2schnorr_priv::parse_keyhalf (&ui->srvprivkey, uv[9])) { warn << "Cannot load server keyhalf for " << uv[0] << "\n"; return false; } } else { ui->srvprivkey.set_type (SFSAUTH_KEYHALF_NONE); } // ui->audit = uv[12]; ui->audit = uv[10]; return true; }
static void parse_arguments(int argc, char *argv[]) { extern char *optarg; int opt; char *c; while ((opt = getopt(argc, argv, "b:p:l:t:u:q:aiSh")) != EOF) { switch (opt) { case 'b': if (sk_count >= MAX_BIND_ADDRS) err_quit(errfd, "ERROR: max number of bind addresses (%d) exceeded", MAX_BIND_ADDRS); if ((c = strdup(optarg)) == NULL) err_sys_quit(errfd, "ERROR: strdup"); srv_socket[sk_count++].addr = c; break; case 'p': vp_count = atoi(optarg); if (vp_count < 1) err_quit(errfd, "ERROR: invalid number of processes: %s", optarg); break; case 'l': logdir = optarg; break; case 't': max_wait_threads = (int) strtol(optarg, &c, 10); if (*c++ == ':') max_threads = atoi(c); if (max_wait_threads < 0 || max_threads < 0) err_quit(errfd, "ERROR: invalid number of threads: %s", optarg); break; case 'u': username = optarg; break; case 'q': listenq_size = atoi(optarg); if (listenq_size < 1) err_quit(errfd, "ERROR: invalid listen queue size: %s", optarg); break; case 'a': log_access = 1; break; case 'i': interactive_mode = 1; break; case 'S': /* * Serialization decision is tricky on some platforms. For example, * Solaris 2.6 and above has kernel sockets implementation, so supposedly * there is no need for serialization. The ST library may be compiled * on one OS version, but used on another, so the need for serialization * should be determined at run time by the application. Since it's just * an example, the serialization decision is left up to user. * Only on platforms where the serialization is never needed on any OS * version st_netfd_serialize_accept() is a no-op. */ serialize_accept = 1; break; case 'h': case '?': usage(argv[0]); } } if (logdir == NULL && !interactive_mode) { err_report(errfd, "ERROR: logging directory is required\n"); usage(argv[0]); } if (getuid() == 0 && username == NULL) err_report(errfd, "WARNING: running as super-user!"); if (vp_count == 0 && (vp_count = cpu_count()) < 1) vp_count = 1; if (sk_count == 0) { sk_count = 1; srv_socket[0].addr = "0.0.0.0"; } }
int CLIF_parse_cmdline (int argc, char *argv[], CLIF_option *option_list, CLIF_argument *argument_list, unsigned int parse_flags) { int i, j; CLIF_option *optn; CLIF_argument *argm; int num_args = 0; int num_argm = 0, strict_beg = 0, strict_end = 0; _CLIF_index arg_n[MAX_ARGC_NUMBER]; unsigned int dirty_flags = 0; int dirty_plus = 0; int exclusive_cnt = 0; int posix = getenv ("POSIXLY_CORRECT") != NULL || (parse_flags & CLIF_POSIX); curr.argc = argc; curr.argv = argv; curr.option_list = option_list; curr.argument_list = argument_list; curr.parse_flags = parse_flags; if (argc <= 1 && (parse_flags & CLIF_HELP_EMPTY)) { CLIF_current_help (); exit (0); } /* Scan argument_list for check and some info. */ if (argument_list) { enum stages { STRICT_BEG, OPTIONAL, STRICT_END }; int stage = STRICT_BEG; for (argm = argument_list; argm->name; argm++) { if (argm->flags & CLIF_STRICT) { if (stage == STRICT_BEG) strict_beg++; else if (stage == OPTIONAL) { stage = STRICT_END; strict_end++; } else if (stage == STRICT_END) strict_end++; } else { if (stage == STRICT_BEG) stage = OPTIONAL; else if (stage == STRICT_END) { err_report ("Incorrect argument list set in program " "source: more than one optional area."); return -1; } } num_argm++; } } /* Scan option_list for some info. */ if (option_list) { dirty_flags = parse_flags; for (optn = option_list; optn->short_opt || optn->long_opt; optn++ ) { dirty_flags |= optn->flags; if (optn->function_plus) dirty_plus = 1; } } if (dirty_flags & CLIF_EXCL) exclusive_cnt = 1; /* only one is allowed... */ /* Go ! Store arguments, parse options. */ for (i = 1; i < argc; i++) { char *arg = argv[i]; char *opt_arg = NULL; char sym = '-'; if (!option_list) goto handle_arg; if (*arg == '+' && dirty_plus) sym = '+'; if (*arg != sym) { /* argument or keyword */ if (dirty_flags & CLIF_MAY_KEYWORD) { optn = find_long (arg, &opt_arg, CLIF_MAY_KEYWORD, 0); if (optn) goto long_found; } if (num_args == 0 && (parse_flags & CLIF_FIRST_GROUP)) { /* ugly... */ parse_flags &= ~CLIF_FIRST_GROUP; dirty_flags &= ~CLIF_FIRST_GROUP; /* to be correct */ goto handle_short; } /* else it is an argument */ goto handle_arg; } else if (*++arg == sym) { /* `--' - long option */ arg++; if (*arg == sym || /* `---' - let it be not option... */ (parse_flags & (_CLIF_STRICT_KEYWORD|_CLIF_STRICT_ONEDASH)) ) { arg -= 2; goto handle_arg; /* not option anyway */ } optn = find_long (arg, &opt_arg, 0, _CLIF_STRICT_KEYWORD | _CLIF_STRICT_ONEDASH); if (optn) goto long_found; /* XXX: May be allow only for `--', not `++' too... */ if (!*arg && sym == '-') { /* `--' and no empty longoption */ option_list = NULL; /* POSIX way... */ continue; } /* XXX: or treat as an argument sometimes??? */ err_bad_opt (argv[i], 0, i); return -1; } else { /* short option, or several short options... */ if (dirty_flags & CLIF_MAY_ONEDASH) { optn = find_long (arg, &opt_arg, CLIF_MAY_ONEDASH, 0); if (optn) goto long_found; } if (!*arg) { /* POSIX say: only "stdout specification"... */ arg--; goto handle_arg; } goto handle_short; } long_found: if (check_sym (optn, sym) < 0) { /* Oops... */ err_bad_opt (argv[i], 0, i); return -1; } if (optn->flags & CLIF_EXCL) { if (!exclusive_cnt) { err_bad_excl (optn, 0, i); return -1; } exclusive_cnt--; } if (optn->arg_name && !opt_arg) { unsigned int flags = optn->flags | parse_flags; if (++i >= argc || !(flags & CLIF_MAY_NOEQUAL) ) { /* missing opt arg */ i--; if (!(flags & CLIF_OPTARG)) { err_bad_arg (optn, 0, i); return -1; } opt_arg = NULL; } else opt_arg = argv[i]; } if (call_function (optn, opt_arg, sym) < 0) { err_bad_res (optn, 0, opt_arg, i); return -1; } if (optn->flags & CLIF_EXIT) exit (0); continue; handle_arg: if (argument_list) { if (i < MAX_ARGC_NUMBER) /* XXX: ugly, better report */ arg_n[num_args++] = i; } else { err_report ("`%s' (argc %d): arguments are not allowed", argv[i], i); return -1; } /* POSIX say: No more options after args... */ if (posix) option_list = NULL; /* geniously... */ continue; handle_short: opt_arg = NULL; do { for (optn = option_list; optn->short_opt || optn->long_opt; optn++ ) { if (optn->short_opt && optn->short_opt[0] == *arg) break; } if (!optn->short_opt || check_sym (optn, sym) < 0 ) { err_bad_opt (argv[i], *arg, i); return -1; } if (optn->flags & CLIF_EXCL) { if (!exclusive_cnt) { err_bad_excl (optn, *arg, i); return -1; } exclusive_cnt--; } if (optn->arg_name) { unsigned int flags = parse_flags | optn->flags; if (arg[1] == '\0') { /* a last one */ /* POSIX say: an option with arg cannot be grouped. */ if (posix && arg != argv[i] && arg[-1] != sym) { err_bad_arg (optn, *arg, i); /* good way? */ return -1; } if (++i >= argc || (flags & _CLIF_STRICT_JOIN_ARG) ) { i--; if (!(flags & CLIF_OPTARG)) { err_bad_arg (optn, *arg, i); return -1; } opt_arg = NULL; } else opt_arg = argv[i]; } else if ((arg == argv[i] || arg[-1] == sym) && (flags & CLIF_MAY_JOIN_ARG) ) { opt_arg = ++arg; } else { /* inside a group... */ if (!(flags & CLIF_OPTARG) || (flags & CLIF_MAY_JOIN_ARG) ) { err_bad_arg (optn, *arg, i); return -1; } opt_arg = NULL; } } if (call_function (optn, opt_arg, sym) < 0) { err_bad_res (optn, optn->short_opt[0], opt_arg, i); return -1; } if (optn->flags & CLIF_EXIT) exit (0); } while (!opt_arg && *++arg); } /* for ( ... ) */ if ((parse_flags & CLIF_STRICT_EXCL) && exclusive_cnt != 0) { err_report ("One of these must be specified:\n %s\n", show_excl (option_list, 0)); return -1; } /* Now, after *ALL* options, handle arguments, if any. */ if (num_args < strict_beg + strict_end) { /* Missing some needed arguments. */ if (num_args < strict_beg) argm = argument_list + num_args; else argm = argument_list + ((num_args - strict_beg) + (num_argm - strict_end)); if (num_args == strict_beg + strict_end - 1) err_report ("Specify \"%s\" missing argument.", argm->name); else err_report ("Specify \"%s\" and other missing arguments.", argm->name); return -1; } if (num_args > 0) { _CLIF_index argm_index[MAX_ARGC_NUMBER]; /* assing argm (by index) for each arg... */ for (i = 0, j = 0; i < strict_beg; i++, j++) argm_index[i] = j; for (i = num_args - strict_end, j = num_argm - strict_end; i < num_args; i++, j++ ) argm_index[i] = j; for (i = strict_beg, j = strict_beg; i < num_args - strict_end && j < num_argm - strict_end; i++ ) { argm_index[i] = j; if (!(argument_list[j].flags & CLIF_MORE)) j++; } if (i < num_args - strict_end) { /* there are extra args... */ err_report ("Extra arg `%s' (position %d, argc %d)", argv[arg_n[i]], i + 1, arg_n[i]); return -1; } if (j < num_argm - strict_end && !(argument_list[j].flags & CLIF_MORE) && /* ...i.e, there are some missing optional args... */ (argument_list[j].flags & CLIF_ACC_PREV) ) { if (j == 0) err_report ("Incorrect argument list set: first arg " "cannot be `accompanied with previous'."); else err_report ("Arg \"%s\" must be specified because " "\"%s\" `%s' is used.", argument_list[j].name, argument_list[j - 1].name, argv[arg_n[i - 1]]); return -1; } if (argm_index[--i] == j && /* above is true only after OPTIONAL area scan and when `j' is stopped on CLIF_MORE */ ++j < num_argm - strict_end /* i.e: there is a *last* one (after CLIF_MORE) in the OPTIONAL area */ ) argm_index[i] = j; /* *last* is better than *more* */ /* ...and work now */ for (i = 0; i < num_args; i++) { argm = argument_list + argm_index[i]; if (argm->function && argm->function (argm, argv[arg_n[i]], i) < 0 ) { err_report ("Cannot handle \"%s\" cmdline arg `%s' " "on position %d (argc %d)", argm->name, argv[arg_n[i]], i + 1, arg_n[i]); return -1; } } /* That`s all. */ } return 0; }