rpm
4.5
|
00001 00006 #include "system.h" 00007 00008 #define _RPMEVR_INTERNAL 00009 #include "rpmbuild.h" 00010 #include "debug.h" 00011 00012 #include <rpmlua.h> 00013 00014 /*@access StringBuf@*/ /* XXX compared with NULL */ 00015 /*@access poptContext @*/ /* compared with NULL */ 00016 00019 static int addTriggerIndex(Package pkg, const char *file, 00020 const char *script, const char *prog) 00021 /*@modifies pkg->triggerFiles @*/ 00022 { 00023 struct TriggerFileEntry *tfe; 00024 struct TriggerFileEntry *list = pkg->triggerFiles; 00025 struct TriggerFileEntry *last = NULL; 00026 int index = 0; 00027 00028 while (list) { 00029 last = list; 00030 list = list->next; 00031 } 00032 00033 if (last) 00034 index = last->index + 1; 00035 00036 tfe = xcalloc(1, sizeof(*tfe)); 00037 00038 tfe->fileName = (file) ? xstrdup(file) : NULL; 00039 tfe->script = (script && *script != '\0') ? xstrdup(script) : NULL; 00040 tfe->prog = xstrdup(prog); 00041 tfe->index = index; 00042 tfe->next = NULL; 00043 00044 if (last) 00045 last->next = tfe; 00046 else 00047 pkg->triggerFiles = tfe; 00048 00049 return index; 00050 } 00051 00052 /* these have to be global because of stupid compilers */ 00053 /*@unchecked@*/ 00054 /*@observer@*/ /*@null@*/ static const char *name = NULL; 00055 /*@unchecked@*/ 00056 /*@observer@*/ /*@null@*/ static const char *prog = NULL; 00057 /*@unchecked@*/ 00058 /*@observer@*/ /*@null@*/ static const char *file = NULL; 00059 /*@unchecked@*/ 00060 static struct poptOption optionsTable[] = { 00061 { NULL, 'p', POPT_ARG_STRING, &prog, 'p', NULL, NULL}, 00062 { NULL, 'n', POPT_ARG_STRING, &name, 'n', NULL, NULL}, 00063 { NULL, 'f', POPT_ARG_STRING, &file, 'f', NULL, NULL}, 00064 { 0, 0, 0, 0, 0, NULL, NULL} 00065 }; 00066 00067 /* %trigger is a strange combination of %pre and Requires: behavior */ 00068 /* We can handle it by parsing the args before "--" in parseScript. */ 00069 /* We then pass the remaining arguments to parseRCPOT, along with */ 00070 /* an index we just determined. */ 00071 00072 /*@-boundswrite@*/ 00073 int parseScript(Spec spec, int parsePart) 00074 { 00075 /* There are a few options to scripts: */ 00076 /* <pkg> */ 00077 /* -n <pkg> */ 00078 /* -p <sh> */ 00079 /* -p "<sh> <args>..." */ 00080 /* -f <file> */ 00081 00082 char *p; 00083 const char **progArgv = NULL; 00084 int progArgc; 00085 char *partname = NULL; 00086 rpmTag reqtag = 0; 00087 rpmTag tag = 0; 00088 int tagflags = 0; 00089 rpmTag progtag = 0; 00090 int flag = PART_SUBNAME; 00091 Package pkg; 00092 StringBuf sb = NULL; 00093 int nextPart; 00094 int index; 00095 char reqargs[BUFSIZ]; 00096 00097 int rc, argc; 00098 int arg; 00099 const char **argv = NULL; 00100 poptContext optCon = NULL; 00101 00102 reqargs[0] = '\0'; 00103 /*@-mods@*/ 00104 name = NULL; 00105 prog = "/bin/sh"; 00106 file = NULL; 00107 /*@=mods@*/ 00108 00109 /*@-branchstate@*/ 00110 switch (parsePart) { 00111 case PART_PRE: 00112 tag = RPMTAG_PREIN; 00113 tagflags = RPMSENSE_SCRIPT_PRE; 00114 progtag = RPMTAG_PREINPROG; 00115 partname = "%pre"; 00116 break; 00117 case PART_POST: 00118 tag = RPMTAG_POSTIN; 00119 tagflags = RPMSENSE_SCRIPT_POST; 00120 progtag = RPMTAG_POSTINPROG; 00121 partname = "%post"; 00122 break; 00123 case PART_PREUN: 00124 tag = RPMTAG_PREUN; 00125 tagflags = RPMSENSE_SCRIPT_PREUN; 00126 progtag = RPMTAG_PREUNPROG; 00127 partname = "%preun"; 00128 break; 00129 case PART_POSTUN: 00130 tag = RPMTAG_POSTUN; 00131 tagflags = RPMSENSE_SCRIPT_POSTUN; 00132 progtag = RPMTAG_POSTUNPROG; 00133 partname = "%postun"; 00134 break; 00135 case PART_PRETRANS: 00136 tag = RPMTAG_PRETRANS; 00137 tagflags = 0; 00138 progtag = RPMTAG_PRETRANSPROG; 00139 partname = "%pretrans"; 00140 break; 00141 case PART_POSTTRANS: 00142 tag = RPMTAG_POSTTRANS; 00143 tagflags = 0; 00144 progtag = RPMTAG_POSTTRANSPROG; 00145 partname = "%posttrans"; 00146 break; 00147 case PART_VERIFYSCRIPT: 00148 tag = RPMTAG_VERIFYSCRIPT; 00149 tagflags = RPMSENSE_SCRIPT_VERIFY; 00150 progtag = RPMTAG_VERIFYSCRIPTPROG; 00151 partname = "%verifyscript"; 00152 break; 00153 case PART_TRIGGERPREIN: 00154 tag = RPMTAG_TRIGGERSCRIPTS; 00155 tagflags = 0; 00156 reqtag = RPMTAG_TRIGGERPREIN; 00157 progtag = RPMTAG_TRIGGERSCRIPTPROG; 00158 partname = "%triggerprein"; 00159 break; 00160 case PART_TRIGGERIN: 00161 tag = RPMTAG_TRIGGERSCRIPTS; 00162 tagflags = 0; 00163 reqtag = RPMTAG_TRIGGERIN; 00164 progtag = RPMTAG_TRIGGERSCRIPTPROG; 00165 partname = "%triggerin"; 00166 break; 00167 case PART_TRIGGERUN: 00168 tag = RPMTAG_TRIGGERSCRIPTS; 00169 tagflags = 0; 00170 reqtag = RPMTAG_TRIGGERUN; 00171 progtag = RPMTAG_TRIGGERSCRIPTPROG; 00172 partname = "%triggerun"; 00173 break; 00174 case PART_TRIGGERPOSTUN: 00175 tag = RPMTAG_TRIGGERSCRIPTS; 00176 tagflags = 0; 00177 reqtag = RPMTAG_TRIGGERPOSTUN; 00178 progtag = RPMTAG_TRIGGERSCRIPTPROG; 00179 partname = "%triggerpostun"; 00180 break; 00181 } 00182 /*@=branchstate@*/ 00183 00184 if (tag == RPMTAG_TRIGGERSCRIPTS) { 00185 /* break line into two */ 00186 p = strstr(spec->line, "--"); 00187 if (!p) { 00188 rpmError(RPMERR_BADSPEC, _("line %d: triggers must have --: %s\n"), 00189 spec->lineNum, spec->line); 00190 return RPMERR_BADSPEC; 00191 } 00192 00193 *p = '\0'; 00194 strcpy(reqargs, p + 2); 00195 } 00196 00197 if ((rc = poptParseArgvString(spec->line, &argc, &argv))) { 00198 rpmError(RPMERR_BADSPEC, _("line %d: Error parsing %s: %s\n"), 00199 spec->lineNum, partname, poptStrerror(rc)); 00200 return RPMERR_BADSPEC; 00201 } 00202 00203 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); 00204 while ((arg = poptGetNextOpt(optCon)) > 0) { 00205 switch (arg) { 00206 case 'p': 00207 if (prog[0] == '<') { 00208 if (prog[strlen(prog)-1] != '>') { 00209 rpmError(RPMERR_BADSPEC, 00210 _("line %d: internal script must end " 00211 "with \'>\': %s\n"), spec->lineNum, prog); 00212 rc = RPMERR_BADSPEC; 00213 goto exit; 00214 } 00215 } else if (prog[0] == '%') { 00216 /* XXX check well-formed macro? */ 00217 } else if (prog[0] != '/') { 00218 rpmError(RPMERR_BADSPEC, 00219 _("line %d: script program must begin " 00220 "with \'/\': %s\n"), spec->lineNum, prog); 00221 rc = RPMERR_BADSPEC; 00222 goto exit; 00223 } 00224 /*@switchbreak@*/ break; 00225 case 'n': 00226 flag = PART_NAME; 00227 /*@switchbreak@*/ break; 00228 } 00229 } 00230 00231 if (arg < -1) { 00232 rpmError(RPMERR_BADSPEC, _("line %d: Bad option %s: %s\n"), 00233 spec->lineNum, 00234 poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 00235 spec->line); 00236 rc = RPMERR_BADSPEC; 00237 goto exit; 00238 } 00239 00240 if (poptPeekArg(optCon)) { 00241 /*@-mods@*/ 00242 if (name == NULL) 00243 name = poptGetArg(optCon); 00244 /*@=mods@*/ 00245 if (poptPeekArg(optCon)) { 00246 rpmError(RPMERR_BADSPEC, _("line %d: Too many names: %s\n"), 00247 spec->lineNum, 00248 spec->line); 00249 rc = RPMERR_BADSPEC; 00250 goto exit; 00251 } 00252 } 00253 00254 if (lookupPackage(spec, name, flag, &pkg)) { 00255 rpmError(RPMERR_BADSPEC, _("line %d: Package does not exist: %s\n"), 00256 spec->lineNum, spec->line); 00257 rc = RPMERR_BADSPEC; 00258 goto exit; 00259 } 00260 00261 if (tag != RPMTAG_TRIGGERSCRIPTS) { 00262 if (headerIsEntry(pkg->header, progtag)) { 00263 rpmError(RPMERR_BADSPEC, _("line %d: Second %s\n"), 00264 spec->lineNum, partname); 00265 rc = RPMERR_BADSPEC; 00266 goto exit; 00267 } 00268 } 00269 00270 if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) { 00271 rpmError(RPMERR_BADSPEC, _("line %d: Error parsing %s: %s\n"), 00272 spec->lineNum, partname, poptStrerror(rc)); 00273 rc = RPMERR_BADSPEC; 00274 goto exit; 00275 } 00276 00277 sb = newStringBuf(); 00278 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { 00279 nextPart = PART_NONE; 00280 } else { 00281 if (rc) 00282 goto exit; 00283 while (! (nextPart = isPart(spec->line))) { 00284 appendStringBuf(sb, spec->line); 00285 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { 00286 nextPart = PART_NONE; 00287 break; 00288 } 00289 if (rc) 00290 goto exit; 00291 } 00292 } 00293 stripTrailingBlanksStringBuf(sb); 00294 p = getStringBuf(sb); 00295 00296 #ifdef WITH_LUA 00297 if (!strcmp(progArgv[0], "<lua>")) { 00298 rpmlua lua = NULL; /* Global state. */ 00299 if (rpmluaCheckScript(lua, p, partname) != RPMRC_OK) { 00300 rc = RPMERR_BADSPEC; 00301 goto exit; 00302 } 00303 (void) rpmlibNeedsFeature(pkg->header, 00304 "BuiltinLuaScripts", "4.2.2-1"); 00305 } else 00306 #endif 00307 if (progArgv[0][0] == '<') { 00308 rpmError(RPMERR_BADSPEC, 00309 _("line %d: unsupported internal script: %s\n"), 00310 spec->lineNum, progArgv[0]); 00311 rc = RPMERR_BADSPEC; 00312 goto exit; 00313 } else { 00314 (void) addReqProv(spec, pkg->header, RPMTAG_REQUIRENAME, 00315 progArgv[0], NULL, (tagflags | RPMSENSE_INTERP), 0); 00316 } 00317 00318 /* Trigger script insertion is always delayed in order to */ 00319 /* get the index right. */ 00320 if (tag == RPMTAG_TRIGGERSCRIPTS) { 00321 /* Add file/index/prog triple to the trigger file list */ 00322 index = addTriggerIndex(pkg, file, p, progArgv[0]); 00323 00324 /* Generate the trigger tags */ 00325 if ((rc = parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags))) 00326 goto exit; 00327 } else { 00328 if (progArgc == 1) 00329 (void) headerAddEntry(pkg->header, progtag, RPM_STRING_TYPE, 00330 *progArgv, progArgc); 00331 else { 00332 (void) rpmlibNeedsFeature(pkg->header, 00333 "ScriptletInterpreterArgs", "4.0.3-1"); 00334 (void) headerAddEntry(pkg->header, progtag, RPM_STRING_ARRAY_TYPE, 00335 progArgv, progArgc); 00336 } 00337 00338 if (*p != '\0') 00339 (void) headerAddEntry(pkg->header, tag, RPM_STRING_TYPE, p, 1); 00340 00341 if (file) { 00342 switch (parsePart) { 00343 case PART_PRE: 00344 pkg->preInFile = xstrdup(file); 00345 break; 00346 case PART_POST: 00347 pkg->postInFile = xstrdup(file); 00348 break; 00349 case PART_PREUN: 00350 pkg->preUnFile = xstrdup(file); 00351 break; 00352 case PART_POSTUN: 00353 pkg->postUnFile = xstrdup(file); 00354 break; 00355 case PART_PRETRANS: 00356 pkg->preTransFile = xstrdup(file); 00357 break; 00358 case PART_POSTTRANS: 00359 pkg->postTransFile = xstrdup(file); 00360 break; 00361 case PART_VERIFYSCRIPT: 00362 pkg->verifyFile = xstrdup(file); 00363 break; 00364 } 00365 } 00366 } 00367 rc = nextPart; 00368 00369 exit: 00370 sb = freeStringBuf(sb); 00371 progArgv = _free(progArgv); 00372 argv = _free(argv); 00373 optCon = poptFreeContext(optCon); 00374 00375 return rc; 00376 } 00377 /*@=boundswrite@*/