/* Only one of longName, shortName may be set at a time */ static int handleAlias(/*@special@*/ poptContext con, /*@null@*/ const char * longName, char shortName, /*@exposed@*/ /*@null@*/ const char * nextCharArg) /*@uses con->aliases, con->numAliases, con->optionStack, con->os, con->os->currAlias, con->os->currAlias->option.longName @*/ /*@modifies con @*/ { poptItem item = con->os->currAlias; int rc; int i; if (item) { if (longName && (item->option.longName && !strcmp(longName, item->option.longName))) return 0; if (shortName && shortName == item->option.shortName) return 0; } if (con->aliases == NULL || con->numAliases <= 0) /* XXX can't happen */ return 0; for (i = con->numAliases - 1; i >= 0; i--) { item = con->aliases + i; if (longName && !(item->option.longName && !strcmp(longName, item->option.longName))) continue; else if (shortName != item->option.shortName) continue; break; } if (i < 0) return 0; if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH) return POPT_ERROR_OPTSTOODEEP; /*@-boundsread@*/ if (nextCharArg && *nextCharArg) con->os->nextCharArg = nextCharArg; /*@=boundsread@*/ con->os++; con->os->next = 0; con->os->stuffed = 0; con->os->nextArg = NULL; con->os->nextCharArg = NULL; con->os->currAlias = con->aliases + i; rc = poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv, &con->os->argc, &con->os->argv); con->os->argb = NULL; return (rc ? rc : 1); }
static void copyLogInfo(struct logInfo *to, struct logInfo *from) { memset(to, 0, sizeof(*to)); if (from->oldDir) to->oldDir = strdup(from->oldDir); to->criterium = from->criterium; to->threshhold = from->threshhold; to->minsize = from->minsize; to->maxsize = from->maxsize; to->rotateCount = from->rotateCount; to->rotateAge = from->rotateAge; to->logStart = from->logStart; if (from->pre) to->pre = strdup(from->pre); if (from->post) to->post = strdup(from->post); if (from->first) to->first = strdup(from->first); if (from->last) to->last = strdup(from->last); if (from->preremove) to->preremove = strdup(from->preremove); if (from->logAddress) to->logAddress = strdup(from->logAddress); if (from->extension) to->extension = strdup(from->extension); if (from->compress_prog) to->compress_prog = strdup(from->compress_prog); if (from->uncompress_prog) to->uncompress_prog = strdup(from->uncompress_prog); if (from->compress_ext) to->compress_ext = strdup(from->compress_ext); to->flags = from->flags; to->shred_cycles = from->shred_cycles; to->createMode = from->createMode; to->createUid = from->createUid; to->createGid = from->createGid; to->suUid = from->suUid; to->suGid = from->suGid; if (from->compress_options_count) { poptDupArgv(from->compress_options_count, from->compress_options_list, &to->compress_options_count, &to->compress_options_list); } if (from->dateformat) to->dateformat = strdup(from->dateformat); }
/* Only one of longName, shortName may be set at a time */ static int handleAlias(poptContext con, const char * longName, char shortName, /*@keep@*/ const char * nextCharArg) { int i; if (con->os->currAlias && con->os->currAlias->longName && longName && !strcmp(con->os->currAlias->longName, longName)) return 0; if (con->os->currAlias && shortName && 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 = NULL; con->os->nextCharArg = NULL; con->os->currAlias = con->aliases + i; poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv, &con->os->argc, &con->os->argv); con->os->argb = NULL; return 1; }
int poptStuffArgs(poptContext con, const char ** argv) { int argc; int rc; if ((con->os - con->optionStack) == POPT_OPTION_DEPTH) return POPT_ERROR_OPTSTOODEEP; for (argc = 0; argv[argc]; argc++) {}; con->os++; con->os->next = 0; con->os->nextArg = NULL; con->os->nextCharArg = NULL; con->os->currAlias = NULL; rc = poptDupArgv(argc, argv, &con->os->argc, &con->os->argv); con->os->argb = NULL; con->os->stuffed = 1; return rc; }
int main(int argc, const char *argv[]) { int np, verbose; int rank, i, rc; int dup_argc; char **dup_argv; int waittime, killtime; unsigned int magic; /* * We can't use popt for argument parsing here. popt is not * capable to stop at the first unrecogniced option, i.e. at the * executable separation options to the mpirun command from * options to the application. */ poptContext optCon; /* context for parsing command-line options */ struct poptOption optionsTable[] = { { "np", '\0', POPT_ARG_INT | POPT_ARGFLAG_ONEDASH, &np, 0, "number of processes to start", "num"}, { "wait", 'w', POPT_ARG_INT, &waittime, 0, "Wait <n> seconds between each spawning step", "n"}, { "kill", 'k', POPT_ARG_INT, &killtime, 0, "Kill all processes <n> seconds after the first exits", "n"}, { NULL, 'v', POPT_ARG_NONE, &verbose, 0, "verbose mode", NULL}, { NULL, '\0', 0, NULL, 0, NULL, NULL} }; /* The duplicated argv will contain the apps commandline */ poptDupArgv(argc, argv, &dup_argc, (const char ***)&dup_argv); optCon = poptGetContext(NULL, dup_argc, (const char **)dup_argv, optionsTable, 0); poptSetOtherOptionHelp(optCon, OTHER_OPTIONS_STR); /* * Split the argv into two parts: * - first one containing the mpirun options * - second one containing the apps argv * The first one is already parsed while splitting */ while (1) { const char *unknownArg; np = -1; verbose = 0; waittime = 0; killtime = -1; rc = poptGetNextOpt(optCon); if ((unknownArg=poptGetArg(optCon))) { /* * Find the first unknown argument (which is the apps * name) within dup_argv. Start searching from dup_argv's end * since the apps name might be used within another * options argument. */ for (i=argc-1; i>0; i--) { if (strcmp(dup_argv[i], unknownArg)==0) { dup_argc = i; dup_argv[dup_argc] = NULL; poptFreeContext(optCon); optCon = poptGetContext(NULL, dup_argc, (const char **)dup_argv, optionsTable, 0); poptSetOtherOptionHelp(optCon, OTHER_OPTIONS_STR); break; } } if (i==0) { printf("unknownArg '%s' not found !?\n", unknownArg); exit(1); } } else { /* No unknownArg left, we are finished */ break; } } if (rc < -1) { /* an error occurred during option processing */ poptPrintUsage(optCon, stderr, 0); fprintf(stderr, "%s: %s\n", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(rc)); exit(1); } if (np == -1) { poptPrintUsage(optCon, stderr, 0); fprintf(stderr, "You have to give at least the -np argument.\n"); exit(1); } if (!argv[dup_argc]) { poptPrintUsage(optCon, stderr, 0); fprintf(stderr, "No <command> specified.\n"); exit(1); } free(dup_argv); if (verbose) { printf("The 'gmspawner' command-line is:\n"); for (i=0; i<dup_argc; i++) { printf("%s ", argv[i]); } printf("\b\n\n"); printf("The applications command-line is:\n"); for (i=dup_argc; i<argc; i++) { printf("%s ", argv[i]); } printf("\b\n\n"); } /* init PSI */ if (!PSI_initClient(TG_GMSPAWNER)) { fprintf(stderr, "Initialization of PSI failed."); exit(10); } PSI_infoInt(-1, PSP_INFO_TASKRANK, NULL, &rank, 0); if (rank != np) { fprintf(stderr, "%s: rank(%d) != np(%d).\n", argv[dup_argc], rank, np); exit(1); } /* Propagate some environment variables */ PSI_propEnv(); PSI_propEnvList("PSI_EXPORTS"); PSI_propEnvList("__PSI_EXPORTS"); srandom(time(NULL)); magic = random()%9999999; setIntEnv("GMPI_MAGIC", magic); setIntEnv("GMPI_NP", np); { char hostname[256]; gethostname(hostname, sizeof(hostname)); setPSIEnv("GMPI_MASTER", hostname, 1); } { int port = createListener(8000, np, magic, verbose); if (port>=0) setIntEnv("GMPI_PORT", port); } propagateEnv("GMPI_SHMEM", 1); propagateEnv("DISPLAY", 0); propagateEnv("GMPI_EAGER", 0); propagateEnv("GMPI_RECV", 1); PSC_setSigHandler(SIGALRM, sighandler); /* spawn all processes */ PSI_RemoteArgs(argc - dup_argc, (char **)&argv[dup_argc], &dup_argc, &dup_argv); for (rank=0; rank<np; rank++) { if (waittime && rank) sleep(waittime); setIntEnv("GMPI_ID", rank); setIntEnv("GMPI_BOARD", -1); char slavestring[20]; PSnodes_ID_t node; struct in_addr ip; int err; err = PSI_infoNodeID(-1, PSP_INFO_RANKID, &rank, &node, 1); if (err) { fprintf(stderr, "Could not determine rank %d's node.\n", rank); exit(1); } err = PSI_infoUInt(-1, PSP_INFO_NODE, &node, &ip.s_addr, 1); if (err) { fprintf(stderr, "Could not determine node %d's IP\n", node); exit(1); } snprintf(slavestring, sizeof(slavestring), "%s", inet_ntoa(ip)); setPSIEnv("GMPI_SLAVE", slavestring, 1); /* spawn the process */ int error; if (!PSI_spawnRank(rank, ".", dup_argc, dup_argv, &error)) { if (error) { char *errstr = strerror(error); fprintf(stderr, "Could not spawn process %d (%s) error = %s.\n", rank, dup_argv[0], errstr ? errstr : "UNKNOWN"); exit(1); } } } /* Wait for the spawned processes to complete */ while (np) { static int firstClient=1; DDErrorMsg_t msg; int ret; ret = PSI_recvMsg((DDMsg_t *)&msg, sizeof(msg)); if (msg.header.type != PSP_CD_SPAWNFINISH || ret != sizeof(msg)) { fprintf(stderr, "got strange message type %s\n", PSP_printMsg(msg.header.type)); } else { if (firstClient && killtime!=-1) { // printf("Alarm set to %d\n", killtime); if (killtime) { alarm(killtime); firstClient=0; } else { /* Stop immediately */ exit(0); } } np--; // printf("%d clients left\n", np); } } PSI_release(PSC_getMyTID()); PSI_exitClient(); return 0; }
/*@-bounds@*/ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) { const char * src; char quote = '\0'; int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA; const char ** argv = malloc(sizeof(*argv) * argvAlloced); int argc = 0; int buflen = strlen(s) + 1; char * buf = memset(alloca(buflen), 0, buflen); int rc = POPT_ERROR_MALLOC; if (argv == NULL) return rc; argv[argc] = buf; for (src = s; *src != '\0'; src++) { if (quote == *src) { quote = '\0'; } else if (quote != '\0') { if (*src == '\\') { src++; if (!*src) { rc = POPT_ERROR_BADQUOTE; goto exit; } if (*src != quote) *buf++ = '\\'; } *buf++ = *src; } else if (isspace(*src)) { if (*argv[argc] != '\0') { buf++, argc++; if (argc == argvAlloced) { argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA; argv = realloc(argv, sizeof(*argv) * argvAlloced); if (argv == NULL) goto exit; } argv[argc] = buf; } } else switch (*src) { case '"': case '\'': quote = *src; /*@switchbreak@*/ break; case '\\': src++; if (!*src) { rc = POPT_ERROR_BADQUOTE; goto exit; } /*@fallthrough@*/ default: *buf++ = *src; /*@switchbreak@*/ break; } } if (strlen(argv[argc])) { argc++, buf++; } rc = poptDupArgv(argc, argv, argcPtr, argvPtr); exit: if (argv) free(argv); return rc; }
int main(int argc, const char *argv[]) { int np, dest, version, verbose, local, source, rusage; int rank, i, arg, rc; char *nList, *hList, *hFile, *sort, *envlist, *msg; char *envstr; int dup_argc; char **dup_argv; int gm_shmem, gm_eager, gm_wait, gm_kill; char *gm_recv; /* * We can't use popt for argument parsing here. popt is not * capable to stop at the first unrecogniced option, i.e. at the * executable separation options to the mpirun command from * options to the application. */ poptContext optCon; /* context for parsing command-line options */ struct poptOption optionsTable[] = { { "np", '\0', POPT_ARG_INT | POPT_ARGFLAG_ONEDASH, &np, 0, "number of processes to start", "num"}, { "nodes", '\0', POPT_ARG_STRING | POPT_ARGFLAG_ONEDASH, &nList, 0, "list of nodes to use", "nodelist"}, { "hosts", '\0', POPT_ARG_STRING | POPT_ARGFLAG_ONEDASH, &hList, 0, "list of hosts to use", "hostlist"}, { "hostfile", '\0', POPT_ARG_STRING | POPT_ARGFLAG_ONEDASH, &hFile, 0, "hostfile to use", "hostfile"}, { "sort", '\0', POPT_ARG_STRING | POPT_ARGFLAG_ONEDASH, &sort, 0, "sorting criterium to use", "{proc|load|proc+load|none}"}, { "all-local", '\0', POPT_ARG_NONE | POPT_ARGFLAG_ONEDASH, &local, 0, "local execution", NULL}, { "inputdest", '\0', POPT_ARG_INT | POPT_ARGFLAG_ONEDASH, &dest, 0, "direction to forward input", "dest"}, { "sourceprintf", '\0', POPT_ARG_NONE | POPT_ARGFLAG_ONEDASH, &source, 0, "print output-source info", NULL}, { "rusage", '\0', POPT_ARG_NONE | POPT_ARGFLAG_ONEDASH, &rusage, 0, "print consumed sys/user time", NULL}, { "exports", '\0', POPT_ARG_STRING | POPT_ARGFLAG_ONEDASH, &envlist, 0, "environment to export to foreign nodes", "envlist"}, { "gm-no-shmem", '\0', POPT_ARG_VAL, &gm_shmem, 0, "Disable the shared memory support" " (enabled by default)", NULL}, { "gm-numa-shmem", '\0', POPT_ARG_VAL, &gm_shmem, 2, "Enable shared memory only for processes sharing" " the same Myrinet interface", NULL}, { "gm-wait", '\0', POPT_ARG_INT, &gm_wait, 0, "Wait <n> seconds between each spawning step", "n"}, { "gm-kill", '\0', POPT_ARG_INT, &gm_kill, 0, "Kill all processes <n> seconds after the first exits", "n"}, { "gm-eager", '\0', POPT_ARG_INT, &gm_eager, 0, "Specifies the Eager/Rendez-vous protocol threshold" " size", "size"}, { "gm-recv", '\0', POPT_ARG_STRING, &gm_recv, 0, "Specifies the receive mode <polling>, <blocking>" " or <hybrid>, <polling> is the default", "mode"}, { "verbose", 'v', POPT_ARG_NONE, &verbose, 0, "verbose mode", NULL}, { "version", 'V', POPT_ARG_NONE, &version, -1, "output version information and exit", NULL}, POPT_AUTOHELP { NULL, '\0', 0, NULL, 0, NULL, NULL} }; /* The duplicated argv will contain the apps commandline */ poptDupArgv(argc, argv, &dup_argc, (const char ***)&dup_argv); optCon = poptGetContext(NULL, dup_argc, (const char **)dup_argv, optionsTable, 0); poptSetOtherOptionHelp(optCon, OTHER_OPTIONS_STR); /* * Split the argv into two parts: * - first one containing the mpirun options * - second one containing the apps argv * The first one is already parsed while splitting */ while (1) { const char *unknownArg; np = dest = -1; version = verbose = local = source = rusage = 0; nList = hList = hFile = sort = envlist = NULL; gm_shmem = gm_eager = gm_wait = 0; gm_kill = -1; gm_recv = "polling"; rc = poptGetNextOpt(optCon); if ((unknownArg=poptGetArg(optCon))) { /* * Find the first unknown argument (which is the apps * name) within dup_argv. Start searching from dup_argv's end * since the apps name might be used within another * options argument. */ for (i=argc-1; i>0; i--) { if (strcmp(dup_argv[i], unknownArg)==0) { dup_argc = i; dup_argv[dup_argc] = NULL; poptFreeContext(optCon); optCon = poptGetContext(NULL, dup_argc, (const char **)dup_argv, optionsTable, 0); poptSetOtherOptionHelp(optCon, OTHER_OPTIONS_STR); break; } } if (i==0) { printf("unknownArg '%s' not found !?\n", unknownArg); exit(1); } } else { /* No unknownArg left, we are finished */ break; } } if (rc < -1) { /* an error occurred during option processing */ poptPrintUsage(optCon, stderr, 0); fprintf(stderr, "%s: %s\n", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(rc)); exit(1); } if (version) { printVersion(); return 0; } if (np == -1) { poptPrintUsage(optCon, stderr, 0); fprintf(stderr, "You have to give at least the -np argument.\n"); exit(1); } if (strcmp(gm_recv, "blocking") && strcmp(gm_recv, "hybrid") && strcmp(gm_recv, "polling")) { poptPrintUsage(optCon, stderr, 0); fprintf(stderr, "Unknown receive mode '%s'.\n", gm_recv); exit(1); } if (!argv[dup_argc]) { poptPrintUsage(optCon, stderr, 0); fprintf(stderr, "No <command> specified.\n"); exit(1); } free(dup_argv); if (verbose) { printf("The 'mpirun' command-line is:\n"); for (i=0; i<dup_argc; i++) { printf("%s ", argv[i]); } printf("\b\n\n"); printf("The applications command-line is:\n"); for (i=dup_argc; i<argc; i++) { printf("%s ", argv[i]); } printf("\b\n\n"); } /* Setup various environment variables depending on passed arguments */ if (dest >= 0) { char val[16]; snprintf(val, sizeof(val), "%d", dest); setenv("PSI_INPUTDEST", val, 1); if (verbose) { printf("Send all input to node with rank %d.\n", dest); } } if (source) { setenv("PSI_SOURCEPRINTF", "", 1); } if (rusage) { setenv("PSI_RUSAGE", "", 1); if (verbose) { printf("Will print info about consumed sys/user time.\n"); } } if (envlist) { char *val; envstr = getenv("PSI_EXPORTS"); if (envstr) { val = malloc(strlen(envstr) + strlen(envlist) + 2); sprintf(val, "%s,%s", envstr, envlist); } else { val = strdup(envlist); } setenv("PSI_EXPORTS", val, 1); free(val); if (verbose) { printf("Environment variables to be exported: %s\n", val); } } msg = PSE_checkAndSetNodeEnv(nList, hList, hFile, NULL, "-", verbose); if (msg) { poptPrintUsage(optCon, stderr, 0); fprintf(stderr, "%s\n", msg); exit(1); } msg = PSE_checkAndSetSortEnv(sort, "-", verbose); if (msg) { poptPrintUsage(optCon, stderr, 0); fprintf(stderr, "%s\n", msg); exit(1); } /* Don't irritate the user with logger messages */ setenv("PSI_NOMSGLOGGERDONE", "", 1); PSE_initialize(); rank = PSE_getRank(); /* Propagate some environment variables */ PSI_propEnv(); PSI_propEnvList("PSI_EXPORTS"); PSI_propEnvList("__PSI_EXPORTS"); if (rank != -1) { fprintf(stderr, "%s: never act as client process.\n", argv[dup_argc]); exit(1); } { char* hwList[] = { "gm", NULL }; if (PSE_setHWList(hwList) < 0) { fprintf(stderr, "%s: Unknown hardware type '%s'.\n", argv[0], hwList[0]); exit(1); } } if (PSE_getPartition(np) < 0) { fprintf(stderr, "%s: unable to get partition.\n", argv[dup_argc]); exit(1); } propagateEnv("LD_LIBRARY_PATH", 0); propagateEnv("DISPLAY", 0); /* Copy and expand the apps commandline */ dup_argv = malloc((argc + 1) * sizeof(char *)); if (!dup_argv) { fprintf(stderr, "%s: no memory", argv[0]); exit(1); } #define SPAWNER "bin/gmspawner" arg=0; dup_argv[arg] = malloc(strlen(PSC_lookupInstalldir(NULL)) + strlen(SPAWNER) + 2); if (!dup_argv[arg]) { fprintf(stderr, "%s: no memory", argv[0]); exit(1); } else { sprintf(dup_argv[arg], "%s/%s", PSC_lookupInstalldir(NULL), SPAWNER); } dup_argv[++arg] = "-np"; dup_argv[++arg] = malloc(16); if (!dup_argv[arg]) { fprintf(stderr, "%s: no memory", argv[0]); exit(1); } else { snprintf(dup_argv[arg], 16, "%d", np); } setIntEnv("GMPI_SHMEM", gm_shmem); if (gm_wait) { dup_argv[++arg] = malloc(32); if (!dup_argv[arg]) { fprintf(stderr, "%s: no memory", argv[0]); exit(1); } else { snprintf(dup_argv[arg], 32, "--wait=%d", gm_wait); } } if (gm_kill!=-1) { dup_argv[++arg] = malloc(32); if (!dup_argv[arg]) { fprintf(stderr, "%s: no memory\n", argv[0]); exit(1); } else { snprintf(dup_argv[arg], 32, "--kill=%d", gm_kill); } } if (gm_eager) setIntEnv("GMPI_EAGER", gm_eager); setPSIEnv("GMPI_RECV", gm_recv, 1); if (verbose) dup_argv[++arg] = "-v"; if (argv[dup_argc][0] != '/' && argv[dup_argc][0] != '.') { dup_argv[++arg] = malloc(sizeof(char) * strlen(argv[dup_argc]) + 3); if (!dup_argv[arg]) { fprintf(stderr, "%s: no memory\n", argv[0]); exit(1); } else { sprintf(dup_argv[arg], "./%s", argv[dup_argc]); } } else { dup_argv[++arg] = strdup(argv[dup_argc]); if (!dup_argv[arg]) { fprintf(stderr, "%s: no memory\n", argv[0]); exit(1); } } arg++; for (i=dup_argc+1; i<argc; i++, arg++) { dup_argv[arg] = strdup(argv[i]); if (!dup_argv[arg]) { fprintf(stderr, "%s: no memory\n", argv[0]); exit(1); } } dup_argc = arg; { /* spawn master processes (we are going to be logger) */ int error; PSI_RemoteArgs(dup_argc, dup_argv, &dup_argc, &dup_argv); /* spawn the process */ if (!PSI_spawnGMSpawner(np, ".", dup_argc, dup_argv, &error)) { if (error) { char *errstr = strerror(error); fprintf(stderr, "Could not spawn spawner process (%s) error = %s.\n", dup_argv[0], errstr ? errstr : "UNKNOWN"); exit(1); } } /* Switch to psilogger */ PSI_execLogger(NULL); } /* Never be here ! */ return 0; }
int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) { const char * se; char quote = '\0'; size_t argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA; const char ** argv = (const char**) xmalloc(sizeof(*argv) * argvAlloced); unsigned int argc = 0; size_t ns = strlen(s); char * t = NULL; char * te; int rc = POPT_ERROR_MALLOC; assert(argv); /* XXX can't happen */ if (argv == NULL) return rc; te = t = (char*) xmalloc(ns + 1); assert(te); /* XXX can't happen */ if (te == NULL) { argv = _free(argv); return rc; } *te = '\0'; argv[argc] = te; for (se = s; *se != '\0'; se++) { if (quote == *se) { quote = '\0'; } else if (quote != '\0') { if (*se == '\\') { se++; if (*se == '\0') { rc = POPT_ERROR_BADQUOTE; goto exit; } if (*se != quote) *te++ = '\\'; } *te++ = *se; } else if (_isspaceptr(se)) { if (*argv[argc] != '\0') { *te++ = '\0', argc++; if (argc == argvAlloced) { argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA; argv = (const char**) xrealloc(argv, sizeof(*argv) * argvAlloced); assert(argv); /* XXX can't happen */ if (argv == NULL) goto exit; } *te = '\0'; argv[argc] = te; } } else switch (*se) { case '"': case '\'': quote = *se; /*@switchbreak@*/ break; case '\\': se++; if (*se == '\0') { rc = POPT_ERROR_BADQUOTE; goto exit; } /*@fallthrough@*/ default: *te++ = *se; /*@switchbreak@*/ break; } } if (strlen(argv[argc])) { argc++, *te++ = '\0'; } rc = poptDupArgv(argc, argv, argcPtr, argvPtr); exit: t = _free(t); argv = _free(argv); return rc; }