00001
00006 #include "system.h"
00007
00008 #include "rpmbuild.h"
00009 #include "debug.h"
00010
00011
00012
00013
00016 static int addTriggerIndex(Package pkg, const char *file,
00017 const char *script, const char *prog)
00018
00019 {
00020 struct TriggerFileEntry *tfe;
00021 struct TriggerFileEntry *list = pkg->triggerFiles;
00022 struct TriggerFileEntry *last = NULL;
00023 int index = 0;
00024
00025 while (list) {
00026 last = list;
00027 list = list->next;
00028 }
00029
00030 if (last)
00031 index = last->index + 1;
00032
00033 tfe = xcalloc(1, sizeof(*tfe));
00034
00035 tfe->fileName = (file) ? xstrdup(file) : NULL;
00036 tfe->script = (script && *script != '\0') ? xstrdup(script) : NULL;
00037 tfe->prog = xstrdup(prog);
00038 tfe->index = index;
00039 tfe->next = NULL;
00040
00041 if (last)
00042 last->next = tfe;
00043 else
00044 pkg->triggerFiles = tfe;
00045
00046 return index;
00047 }
00048
00049
00050
00051 static const char *name = NULL;
00052
00053 static const char *prog = NULL;
00054
00055 static const char *file = NULL;
00056
00057 static struct poptOption optionsTable[] = {
00058 { NULL, 'p', POPT_ARG_STRING, &prog, 'p', NULL, NULL},
00059 { NULL, 'n', POPT_ARG_STRING, &name, 'n', NULL, NULL},
00060 { NULL, 'f', POPT_ARG_STRING, &file, 'f', NULL, NULL},
00061 { 0, 0, 0, 0, 0, NULL, NULL}
00062 };
00063
00064
00065
00066
00067
00068
00069 int parseScript(Spec spec, int parsePart)
00070 {
00071
00072
00073
00074
00075
00076
00077
00078 char *p;
00079 const char **progArgv = NULL;
00080 int progArgc;
00081 char *partname = NULL;
00082 int reqtag = 0;
00083 int tag = 0;
00084 int tagflags = 0;
00085 int progtag = 0;
00086 int flag = PART_SUBNAME;
00087 Package pkg;
00088 StringBuf sb = NULL;
00089 int nextPart;
00090 int index;
00091 char reqargs[BUFSIZ];
00092
00093 int rc, argc;
00094 int arg;
00095 const char **argv = NULL;
00096 poptContext optCon = NULL;
00097
00098 reqargs[0] = '\0';
00099
00100 name = NULL;
00101 prog = "/bin/sh";
00102 file = NULL;
00103
00104
00105
00106 switch (parsePart) {
00107 case PART_PRE:
00108 tag = RPMTAG_PREIN;
00109 tagflags = RPMSENSE_SCRIPT_PRE;
00110 progtag = RPMTAG_PREINPROG;
00111 partname = "%pre";
00112 break;
00113 case PART_POST:
00114 tag = RPMTAG_POSTIN;
00115 tagflags = RPMSENSE_SCRIPT_POST;
00116 progtag = RPMTAG_POSTINPROG;
00117 partname = "%post";
00118 break;
00119 case PART_PREUN:
00120 tag = RPMTAG_PREUN;
00121 tagflags = RPMSENSE_SCRIPT_PREUN;
00122 progtag = RPMTAG_PREUNPROG;
00123 partname = "%preun";
00124 break;
00125 case PART_POSTUN:
00126 tag = RPMTAG_POSTUN;
00127 tagflags = RPMSENSE_SCRIPT_POSTUN;
00128 progtag = RPMTAG_POSTUNPROG;
00129 partname = "%postun";
00130 break;
00131 case PART_VERIFYSCRIPT:
00132 tag = RPMTAG_VERIFYSCRIPT;
00133 tagflags = RPMSENSE_SCRIPT_VERIFY;
00134 progtag = RPMTAG_VERIFYSCRIPTPROG;
00135 partname = "%verifyscript";
00136 break;
00137 case PART_TRIGGERIN:
00138 tag = RPMTAG_TRIGGERSCRIPTS;
00139 tagflags = 0;
00140 reqtag = RPMTAG_TRIGGERIN;
00141 progtag = RPMTAG_TRIGGERSCRIPTPROG;
00142 partname = "%triggerin";
00143 break;
00144 case PART_TRIGGERUN:
00145 tag = RPMTAG_TRIGGERSCRIPTS;
00146 tagflags = 0;
00147 reqtag = RPMTAG_TRIGGERUN;
00148 progtag = RPMTAG_TRIGGERSCRIPTPROG;
00149 partname = "%triggerun";
00150 break;
00151 case PART_TRIGGERPOSTUN:
00152 tag = RPMTAG_TRIGGERSCRIPTS;
00153 tagflags = 0;
00154 reqtag = RPMTAG_TRIGGERPOSTUN;
00155 progtag = RPMTAG_TRIGGERSCRIPTPROG;
00156 partname = "%triggerpostun";
00157 break;
00158 }
00159
00160
00161 if (tag == RPMTAG_TRIGGERSCRIPTS) {
00162
00163 p = strstr(spec->line, "--");
00164 if (!p) {
00165 rpmError(RPMERR_BADSPEC, _("line %d: triggers must have --: %s\n"),
00166 spec->lineNum, spec->line);
00167 return RPMERR_BADSPEC;
00168 }
00169
00170 *p = '\0';
00171 strcpy(reqargs, p + 2);
00172 }
00173
00174 if ((rc = poptParseArgvString(spec->line, &argc, &argv))) {
00175 rpmError(RPMERR_BADSPEC, _("line %d: Error parsing %s: %s\n"),
00176 spec->lineNum, partname, poptStrerror(rc));
00177 return RPMERR_BADSPEC;
00178 }
00179
00180 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
00181 while ((arg = poptGetNextOpt(optCon)) > 0) {
00182 switch (arg) {
00183 case 'p':
00184 if (prog[0] != '/') {
00185 rpmError(RPMERR_BADSPEC,
00186 _("line %d: script program must begin "
00187 "with \'/\': %s\n"), spec->lineNum, prog);
00188 rc = RPMERR_BADSPEC;
00189 goto exit;
00190 }
00191 break;
00192 case 'n':
00193 flag = PART_NAME;
00194 break;
00195 }
00196 }
00197
00198 if (arg < -1) {
00199 rpmError(RPMERR_BADSPEC, _("line %d: Bad option %s: %s\n"),
00200 spec->lineNum,
00201 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
00202 spec->line);
00203 rc = RPMERR_BADSPEC;
00204 goto exit;
00205 }
00206
00207 if (poptPeekArg(optCon)) {
00208
00209 if (name == NULL)
00210 name = poptGetArg(optCon);
00211
00212 if (poptPeekArg(optCon)) {
00213 rpmError(RPMERR_BADSPEC, _("line %d: Too many names: %s\n"),
00214 spec->lineNum,
00215 spec->line);
00216 rc = RPMERR_BADSPEC;
00217 goto exit;
00218 }
00219 }
00220
00221 if (lookupPackage(spec, name, flag, &pkg)) {
00222 rpmError(RPMERR_BADSPEC, _("line %d: Package does not exist: %s\n"),
00223 spec->lineNum, spec->line);
00224 rc = RPMERR_BADSPEC;
00225 goto exit;
00226 }
00227
00228 if (tag != RPMTAG_TRIGGERSCRIPTS) {
00229 if (headerIsEntry(pkg->header, progtag)) {
00230 rpmError(RPMERR_BADSPEC, _("line %d: Second %s\n"),
00231 spec->lineNum, partname);
00232 rc = RPMERR_BADSPEC;
00233 goto exit;
00234 }
00235 }
00236
00237 if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) {
00238 rpmError(RPMERR_BADSPEC, _("line %d: Error parsing %s: %s\n"),
00239 spec->lineNum, partname, poptStrerror(rc));
00240 rc = RPMERR_BADSPEC;
00241 goto exit;
00242 }
00243
00244 sb = newStringBuf();
00245 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
00246 nextPart = PART_NONE;
00247 } else {
00248 if (rc)
00249 goto exit;
00250 while (! (nextPart = isPart(spec->line))) {
00251 appendStringBuf(sb, spec->line);
00252 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
00253 nextPart = PART_NONE;
00254 break;
00255 }
00256 if (rc)
00257 goto exit;
00258 }
00259 }
00260 stripTrailingBlanksStringBuf(sb);
00261 p = getStringBuf(sb);
00262
00263 (void) addReqProv(spec, pkg->header, (tagflags | RPMSENSE_INTERP), progArgv[0], NULL, 0);
00264
00265
00266
00267 if (tag == RPMTAG_TRIGGERSCRIPTS) {
00268
00269 index = addTriggerIndex(pkg, file, p, progArgv[0]);
00270
00271
00272 if ((rc = parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags)))
00273 goto exit;
00274 } else {
00275 if (progArgc == 1)
00276 (void) headerAddEntry(pkg->header, progtag, RPM_STRING_TYPE,
00277 *progArgv, progArgc);
00278 else {
00279 (void) rpmlibNeedsFeature(pkg->header,
00280 "ScriptletInterpreterArgs", "4.0.3-1");
00281 (void) headerAddEntry(pkg->header, progtag, RPM_STRING_ARRAY_TYPE,
00282 progArgv, progArgc);
00283 }
00284
00285 if (*p != '\0')
00286 (void) headerAddEntry(pkg->header, tag, RPM_STRING_TYPE, p, 1);
00287
00288 if (file) {
00289 switch (parsePart) {
00290 case PART_PRE:
00291 pkg->preInFile = xstrdup(file);
00292 break;
00293 case PART_POST:
00294 pkg->postInFile = xstrdup(file);
00295 break;
00296 case PART_PREUN:
00297 pkg->preUnFile = xstrdup(file);
00298 break;
00299 case PART_POSTUN:
00300 pkg->postUnFile = xstrdup(file);
00301 break;
00302 case PART_VERIFYSCRIPT:
00303 pkg->verifyFile = xstrdup(file);
00304 break;
00305 }
00306 }
00307 }
00308 rc = nextPart;
00309
00310 exit:
00311 sb = freeStringBuf(sb);
00312 progArgv = _free(progArgv);
00313 argv = _free(argv);
00314 optCon = poptFreeContext(optCon);
00315
00316 return rc;
00317 }