diff options
author | Erik Troan <ewt@src.gnome.org> | 1998-07-27 15:53:36 +0000 |
---|---|---|
committer | Erik Troan <ewt@src.gnome.org> | 1998-07-27 15:53:36 +0000 |
commit | 80559dee64a68499347e2ed8557d88f53e8d52d3 (patch) | |
tree | ab392b5408af98f047d8970f93182ba738ffeb8a /support | |
parent | 2b3e2351372e6ca3811c80d84ba5804aaf5031f1 (diff) | |
download | shared-mime-info-80559dee64a68499347e2ed8557d88f53e8d52d3.tar.gz |
1) moved duplicated alias handling code into handleAlias()
2) added support for exec options
svn path=/trunk/; revision=293
Diffstat (limited to 'support')
-rw-r--r-- | support/popt.c | 284 |
1 files changed, 199 insertions, 85 deletions
diff --git a/support/popt.c b/support/popt.c index d5725363..0d533494 100644 --- a/support/popt.c +++ b/support/popt.c @@ -20,6 +20,13 @@ struct optionStackEntry { char * nextArg; char * nextCharArg; struct poptAlias * currAlias; + int stuffed; +}; + +struct execEntry { + char * longName; + char shortName; + char * script; }; struct poptContext_s { @@ -33,6 +40,12 @@ struct poptContext_s { struct poptAlias * aliases; int numAliases; int flags; + struct execEntry * execs; + int numExecs; + char ** finalArgv; + int finalArgvCount; + int finalArgvAlloced; + struct execEntry * doExec; }; #ifndef HAVE_STRERROR @@ -47,34 +60,26 @@ static char * strerror(int errno) { } #endif -poptContext poptGetContext(char * name ,int argc, char ** argv, +poptContext poptGetContext(char * name, int argc, char ** argv, const struct poptOption * options, int flags) { poptContext con = malloc(sizeof(*con)); + memset(con, 0, sizeof(*con)); + con->os = con->optionStack; con->os->argc = argc; con->os->argv = argv; - con->os->currAlias = NULL; - con->os->nextCharArg = NULL; - con->os->nextArg = NULL; - if (flags & POPT_KEEP_FIRST) - con->os->next = 0; /* include argv[0] */ - else + if (!(flags & POPT_CONTEXT_KEEP_FIRST)) con->os->next = 1; /* skip argv[0] */ con->leftovers = malloc(sizeof(char *) * (argc + 1)); - con->numLeftovers = 0; - con->nextLeftover = 0; - con->restLeftover = 0; con->options = options; - con->aliases = NULL; - con->numAliases = 0; - con->flags = 0; + con->finalArgv = malloc(sizeof(*con->finalArgv) * (argc * 2)); + con->finalArgvAlloced = argc * 2; + con->flags = flags; - if (!name) - con->appName = NULL; - else + if (name) con->appName = strcpy(malloc(strlen(name) + 1), name); return con; @@ -90,6 +95,111 @@ void poptResetContext(poptContext con) { con->numLeftovers = 0; con->nextLeftover = 0; con->restLeftover = 0; + con->doExec = NULL; + con->finalArgvCount = 0; +} + +/* Only one of longName, shortName may be set at a time */ +static int handleExec(poptContext con, char * longName, char shortName) { + int i; + + i = con->numExecs - 1; + if (longName) { + while (i >= 0 && (!con->execs[i].longName || + strcmp(con->execs[i].longName, longName))) i--; + } else { + while (i >= 0 && + con->execs[i].shortName != shortName) i--; + } + + if (i < 0) return 0; + + if (con->flags & POPT_CONTEXT_NO_EXEC) + return 1; + + if (!con->doExec) { + con->doExec = con->execs + i; + return 1; + } + + /* We already have an exec to do; remember this option for next + time 'round */ + if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) { + con->finalArgvAlloced += 10; + con->finalArgv = realloc(con->finalArgv, + sizeof(*con->finalArgv) * con->finalArgvAlloced); + } + + i = con->finalArgvCount++; + con->finalArgv[i] = malloc((longName ? strlen(longName) : 0) + 3); + if (longName) + sprintf(con->finalArgv[i], "--%s", longName); + else + sprintf(con->finalArgv[i], "-%c", shortName); + + return 1; +} + +/* Only one of longName, shortName may be set at a time */ +static int handleAlias(poptContext con, char * longName, char shortName, + char * nextCharArg) { + int i; + + if (con->os->currAlias && con->os->currAlias->longName && + !strcmp(con->os->currAlias->longName, longName)) + return 0; + if (con->os->currAlias && shortName == con->os->currAlias->shortName) + return 0; + + i = con->numAliases - 1; + if (longName) { + while (i >= 0 && (!con->aliases[i].longName || + strcmp(con->aliases[i].longName, longName))) i--; + } else { + while (i >= 0 && + con->aliases[i].shortName != shortName) i--; + } + + if (i < 0) return 0; + + if ((con->os - con->optionStack + 1) + == POPT_OPTION_DEPTH) + return POPT_ERROR_OPTSTOODEEP; + + if (nextCharArg && *nextCharArg) + con->os->nextCharArg = nextCharArg; + + con->os++; + con->os->next = 0; + con->os->stuffed = 0; + con->os->nextArg = con->os->nextCharArg = NULL; + con->os->currAlias = con->aliases + i; + con->os->argc = con->os->currAlias->argc; + con->os->argv = con->os->currAlias->argv; + + return 1; +} + +static void execCommand(poptContext con) { + char ** argv; + + argv = malloc(sizeof(*argv) * + (4 + con->numLeftovers + con->finalArgvCount)); + argv[0] = con->doExec->script; + memcpy(argv + 1, con->finalArgv, sizeof(*argv) * con->finalArgvCount); + + if (con->numLeftovers) { + argv[con->finalArgvCount + 1] = "--"; + memcpy(argv + 2 + con->finalArgvCount, con->leftovers, + sizeof(*argv) * con->numLeftovers); + argv[con->numLeftovers + con->finalArgvCount + 2] = NULL; + } else { + argv[con->finalArgvCount + 1] = NULL; + } + + setreuid(getuid(), getuid()); + + execvp(argv[0], argv); } /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ @@ -107,8 +217,10 @@ int poptGetNextOpt(poptContext con) { while (!con->os->nextCharArg && con->os->next == con->os->argc && con->os > con->optionStack) con->os--; - if (!con->os->nextCharArg && con->os->next == con->os->argc) + if (!con->os->nextCharArg && con->os->next == con->os->argc) { + if (con->doExec) execCommand(con); return -1; + } if (!con->os->nextCharArg) { @@ -133,27 +245,10 @@ int poptGetNextOpt(poptContext con) { } else if (optString[1] == '-') { optString += 2; - if (!con->os->currAlias || !con->os->currAlias->longName || - strcmp(con->os->currAlias->longName, optString)) { - - i = con->numAliases - 1; - while (i >= 0 && (!con->aliases[i].longName || - strcmp(con->aliases[i].longName, optString))) i--; - - if (i >= 0) { - if ((con->os - con->optionStack + 1) - == POPT_OPTION_DEPTH) - return POPT_ERROR_OPTSTOODEEP; - - con->os++; - con->os->next = 0; - con->os->nextArg = con->os->nextCharArg = NULL; - con->os->currAlias = con->aliases + i; - con->os->argc = con->os->currAlias->argc; - con->os->argv = con->os->currAlias->argv; - continue; - } - } + if (handleAlias(con, optString, '\0', NULL)) + continue; + if (handleExec(con, optString, '\0')) + continue; chptr = optString; while (*chptr && *chptr != '=') chptr++; @@ -179,31 +274,13 @@ int poptGetNextOpt(poptContext con) { con->os->nextCharArg = NULL; - if (!con->os->currAlias || *origOptString != - con->os->currAlias->shortName) { - - i = con->numAliases - 1; - while (i >= 0 && - con->aliases[i].shortName != *origOptString) i--; - - if (i >= 0) { - if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH) - return POPT_ERROR_OPTSTOODEEP; - - /* We'll need this on the way out */ - origOptString++; - if (*origOptString) - con->os->nextCharArg = origOptString; - - con->os++; - con->os->next = 0; - con->os->nextArg = con->os->nextCharArg = NULL; - con->os->currAlias = con->aliases + i; - con->os->argc = con->os->currAlias->argc; - con->os->argv = con->os->currAlias->argv; - continue; - } + if (handleAlias(con, NULL, *origOptString, + origOptString + 1)) { + origOptString++; + continue; } + if (handleExec(con, NULL, *origOptString)) + continue; opt = con->options; while ((opt->longName || opt->shortName) && @@ -264,6 +341,23 @@ int poptGetNextOpt(poptContext con) { } if (opt->val) done = 1; + + if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) { + con->finalArgvAlloced += 10; + con->finalArgv = realloc(con->finalArgv, + sizeof(*con->finalArgv) * con->finalArgvAlloced); + } + + i = con->finalArgvCount++; + con->finalArgv[i] = + malloc((opt->longName ? strlen(opt->longName) : 0) + 3); + if (opt->longName) + sprintf(con->finalArgv[i], "--%s", opt->longName); + else + sprintf(con->finalArgv[i], "-%c", opt->shortName); + + if (opt->arg && opt->argInfo != POPT_ARG_NONE) + con->finalArgv[con->finalArgvCount++] = strdup(con->os->nextArg); } return opt->val; @@ -298,11 +392,20 @@ void poptFreeContext(poptContext con) { int i; for (i = 0; i < con->numAliases; i++) { - free(con->aliases[i].longName); + if (con->aliases[i].longName) free(con->aliases[i].longName); free(con->aliases[i].argv); } + for (i = 0; i < con->numExecs; i++) { + if (con->execs[i].longName) free(con->execs[i].longName); + free(con->execs[i].script); + } + + for (i = 0; i < con->finalArgvCount; i++) + free(con->finalArgv[i]); + free(con->leftovers); + free(con->finalArgv); if (con->appName) free(con->appName); if (con->aliases) free(con->aliases); free(con); @@ -414,38 +517,48 @@ static void configLine(poptContext con, char * line) { int nameLength = strlen(con->appName); char * opt; struct poptAlias alias; + char * entryType; + char * longName = NULL; + char shortName = '\0'; if (strncmp(line, con->appName, nameLength)) return; line += nameLength; if (!*line || !isspace(*line)) return; while (*line && isspace(*line)) line++; + entryType = line; - if (!strncmp(line, "alias", 5)) { - line += 5; - if (!*line || !isspace(*line)) return; - while (*line && isspace(*line)) line++; - if (!*line) return; + while (!*line || !isspace(*line)) line++; + *line++ = '\0'; + while (*line && isspace(*line)) line++; + if (!*line) return; + opt = line; - opt = line; - while (*line && !isspace(*line)) line++; - if (!*line) return; - *line++ = '\0'; - while (*line && isspace(*line)) line++; - if (!*line) return; + while (!*line || !isspace(*line)) line++; + *line++ = '\0'; + while (*line && isspace(*line)) line++; + if (!*line) return; - if (!strlen(opt)) return; + if (opt[0] == '-' && opt[1] == '-') + longName = opt + 2; + else if (opt[0] == '-' && !opt[2]) + shortName = opt[1]; + if (!strcmp(entryType, "alias")) { if (poptParseArgvString(line, &alias.argc, &alias.argv)) return; - - if (opt[0] == '-' && opt[1] == '-') { - alias.longName = opt + 2; - alias.shortName = '\0'; - poptAddAlias(con, alias, 0); - } else if (opt[0] == '-' && !opt[2]) { - alias.longName = NULL; - alias.shortName = opt[1]; - poptAddAlias(con, alias, 0); - } + alias.longName = longName, alias.shortName = shortName; + poptAddAlias(con, alias, 0); + } else if (!strcmp(entryType, "exec")) { + con->execs = realloc(con->execs, + sizeof(*con->execs) * (con->numExecs + 1)); + if (longName) + con->execs[con->numExecs].longName = strdup(longName); + else + con->execs[con->numExecs].longName = NULL; + + con->execs[con->numExecs].shortName = shortName; + con->execs[con->numExecs].script = strdup(line); + + con->numExecs++; } } @@ -631,6 +744,7 @@ int poptStuffArgs(poptContext con, char ** argv) { con->os->currAlias = NULL; con->os->argc = i; con->os->argv = argv; + con->os->stuffed = 1; return 0; } |