Exemplo n.º 1
0
int parseScript(rpmSpec spec, int parsePart)
{
    /* There are a few options to scripts: */
    /*  <pkg>                              */
    /*  -n <pkg>                           */
    /*  -p <sh>                            */
    /*  -p "<sh> <args>..."                */
    /*  -f <file>                          */

    const char *p;
    const char **progArgv = NULL;
    int progArgc;
    const char *partname = NULL;
    rpmTagVal reqtag = 0;
    rpmTagVal tag = 0;
    rpmsenseFlags tagflags = 0;
    rpmTagVal progtag = 0;
    rpmTagVal flagtag = 0;
    rpmscriptFlags scriptFlags = 0;
    int flag = PART_SUBNAME;
    Package pkg;
    StringBuf sb = NULL;
    int nextPart;
    int index;
    char * reqargs = NULL;

    int res = PART_ERROR; /* assume failure */
    int rc, argc;
    int arg;
    const char **argv = NULL;
    poptContext optCon = NULL;
    const char *name = NULL;
    const char *prog = "/bin/sh";
    const char *file = NULL;
    int priority = 1000000;
    struct poptOption optionsTable[] = {
	{ NULL, 'p', POPT_ARG_STRING, &prog, 'p',	NULL, NULL},
	{ NULL, 'n', POPT_ARG_STRING, &name, 'n',	NULL, NULL},
	{ NULL, 'f', POPT_ARG_STRING, &file, 'f',	NULL, NULL},
	{ NULL, 'e', POPT_BIT_SET, &scriptFlags, RPMSCRIPT_FLAG_EXPAND,
	  NULL, NULL},
	{ NULL, 'q', POPT_BIT_SET, &scriptFlags, RPMSCRIPT_FLAG_QFORMAT,
	  NULL, NULL},
	{ NULL, 'c', POPT_BIT_SET, &scriptFlags, RPMSCRIPT_FLAG_CRITICAL,
	  NULL, NULL},
	{ NULL, 'P', POPT_ARG_INT, &priority, 'P', NULL, NULL},
	{ 0, 0, 0, 0, 0,	NULL, NULL}
    };

    switch (parsePart) {
      case PART_PRE:
	tag = RPMTAG_PREIN;
	tagflags = RPMSENSE_SCRIPT_PRE;
	progtag = RPMTAG_PREINPROG;
	flagtag = RPMTAG_PREINFLAGS;
	partname = "%pre";
	break;
      case PART_POST:
	tag = RPMTAG_POSTIN;
	tagflags = RPMSENSE_SCRIPT_POST;
	progtag = RPMTAG_POSTINPROG;
	flagtag = RPMTAG_POSTINFLAGS;
	partname = "%post";
	break;
      case PART_PREUN:
	tag = RPMTAG_PREUN;
	tagflags = RPMSENSE_SCRIPT_PREUN;
	progtag = RPMTAG_PREUNPROG;
	flagtag = RPMTAG_PREUNFLAGS;
	partname = "%preun";
	break;
      case PART_POSTUN:
	tag = RPMTAG_POSTUN;
	tagflags = RPMSENSE_SCRIPT_POSTUN;
	progtag = RPMTAG_POSTUNPROG;
	flagtag = RPMTAG_POSTUNFLAGS;
	partname = "%postun";
	break;
      case PART_PRETRANS:
	tag = RPMTAG_PRETRANS;
	tagflags = RPMSENSE_PRETRANS;
	progtag = RPMTAG_PRETRANSPROG;
	flagtag = RPMTAG_PRETRANSFLAGS;
	partname = "%pretrans";
	break;
      case PART_POSTTRANS:
	tag = RPMTAG_POSTTRANS;
	tagflags = RPMSENSE_POSTTRANS;
	progtag = RPMTAG_POSTTRANSPROG;
	flagtag = RPMTAG_POSTTRANSFLAGS;
	partname = "%posttrans";
	break;
      case PART_VERIFYSCRIPT:
	tag = RPMTAG_VERIFYSCRIPT;
	tagflags = RPMSENSE_SCRIPT_VERIFY;
	progtag = RPMTAG_VERIFYSCRIPTPROG;
	flagtag = RPMTAG_VERIFYSCRIPTFLAGS;
	partname = "%verifyscript";
	break;
      case PART_TRIGGERPREIN:
	tag = RPMTAG_TRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRIGGERPREIN;
	progtag = RPMTAG_TRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRIGGERSCRIPTFLAGS;
	partname = "%triggerprein";
	break;
      case PART_TRIGGERIN:
	tag = RPMTAG_TRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRIGGERIN;
	progtag = RPMTAG_TRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRIGGERSCRIPTFLAGS;
	partname = "%triggerin";
	break;
      case PART_TRIGGERUN:
	tag = RPMTAG_TRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRIGGERUN;
	progtag = RPMTAG_TRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRIGGERSCRIPTFLAGS;
	partname = "%triggerun";
	break;
      case PART_TRIGGERPOSTUN:
	tag = RPMTAG_TRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRIGGERPOSTUN;
	progtag = RPMTAG_TRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRIGGERSCRIPTFLAGS;
	partname = "%triggerpostun";
	break;
      case PART_FILETRIGGERIN:
	tag = RPMTAG_FILETRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_FILETRIGGERIN;
	progtag = RPMTAG_FILETRIGGERSCRIPTPROG;
	flagtag = RPMTAG_FILETRIGGERSCRIPTFLAGS;
	partname = "%filetriggerin";
	break;
      case PART_FILETRIGGERUN:
	tag = RPMTAG_FILETRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_FILETRIGGERUN;
	progtag = RPMTAG_FILETRIGGERSCRIPTPROG;
	flagtag = RPMTAG_FILETRIGGERSCRIPTFLAGS;
	partname = "%filetriggerun";
	break;
      case PART_FILETRIGGERPOSTUN:
	tag = RPMTAG_FILETRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_FILETRIGGERPOSTUN;
	progtag = RPMTAG_FILETRIGGERSCRIPTPROG;
	flagtag = RPMTAG_FILETRIGGERSCRIPTFLAGS;
	partname = "%filetriggerpostun";
	break;
      case PART_TRANSFILETRIGGERIN:
	tag = RPMTAG_TRANSFILETRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRANSFILETRIGGERIN;
	progtag = RPMTAG_TRANSFILETRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS;
	partname = "%transfiletriggerin";
	break;
      case PART_TRANSFILETRIGGERUN:
	tag = RPMTAG_TRANSFILETRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRANSFILETRIGGERUN;
	progtag = RPMTAG_TRANSFILETRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS;
	partname = "%transfiletriggerun";
	break;
      case PART_TRANSFILETRIGGERPOSTUN:
	tag = RPMTAG_TRANSFILETRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRANSFILETRIGGERPOSTUN;
	progtag = RPMTAG_TRANSFILETRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS;
	partname = "%transfiletriggerpostun";
	break;
    }

    if (tag == RPMTAG_TRIGGERSCRIPTS || tag == RPMTAG_FILETRIGGERSCRIPTS ||
	tag == RPMTAG_TRANSFILETRIGGERSCRIPTS) {
	/* break line into two at the -- separator */
	char *sep, *s = spec->line;
	while ((s = strstr(s, "--")) != NULL) {
	    s += 2;
	    if (risblank(*(s-3)) && risblank(*s))
		break;
	}

	if (s == NULL) {
	    rpmlog(RPMLOG_ERR, _("line %d: triggers must have --: %s\n"),
		     spec->lineNum, spec->line);
	    goto exit;
	}

	sep = s;
	SKIPSPACE(s);
	if (*s == '\0') {
	    rpmlog(RPMLOG_ERR, _("line %d: missing trigger condition: %s\n"),
				spec->lineNum, spec->line);
	    goto exit;
	}

	*sep = '\0';
	reqargs = xstrdup(s);
    }
    
    if ((rc = poptParseArgvString(spec->line, &argc, &argv))) {
	rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
		 spec->lineNum, partname, poptStrerror(rc));
	goto exit;
    }
    
    optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
    while ((arg = poptGetNextOpt(optCon)) > 0) {
	switch (arg) {
	case 'p':
	    if (prog[0] == '<') {
		if (prog[strlen(prog)-1] != '>') {
		    rpmlog(RPMLOG_ERR,
			     _("line %d: internal script must end "
			     "with \'>\': %s\n"), spec->lineNum, prog);
		    goto exit;
		}
	    } else if (prog[0] != '/') {
		rpmlog(RPMLOG_ERR,
			 _("line %d: script program must begin "
			 "with \'/\': %s\n"), spec->lineNum, prog);
		goto exit;
	    }
	    break;
	case 'n':
	    flag = PART_NAME;
	    break;
	case 'P':
	    if (tag != RPMTAG_TRIGGERSCRIPTS &&
		tag != RPMTAG_FILETRIGGERSCRIPTS &&
		tag != RPMTAG_TRANSFILETRIGGERSCRIPTS) {

		rpmlog(RPMLOG_ERR,
			 _("line %d: Priorities are allowed only for file "
			 "triggers : %s\n"), spec->lineNum, prog);
		goto exit;
	    }
	}
    }

    if (arg < -1) {
	rpmlog(RPMLOG_ERR, _("line %d: Bad option %s: %s\n"),
		 spec->lineNum,
		 poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 
		 spec->line);
	goto exit;
    }

    if (poptPeekArg(optCon)) {
	if (name == NULL)
	    name = poptGetArg(optCon);
	if (poptPeekArg(optCon)) {
	    rpmlog(RPMLOG_ERR, _("line %d: Too many names: %s\n"),
		     spec->lineNum,
		     spec->line);
	    goto exit;
	}
    }
    
    if (lookupPackage(spec, name, flag, &pkg))
	goto exit;

    if (tag != RPMTAG_TRIGGERSCRIPTS) {
	if (headerIsEntry(pkg->header, progtag)) {
	    rpmlog(RPMLOG_ERR, _("line %d: Second %s\n"),
		     spec->lineNum, partname);
	    goto exit;
	}
    }

    if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) {
	rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
		 spec->lineNum, partname, poptStrerror(rc));
	goto exit;
    }

    sb = newStringBuf();
    if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
	nextPart = PART_NONE;
    } else if (rc < 0) {
	goto exit;
    } else {
	while (! (nextPart = isPart(spec->line))) {
	    appendStringBuf(sb, spec->line);
	    if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
		nextPart = PART_NONE;
		break;
	    } else if (rc < 0) {
		goto exit;
	    }
	}
    }
    stripTrailingBlanksStringBuf(sb);
    p = getStringBuf(sb);

#ifdef WITH_LUA
    if (rstreq(progArgv[0], "<lua>")) {
	rpmlua lua = NULL; /* Global state. */
	if (rpmluaCheckScript(lua, p, partname) != RPMRC_OK) {
	    goto exit;
	}
	(void) rpmlibNeedsFeature(pkg, "BuiltinLuaScripts", "4.2.2-1");
    } else
#endif
    if (progArgv[0][0] == '<') {
	rpmlog(RPMLOG_ERR,
		 _("line %d: unsupported internal script: %s\n"),
		 spec->lineNum, progArgv[0]);
	goto exit;
    } else {
        (void) addReqProv(pkg, RPMTAG_REQUIRENAME,
		progArgv[0], NULL, (tagflags | RPMSENSE_INTERP), 0);
    }

    if (scriptFlags) {
	rpmlibNeedsFeature(pkg, "ScriptletExpansion", "4.9.0-1");
    }

    /* Trigger script insertion is always delayed in order to */
    /* get the index right.                                   */
    if (tag == RPMTAG_TRIGGERSCRIPTS || tag == RPMTAG_FILETRIGGERSCRIPTS ||
	tag == RPMTAG_TRANSFILETRIGGERSCRIPTS) {
	if (tag != RPMTAG_TRIGGERSCRIPTS && *reqargs != '/') {
	    rpmlog(RPMLOG_ERR,
	       _("line %d: file trigger condition must begin with '/': %s"),
		spec->lineNum, reqargs);
	    goto exit;
	}
	if (progArgc > 1) {
	    rpmlog(RPMLOG_ERR,
	      _("line %d: interpreter arguments not allowed in triggers: %s\n"),
	      spec->lineNum, prog);
	    goto exit;
	}
	/* Add file/index/prog triple to the trigger file list */
	index = addTriggerIndex(pkg, file, p, progArgv[0], scriptFlags, tag,
				priority);

	/* Generate the trigger tags */
	if (parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags, addReqProvPkg, NULL))
	    goto exit;
    } else {
	struct rpmtd_s td;

	/*
 	 * XXX Ancient rpm uses STRING, not STRING_ARRAY type here. Construct
 	 * the td manually and preserve legacy compat for now...
 	 */
	rpmtdReset(&td);
	td.tag = progtag;
	td.count = progArgc;
	if (progArgc == 1) {
	    td.data = (void *) *progArgv;
	    td.type = RPM_STRING_TYPE;
	} else {
	    (void) rpmlibNeedsFeature(pkg,
			"ScriptletInterpreterArgs", "4.0.3-1");
	    td.data = progArgv;
	    td.type = RPM_STRING_ARRAY_TYPE;
	}
	headerPut(pkg->header, &td, HEADERPUT_DEFAULT);

	if (*p != '\0') {
	    headerPutString(pkg->header, tag, p);
	}
	if (scriptFlags) {
	    headerPutUint32(pkg->header, flagtag, &scriptFlags, 1);
	}

	if (file) {
	    switch (parsePart) {
	      case PART_PRE:
		pkg->preInFile = xstrdup(file);
		break;
	      case PART_POST:
		pkg->postInFile = xstrdup(file);
		break;
	      case PART_PREUN:
		pkg->preUnFile = xstrdup(file);
		break;
	      case PART_POSTUN:
		pkg->postUnFile = xstrdup(file);
		break;
	      case PART_PRETRANS:
		pkg->preTransFile = xstrdup(file);
		break;
	      case PART_POSTTRANS:
		pkg->postTransFile = xstrdup(file);
		break;
	      case PART_VERIFYSCRIPT:
		pkg->verifyFile = xstrdup(file);
		break;
	    }
	}
    }
    res = nextPart;
    
exit:
    free(reqargs);
    freeStringBuf(sb);
    free(progArgv);
    free(argv);
    poptFreeContext(optCon);
    
    return res;
}
Exemplo n.º 2
0
static int
ds_ip4set_line(struct dataset *ds, char *s, struct dsctx *dsc) {
    struct dsdata *dsd = ds->ds_dsd;
    ip4addr_t a, b;
    const char *rr;
    unsigned rrl;

    int not;
    int bits;

    if (*s == ':') {
        if (!(rrl = parse_a_txt(s, &rr, def_rr, dsc)))
            return 1;
        if (!(dsd->def_rr = mp_dmemdup(ds->ds_mp, rr, rrl)))
            return 0;
        return 1;
    }

    if (*s == '!') {
        not = 1;
        ++s;
        SKIPSPACE(s);
    }
    else
        not = 0;
    if ((bits = ip4range(s, &a, &b, &s)) <= 0 ||
            (*s && !ISSPACE(*s) && !ISCOMMENT(*s) && *s != ':')) {
        dswarn(dsc, "invalid address");
        return 1;
    }
    if (accept_in_cidr)
        a &= ip4mask(bits);
    else if (a & ~ip4mask(bits)) {
        dswarn(dsc, "invalid range (non-zero host part)");
        return 1;
    }
    if (dsc->dsc_ip4maxrange && dsc->dsc_ip4maxrange <= (b - a)) {
        dswarn(dsc, "too large range (%u) ignored (%u max)",
               b - a + 1, dsc->dsc_ip4maxrange);
        return 1;
    }
    if (not)
        rr = NULL;
    else {
        SKIPSPACE(s);
        if (!*s || ISCOMMENT(*s))
            rr = dsd->def_rr;
        else if (!(rrl = parse_a_txt(s, &rr, dsd->def_rr, dsc)))
            return 1;
        else if (!(rr = mp_dmemdup(ds->ds_mp, rr, rrl)))
            return 0;
    }

    /*XXX some comments about funny ip4range_expand et al */

#define fn(idx,start,count) ds_ip4set_addent(dsd, idx, start, count, rr)

    /* helper macro for ip4range_expand:
     * deal with last octet, shifting a and b when done
     */
#define ip4range_expand_octet(bits)			\
  if ((a | 255u) >= b) {				\
    if (b - a == 255u)					\
      return fn((bits>>3)+1, a<<bits, 1);		\
    else						\
      return fn(bits>>3, a<<bits, b - a + 1);		\
  }							\
  if (a & 255u) {					\
    if (!fn(bits>>3, a<<bits, 256u - (a & 255u)))	\
      return 0;						\
    a = (a >> 8) + 1;					\
  }							\
  else							\
    a >>= 8;						\
  if ((b & 255u) != 255u) {				\
    if (!fn((bits>>3), (b & ~255u)<<bits, (b&255u)+1))	\
      return 0;						\
    b = (b >> 8) - 1;					\
  }							\
  else							\
    b >>= 8

    ip4range_expand_octet(0);
    ip4range_expand_octet(8);
    ip4range_expand_octet(16);
    return fn(3, a << 24, b - a + 1);

}
Exemplo n.º 3
0
/**
 * Add %changelog section to header.
 * @param h		header
 * @param sb		changelog strings
 * @return		RPMRC_OK on success
 */
static rpmRC addChangelog(Header h, StringBuf sb)
{
    char *s;
    int i;
    time_t time;
    time_t lastTime = 0;
    time_t trimtime = rpmExpandNumeric("%{?_changelog_trimtime}");
    char *date, *name, *text, *next;

    s = getStringBuf(sb);

    /* skip space */
    SKIPSPACE(s);

    while (*s != '\0') {
	if (*s != '*') {
	    rpmlog(RPMLOG_ERR,
			_("%%changelog entries must start with *\n"));
	    return RPMRC_FAIL;
	}

	/* find end of line */
	date = s;
	while(*s && *s != '\n') s++;
	if (! *s) {
	    rpmlog(RPMLOG_ERR, _("incomplete %%changelog entry\n"));
	    return RPMRC_FAIL;
	}
	*s = '\0';
	text = s + 1;
	
	/* 4 fields of date */
	date++;
	s = date;
	for (i = 0; i < 4; i++) {
	    SKIPSPACE(s);
	    SKIPNONSPACE(s);
	}
	SKIPSPACE(date);
	if (dateToTimet(date, &time)) {
	    rpmlog(RPMLOG_ERR, _("bad date in %%changelog: %s\n"), date);
	    return RPMRC_FAIL;
	}
	if (lastTime && lastTime < time) {
	    rpmlog(RPMLOG_ERR,
		     _("%%changelog not in descending chronological order\n"));
	    return RPMRC_FAIL;
	}
	lastTime = time;

	/* skip space to the name */
	SKIPSPACE(s);
	if (! *s) {
	    rpmlog(RPMLOG_ERR, _("missing name in %%changelog\n"));
	    return RPMRC_FAIL;
	}

	/* name */
	name = s;
	while (*s != '\0') s++;
	while (s > name && risspace(*s)) {
	    *s-- = '\0';
	}
	if (s == name) {
	    rpmlog(RPMLOG_ERR, _("missing name in %%changelog\n"));
	    return RPMRC_FAIL;
	}

	/* text */
	SKIPSPACE(text);
	if (! *text) {
	    rpmlog(RPMLOG_ERR, _("no description in %%changelog\n"));
	    return RPMRC_FAIL;
	}
	    
	/* find the next leading '*' (or eos) */
	s = text;
	do {
	   s++;
	} while (*s && (*(s-1) != '\n' || *s != '*'));
	next = s;
	s--;

	/* backup to end of description */
	while ((s > text) && risspace(*s)) {
	    *s-- = '\0';
	}
	
	if ( !trimtime || time >= trimtime ) {
	    addChangelogEntry(h, time, name, text);
	} else break;
	
	s = next;
    }

    return RPMRC_OK;
}
Exemplo n.º 4
0
/**
 * Parse date string to seconds.
 * @param datestr	date string (e.g. 'Wed Jan 1 1997')
 * @retval secs		secs since the unix epoch
 * @return 		0 on success, -1 on error
 */
static int dateToTimet(const char * datestr, time_t * secs)
{
    int rc = -1; /* assume failure */
    struct tm time;
    const char * const * idx;
    char *p, *pe, *q, *date, *tz;
    
    static const char * const days[] =
	{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL };
    static const char * const months[] =
	{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
 	  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
    static const char const lengths[] =
	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    
    memset(&time, 0, sizeof(time));

    date = xstrdup(datestr);
    pe = date;

    /* day of week */
    p = pe; SKIPSPACE(p);
    if (*p == '\0') goto exit;
    pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe++ = '\0';
    for (idx = days; *idx && !rstreq(*idx, p); idx++)
	{};
    if (*idx == NULL) goto exit;

    /* month */
    p = pe; SKIPSPACE(p);
    if (*p == '\0') goto exit;
    pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe++ = '\0';
    for (idx = months; *idx && !rstreq(*idx, p); idx++)
	{};
    if (*idx == NULL) goto exit;
    time.tm_mon = idx - months;

    /* day */
    p = pe; SKIPSPACE(p);
    if (*p == '\0') goto exit;
    pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe++ = '\0';

    /* make this noon so the day is always right (as we make this UTC) */
    time.tm_hour = 12;

    time.tm_mday = strtol(p, &q, 10);
    if (!(q && *q == '\0')) goto exit;
    if (time.tm_mday < 0 || time.tm_mday > lengths[time.tm_mon]) goto exit;

    /* year */
    p = pe; SKIPSPACE(p);
    if (*p == '\0') goto exit;
    pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe++ = '\0';
    time.tm_year = strtol(p, &q, 10);
    if (!(q && *q == '\0')) goto exit;
    if (time.tm_year < 1990 || time.tm_year >= 3000) goto exit;
    time.tm_year -= 1900;

    /* chnagelog date is always in UTC */
    tz = getenv("TZ");
    if (tz) tz = xstrdup(tz);
    setenv("TZ", "UTC", 1);
    *secs = mktime(&time);
    unsetenv("TZ");
    if (tz) {
	setenv("TZ", tz, 1);
	free(tz);
    }
    if (*secs == -1) goto exit;

    rc = 0;

exit:
    free(date);
    return rc;
}
Exemplo n.º 5
0
int readLine(rpmSpec spec, int strip)
{
    char  *s;
    int match;
    struct ReadLevelEntry *rl;
    OFI_t *ofi = spec->fileStack;
    int rc;

    if (!restoreFirstChar(spec)) {
    retry:
	if ((rc = readLineFromOFI(spec, ofi)) != 0)
	    return rc;

	/* Copy next file line into the spec line buffer */
	rc = copyNextLineFromOFI(spec, ofi);
	if (rc > 0) {
	    goto retry;
	} else if (rc < 0) {
	    return PART_ERROR;
	}
    }

    copyNextLineFinish(spec, strip);

    s = spec->line;
    SKIPSPACE(s);

    match = -1;
    if (!spec->readStack->reading && rstreqn("%if", s, sizeof("%if")-1)) {
	match = 0;
    } else if (rstreqn("%ifarch", s, sizeof("%ifarch")-1)) {
	char *arch = rpmExpand("%{_target_cpu}", NULL);
	s += 7;
	match = matchTok(arch, s);
	arch = _free(arch);
    } else if (rstreqn("%ifnarch", s, sizeof("%ifnarch")-1)) {
	char *arch = rpmExpand("%{_target_cpu}", NULL);
	s += 8;
	match = !matchTok(arch, s);
	arch = _free(arch);
    } else if (rstreqn("%ifos", s, sizeof("%ifos")-1)) {
	char *os = rpmExpand("%{_target_os}", NULL);
	s += 5;
	match = matchTok(os, s);
	os = _free(os);
    } else if (rstreqn("%ifnos", s, sizeof("%ifnos")-1)) {
	char *os = rpmExpand("%{_target_os}", NULL);
	s += 6;
	match = !matchTok(os, s);
	os = _free(os);
    } else if (rstreqn("%if", s, sizeof("%if")-1)) {
	s += 3;
        match = parseExpressionBoolean(spec, s);
	if (match < 0) {
	    rpmlog(RPMLOG_ERR,
			_("%s:%d: parseExpressionBoolean returns %d\n"),
			ofi->fileName, ofi->lineNum, match);
	    return PART_ERROR;
	}
    } else if (rstreqn("%else", s, sizeof("%else")-1)) {
	s += 5;
	if (! spec->readStack->next) {
	    /* Got an else with no %if ! */
	    rpmlog(RPMLOG_ERR,
			_("%s:%d: Got a %%else with no %%if\n"),
			ofi->fileName, ofi->lineNum);
	    return PART_ERROR;
	}
	spec->readStack->reading =
	    spec->readStack->next->reading && ! spec->readStack->reading;
	spec->line[0] = '\0';
    } else if (rstreqn("%endif", s, sizeof("%endif")-1)) {
	s += 6;
	if (! spec->readStack->next) {
	    /* Got an end with no %if ! */
	    rpmlog(RPMLOG_ERR,
			_("%s:%d: Got a %%endif with no %%if\n"),
			ofi->fileName, ofi->lineNum);
	    return PART_ERROR;
	}
	rl = spec->readStack;
	spec->readStack = spec->readStack->next;
	free(rl);
	spec->line[0] = '\0';
    } else if (rstreqn("%include", s, sizeof("%include")-1)) {
	char *fileName, *endFileName, *p;

	s += 8;
	fileName = s;
	if (! risspace(*fileName)) {
	    rpmlog(RPMLOG_ERR, _("malformed %%include statement\n"));
	    return PART_ERROR;
	}
	SKIPSPACE(fileName);
	endFileName = fileName;
	SKIPNONSPACE(endFileName);
	p = endFileName;
	SKIPSPACE(p);
	if (*p != '\0') {
	    rpmlog(RPMLOG_ERR, _("malformed %%include statement\n"));
	    return PART_ERROR;
	}
	*endFileName = '\0';

	forceIncludeFile(spec, fileName);

	ofi = spec->fileStack;
	goto retry;
    }

    if (match != -1) {
	rl = xmalloc(sizeof(*rl));
	rl->reading = spec->readStack->reading && match;
	rl->next = spec->readStack;
	spec->readStack = rl;
	spec->line[0] = '\0';
    }

    if (! spec->readStack->reading) {
	spec->line[0] = '\0';
    }

    /* FIX: spec->readStack->next should be dependent */
    return 0;
}
Exemplo n.º 6
0
void handleComments(char *s)
{
    SKIPSPACE(s);
    if (*s == '#')
	*s = '\0';
}
Exemplo n.º 7
0
static int
parseLine2(char *line, int *embedArgc, char ***embedArgv, int option)
{
#define INCREASE 40

    static int parsing = TRUE;
    static char **argBuf = NULL, *key;
    static int  bufSize = 0;

    char *sp, *sQuote, *dQuote, quoteMark;

    if (argBuf == NULL) {
        if ((argBuf = (char **) malloc(INCREASE * sizeof(char *)))
            == NULL) {
            fprintf(stderr, (_i18n_msg_get(ls_catd,NL_SETN,803 , "Unable to allocate memory for options"))); /* catgets  803   */
            return -1;
        }
        bufSize = INCREASE;
        *embedArgc = 1;
        *embedArgv = argBuf;

        if (option & EMBED_BSUB) {
            argBuf[0] = "bsub";
            key = "BSUB";
        }
        else if (option & EMBED_RESTART) {
            argBuf[0] = "brestart";
            key = "BRESTART";
        }
        else if (option & EMBED_QSUB) {
            argBuf[0] = "qsub";
            key = "QSUB";
        }
        else {
            fprintf(stderr, (_i18n_msg_get(ls_catd,NL_SETN,804 , "Invalid option"))); /* catgets  804   */
            return -1;
        }
        argBuf[1] = NULL;
    }

    if (!parsing && !emptyCmd)
        return 0;

    SKIPSPACE(line);
    if (*line == '\0')
        return 0;
    if (*line != '#') {
        emptyCmd = FALSE;
        return 0;
    }

    if (!parsing)
        return 0;

    ++line;
    SKIPSPACE(line);
    if (strncmp (line, key, strlen(key)) == 0) {
        line += strlen(key);
        SKIPSPACE(line);
        if (*line != '-') {
            parsing = FALSE;
            return 0;
        }
        while (TRUE) {
            quoteMark = '"';
            if ((sQuote = strchr(line, '\'')) != NULL)
                if ((dQuote = strchr(line, '"')) == NULL || sQuote < dQuote)

                    quoteMark = '\'';

            if ((sp = getNextValueQ_(&line, quoteMark, quoteMark)) == NULL)
                return 0;

            if (*sp == '#')
                return 0;

            if (*embedArgc + 2 > bufSize) {
                char **tmp;
                bufSize += INCREASE;
                if ((tmp = (char **) realloc(argBuf,
                                             bufSize * sizeof(char *)))
                    == NULL) {
                    fprintf(stderr,
                            _i18n_msg_get(ls_catd, NL_SETN, 803,
                                          "Unable to allocate memory for options"));
                    return -1;
                }
                argBuf = tmp;
            }
            argBuf[*embedArgc] = putstr_(sp);
            (*embedArgc)++;
            argBuf[*embedArgc] = NULL;
        }
    }
    return 0;

}
Exemplo n.º 8
0
static int addSource(rpmSpec spec, Package pkg, const char *field, rpmTagVal tag)
{
    struct Source *p;
    int flag = 0;
    const char *name = NULL;
    char *nump;
    char *fieldp = NULL;
    char *buf = NULL;
    uint32_t num = 0;

    switch (tag) {
      case RPMTAG_SOURCE:
	flag = RPMBUILD_ISSOURCE;
	name = "source";
	fieldp = spec->line + 6;
	break;
      case RPMTAG_PATCH:
	flag = RPMBUILD_ISPATCH;
	name = "patch";
	fieldp = spec->line + 5;
	break;
      case RPMTAG_ICON:
	flag = RPMBUILD_ISICON;
	fieldp = NULL;
	break;
      default:
	return -1;
	break;
    }

    /* Get the number */
    if (tag != RPMTAG_ICON) {
	/* We already know that a ':' exists, and that there */
	/* are no spaces before it.                          */
	/* This also now allows for spaces and tabs between  */
	/* the number and the ':'                            */
	char ch;
	char *fieldp_backup = fieldp;

	while ((*fieldp != ':') && (*fieldp != ' ') && (*fieldp != '\t')) {
	    fieldp++;
	}
	ch = *fieldp;
	*fieldp = '\0';

	nump = fieldp_backup;
	SKIPSPACE(nump);
	if (nump == NULL || *nump == '\0') {
	    num = flag == RPMBUILD_ISSOURCE ? 0 : INT_MAX;
	} else {
	    if (parseUnsignedNum(fieldp_backup, &num)) {
		rpmlog(RPMLOG_ERR, _("line %d: Bad %s number: %s\n"),
			 spec->lineNum, name, spec->line);
		*fieldp = ch;
		return RPMRC_FAIL;
	    }
	}
	*fieldp = ch;
    }

    /* Check whether tags of the same number haven't already been defined */
    for (p = spec->sources; p != NULL; p = p->next) {
	if ( p->num != num ) continue;
	if ((tag == RPMTAG_SOURCE && p->flags == RPMBUILD_ISSOURCE) ||
	    (tag == RPMTAG_PATCH  && p->flags == RPMBUILD_ISPATCH)) {
		rpmlog(RPMLOG_ERR, _("%s %d defined multiple times\n"), name, num);
		return RPMRC_FAIL;
	    }
    }

    /* Create the entry and link it in */
    p = xmalloc(sizeof(*p));
    p->num = num;
    p->fullSource = xstrdup(field);
    p->flags = flag;
    p->source = strrchr(p->fullSource, '/');
    if (p->source) {
	if ((buf = strrchr(p->source,'='))) p->source = buf;
	p->source++;
    } else {
	p->source = p->fullSource;
    }

    if (tag != RPMTAG_ICON) {
	p->next = spec->sources;
	spec->sources = p;
    } else {
	p->next = pkg->icon;
	pkg->icon = p;
    }

    spec->numSources++;

    if (tag != RPMTAG_ICON) {
	char *body = rpmGetPath("%{_sourcedir}/", p->source, NULL);
	struct stat st;
	int nofetch = (spec->flags & RPMSPEC_FORCE) ||
		      rpmExpandNumeric("%{_disable_source_fetch}");

	/* try to download source/patch if it's missing */
	if (lstat(body, &st) != 0 && errno == ENOENT && !nofetch) {
	    char *url = NULL;
	    if (urlIsURL(p->fullSource) != URL_IS_UNKNOWN) {
		url = rstrdup(p->fullSource);
	    } else {
		url = rpmExpand("%{_default_source_url}", NULL);
		rstrcat(&url, p->source);
		if (*url == '%') url = _free(url);
	    }
	    if (url) {
		rpmlog(RPMLOG_WARNING, _("Downloading %s to %s\n"), url, body);
		if (urlGetFile(url, body) != 0) {
		    free(url);
		    rpmlog(RPMLOG_ERR, _("Couldn't download %s\n"), p->fullSource);
		    return RPMRC_FAIL;
		}
		free(url);
	    }
	}

	rasprintf(&buf, "%s%d",
		(flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
	rpmPushMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
	free(buf);
	rasprintf(&buf, "%sURL%d",
		(flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
	rpmPushMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
	free(buf);
#ifdef WITH_LUA
	{
	    rpmlua lua = NULL; /* global state */
	    const char * what = (flag & RPMBUILD_ISPATCH) ? "patches" : "sources";
	    rpmluaPushTable(lua, what);
	    rpmluav var = rpmluavNew();
	    rpmluavSetListMode(var, 1);
	    rpmluavSetValue(var, RPMLUAV_STRING, body);
	    rpmluaSetVar(lua, var);
	    rpmluavFree(var);
	    rpmluaPop(lua);
	}
#endif
	free(body);
    }
    
    return 0;
}
Exemplo n.º 9
0
static rpmRC handlePreambleTag(Spec spec, Package pkg, rpmTag tag,
		const char *macro, const char *lang)
	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
	/*@modifies spec->macros, spec->st,
		spec->sources, spec->numSources, spec->noSource,
		spec->sourceHeader, spec->BANames, spec->BACount,
		spec->line,
		pkg->header, pkg->autoProv, pkg->autoReq, pkg->noarch,
		rpmGlobalMacroContext, fileSystem, internalState @*/
{
    HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    char * field = spec->line;
    char * end;
    int multiToken = 0;
    rpmsenseFlags tagflags;
    int len;
    rpmuint32_t num;
    int rc;
    int xx;
    
    if (field == NULL) return RPMRC_FAIL;	/* XXX can't happen */
    /* Find the start of the "field" and strip trailing space */
    while ((*field) && (*field != ':'))
	field++;
    if (*field != ':') {
	rpmlog(RPMLOG_ERR, _("line %d: Malformed tag: %s\n"),
		 spec->lineNum, spec->line);
	return RPMRC_FAIL;
    }
    field++;
    SKIPSPACE(field);
    if (!*field) {
	/* Empty field */
	rpmlog(RPMLOG_ERR, _("line %d: Empty tag: %s\n"),
		 spec->lineNum, spec->line);
	return RPMRC_FAIL;
    }
    end = findLastChar(field);

    /* Validate tag data content. */
    if (tagValidate(spec, tag, field) != RPMRC_OK)
	return RPMRC_FAIL;

    /* See if this is multi-token */
    end = field;
    SKIPNONSPACE(end);
    if (*end != '\0')
	multiToken = 1;

    switch (tag) {
    case RPMTAG_NAME:
    case RPMTAG_VERSION:
    case RPMTAG_RELEASE:
    case RPMTAG_DISTEPOCH:
    case RPMTAG_URL:
    case RPMTAG_DISTTAG:
    case RPMTAG_REPOTAG:
    case RPMTAG_CVSID:
    case RPMTAG_BUGURL:
	SINGLE_TOKEN_ONLY;
	/* These macros are for backward compatibility */
	if (tag == RPMTAG_VERSION) {
	    if (strchr(field, '-') != NULL) {
		rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"),
		    spec->lineNum, "version", spec->line);
		return RPMRC_FAIL;
	    }
	    addMacro(spec->macros, "PACKAGE_VERSION", NULL, field, RMIL_OLDSPEC);
	} else if (tag == RPMTAG_RELEASE) {
	    if (strchr(field, '-') != NULL) {
		rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"),
		    spec->lineNum, "release", spec->line);
		return RPMRC_FAIL;
	    }
	    addMacro(spec->macros, "PACKAGE_RELEASE", NULL, field, RMIL_OLDSPEC-1);
	}
	he->tag = tag;
	he->t = RPM_STRING_TYPE;
	he->p.str = field;
	he->c = 1;
	xx = headerPut(pkg->header, he, 0);
	break;
    case RPMTAG_GROUP:
    case RPMTAG_SUMMARY:
#if defined(RPM_VENDOR_OPENPKG) /* make-class-available-as-macro */
    case RPMTAG_CLASS:
#endif
	(void) stashSt(spec, pkg->header, tag, lang);
	/*@fallthrough@*/
    case RPMTAG_DISTRIBUTION:
    case RPMTAG_VENDOR:
    case RPMTAG_LICENSE:
    case RPMTAG_PACKAGER:
	if (!*lang) {
	    he->tag = tag;
	    he->t = RPM_STRING_TYPE;
	    he->p.str = field;
	    he->c = 1;
	    xx = headerPut(pkg->header, he, 0);
	} else if (!(noLang && strcmp(lang, RPMBUILD_DEFAULT_LANG))) {
	    (void) headerAddI18NString(pkg->header, tag, field, lang);
	}
	break;
    /* XXX silently ignore BuildRoot: */
    case RPMTAG_BUILDROOT:
	SINGLE_TOKEN_ONLY;
	macro = NULL;
#ifdef	DYING
	buildRootURL = rpmGenPath(spec->rootURL, "%{?buildroot}", NULL);
	(void) urlPath(buildRootURL, &buildRoot);
	if (*buildRoot == '\0') buildRoot = "/";
	if (!strcmp(buildRoot, "/")) {
	    rpmlog(RPMLOG_ERR,
		     _("BuildRoot can not be \"/\": %s\n"), spec->buildRootURL);
	    buildRootURL = _free(buildRootURL);
	    return RPMRC_FAIL;
	}
	buildRootURL = _free(buildRootURL);
#endif
	break;
    case RPMTAG_KEYWORDS:
    case RPMTAG_VARIANTS:
    case RPMTAG_PREFIXES:
	addOrAppendListEntry(pkg->header, tag, field);
	he->tag = tag;
	xx = headerGet(pkg->header, he, 0);
	if (tag == RPMTAG_PREFIXES)
	while (he->c--) {
	    if (he->p.argv[he->c][0] != '/') {
		rpmlog(RPMLOG_ERR,
			 _("line %d: Prefixes must begin with \"/\": %s\n"),
			 spec->lineNum, spec->line);
		he->p.ptr = _free(he->p.ptr);
		return RPMRC_FAIL;
	    }
	    len = (int)strlen(he->p.argv[he->c]);
	    if (he->p.argv[he->c][len - 1] == '/' && len > 1) {
		rpmlog(RPMLOG_ERR,
			 _("line %d: Prefixes must not end with \"/\": %s\n"),
			 spec->lineNum, spec->line);
		he->p.ptr = _free(he->p.ptr);
		return RPMRC_FAIL;
	    }
	}
	he->p.ptr = _free(he->p.ptr);
	break;
    case RPMTAG_DOCDIR:
	SINGLE_TOKEN_ONLY;
	if (field[0] != '/') {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: Docdir must begin with '/': %s\n"),
		     spec->lineNum, spec->line);
	    return RPMRC_FAIL;
	}
	macro = NULL;
	delMacro(NULL, "_docdir");
	addMacro(NULL, "_docdir", NULL, field, RMIL_SPEC);
	break;
    case RPMTAG_XMAJOR:
    case RPMTAG_XMINOR:
    case RPMTAG_EPOCH:
	SINGLE_TOKEN_ONLY;
	if (parseNum(field, &num)) {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: %s takes an integer value: %s\n"),
		     spec->lineNum, tagName(tag), spec->line);
	    return RPMRC_FAIL;
	}
	he->tag = tag;
	he->t = RPM_UINT32_TYPE;
	he->p.ui32p = &num;
	he->c = 1;
	xx = headerPut(pkg->header, he, 0);
	break;
    case RPMTAG_AUTOREQPROV:
	pkg->autoReq = parseYesNo(field);
	pkg->autoProv = pkg->autoReq;
	break;
    case RPMTAG_AUTOREQ:
	pkg->autoReq = parseYesNo(field);
	break;
    case RPMTAG_AUTOPROV:
	pkg->autoProv = parseYesNo(field);
	break;
    case RPMTAG_SOURCE:
    case RPMTAG_PATCH:
	SINGLE_TOKEN_ONLY;
	macro = NULL;
	if ((rc = addSource(spec, pkg, field, tag)))
	    return rc;
	break;
    case RPMTAG_ICON:
	SINGLE_TOKEN_ONLY;
	macro = NULL;
	if ((rc = addSource(spec, pkg, field, tag)))
	    return rc;
	/* XXX the fetch/load of icon needs to be elsewhere. */
	if ((rc = doIcon(spec, pkg->header)))
	    return rc;
	break;
    case RPMTAG_NOSOURCE:
    case RPMTAG_NOPATCH:
	spec->noSource = 1;
	if ((rc = parseNoSource(spec, field, tag)))
	    return rc;
	break;
    case RPMTAG_BUILDPREREQ:
    case RPMTAG_BUILDREQUIRES:
	if ((rc = parseBits(lang, buildScriptBits, &tagflags))) {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: Bad %s: qualifiers: %s\n"),
		     spec->lineNum, tagName(tag), spec->line);
	    return rc;
	}
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    case RPMTAG_PREREQ:
    case RPMTAG_REQUIREFLAGS:
	if ((rc = parseBits(lang, installScriptBits, &tagflags))) {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: Bad %s: qualifiers: %s\n"),
		     spec->lineNum, tagName(tag), spec->line);
	    return rc;
	}
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    /* Aliases for BuildRequires(hint): */
    case RPMTAG_BUILDSUGGESTS:
    case RPMTAG_BUILDENHANCES:
	tagflags = RPMSENSE_MISSINGOK;
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    /* Aliases for Requires(hint): */
    case RPMTAG_SUGGESTSFLAGS:
    case RPMTAG_ENHANCESFLAGS:
	tag = RPMTAG_REQUIREFLAGS;
	tagflags = RPMSENSE_MISSINGOK;
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    case RPMTAG_BUILDOBSOLETES:
    case RPMTAG_BUILDPROVIDES:
    case RPMTAG_BUILDCONFLICTS:
    case RPMTAG_CONFLICTFLAGS:
    case RPMTAG_OBSOLETEFLAGS:
    case RPMTAG_PROVIDEFLAGS:
	tagflags = RPMSENSE_ANY;
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    case RPMTAG_BUILDPLATFORMS:		/* XXX needs pattern parsing */
    case RPMTAG_EXCLUDEARCH:
    case RPMTAG_EXCLUSIVEARCH:
    case RPMTAG_EXCLUDEOS:
    case RPMTAG_EXCLUSIVEOS:
	addOrAppendListEntry(spec->sourceHeader, tag, field);
	break;

    case RPMTAG_BUILDARCHS:
    {	const char ** BANames = NULL;
	int BACount = 0;
	if ((rc = poptParseArgvString(field, &BACount, &BANames))) {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: Bad BuildArchitecture format: %s\n"),
		     spec->lineNum, spec->line);
	    return RPMRC_FAIL;
	}
	if (spec->toplevel) {
	    if (BACount > 0 && BANames != NULL) {
		spec->BACount = BACount;
		spec->BANames = BANames;
		BANames = NULL;		/* XXX don't free. */
	    }
	} else {
	    if (BACount != 1 || strcmp(BANames[0], "noarch")) {
		rpmlog(RPMLOG_ERR,
		     _("line %d: Only \"noarch\" sub-packages are supported: %s\n"),
		     spec->lineNum, spec->line);
		BANames = _free(BANames);
		return RPMRC_FAIL;
	    }
	    pkg->noarch = 1;
	}
	BANames = _free(BANames);
    }	break;

    default:
	macro = NULL;
	he->tag = tag;
	he->t = RPM_STRING_ARRAY_TYPE;
	he->p.argv= (const char **) &field;	/* XXX NOCAST */
	he->c = 1;
	he->append = 1;
	xx = headerPut(pkg->header, he, 0);
	he->append = 0;
	break;
    }

/*@-usereleased@*/
    if (macro)
	addMacro(spec->macros, macro, NULL, field, RMIL_SPEC);
/*@=usereleased@*/
    
    return RPMRC_OK;
}
Exemplo n.º 10
0
static int findPreambleTag(Spec spec, /*@out@*/rpmTag * tagp,
		/*@null@*/ /*@out@*/ const char ** macro, /*@out@*/ char * lang)
	/*@modifies *tagp, *macro, *lang @*/
{
    PreambleRec p;
    char *s;
    size_t len = 0;

    /* Search for defined tags. */
    for (p = preambleList; p->token != NULL; p++) {
	len = strlen(p->token);
	if (!(p->token && !xstrncasecmp(spec->line, p->token, len)))
	    continue;
	if (p->obsolete) {
	    rpmlog(RPMLOG_ERR, _("Legacy syntax is unsupported: %s\n"),
			p->token);
	    p = NULL;
	}
	break;
    }
    if (p == NULL)
	return 1;

    /* Search for arbitrary tags. */
    if (tagp && p->token == NULL) {
	ARGV_t aTags = NULL;
	int rc = 1;	/* assume failure */

/*@-noeffect@*/
	(void) tagName(0); /* XXX force arbitrary tags to be initialized. */
/*@=noeffect@*/
	aTags = rpmTags->aTags;
	if (aTags != NULL && aTags[0] != NULL) {
	    ARGV_t av;
	    s = tagCanonicalize(spec->line);
#if defined(RPM_VENDOR_OPENPKG) /* wildcard-matching-arbitrary-tagnames */
	    av = argvSearchLinear(aTags, s, argvFnmatchCasefold);
#else
	    av = argvSearch(aTags, s, argvStrcasecmp);
#endif
	    if (av != NULL) {
		*tagp = tagGenerate(s);
		rc = 0;
	    }
	    s = _free(s);
	}
	return rc;
    }

    s = spec->line + len;
    SKIPSPACE(s);

    switch (p->multiLang) {
    default:
    case 0:
	/* Unless this is a source or a patch, a ':' better be next */
	if (p->tag != RPMTAG_SOURCE && p->tag != RPMTAG_PATCH) {
	    if (*s != ':') return 1;
	}
	*lang = '\0';
	break;
    case 1:	/* Parse optional ( <token> ). */
	if (*s == ':') {
	    strcpy(lang, RPMBUILD_DEFAULT_LANG);
	    break;
	}
	if (*s != '(') return 1;
	s++;
	SKIPSPACE(s);
	while (!xisspace(*s) && *s != ')')
	    *lang++ = *s++;
	*lang = '\0';
	SKIPSPACE(s);
	if (*s != ')') return 1;
	s++;
	SKIPSPACE(s);
	if (*s != ':') return 1;
	break;
    }

    if (tagp)
	*tagp = p->tag;
    if (macro)
	/*@-onlytrans -observertrans -dependenttrans@*/	/* FIX: double indirection. */
	*macro = p->token;
	/*@=onlytrans =observertrans =dependenttrans@*/
    return 0;
}
Exemplo n.º 11
0
/* XXX should return rpmParseState, but RPMRC_FAIL forces int return. */
int parsePreamble(Spec spec, int initialPackage)
{
    HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    rpmParseState nextPart;
    int xx;
    char *linep;
    Package pkg;
    char NVR[BUFSIZ];
    char lang[BUFSIZ];
    rpmRC rc;

    strcpy(NVR, "(main package)");

    pkg = newPackage(spec);
    if (spec->packages == NULL) {
	spec->packages = pkg;
assert(initialPackage);
    } else if (! initialPackage) {
	char *name = NULL;
	rpmParseState flag;
	Package lastpkg;

	/* There is one option to %package: <pkg> or -n <pkg> */
	flag = PART_NONE;
	if (parseSimplePart(spec, &name, &flag)) {
	    rpmlog(RPMLOG_ERR, _("Bad package specification: %s\n"),
			spec->line);
	    pkg = freePackages(pkg);
	    return RPMRC_FAIL;
	}
	
	lastpkg = NULL;
	if (lookupPackage(spec, name, flag, &lastpkg) == RPMRC_OK) {
	    pkg->next = lastpkg->next;
	} else {
	    /* Add package to end of list */
	    for (lastpkg = spec->packages; lastpkg->next != NULL; lastpkg = lastpkg->next)
	    {};
	}
assert(lastpkg != NULL);
	lastpkg->next = pkg;
	
	/* Construct the package */
	if (flag == PART_SUBNAME) {
	    he->tag = RPMTAG_NAME;
	    xx = headerGet(spec->packages->header, he, 0);
	    sprintf(NVR, "%s-%s", he->p.str, name);
	    he->p.ptr = _free(he->p.ptr);
	} else
	    strcpy(NVR, name);
	name = _free(name);
	he->tag = RPMTAG_NAME;
	he->t = RPM_STRING_TYPE;
	he->p.str = NVR;
	he->c = 1;
	xx = headerPut(pkg->header, he, 0);
    }

    if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
	nextPart = PART_NONE;
    } else {
	if (rc)
	    return rc;
	while ((nextPart = isPart(spec)) == PART_NONE) {
	    const char * macro = NULL;
	    rpmTag tag = 0;

	    /* Skip blank lines */
	    linep = spec->line;
	    SKIPSPACE(linep);
	    if (*linep != '\0') {
		if (findPreambleTag(spec, &tag, &macro, lang)) {
		    rpmlog(RPMLOG_ERR, _("line %d: Unknown tag: %s\n"),
				spec->lineNum, spec->line);
		    return RPMRC_FAIL;
		}
		if (handlePreambleTag(spec, pkg, tag, macro, lang))
		    return RPMRC_FAIL;
		if (spec->BANames && !spec->recursing && spec->toplevel)
		    return PART_BUILDARCHITECTURES;
	    }
	    if ((rc =
		 readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
		nextPart = PART_NONE;
		break;
	    }
	    if (rc)
		return rc;
	}
    }

    /* Do some final processing on the header */

    /* 
     * Expand buildroot one more time to get %{version} and the like
     * from the main package.
     */
    if (initialPackage) {
        const char *s = rpmExpand("%{?buildroot}", NULL);
	if (s && *s) 
	    (void) addMacro(NULL, "buildroot", NULL, s, -1);
	s = _free(s);
    }
    
    /* XXX Skip valid arch check if not building binary package */
    if (!spec->anyarch && checkForValidArchitectures(spec))
	return RPMRC_FAIL;

    if (pkg == spec->packages)
	fillOutMainPackage(pkg->header);

    if (checkForDuplicates(pkg->header, NVR) != RPMRC_OK)
	return RPMRC_FAIL;

    if (pkg != spec->packages)
	headerCopyTags(spec->packages->header, pkg->header,
			(void *)copyTagsDuringParse);

#ifdef RPM_VENDOR_PLD /* rpm-epoch0 */
    /* Add Epoch: 0 to package header if it was not set by spec */
    he->tag = RPMTAG_NAME;
    if (headerGet(spec->packages->header, he, 0) == 0) {
    	rpmuint32_t num = 0;

	he->tag = RPMTAG_EPOCH;
	he->t = RPM_UINT32_TYPE;
	he->p.ui32p = &num;
	he->c = 1;
	xx = headerPut(pkg->header, he, 0);

	/* also declare %{epoch} to be same */
	addMacro(spec->macros, "epoch", NULL, "0", RMIL_SPEC);
    }
#endif /* RPM_VENDOR_PLD rpm-epoch0 */

    if (checkForRequired(pkg->header, NVR) != RPMRC_OK)
	return RPMRC_FAIL;

    return nextPart;
}
Exemplo n.º 12
0
int addSource(Spec spec, /*@unused@*/ Package pkg,
		const char *field, rpmTag tag)
{
    struct Source *p;
#if defined(RPM_VENDOR_OPENPKG) /* regular-ordered-sources */
    struct Source *p_last;
#endif
    int flag = 0;
    const char *name = NULL;
    const char *mdir = NULL;
    const char *fieldp = NULL;
    char buf[BUFSIZ];
    uint32_t num = 0;

    buf[0] = '\0';
    switch (tag) {
    case RPMTAG_SOURCE:
	flag = RPMFILE_SOURCE;
	name = "source";
	fieldp = spec->line + strlen(name);
	break;
    case RPMTAG_PATCH:
	flag = RPMFILE_PATCH;
	name = "patch";
	fieldp = spec->line + strlen(name);
	break;
    case RPMTAG_ICON:
	flag = RPMFILE_ICON;
	name = "icon";
	fieldp = NULL;
	break;
    default:
assert(0);
	/*@notreached@*/ break;
    }
#if !defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
    mdir = getSourceDir(flag);
assert(mdir != NULL);
#endif

    /* Get the number */
    if (fieldp != NULL) {
	char * end = NULL;

	num = strtoul(fieldp, &end, 10);
	SKIPSPACE(end);
	if (*end != ':') {
	    rpmlog(RPMLOG_ERR, _("line %d: No ':' terminator: %s\n"),
			 spec->lineNum, spec->line);
	    return RPMRC_FAIL;
	}
    }

    /* Check whether tags of the same number haven't already been defined */
    for (p = spec->sources; p != NULL; p = p->next) {
	if ( p->num != num ) continue;
	if ((tag == RPMTAG_SOURCE && p->flags == RPMFILE_SOURCE) ||
	    (tag == RPMTAG_PATCH  && p->flags == RPMFILE_PATCH)) {
		rpmlog(RPMLOG_ERR, _("%s %d defined multiple times\n"), name, num);
		return RPMRC_FAIL;
	    }
    }

    /* Create the entry and link it in */
    p = xmalloc(sizeof(*p));
    p->num = num;
    p->fullSource = xstrdup(field);
    p->flags = flag;
    p->source = strrchr(p->fullSource, '/');
    if (p->source)
	p->source++;
    else
	p->source = p->fullSource;

#if defined(RPM_VENDOR_OPENPKG) /* regular-ordered-sources */
    p->next = NULL;
    p_last = spec->sources;
    while (p_last != NULL && p_last->next != NULL)
        p_last = p_last->next;
    if (p_last != NULL)
        p_last->next = p;
    else
        spec->sources = p;
#else
    p->next = spec->sources;
    spec->sources = p;
#endif

    spec->numSources++;

    /* XXX FIXME: need to add ICON* macros. */
#if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
    mdir = getSourceDir(flag, p->source);
#endif
    if (tag != RPMTAG_ICON) {
	const char *body = rpmGenPath(NULL, mdir, p->source);

	sprintf(buf, "%s%d",
		(flag & RPMFILE_PATCH) ? "PATCH" : "SOURCE", num);
	addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
	sprintf(buf, "%sURL%d",
		(flag & RPMFILE_PATCH) ? "PATCH" : "SOURCE", num);
	addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
#ifdef WITH_LUA
	if (!spec->recursing) {
	    rpmlua lua = NULL; /* global state */
	    const char * what = (flag & RPMFILE_PATCH) ? "patches" : "sources";
	    rpmluav var = rpmluavNew();

	    rpmluaPushTable(lua, what);
	    rpmluavSetListMode(var, 1);
	    rpmluavSetValue(var, RPMLUAV_STRING, body);
	    rpmluaSetVar(lua, var);
/*@-moduncon@*/
	    var = (rpmluav) rpmluavFree(var);
/*@=moduncon@*/
	    rpmluaPop(lua);
	}
#endif
	body = _free(body);
    }
    
    return RPMRC_OK;
}
Exemplo n.º 13
0
static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag,
		const char *macro, const char *lang)
{
    char * field = spec->line;
    char * end;
    int multiToken = 0;
    rpmsenseFlags tagflags = RPMSENSE_ANY;
    rpmRC rc = RPMRC_FAIL;
    
    if (field == NULL) /* XXX can't happen */
	goto exit;
    /* Find the start of the "field" and strip trailing space */
    while ((*field) && (*field != ':'))
	field++;
    if (*field != ':') {
	rpmlog(RPMLOG_ERR, _("line %d: Malformed tag: %s\n"),
		 spec->lineNum, spec->line);
	goto exit;
    }
    field++;
    SKIPSPACE(field);
    if (!*field) {
	/* Empty field */
	rpmlog(RPMLOG_ERR, _("line %d: Empty tag: %s\n"),
		 spec->lineNum, spec->line);
	goto exit;
    }
    end = findLastChar(field);
    *(end+1) = '\0';

    /* See if this is multi-token */
    end = field;
    SKIPNONSPACE(end);
    if (*end != '\0')
	multiToken = 1;

    switch (tag) {
    case RPMTAG_NAME:
	SINGLE_TOKEN_ONLY;
	if (rpmCharCheck(spec, field, WHITELIST_NAME))
	   goto exit;
	headerPutString(pkg->header, tag, field);
	/* Main pkg name is unknown at the start, populate as soon as we can */
	if (pkg == spec->packages)
	    pkg->name = rpmstrPoolId(spec->pool, field, 1);
	break;
    case RPMTAG_VERSION:
    case RPMTAG_RELEASE:
	SINGLE_TOKEN_ONLY;
	if (rpmCharCheck(spec, field, "._+%{}~"))
	   goto exit;
	headerPutString(pkg->header, tag, field);
	break;
    case RPMTAG_URL:
    case RPMTAG_DISTTAG:
    case RPMTAG_BUGURL:
    /* XXX TODO: validate format somehow */
    case RPMTAG_VCS:
	SINGLE_TOKEN_ONLY;
	headerPutString(pkg->header, tag, field);
	break;
    case RPMTAG_GROUP:
    case RPMTAG_SUMMARY:
    case RPMTAG_DISTRIBUTION:
    case RPMTAG_VENDOR:
    case RPMTAG_LICENSE:
    case RPMTAG_PACKAGER:
	if (addLangTag(spec, pkg->header, tag, field, lang))
	    goto exit;
	break;
    case RPMTAG_BUILDROOT:
	/* just silently ignore BuildRoot */
	macro = NULL;
	break;
    case RPMTAG_PREFIXES: {
	struct rpmtd_s td;
	const char *str;
	if (addOrAppendListEntry(pkg->header, tag, field))
	   goto exit;
	headerGet(pkg->header, tag, &td, HEADERGET_MINMEM);
	while ((str = rpmtdNextString(&td))) {
	    size_t len = strlen(str);
	    if (len > 1 && str[len-1] == '/') {
		rpmlog(RPMLOG_ERR,
			 _("line %d: Prefixes must not end with \"/\": %s\n"),
			 spec->lineNum, spec->line);
		rpmtdFreeData(&td);
		goto exit;
	    }
	}
	rpmtdFreeData(&td);
	break;
    }
    case RPMTAG_DOCDIR:
	SINGLE_TOKEN_ONLY;
	if (field[0] != '/') {
	    rpmlog(RPMLOG_ERR, _("line %d: Docdir must begin with '/': %s\n"),
		     spec->lineNum, spec->line);
	    goto exit;
	}
	macro = NULL;
	rpmPopMacro(NULL, "_docdir");
	rpmPushMacro(NULL, "_docdir", NULL, field, RMIL_SPEC);
	break;
    case RPMTAG_EPOCH: {
	SINGLE_TOKEN_ONLY;
	uint32_t epoch;
	if (parseUnsignedNum(field, &epoch)) {
	    rpmlog(RPMLOG_ERR,
		   _("line %d: Epoch field must be an unsigned number: %s\n"),
		   spec->lineNum, spec->line);
	    goto exit;
	}
	headerPutUint32(pkg->header, tag, &epoch, 1);
	break;
    }
    case RPMTAG_AUTOREQPROV:
	pkg->autoReq = parseYesNo(field);
	pkg->autoProv = pkg->autoReq;
	break;
    case RPMTAG_AUTOREQ:
	pkg->autoReq = parseYesNo(field);
	break;
    case RPMTAG_AUTOPROV:
	pkg->autoProv = parseYesNo(field);
	break;
    case RPMTAG_SOURCE:
    case RPMTAG_PATCH:
	macro = NULL;
	if (addSource(spec, pkg, field, tag))
	    goto exit;
	break;
    case RPMTAG_ICON:
	SINGLE_TOKEN_ONLY;
	if (addSource(spec, pkg, field, tag) || readIcon(pkg->header, field))
	    goto exit;
	break;
    case RPMTAG_NOSOURCE:
    case RPMTAG_NOPATCH:
	spec->noSource = 1;
	if (parseNoSource(spec, field, tag))
	    goto exit;
	break;
    case RPMTAG_ORDERFLAGS:
    case RPMTAG_REQUIREFLAGS:
	if (parseBits(lang, installScriptBits, &tagflags)) {
	    rpmlog(RPMLOG_ERR, _("line %d: Bad %s: qualifiers: %s\n"),
		     spec->lineNum, rpmTagGetName(tag), spec->line);
	    goto exit;
	}
	/* fallthrough */
    case RPMTAG_PREREQ:
    case RPMTAG_RECOMMENDFLAGS:
    case RPMTAG_SUGGESTFLAGS:
    case RPMTAG_SUPPLEMENTFLAGS:
    case RPMTAG_ENHANCEFLAGS:
    case RPMTAG_CONFLICTFLAGS:
    case RPMTAG_OBSOLETEFLAGS:
    case RPMTAG_PROVIDEFLAGS:
	if (parseRCPOT(spec, pkg, field, tag, 0, tagflags))
	    goto exit;
	break;
    case RPMTAG_BUILDPREREQ:
    case RPMTAG_BUILDREQUIRES:
    case RPMTAG_BUILDCONFLICTS:
	if (parseRCPOT(spec, spec->sourcePackage, field, tag, 0, tagflags))
	    goto exit;
	break;
    case RPMTAG_EXCLUDEARCH:
    case RPMTAG_EXCLUSIVEARCH:
    case RPMTAG_EXCLUDEOS:
    case RPMTAG_EXCLUSIVEOS:
	if (addOrAppendListEntry(spec->buildRestrictions, tag, field))
	   goto exit;
	break;
    case RPMTAG_BUILDARCHS: {
	int BACount;
	const char **BANames = NULL;
	if (poptParseArgvString(field, &BACount, &BANames)) {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: Bad BuildArchitecture format: %s\n"),
		     spec->lineNum, spec->line);
	    goto exit;
	}
	if (spec->packages == pkg) {
	    if (spec->BANames) {
		rpmlog(RPMLOG_ERR,
		       _("line %d: Duplicate BuildArch entry: %s\n"),
		       spec->lineNum, spec->line);
		BANames = _free(BANames);
		goto exit;
	    }
	    spec->BACount = BACount;
	    spec->BANames = BANames;
	} else {
	    if (BACount != 1 || !rstreq(BANames[0], "noarch")) {
		rpmlog(RPMLOG_ERR,
		     _("line %d: Only noarch subpackages are supported: %s\n"),
		     spec->lineNum, spec->line);
		BANames = _free(BANames);
		goto exit;
	    }
	    headerPutString(pkg->header, RPMTAG_ARCH, "noarch");
	}
	if (!BACount)
	    spec->BANames = _free(spec->BANames);
	break;
    }
    case RPMTAG_REMOVEPATHPOSTFIXES:
	argvSplit(&pkg->removePostfixes, field, ":");
	break;
    default:
	rpmlog(RPMLOG_ERR, _("Internal error: Bogus tag %d\n"), tag);
	goto exit;
    }

    if (macro) {
	rpmPushMacro(spec->macros, macro, NULL, field, RMIL_SPEC);
	/* Add a separate uppercase macro for tags from the main package */
	if (pkg == spec->packages) {
	    char *m = xstrdup(macro);
	    for (char *p = m; *p; ++p)
		*p = rtoupper(*p);
	    rpmPushMacro(spec->macros, m, NULL, field, RMIL_SPEC);
	    free(m);
	}
    }
    rc = RPMRC_OK;
exit:
    return rc;	
}
Exemplo n.º 14
0
Arquivo: r.c Projeto: shigio/ctags
static void createRTags (void)
{
	vString *vLine = vStringNew ();
	vString *name = vStringNew ();
	int ikind;
	const unsigned char *line;

	while ((line = fileReadLine ()) != NULL)
	{
		const unsigned char *cp = (const unsigned char *) line;

		vStringClear (name);
		while ((*cp != '\0') && (*cp != '#'))
		{
			/* iterate to the end of line or to a comment */
			ikind = -1;
			switch (*cp)
			{
			case 'l':
			case 's':
				if (strncasecmp ((const char *) cp, "library", (size_t) 7) == 0)
				{
					/* load a library: library(tools) */
					cp += 7;
					SKIPSPACE (cp);
					if (*cp == '(')
						ikind = K_LIBRARY;
					else
						cp -= 7;
				}
				else if (strncasecmp ((const char *) cp, "source",
						(size_t) 6) == 0)
				{
					/* load a source file: source("myfile.r") */
					cp += 6;
					SKIPSPACE (cp);
					if (*cp == '(')
						ikind = K_SOURCE;
					else
						cp -= 6;
				}
				if (ikind != -1)
				{
					cp++;

					vStringClear (name);
					while ((!isspace ((int) *cp)) && *cp != '\0' && *cp != ')')
					{
						vStringPut (name, (int) *cp);
						cp++;
					}
					vStringTerminate (name);

					/* if the string really exists, make a tag of it */
					if (vStringLength (name) > 0)
						makeRTag (name, ikind);

					/* prepare for the next iteration */
					vStringClear (name);
				}
				else
				{
					vStringPut (name, (int) *cp);
					cp++;
				}
				break;
			case '<':
				cp++;
				if (*cp == '-')
				{
					/* assignment: ident <- someval */
					cp++;
					SKIPSPACE (cp);

					if (*cp == '\0')
					{
						/* not in this line, read next */
						/* sometimes functions are declared this way:
						 * ident <-
						 * function(...)
						 * {
						 * ...
						 * }
						 * I don't know if there is a reason to write the function keyword
						 * in a new line
						 */
						if ((line = fileReadLine ()) != NULL)
						{
							cp = (const unsigned char *) line;
							SKIPSPACE (cp);
						}
					}

					if (strncasecmp ((const char *) cp, "function",
							(size_t) 8) == 0)
					{
						/* it's a function: ident <- function(args) */
						cp += 8;
						vStringTerminate (name);
						/* if the string really exists, make a tag of it */
						if (vStringLength (name) > 0)
							makeRTag (name, K_FUNCTION);

						/* prepare for the next iteration */
						vStringClear (name);
						break;
					}
					else
					{
						/* it's a variable: ident <- value */
						vStringTerminate (name);
						/* if the string really exists, make a tag of it */
						if (vStringLength (name) > 0)
						{
							if (line[0] == ' ' || line[0] == '\t')
								makeRTag (name, K_FUNCVAR);
							else
								makeRTag (name, K_GLOBALVAR);
						}

						/* prepare for the next iteration */
						vStringClear (name);
						break;
					}
				}
			case ' ':
			case '\x009':
				/* skip whitespace */
				cp++;
				break;
			default:
				/* collect all characters that could be a part of an identifier */
				vStringPut (name, (int) *cp);
				cp++;
				break;
			}
		}
	}

	vStringDelete (name);
	vStringDelete (vLine);
}
Exemplo n.º 15
0
/**
 * Parses attributes from opening text of the tag. This function does nothing
 * when node type is different from tag. The parser tries to be as tolerant
 * as possible (unquoted attribute values, extra spaces ...). When attribute
 * with no value is found (common in HTML, not in XHTML), its value is set
 * to its name (to ensure forward compatibility - e.g. in option tag it is
 * common to use <code>selected="selected"</code> in XHTML instead of
 * <code>selected</code> in HTML).
 * 
 */
void HtmlNode::parseAttributes(bool normalizeAttributes) {
	#define SKIPSPACE(ptr) while (isspace(*ptr)) ptr++
	if (type != TAG) {
		return;
	}
	
	if (attributesParsed_) {
		return;
	}
	
	const char *ptr = openingText_.c_str();
	if ((ptr = strchr(ptr, '<')) == 0) {
		return; // no <, probably something weird is going on...
	}
	ptr++;
	SKIPSPACE(ptr);
	
	// here shall be the tag name (which shall be skipped
	// as well as following blanks
	if (!isalpha(*ptr)) {
		return;
	}
	while (isalnum(*ptr)) {
		ptr++;
	}
	SKIPSPACE(ptr);
		
	// iterate through attributes
	while (*ptr && (*ptr != '>')) {
		const char * attrStart;
	
		// skip garbage before attribute name
		while (*ptr && !isalpha(*ptr)) {
			ptr++;
		}		
		if (*ptr == 0) {
			return;
		}
		
		// read in attribute name
		attrStart = ptr++;
		while (*ptr && (isalnum(*ptr) || (*ptr == '-'))) {
			ptr++;
		}
		if (*ptr == 0) {
			return;
		}
		std::string key(attrStart, ptr - attrStart);
		
		// skip '=' and spaces
		bool foundAssign = false;
		while (*ptr && (isspace(*ptr) || ((*ptr == '=') && (foundAssign=true)))) {
			ptr++;
		}
		if (*ptr == 0) {
			return;
		}
		
		// find the attribute value
		std::string val;
		if (!foundAssign) {
			// attribute without value
			// by this we somehow ensure compatibility (fingers crossed)
			// FIXME - how about extra parameter for this
			val = key;
		} else {
			char quitchar = 0;
			const char * start;
			if ((*ptr == '"') || (*ptr == '\'')) {
				quitchar = *ptr;
				start = ++ptr;
			} else {
				start = ptr;
			}
			// FIXME - how is it with escaped quotes?
			while (*ptr && (
					((quitchar == 0) && (!isspace(*ptr))) ||
					(quitchar && (*ptr != quitchar))
				)) {
				ptr++;
			}
			if (*ptr == 0) {
				return;
			}
			val = std::string(start, ptr - start);
			ptr++; //skip the space or the quote
		}
		
		// normalize (attribute name to lower case)
		if (normalizeAttributes) {
			// transform would be ideal here, thought it may not be
			// portable, so let's do it the ugly way
			// (see http://bytes.com/groups/c/60652-tolower-used-transform)
			std::string::iterator e = key.end();
			for (std::string::iterator it = key.begin(); it != e; ++it) {
				*it = tolower(*it);
			}
		}
				
		// store the attribute
		attributes_[key] = val;
	}
	
	attributesParsed_ = true;
	#undef SKIPSPACE
}
Exemplo n.º 16
0
/* read XPM from either array or RWops */
static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src)
{
    Sint64 start = 0;
    SDL_Surface *image = NULL;
    int index;
    int x, y;
    int w, h, ncolors, cpp;
    int indexed;
    Uint8 *dst;
    struct color_hash *colors = NULL;
    SDL_Color *im_colors = NULL;
    char *keystrings = NULL, *nextkey;
    char *line;
    char ***xpmlines = NULL;
    int pixels_len;

    error = NULL;
    linebuf = NULL;
    buflen = 0;

    if (src)
        start = SDL_RWtell(src);

    if (xpm)
        xpmlines = &xpm;

    line = get_next_line(xpmlines, src, 0);
    if (!line)
        goto done;
    /*
     * The header string of an XPMv3 image has the format
     *
     * <width> <height> <ncolors> <cpp> [ <hotspot_x> <hotspot_y> ]
     *
     * where the hotspot coords are intended for mouse cursors.
     * Right now we don't use the hotspots but it should be handled
     * one day.
     */
    if (SDL_sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4
       || w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) {
        error = "Invalid format description";
        goto done;
    }

    keystrings = (char *)SDL_malloc(ncolors * cpp);
    if (!keystrings) {
        error = "Out of memory";
        goto done;
    }
    nextkey = keystrings;

    /* Create the new surface */
    if (ncolors <= 256) {
        indexed = 1;
        image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8,
                         0, 0, 0, 0);
        im_colors = image->format->palette->colors;
        image->format->palette->ncolors = ncolors;
    } else {
        indexed = 0;
        image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
                         0xff0000, 0x00ff00, 0x0000ff, 0);
    }
    if (!image) {
        /* Hmm, some SDL error (out of memory?) */
        goto done;
    }

    /* Read the colors */
    colors = create_colorhash(ncolors);
    if (!colors) {
        error = "Out of memory";
        goto done;
    }
    for (index = 0; index < ncolors; ++index ) {
        char *p;
        line = get_next_line(xpmlines, src, 0);
        if (!line)
            goto done;

        p = line + cpp + 1;

        /* parse a colour definition */
        for (;;) {
            char nametype;
            char *colname;
            Uint32 rgb, pixel;

            SKIPSPACE(p);
            if (!*p) {
                error = "colour parse error";
                goto done;
            }
            nametype = *p;
            SKIPNONSPACE(p);
            SKIPSPACE(p);
            colname = p;
            SKIPNONSPACE(p);
            if (nametype == 's')
                continue;      /* skip symbolic colour names */

            if (!color_to_rgb(colname, p - colname, &rgb))
                continue;

            SDL_memcpy(nextkey, line, cpp);
            if (indexed) {
                SDL_Color *c = im_colors + index;
                c->r = (Uint8)(rgb >> 16);
                c->g = (Uint8)(rgb >> 8);
                c->b = (Uint8)(rgb);
                pixel = index;
            } else
                pixel = rgb;
            add_colorhash(colors, nextkey, cpp, pixel);
            nextkey += cpp;
            if (rgb == 0xffffffff)
                SDL_SetColorKey(image, SDL_TRUE, pixel);
            break;
        }
    }
Exemplo n.º 17
0
int parsePreamble(rpmSpec spec, int initialPackage)
{
    int nextPart = PART_ERROR;
    int res = PART_ERROR; /* assume failure */
    int rc;
    char *name, *linep;
    int flag = 0;
    Package pkg;
    char *NVR = NULL;
    char lang[BUFSIZ];

    if (! initialPackage) {
	/* There is one option to %package: <pkg> or -n <pkg> */
	if (parseSimplePart(spec->line, &name, &flag)) {
	    rpmlog(RPMLOG_ERR, _("Bad package specification: %s\n"),
			spec->line);
	    goto exit;
	}

	if (rpmCharCheck(spec, name, WHITELIST_NAME))
	    goto exit;
	
	if (!lookupPackage(spec, name, flag, NULL)) {
	    free(name);
	    goto exit;
	}
	
	/* Construct the package */
	if (flag == PART_SUBNAME) {
	    rasprintf(&NVR, "%s-%s", 
		    headerGetString(spec->packages->header, RPMTAG_NAME), name);
	} else
	    NVR = xstrdup(name);
	free(name);
	pkg = newPackage(NVR, spec->pool, &spec->packages);
	headerPutString(pkg->header, RPMTAG_NAME, NVR);
    } else {
	NVR = xstrdup("(main package)");
	pkg = newPackage(NULL, spec->pool, &spec->packages);
	spec->sourcePackage = newPackage(NULL, spec->pool, NULL);
	
    }

    if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
	nextPart = PART_NONE;
    } else if (rc < 0) {
	goto exit;
    } else {
	while (! (nextPart = isPart(spec->line))) {
	    const char * macro;
	    rpmTagVal tag;

	    /* Skip blank lines */
	    linep = spec->line;
	    SKIPSPACE(linep);
	    if (*linep != '\0') {
		if (findPreambleTag(spec, &tag, &macro, lang)) {
		    if (spec->lineNum == 1 &&
			(unsigned char)(spec->line[0]) == 0xed &&
			(unsigned char)(spec->line[1]) == 0xab &&
			(unsigned char)(spec->line[2]) == 0xee &&
			(unsigned char)(spec->line[3]) == 0xdb) {
			rpmlog(RPMLOG_ERR, _("Binary rpm package found. Expected spec file!\n"));
			goto exit;
		    }
		    rpmlog(RPMLOG_ERR, _("line %d: Unknown tag: %s\n"),
				spec->lineNum, spec->line);
		    goto exit;
		}
		if (handlePreambleTag(spec, pkg, tag, macro, lang)) {
		    goto exit;
		}
		if (spec->BANames && !spec->recursing) {
		    res = PART_BUILDARCHITECTURES;
		    goto exit;
		}
	    }
	    if ((rc =
		 readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
		nextPart = PART_NONE;
		break;
	    }
	    if (rc) {
		goto exit;
	    }
	}
    }

    /* 
     * Expand buildroot one more time to get %{version} and the like
     * from the main package, validate sanity. The spec->buildRoot could
     * still contain unexpanded macros but it cannot be empty or '/', and it
     * can't be messed with by anything spec does beyond this point.
     */
    if (initialPackage) {
	char *buildRoot = rpmGetPath(spec->buildRoot, NULL);
	if (*buildRoot == '\0') {
	    rpmlog(RPMLOG_ERR, _("%%{buildroot} couldn't be empty\n"));
	    goto exit;
	}
	if (rstreq(buildRoot, "/")) {
	    rpmlog(RPMLOG_ERR, _("%%{buildroot} can not be \"/\"\n"));
	    goto exit;
	}
	free(spec->buildRoot);
	spec->buildRoot = buildRoot;
	rpmPushMacro(spec->macros, "buildroot", NULL, spec->buildRoot, RMIL_SPEC);
    }

    /* XXX Skip valid arch check if not building binary package */
    if (!(spec->flags & RPMSPEC_ANYARCH) && checkForValidArchitectures(spec)) {
	goto exit;
    }

    /* It is the main package */
    if (pkg == spec->packages) {
	fillOutMainPackage(pkg->header);
	/* Define group tag to something when group is undefined in main package*/
	if (!headerIsEntry(pkg->header, RPMTAG_GROUP)) {
	    headerPutString(pkg->header, RPMTAG_GROUP, "Unspecified");
	}
    }

    if (checkForDuplicates(pkg->header, NVR)) {
	goto exit;
    }

    if (pkg != spec->packages) {
	headerCopyTags(spec->packages->header, pkg->header,
			(rpmTagVal *)copyTagsDuringParse);
    }

    if (checkForRequired(pkg->header, NVR)) {
	goto exit;
    }

    /* if we get down here nextPart has been set to non-error */
    res = nextPart;

exit:
    free(NVR);
    return res;
}