Esempio n. 1
0
/*@-compmempass@*/	/* FIX: item->option.longName kept, not dependent. */
static int poptConfigLine(poptContext con, char * line)
	/*@globals fileSystem, internalState @*/
	/*@modifies con, fileSystem, internalState @*/
{
    char *b = NULL;
    size_t nb = 0;
    char * se = line;
    const char * appName;
    const char * entryType;
    const char * opt;
    struct poptItem_s item_buf;
    poptItem item = &item_buf;
    int i, j;
    int rc = POPT_ERROR_BADCONFIG;

    if (con->appName == NULL)
	goto exit;
    
    memset(item, 0, sizeof(*item));

    appName = se;
    while (*se != '\0' && !_isspaceptr(se)) se++;
    if (*se == '\0')
	goto exit;
    else
	*se++ = '\0';

    if (configAppMatch(con, appName)) goto exit;

    while (*se != '\0' && _isspaceptr(se)) se++;
    entryType = se;
    while (*se != '\0' && !_isspaceptr(se)) se++;
    if (*se != '\0') *se++ = '\0';

    while (*se != '\0' && _isspaceptr(se)) se++;
    if (*se == '\0') goto exit;
    opt = se;
    while (*se != '\0' && !_isspaceptr(se)) se++;
    if (opt[0] == '-' && *se == '\0') goto exit;
    if (*se != '\0') *se++ = '\0';

    while (*se != '\0' && _isspaceptr(se)) se++;
    if (opt[0] == '-' && *se == '\0') goto exit;

/*@-temptrans@*/ /* FIX: line alias is saved */
    if (opt[0] == '-' && opt[1] == '-')
	item->option.longName = opt + 2;
    else if (opt[0] == '-' && opt[2] == '\0')
	item->option.shortName = opt[1];
    else {
	const char * fn = opt;

	/* XXX handle globs and directories in fn? */
	if ((rc = poptReadFile(fn, &b, &nb, POPT_READFILE_TRIMNEWLINES)) != 0)
	    goto exit;
	if (b == NULL || nb == 0)
	    goto exit;

	/* Append remaining text to the interpolated file option text. */
	if (*se != '\0') {
	    size_t nse = strlen(se) + 1;
	    if ((b = realloc(b, (nb + nse))) == NULL)	/* XXX can't happen */
		goto exit;
	    (void) stpcpy( stpcpy(&b[nb-1], " "), se);
	    nb += nse;
	}
	se = b;

	/* Use the basename of the path as the long option name. */
	{   const char * longName = strrchr(fn, '/');
	    if (longName != NULL)
		longName++;
	    else
		longName = fn;
	    if (longName == NULL)	/* XXX can't happen. */
		goto exit;
	    /* Single character basenames are treated as short options. */
	    if (longName[1] != '\0')
		item->option.longName = longName;
	    else
		item->option.shortName = longName[0];
	}
    }
/*@=temptrans@*/

    if (poptParseArgvString(se, &item->argc, &item->argv)) goto exit;

/*@-modobserver@*/
    item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
    for (i = 0, j = 0; i < item->argc; i++, j++) {
	const char * f;
	if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) {
	    f = item->argv[i] + sizeof("--POPTdesc=");
	    if (f[0] == '$' && f[1] == '"') f++;
	    item->option.descrip = f;
	    item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
	    j--;
	} else
	if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) {
	    f = item->argv[i] + sizeof("--POPTargs=");
	    if (f[0] == '$' && f[1] == '"') f++;
	    item->option.argDescrip = f;
	    item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
	    item->option.argInfo |= POPT_ARG_STRING;
	    j--;
	} else
	if (j != i)
	    item->argv[j] = item->argv[i];
    }
    if (j != i) {
	item->argv[j] = NULL;
	item->argc = j;
    }
/*@=modobserver@*/
	
/*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
    if (!strcmp(entryType, "alias"))
	rc = poptAddItem(con, item, 0);
    else if (!strcmp(entryType, "exec"))
	rc = poptAddItem(con, item, 1);
/*@=nullstate@*/
exit:
    rc = 0;	/* XXX for now, always return success */
    if (b)
	free(b);
    return rc;
}
Esempio n. 2
0
/**
 * Display help text for an option.
 * @param fp		output file handle
 * @param columns	output display width control
 * @param opt		option(s)
 * @param translation_domain	translation domain
 */
static void singleOptionHelp(FILE * fp, columns_t columns,
		const struct poptOption * opt,
		/*@null@*/ const char * translation_domain)
	/*@globals fileSystem @*/
	/*@modifies fp, fileSystem @*/
{
    size_t maxLeftCol = columns->cur;
    size_t indentLength = maxLeftCol + 5;
    size_t lineLength = columns->max - indentLength;
    const char * help = D_(translation_domain, opt->descrip);
    const char * argDescrip = getArgDescrip(opt, translation_domain);
    /* Display shortName iff printable non-space. */
    int prtshort = (int)(isprint((int)opt->shortName) && opt->shortName != ' ');
    size_t helpLength;
    char * defs = NULL;
    char * left;
    size_t nb = maxLeftCol + 1;
    int displaypad = 0;

    /* Make sure there's more than enough room in target buffer. */
    if (opt->longName)	nb += strlen(opt->longName);
    if (F_ISSET(opt, TOGGLE)) nb += sizeof("[no]") - 1;
    if (argDescrip)	nb += strlen(argDescrip);

    left = (char*) xmalloc(nb);
assert(left);	/* XXX can't happen */
    if (left == NULL) return;
    left[0] = '\0';
    left[maxLeftCol] = '\0';

#define	prtlong	(opt->longName != NULL)	/* XXX splint needs a clue */
    if (!(prtshort || prtlong))
	goto out;
    if (prtshort && prtlong) {
	char *dash = F_ISSET(opt, ONEDASH) ? "-" : "--";
	left[0] = '-';
	left[1] = opt->shortName;
	(void) stpcpy(stpcpy(stpcpy(left+2, ", "), dash), opt->longName);
    } else if (prtshort) {
	left[0] = '-';
	left[1] = opt->shortName;
	left[2] = '\0';
    } else if (prtlong) {
	/* XXX --long always padded for alignment with/without "-X, ". */
	char *dash = poptArgType(opt) == POPT_ARG_MAINCALL ? ""
		   : (F_ISSET(opt, ONEDASH) ? "-" : "--");
	const char *longName = opt->longName;
	const char *toggle;
	if (F_ISSET(opt, TOGGLE)) {
	    toggle = "[no]";
	    if (longName[0] == 'n' && longName[1] == 'o') {
		longName += sizeof("no") - 1;
		if (longName[0] == '-')
		    longName++;
	    }
	} else
	    toggle = "";
	(void) stpcpy(stpcpy(stpcpy(stpcpy(left, "    "), dash), toggle), longName);
    }
#undef	prtlong

    if (argDescrip) {
	char * le = left + strlen(left);

	if (F_ISSET(opt, OPTIONAL))
	    *le++ = '[';

	/* Choose type of output */
	if (F_ISSET(opt, SHOW_DEFAULT)) {
	    defs = singleOptionDefaultValue(lineLength, opt, translation_domain);
	    if (defs) {
		char * t = (char*) xmalloc((help ? strlen(help) : 0) +
				strlen(defs) + sizeof(" "));
assert(t);	/* XXX can't happen */
		if (t) {
		    char * te = t;
		    if (help)
			te = stpcpy(te, help);
		    *te++ = ' ';
		    strcpy(te, defs);
		    defs = _free(defs);
		    defs = t;
		}
	    }
	}

	if (opt->argDescrip == NULL) {
	    switch (poptArgType(opt)) {
	    case POPT_ARG_NONE:
		break;
	    case POPT_ARG_VAL:
#ifdef	NOTNOW	/* XXX pug ugly nerdy output */
	    {	long aLong = opt->val;
		int ops = F_ISSET(opt, LOGICALOPS);
		int negate = F_ISSET(opt, NOT);

		/* Don't bother displaying typical values */
		if (!ops && (aLong == 0L || aLong == 1L || aLong == -1L))
		    break;
		*le++ = '[';
		switch (ops) {
		case POPT_ARGFLAG_OR:
		    *le++ = '|';
		    /*@innerbreak@*/ break;
		case POPT_ARGFLAG_AND:
		    *le++ = '&';
		    /*@innerbreak@*/ break;
		case POPT_ARGFLAG_XOR:
		    *le++ = '^';
		    /*@innerbreak@*/ break;
		default:
		    /*@innerbreak@*/ break;
		}
		*le++ = (opt->longName != NULL ? '=' : ' ');
		if (negate) *le++ = '~';
		/*@-formatconst@*/
		le += sprintf(le, (ops ? "0x%lx" : "%ld"), aLong);
		/*@=formatconst@*/
		*le++ = ']';
	    }
#endif
		break;
	    case POPT_ARG_INT:
	    case POPT_ARG_SHORT:
	    case POPT_ARG_LONG:
	    case POPT_ARG_LONGLONG:
	    case POPT_ARG_FLOAT:
	    case POPT_ARG_DOUBLE:
	    case POPT_ARG_STRING:
		*le++ = (opt->longName != NULL ? '=' : ' ');
		le = stpcpy(le, argDescrip);
		break;
	    default:
		break;
	    }
	} else {
	    char *leo;

	    /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
	    if (!strchr(" =(", argDescrip[0]))
		*le++ = ((poptArgType(opt) == POPT_ARG_MAINCALL) ? ' ' :
			 (poptArgType(opt) == POPT_ARG_ARGV) ? ' ' : '=');
	    le = stpcpy(leo = le, argDescrip);

	    /* Adjust for (possible) wide characters. */
	    displaypad = (int)((le - leo) - stringDisplayWidth(argDescrip));
	}
	if (F_ISSET(opt, OPTIONAL))
	    *le++ = ']';
	*le = '\0';
    }

    if (help)
	POPT_fprintf(fp,"  %-*s   ", (int)(maxLeftCol+displaypad), left);
    else {
	POPT_fprintf(fp,"  %s\n", left);
	goto out;
    }

    left = _free(left);
    if (defs)
	help = defs;

    helpLength = strlen(help);
    while (helpLength > lineLength) {
	const char * ch;
	char format[16];

	ch = help + lineLength - 1;
	while (ch > help && !_isspaceptr(ch))
	    ch = POPT_prev_char(ch);
	if (ch == help) break;		/* give up */
	while (ch > (help + 1) && _isspaceptr(ch))
	    ch = POPT_prev_char (ch);
	ch = POPT_next_char(ch);

	/*
	 *  XXX strdup is necessary to add NUL terminator so that an unknown
	 *  no. of (possible) multi-byte characters can be displayed.
	 */
	{   char * fmthelp = xstrdup(help);
	    if (fmthelp) {
		fmthelp[ch - help] = '\0';
		sprintf(format, "%%s\n%%%ds", (int) indentLength);
		/*@-formatconst@*/
		POPT_fprintf(fp, format, fmthelp, " ");
		/*@=formatconst@*/
		free(fmthelp);
	    }
	}

	help = ch;
	while (_isspaceptr(help) && *help)
	    help = POPT_next_char(help);
	helpLength = strlen(help);
    }

    if (helpLength) fprintf(fp, "%s\n", help);
    help = NULL;

out:
    /*@-dependenttrans@*/
    defs = _free(defs);
    /*@=dependenttrans@*/
    left = _free(left);
}
Esempio n. 3
0
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;
    size_t buflen = strlen(s) + 1;
    char * buf, * bufOrig = NULL;
    int rc = POPT_ERROR_MALLOC;

    if (argv == NULL) return rc;
    buf = bufOrig = calloc((size_t)1, buflen);
    if (buf == NULL) {
	free(argv);
	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 (_isspaceptr(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 (bufOrig) free(bufOrig);
    if (argv) free(argv);
    return rc;
}
Esempio n. 4
0
/* still in the dev stage.
 * return values, perhaps 1== file erro
 * 2== line to long
 * 3== umm.... more?
 */
int poptConfigFileToString(FILE *fp, char ** argstrp,
		/*@unused@*/ UNUSED(int flags))
{
    char line[999];
    char * argstr;
    char * p;
    char * q;
    char * x;
    size_t t;
    size_t argvlen = 0;
    size_t maxlinelen = sizeof(line);
    size_t linelen;
    size_t maxargvlen = (size_t)480;

    *argstrp = NULL;

    /*   |   this_is   =   our_line
     *	     p             q      x
     */

    if (fp == NULL)
	return POPT_ERROR_NULLARG;

    argstr = calloc(maxargvlen, sizeof(*argstr));
    if (argstr == NULL) return POPT_ERROR_MALLOC;

    while (fgets(line, (int)maxlinelen, fp) != NULL) {
	p = line;

	/* loop until first non-space char or EOL */
	while( *p != '\0' && _isspaceptr(p) )
	    p++;

	linelen = strlen(p);
	if (linelen >= maxlinelen-1) {
	    free(argstr);
	    return POPT_ERROR_OVERFLOW;	/* XXX line too long */
	}

	if (*p == '\0' || *p == '\n') continue;	/* line is empty */
	if (*p == '#') continue;		/* comment line */

	q = p;

	while (*q != '\0' && (!_isspaceptr(q)) && *q != '=')
	    q++;

	if (_isspaceptr(q)) {
	    /* a space after the name, find next non space */
	    *q++='\0';
	    while( *q != '\0' && _isspaceptr(q) ) q++;
	}
	if (*q == '\0') {
	    /* single command line option (ie, no name=val, just name) */
	    q[-1] = '\0';		/* kill off newline from fgets() call */
	    argvlen += (t = (size_t)(q - p)) + (sizeof(" --")-1);
	    if (argvlen >= maxargvlen) {
		maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
		argstr = realloc(argstr, maxargvlen);
		if (argstr == NULL) return POPT_ERROR_MALLOC;
	    }
	    strcat(argstr, " --");
	    strcat(argstr, p);
	    continue;
	}
	if (*q != '=')
	    continue;	/* XXX for now, silently ignore bogus line */
		
	/* *q is an equal sign. */
	*q++ = '\0';

	/* find next non-space letter of value */
	while (*q != '\0' && _isspaceptr(q))
	    q++;
	if (*q == '\0')
	    continue;	/* XXX silently ignore missing value */

	/* now, loop and strip all ending whitespace */
	x = p + linelen;
	while (_isspaceptr(--x))
	    *x = '\0';	/* null out last char if space (including fgets() NL) */

	/* rest of line accept */
	t = (size_t)(x - p);
	argvlen += t + (sizeof("' --='")-1);
	if (argvlen >= maxargvlen) {
	    maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
	    argstr = realloc(argstr, maxargvlen);
	    if (argstr == NULL) return POPT_ERROR_MALLOC;
	}
	strcat(argstr, " --");
	strcat(argstr, p);
	strcat(argstr, "=\"");
	strcat(argstr, q);
	strcat(argstr, "\"");
    }

    *argstrp = argstr;
    return 0;
}
Esempio n. 5
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;
}
Esempio n. 6
0
/* still in the dev stage.
 * return values, perhaps 1== file erro
 * 2== line to long
 * 3== umm.... more?
 */
int poptConfigFileToString(FILE *fp, char ** argstrp,
		/*@unused@*/ UNUSED(int flags))
{
    size_t nline = 8192;	/* XXX configurable? */
    char * line = (char*) alloca(nline);
    char * argstr;
    char * q;
    char * x;
    size_t t;
    size_t argvlen = 0;
    size_t maxargvlen = (size_t)480;

    if (argstrp)
	*argstrp = NULL;

    /*   |   this_is   =   our_line
     *	     p             q      x
     */

    if (fp == NULL)
	return POPT_ERROR_NULLARG;

    argstr = (char*) xmalloc(maxargvlen * sizeof(*argstr));
assert(argstr);	/* XXX can't happen */
    if (argstr == NULL) return POPT_ERROR_MALLOC;
    argstr[0] = '\0';

    while (fgets(line, (int)nline, fp) != NULL) {
	char * l = line;
	size_t nl;

	/* loop until first non-space char or EOL */
	while( *l != '\0' && _isspaceptr(l) )
	    l++;

	nl = strlen(l);
	if (nl >= nline-1) {
	    argstr = _free(argstr);
	    return POPT_ERROR_OVERFLOW;	/* XXX line too long */
	}

	if (*l == '\0' || *l == '\n') continue;	/* line is empty */
	if (*l == '#') continue;		/* comment line */

	q = l;

	while (*q != '\0' && (!_isspaceptr(q)) && *q != '=')
	    q++;

	if (_isspaceptr(q)) {
	    /* a space after the name, find next non space */
	    *q++='\0';
	    while( *q != '\0' && _isspaceptr(q) ) q++;
	}
	if (*q == '\0') {
	    /* single command line option (ie, no name=val, just name) */
	    q[-1] = '\0';		/* kill off newline from fgets() call */
	    argvlen += (t = (size_t)(q - l)) + (sizeof(" --")-1);
	    if (argvlen >= maxargvlen) {
		maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
		argstr = (char*) xrealloc(argstr, maxargvlen);
assert(argstr);	/* XXX can't happen */
		if (argstr == NULL) return POPT_ERROR_MALLOC;
	    }
	    strcat(argstr, " --");	/* XXX stpcpy */
	    strcat(argstr, l);		/* XXX stpcpy */
	    continue;
	}
	if (*q != '=')
	    continue;	/* XXX for now, silently ignore bogus line */

	/* *q is an equal sign. */
	*q++ = '\0';

	/* find next non-space letter of value */
	while (*q != '\0' && _isspaceptr(q))
	    q++;
	if (*q == '\0')
	    continue;	/* XXX silently ignore missing value */

	/* now, loop and strip all ending whitespace */
	x = l + nl;
	while (_isspaceptr(--x))
	    *x = '\0';	/* null out last char if space (including fgets() NL) */

	/* rest of line accept */
	t = (size_t)(x - l);
	argvlen += t + (sizeof("' --='")-1);
	if (argvlen >= maxargvlen) {
	    maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
	    argstr = (char*) xrealloc(argstr, maxargvlen);
assert(argstr);	/* XXX can't happen */
	    if (argstr == NULL) return POPT_ERROR_MALLOC;
	}
	strcat(argstr, " --");	/* XXX stpcpy */
	strcat(argstr, l);	/* XXX stpcpy */
	strcat(argstr, "=\"");	/* XXX stpcpy */
	strcat(argstr, q);	/* XXX stpcpy */
	strcat(argstr, "\"");	/* XXX stpcpy */
    }

    *argstrp = argstr;
    return 0;
}