00001
00005 #include "system.h"
00006 #include <stdarg.h>
00007
00008 #if !defined(isblank)
00009 #define isblank(_c) ((char)(_c) == ' ' || (char)(_c) == '\t')
00010 #endif
00011 #define iseol(_c) ((char)(_c) == '\n' || (char)(_c) == '\r')
00012
00013 #define STREQ(_t, _f, _fn) ((_fn) == (sizeof(_t)-1) && !strncmp((_t), (_f), (_fn)))
00014
00015 #ifdef DEBUG_MACROS
00016 #undef WITH_LUA
00017 #include <sys/types.h>
00018 #include <errno.h>
00019 #include <fcntl.h>
00020 #include <getopt.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <ctype.h>
00025 #define rpmlog fprintf
00026 #define RPMLOG_ERR stderr
00027 #undef _
00028 #define _(x) x
00029
00030 #define vmefail(_nb) (exit(1), NULL)
00031 #define URL_IS_DASH 1
00032 #define URL_IS_PATH 2
00033 #define urlPath(_xr, _r) (*(_r) = (_xr), URL_IS_PATH)
00034 #define xisalnum(_c) isalnum(_c)
00035 #define xisalpha(_c) isalpha(_c)
00036 #define xisdigit(_c) isdigit(_c)
00037
00038 typedef FILE * FD_t;
00039 #define Fopen(_path, _fmode) fopen(_path, "r");
00040 #define Ferror ferror
00041 #define Fstrerror(_fd) strerror(errno)
00042 #define Fread fread
00043 #define Fclose fclose
00044
00045 #define fdGetFILE(_fd) (_fd)
00046
00047 static inline void *
00048 _free( const void * p)
00049
00050 {
00051 if (p != NULL) free((void *)p);
00052 return NULL;
00053 }
00054
00055 #else
00056
00057
00058 const char * rpmMacrofiles = MACROFILES;
00059
00060 #include <rpmio_internal.h>
00061 #include <rpmlog.h>
00062
00063 #ifdef WITH_LUA
00064 #define _RPMLUA_INTERNAL
00065 #include <rpmlua.h>
00066 #endif
00067
00068 #endif
00069
00070 #define _MACRO_INTERNAL
00071 #include <rpmmacro.h>
00072
00073 #include "debug.h"
00074
00075 #if defined(__LCLINT__)
00076
00077 extern const unsigned short int **__ctype_b_loc (void) ;
00078
00079 #endif
00080
00081
00082
00083
00084
00085
00086 static struct MacroContext_s rpmGlobalMacroContext_s;
00087
00088 MacroContext rpmGlobalMacroContext = &rpmGlobalMacroContext_s;
00089
00090
00091 static struct MacroContext_s rpmCLIMacroContext_s;
00092
00093 MacroContext rpmCLIMacroContext = &rpmCLIMacroContext_s;
00094
00095
00099 typedef struct MacroBuf_s {
00100
00101 const char * s;
00102
00103 char * t;
00104 size_t nb;
00105 int depth;
00106 int macro_trace;
00107 int expand_trace;
00108
00109 void * spec;
00110
00111 MacroContext mc;
00112 } * MacroBuf;
00113
00114 #define SAVECHAR(_mb, _c) { *(_mb)->t = (char) (_c), (_mb)->t++, (_mb)->nb--; }
00115
00116
00117
00118 #define _MAX_MACRO_DEPTH 16
00119
00120 int max_macro_depth = _MAX_MACRO_DEPTH;
00121
00122 #define _PRINT_MACRO_TRACE 0
00123
00124 int print_macro_trace = _PRINT_MACRO_TRACE;
00125
00126 #define _PRINT_EXPAND_TRACE 0
00127
00128 int print_expand_trace = _PRINT_EXPAND_TRACE;
00129
00130
00131 #define MACRO_CHUNK_SIZE 16
00132
00133
00134 static size_t _macro_BUFSIZ = 16 * 1024;
00135
00136
00137 static int expandMacro(MacroBuf mb)
00138
00139
00140
00141
00142
00143 ;
00144
00145
00146
00153 static int
00154 compareMacroName(const void * ap, const void * bp)
00155
00156 {
00157 MacroEntry ame = *((MacroEntry *)ap);
00158 MacroEntry bme = *((MacroEntry *)bp);
00159
00160 if (ame == NULL && bme == NULL)
00161 return 0;
00162 if (ame == NULL)
00163 return 1;
00164 if (bme == NULL)
00165 return -1;
00166 return strcmp(ame->name, bme->name);
00167 }
00168
00173 static void
00174 expandMacroTable(MacroContext mc)
00175
00176 {
00177 if (mc->macroTable == NULL) {
00178 mc->macrosAllocated = MACRO_CHUNK_SIZE;
00179 mc->macroTable = (MacroEntry *)
00180 xmalloc(sizeof(*(mc->macroTable)) * mc->macrosAllocated);
00181 mc->firstFree = 0;
00182 } else {
00183 mc->macrosAllocated += MACRO_CHUNK_SIZE;
00184 mc->macroTable = (MacroEntry *)
00185 xrealloc(mc->macroTable, sizeof(*(mc->macroTable)) *
00186 mc->macrosAllocated);
00187 }
00188 memset(&mc->macroTable[mc->firstFree], 0, MACRO_CHUNK_SIZE * sizeof(*(mc->macroTable)));
00189 }
00190
00195 static void
00196 sortMacroTable(MacroContext mc)
00197
00198 {
00199 int i;
00200
00201 if (mc == NULL || mc->macroTable == NULL)
00202 return;
00203
00204 qsort(mc->macroTable, mc->firstFree, sizeof(mc->macroTable[0]),
00205 compareMacroName);
00206
00207
00208 for (i = 0; i < mc->firstFree; i++) {
00209 if (mc->macroTable[i] != NULL)
00210 continue;
00211 mc->firstFree = i;
00212 break;
00213 }
00214 }
00215
00216
00217 static char * dupMacroEntry(MacroEntry me)
00218
00219 {
00220 char * t, * te;
00221 size_t nb;
00222
00223 assert(me != NULL);
00224 nb = strlen(me->name) + sizeof("%") - 1;
00225 if (me->opts)
00226 nb += strlen(me->opts) + sizeof("()") - 1;
00227 if (me->body)
00228 nb += strlen(me->body) + sizeof("\t") - 1;
00229 nb++;
00230
00231 t = te = xmalloc(nb);
00232 *te = '\0';
00233 te = stpcpy( stpcpy(te, "%"), me->name);
00234 if (me->opts)
00235 te = stpcpy( stpcpy( stpcpy(te, "("), me->opts), ")");
00236 if (me->body)
00237 te = stpcpy( stpcpy(te, "\t"), me->body);
00238 *te = '\0';
00239
00240 return t;
00241 }
00242
00243 void
00244 rpmDumpMacroTable(MacroContext mc, FILE * fp)
00245 {
00246 int nempty = 0;
00247 int nactive = 0;
00248
00249 if (mc == NULL) mc = rpmGlobalMacroContext;
00250 if (fp == NULL) fp = stderr;
00251
00252 fprintf(fp, "========================\n");
00253 if (mc->macroTable != NULL) {
00254 int i;
00255 for (i = 0; i < mc->firstFree; i++) {
00256 MacroEntry me;
00257 if ((me = mc->macroTable[i]) == NULL) {
00258
00259 nempty++;
00260 continue;
00261 }
00262 fprintf(fp, "%3d%c %s", me->level,
00263 (me->used > 0 ? '=' : ':'), me->name);
00264 if (me->opts && *me->opts)
00265 fprintf(fp, "(%s)", me->opts);
00266 if (me->body && *me->body)
00267 fprintf(fp, "\t%s", me->body);
00268 fprintf(fp, "\n");
00269 nactive++;
00270 }
00271 }
00272 fprintf(fp, _("======================== active %d empty %d\n"),
00273 nactive, nempty);
00274 }
00275
00276 int
00277 rpmGetMacroEntries(MacroContext mc, miRE mire, int used,
00278 const char *** avp)
00279 {
00280 const char ** av;
00281 int ac = 0;
00282 int i;
00283
00284 if (mc == NULL)
00285 mc = rpmGlobalMacroContext;
00286
00287 if (avp == NULL)
00288 return mc->firstFree;
00289
00290 av = xcalloc( (mc->firstFree+1), sizeof(mc->macroTable[0]));
00291 if (mc->macroTable != NULL)
00292 for (i = 0; i < mc->firstFree; i++) {
00293 MacroEntry me;
00294 me = mc->macroTable[i];
00295 if (used > 0 && me->used < used)
00296 continue;
00297 if (used == 0 && me->used != 0)
00298 continue;
00299 #if !defined(DEBUG_MACROS)
00300 if (mire != NULL && mireRegexec(mire, me->name))
00301 continue;
00302 #endif
00303 av[ac++] = dupMacroEntry(me);
00304 }
00305 av[ac] = NULL;
00306 *avp = av = xrealloc(av, (ac+1) * sizeof(*av));
00307
00308 return ac;
00309 }
00310
00318
00319 static MacroEntry *
00320 findEntry(MacroContext mc, const char * name, size_t namelen)
00321
00322 {
00323 MacroEntry key, *ret;
00324
00325
00326 if (mc == NULL) mc = rpmGlobalMacroContext;
00327
00328 if (mc->macroTable == NULL || mc->firstFree == 0)
00329 return NULL;
00330
00331 if (namelen > 0) {
00332 char * t = strncpy(alloca(namelen + 1), name, namelen);
00333 t[namelen] = '\0';
00334 name = t;
00335 }
00336
00337 key = memset(alloca(sizeof(*key)), 0, sizeof(*key));
00338
00339 key->name = (char *)name;
00340
00341 ret = (MacroEntry *) bsearch(&key, mc->macroTable, mc->firstFree,
00342 sizeof(*(mc->macroTable)), compareMacroName);
00343
00344 return ret;
00345 }
00346
00347
00348
00356
00357 static char *
00358 rdcl( char * buf, size_t size, FD_t fd)
00359
00360
00361 {
00362 char *q = buf - 1;
00363 size_t nb = 0;
00364 size_t nread = 0;
00365 FILE * f = fdGetFILE(fd);
00366 int pc = 0, bc = 0;
00367 char *p = buf;
00368
00369 if (f != NULL)
00370 do {
00371 *(++q) = '\0';
00372 if (fgets(q, (int)size, f) == NULL)
00373 break;
00374 nb = strlen(q);
00375 nread += nb;
00376 for (q += nb - 1; nb > 0 && iseol(*q); q--)
00377 nb--;
00378 for (; p <= q; p++) {
00379 switch (*p) {
00380 case '\\':
00381 switch (*(p+1)) {
00382 case '\r': break;
00383 case '\n': break;
00384 case '\0': break;
00385 default: p++; break;
00386 }
00387 break;
00388 case '%':
00389 switch (*(p+1)) {
00390 case '{': p++, bc++; break;
00391 case '(': p++, pc++; break;
00392 case '%': p++; break;
00393 }
00394 break;
00395 case '{': if (bc > 0) bc++; break;
00396 case '}': if (bc > 0) bc--; break;
00397 case '(': if (pc > 0) pc++; break;
00398 case ')': if (pc > 0) pc--; break;
00399 }
00400 }
00401 if (nb == 0 || (*q != '\\' && !bc && !pc) || *(q+1) == '\0') {
00402 *(++q) = '\0';
00403 break;
00404 }
00405 q++; p++; nb++;
00406 size -= nb;
00407 if (*q == '\r')
00408 *q = '\n';
00409 } while (size > 0);
00410 return (nread > 0 ? buf : NULL);
00411 }
00412
00420
00421 static const char *
00422 matchchar(const char * p, char pl, char pr)
00423
00424 {
00425 int lvl = 0;
00426 char c;
00427
00428 while ((c = *p++) != '\0') {
00429 if (c == '\\') {
00430 p++;
00431 continue;
00432 }
00433 if (c == pr) {
00434 if (--lvl <= 0) return --p;
00435 } else if (c == pl)
00436 lvl++;
00437 }
00438 return (const char *)NULL;
00439 }
00440
00447 static void
00448 printMacro(MacroBuf mb, const char * s, const char * se)
00449
00450
00451 {
00452 const char *senl;
00453 const char *ellipsis;
00454 int choplen;
00455
00456 if (s >= se) {
00457 fprintf(stderr, _("%3d>%*s(empty)"), mb->depth,
00458 (2 * mb->depth + 1), "");
00459 return;
00460 }
00461
00462 if (s[-1] == '{')
00463 s--;
00464
00465
00466 for (senl = se; *senl && !iseol(*senl); senl++)
00467 {};
00468
00469
00470 choplen = 61 - (2 * mb->depth);
00471 if ((senl - s) > choplen) {
00472 senl = s + choplen;
00473 ellipsis = "...";
00474 } else
00475 ellipsis = "";
00476
00477
00478 fprintf(stderr, "%3d>%*s%%%.*s^", mb->depth,
00479 (2 * mb->depth + 1), "", (int)(se - s), s);
00480 if (se[1] != '\0' && (senl - (se+1)) > 0)
00481 fprintf(stderr, "%-.*s%s", (int)(senl - (se+1)), se+1, ellipsis);
00482 fprintf(stderr, "\n");
00483 }
00484
00491 static void
00492 printExpansion(MacroBuf mb, const char * t, const char * te)
00493
00494
00495 {
00496 const char *ellipsis;
00497 int choplen;
00498
00499 if (!(te > t)) {
00500 fprintf(stderr, _("%3d<%*s(empty)\n"), mb->depth, (2 * mb->depth + 1), "");
00501 return;
00502 }
00503
00504
00505 while (te > t && iseol(te[-1]))
00506 te--;
00507 ellipsis = "";
00508 if (mb->depth > 0) {
00509 const char *tenl;
00510
00511
00512 while ((tenl = strchr(t, '\n')) && tenl < te)
00513 t = ++tenl;
00514
00515
00516 choplen = 61 - (2 * mb->depth);
00517 if ((te - t) > choplen) {
00518 te = t + choplen;
00519 ellipsis = "...";
00520 }
00521 }
00522
00523 fprintf(stderr, "%3d<%*s", mb->depth, (2 * mb->depth + 1), "");
00524 if (te > t)
00525 fprintf(stderr, "%.*s%s", (int)(te - t), t, ellipsis);
00526 fprintf(stderr, "\n");
00527 }
00528
00529 #define SKIPBLANK(_s, _c) \
00530 \
00531 while (((_c) = (int) *(_s)) && isblank(_c)) \
00532 (_s)++; \
00533
00534
00535 #define SKIPNONBLANK(_s, _c) \
00536 \
00537 while (((_c) = (int) *(_s)) && !(isblank(_c) || iseol(_c))) \
00538 (_s)++; \
00539
00540
00541 #define COPYNAME(_ne, _s, _c) \
00542 { SKIPBLANK(_s,_c); \
00543 while(((_c) = (int) *(_s)) && (xisalnum(_c) || (_c) == (int) '_')) \
00544 *(_ne)++ = *(_s)++; \
00545 *(_ne) = '\0'; \
00546 }
00547
00548 #define COPYOPTS(_oe, _s, _c) \
00549 { while(((_c) = (int) *(_s)) && (_c) != (int) ')') \
00550 *(_oe)++ = *(_s)++; \
00551 *(_oe) = '\0'; \
00552 }
00553
00561 static int
00562 expandT(MacroBuf mb, const char * f, size_t flen)
00563
00564
00565 {
00566 char *sbuf;
00567 const char *s = mb->s;
00568 int rc;
00569
00570 sbuf = alloca(flen + 1);
00571 memset(sbuf, 0, (flen + 1));
00572
00573 strncpy(sbuf, f, flen);
00574 sbuf[flen] = '\0';
00575 mb->s = sbuf;
00576 rc = expandMacro(mb);
00577 mb->s = s;
00578 return rc;
00579 }
00580
00581 #if 0
00582
00589 static int
00590 expandS(MacroBuf mb, char * tbuf, size_t tbuflen)
00591
00592
00593 {
00594 const char *t = mb->t;
00595 size_t nb = mb->nb;
00596 int rc;
00597
00598 mb->t = tbuf;
00599 mb->nb = tbuflen;
00600 rc = expandMacro(mb);
00601 mb->t = t;
00602 mb->nb = nb;
00603 return rc;
00604 }
00605 #endif
00606
00614 static int
00615 expandU(MacroBuf mb, char * u, size_t ulen)
00616
00617
00618 {
00619 const char *s = mb->s;
00620 char *t = mb->t;
00621 size_t nb = mb->nb;
00622 char *tbuf;
00623 int rc;
00624
00625 tbuf = alloca(ulen + 1);
00626 memset(tbuf, 0, (ulen + 1));
00627
00628 mb->s = u;
00629 mb->t = tbuf;
00630 mb->nb = ulen;
00631 rc = expandMacro(mb);
00632
00633 tbuf[ulen] = '\0';
00634 if (ulen > mb->nb)
00635 strncpy(u, tbuf, (ulen - mb->nb + 1));
00636
00637 mb->s = s;
00638 mb->t = t;
00639 mb->nb = nb;
00640
00641 return rc;
00642 }
00643
00651 static int
00652 doShellEscape(MacroBuf mb, const char * cmd, size_t clen)
00653
00654
00655 {
00656 size_t bufn = _macro_BUFSIZ + clen;
00657 char * buf = alloca(bufn);
00658 FILE *shf;
00659 int rc;
00660 int c;
00661
00662 strncpy(buf, cmd, clen);
00663 buf[clen] = '\0';
00664 rc = expandU(mb, buf, bufn);
00665 if (rc)
00666 return rc;
00667
00668 if ((shf = popen(buf, "r")) == NULL)
00669 return 1;
00670 while(mb->nb > 0 && (c = fgetc(shf)) != EOF)
00671 SAVECHAR(mb, c);
00672 (void) pclose(shf);
00673
00674
00675 while (iseol(mb->t[-1])) {
00676 *(mb->t--) = '\0';
00677 mb->nb++;
00678 }
00679 return 0;
00680 }
00681
00690 static const char *
00691 doDefine(MacroBuf mb, const char * se, int level, int expandbody)
00692
00693
00694 {
00695 const char *s = se;
00696 size_t bufn = _macro_BUFSIZ;
00697 char *buf = alloca(bufn);
00698 char *n = buf, *ne;
00699 char *o = NULL, *oe;
00700 char *b, *be;
00701 int c;
00702 int oc = (int) ')';
00703
00704 SKIPBLANK(s, c);
00705 if (c == (int) '.')
00706 *n++ = c = *s++;
00707 if (c == (int) '.')
00708 *n++ = c = *s++;
00709 ne = n;
00710
00711
00712 COPYNAME(ne, s, c);
00713
00714
00715 oe = ne + 1;
00716 if (*s == '(') {
00717 s++;
00718 o = oe;
00719 COPYOPTS(oe, s, oc);
00720 s++;
00721 }
00722
00723
00724 b = be = oe + 1;
00725 SKIPBLANK(s, c);
00726 if (c == (int) '{') {
00727 if ((se = matchchar(s, (char) c, '}')) == NULL) {
00728 rpmlog(RPMLOG_ERR,
00729 _("Macro %%%s has unterminated body\n"), n);
00730 se = s;
00731 return se;
00732 }
00733 s++;
00734 strncpy(b, s, (se - s));
00735 b[se - s] = '\0';
00736 be += strlen(b);
00737 se++;
00738 s = se;
00739 } else {
00740 int bc = 0, pc = 0;
00741 while (*s && (bc || pc || !iseol(*s))) {
00742 switch (*s) {
00743 case '\\':
00744 switch (*(s+1)) {
00745 case '\0': break;
00746 default: s++; break;
00747 }
00748 break;
00749 case '%':
00750 switch (*(s+1)) {
00751 case '{': *be++ = *s++; bc++; break;
00752 case '(': *be++ = *s++; pc++; break;
00753 case '%': *be++ = *s++; break;
00754 }
00755 break;
00756 case '{': if (bc > 0) bc++; break;
00757 case '}': if (bc > 0) bc--; break;
00758 case '(': if (pc > 0) pc++; break;
00759 case ')': if (pc > 0) pc--; break;
00760 }
00761 *be++ = *s++;
00762 }
00763 *be = '\0';
00764
00765 if (bc || pc) {
00766 rpmlog(RPMLOG_ERR,
00767 _("Macro %%%s has unterminated body\n"), n);
00768 se = s;
00769 return se;
00770 }
00771
00772
00773
00774 while (--be >= b && (c = (int) *be) && (isblank(c) || iseol(c)))
00775 {};
00776
00777 *(++be) = '\0';
00778 }
00779
00780
00781 while (iseol(*s))
00782 s++;
00783 se = s;
00784
00785
00786 if (!((c = (int) *n) && (xisalpha(c) || c == (int) '_') && (ne - n) > 2)) {
00787 rpmlog(RPMLOG_ERR,
00788 _("Macro %%%s has illegal name (%%define)\n"), n);
00789 return se;
00790 }
00791
00792
00793 if (o && oc != (int) ')') {
00794 rpmlog(RPMLOG_ERR, _("Macro %%%s has unterminated opts\n"), n);
00795 return se;
00796 }
00797
00798 if ((be - b) < 1) {
00799 rpmlog(RPMLOG_ERR, _("Macro %%%s has empty body\n"), n);
00800 return se;
00801 }
00802
00803
00804 if (expandbody && expandU(mb, b, (&buf[bufn] - b))) {
00805 rpmlog(RPMLOG_ERR, _("Macro %%%s failed to expand\n"), n);
00806 return se;
00807 }
00808
00809
00810 if (n != buf)
00811 n--;
00812 if (n != buf)
00813 n--;
00814 addMacro(mb->mc, n, o, b, (level - 1));
00815
00816 return se;
00817 }
00818
00825 static const char *
00826 doUndefine(MacroContext mc, const char * se)
00827
00828
00829 {
00830 const char *s = se;
00831 char *buf = alloca(_macro_BUFSIZ);
00832 char *n = buf, *ne = n;
00833 int c;
00834
00835 COPYNAME(ne, s, c);
00836
00837
00838 while (iseol(*s))
00839 s++;
00840 se = s;
00841
00842
00843 if (!((c = (int) *n) && (xisalpha(c) || c == (int) '_') && (ne - n) > 2)) {
00844 rpmlog(RPMLOG_ERR,
00845 _("Macro %%%s has illegal name (%%undefine)\n"), n);
00846 return se;
00847 }
00848
00849 delMacro(mc, n);
00850
00851 return se;
00852 }
00853
00854 #ifdef DYING
00855 static void
00856 dumpME(const char * msg, MacroEntry me)
00857
00858
00859 {
00860 if (msg)
00861 fprintf(stderr, "%s", msg);
00862 fprintf(stderr, "\tme %p", me);
00863 if (me)
00864 fprintf(stderr,"\tname %p(%s) prev %p",
00865 me->name, me->name, me->prev);
00866 fprintf(stderr, "\n");
00867 }
00868 #endif
00869
00878 static void
00879 pushMacro( MacroEntry * mep, const char * n, const char * o,
00880 const char * b, int level)
00881
00882 {
00883 MacroEntry prev = (mep && *mep ? *mep : NULL);
00884 MacroEntry me = (MacroEntry) xmalloc(sizeof(*me));
00885 const char *name = n;
00886
00887 if (*name == '.')
00888 name++;
00889 if (*name == '.')
00890 name++;
00891
00892
00893 me->prev = prev;
00894
00895 me->name = (prev ? prev->name : xstrdup(name));
00896 me->opts = (o ? xstrdup(o) : NULL);
00897 me->body = xstrdup(b ? b : "");
00898 me->used = 0;
00899 me->level = level;
00900 me->flags = (name != n);
00901 if (mep)
00902 *mep = me;
00903 else
00904 me = _free(me);
00905 }
00906
00911 static void
00912 popMacro(MacroEntry * mep)
00913
00914 {
00915 MacroEntry me = (*mep ? *mep : NULL);
00916
00917 if (me) {
00918
00919
00920 if ((*mep = me->prev) == NULL)
00921 me->name = _free(me->name);
00922 me->opts = _free(me->opts);
00923 me->body = _free(me->body);
00924 me = _free(me);
00925
00926 }
00927 }
00928
00933 static void
00934 freeArgs(MacroBuf mb)
00935
00936 {
00937 MacroContext mc = mb->mc;
00938 int ndeleted = 0;
00939 int i;
00940
00941 if (mc == NULL || mc->macroTable == NULL)
00942 return;
00943
00944
00945 for (i = 0; i < mc->firstFree; i++) {
00946 MacroEntry *mep, me;
00947 int skiptest = 0;
00948 mep = &mc->macroTable[i];
00949 me = *mep;
00950
00951 if (me == NULL)
00952 continue;
00953 if (me->level < mb->depth)
00954 continue;
00955 if (strlen(me->name) == 1 && strchr("#*0", *me->name)) {
00956 if (*me->name == '*' && me->used > 0)
00957 skiptest = 1;
00958 } else if (!skiptest && me->used <= 0) {
00959 #if NOTYET
00960 rpmlog(RPMLOG_ERR,
00961 _("Macro %%%s (%s) was not used below level %d\n"),
00962 me->name, me->body, me->level);
00963 #endif
00964 }
00965 popMacro(mep);
00966 if (!(mep && *mep))
00967 ndeleted++;
00968 }
00969
00970
00971 if (ndeleted)
00972 sortMacroTable(mc);
00973 }
00974
00984 static const char *
00985 grabArgs(MacroBuf mb, const MacroEntry me, const char * se,
00986 const char * lastc)
00987
00988
00989 {
00990 size_t bufn = _macro_BUFSIZ;
00991 char *buf = alloca(bufn);
00992 char *b, *be;
00993 char aname[16];
00994 const char *opts, *o;
00995 int argc = 0;
00996 const char **argv;
00997 int c;
00998 #ifdef __GLIBC__
00999 char *posixly_correct;
01000 #endif
01001
01002
01003 buf[0] = '\0';
01004 b = be = stpcpy(buf, me->name);
01005
01006 addMacro(mb->mc, "0", NULL, buf, mb->depth);
01007
01008 argc = 1;
01009
01010
01011 *be++ = ' ';
01012 while ((c = (int) *se++) != (int) '\0' && (se-1) != lastc) {
01013
01014 if (!isblank(c)) {
01015 *be++ = (char) c;
01016 continue;
01017 }
01018
01019
01020 if (be[-1] == ' ')
01021 continue;
01022
01023 *be++ = ' ';
01024 argc++;
01025 }
01026 if (c == (int) '\0') se--;
01027 if (be[-1] != ' ')
01028 argc++, be++;
01029 be[-1] = '\0';
01030 if (*b == ' ') b++;
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041 addMacro(mb->mc, "**", NULL, b, mb->depth);
01042
01043 #ifdef NOTYET
01044
01045 expandU(mb, buf, bufn);
01046 #endif
01047
01048
01049 argv = (const char **) alloca((argc + 1) * sizeof(*argv));
01050 be[-1] = ' ';
01051 be[0] = '\0';
01052 b = buf;
01053 for (c = 0; c < argc; c++) {
01054 argv[c] = b;
01055 b = strchr(b, ' ');
01056 *b++ = '\0';
01057 }
01058
01059 argv[argc] = NULL;
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076 #ifdef __GLIBC__
01077
01078 optind = 0;
01079
01080 #else
01081 optind = 1;
01082 #endif
01083
01084 opts = me->opts;
01085
01086 #ifdef __GLIBC__
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105 posixly_correct = getenv("POSIXLY_CORRECT");
01106 setenv("POSIXLY_CORRECT", "1", 1);
01107 #endif
01108
01109
01110
01111 while((c = getopt(argc, (char **)argv, opts)) != -1)
01112
01113 {
01114 if (c == (int) '?' || (o = strchr(opts, c)) == NULL) {
01115 rpmlog(RPMLOG_ERR, _("Unknown option %c in %s(%s)\n"),
01116 (char)c, me->name, opts);
01117 return se;
01118 }
01119 *be++ = '-';
01120 *be++ = (char) c;
01121 if (o[1] == ':') {
01122 *be++ = ' ';
01123 be = stpcpy(be, optarg);
01124 }
01125 *be++ = '\0';
01126 aname[0] = '-'; aname[1] = (char)c; aname[2] = '\0';
01127 addMacro(mb->mc, aname, NULL, b, mb->depth);
01128 if (o[1] == ':') {
01129 aname[0] = '-'; aname[1] = (char)c; aname[2] = '*'; aname[3] = '\0';
01130 addMacro(mb->mc, aname, NULL, optarg, mb->depth);
01131 }
01132 be = b;
01133 }
01134
01135 #ifdef __GLIBC__
01136 if (posixly_correct != NULL)
01137 setenv("POSIXLY_CORRECT", posixly_correct, 1);
01138 else
01139 unsetenv("POSIXLY_CORRECT");
01140 #endif
01141
01142
01143 sprintf(aname, "%d", (argc - optind));
01144 addMacro(mb->mc, "#", NULL, aname, mb->depth);
01145
01146
01147 if (be) {
01148 *be = '\0';
01149 for (c = optind; c < argc; c++) {
01150 sprintf(aname, "%d", (c - optind + 1));
01151 addMacro(mb->mc, aname, NULL, argv[c], mb->depth);
01152 if (be != b) *be++ = ' ';
01153
01154 be = stpcpy(be, argv[c]);
01155
01156 }
01157 }
01158
01159
01160 addMacro(mb->mc, "*", NULL, b, mb->depth);
01161
01162 return se;
01163 }
01164
01172 static void
01173 doOutput(MacroBuf mb, int waserror, const char * msg, size_t msglen)
01174
01175
01176 {
01177 size_t bufn = _macro_BUFSIZ + msglen;
01178 char *buf = alloca(bufn);
01179
01180 strncpy(buf, msg, msglen);
01181 buf[msglen] = '\0';
01182 (void) expandU(mb, buf, bufn);
01183 if (waserror)
01184 rpmlog(RPMLOG_ERR, "%s\n", buf);
01185 else
01186 fprintf(stderr, "%s", buf);
01187 }
01188
01198 static void
01199 doFoo(MacroBuf mb, int negate, const char * f, size_t fn,
01200 const char * g, size_t gn)
01201
01202
01203 {
01204 size_t bufn = _macro_BUFSIZ + fn + gn;
01205 char * buf = alloca(bufn);
01206 char *b = NULL, *be;
01207 int c;
01208
01209 buf[0] = '\0';
01210 if (g != NULL) {
01211 strncpy(buf, g, gn);
01212 buf[gn] = '\0';
01213 (void) expandU(mb, buf, bufn);
01214 }
01215 if (fn > 5 && STREQ("patch", f, 5) && xisdigit((int)f[5])) {
01216
01217 for (c = 5; c < fn-1 && f[c] == '0' && xisdigit((int)f[c+1]);)
01218 c++;
01219 b = buf;
01220 be = stpncpy( stpcpy(b, "%patch -P "), f+c, fn-c);
01221 *be = '\0';
01222 } else
01223 if (STREQ("basename", f, fn)) {
01224 if ((b = strrchr(buf, '/')) == NULL)
01225 b = buf;
01226 else
01227 b++;
01228 } else if (STREQ("dirname", f, fn)) {
01229 if ((b = strrchr(buf, '/')) != NULL)
01230 *b = '\0';
01231 b = buf;
01232 } else if (STREQ("realpath", f, fn)) {
01233 char rp[PATH_MAX];
01234 char *cp;
01235 size_t l;
01236 if ((cp = realpath(buf, rp)) != NULL) {
01237 l = strlen(cp);
01238 if ((size_t)(l+1) <= bufn) {
01239 memcpy(buf, cp, l+1);
01240 b = buf;
01241 }
01242 }
01243 } else if (STREQ("getenv", f, fn)) {
01244 char *cp;
01245 if ((cp = getenv(buf)) != NULL)
01246 b = cp;
01247 } else if (STREQ("shrink", f, fn)) {
01248
01249
01250 int i, j, k, was_space = 0;
01251 for (i = 0, j = 0, k = strlen(buf); i < k; ) {
01252 if (xisspace((int)(buf[i]))) {
01253 was_space = 1;
01254 i++;
01255 continue;
01256 }
01257 else if (was_space) {
01258 was_space = 0;
01259 if (j > 0)
01260 buf[j++] = ' ';
01261
01262 }
01263 buf[j++] = buf[i++];
01264 }
01265 buf[j] = '\0';
01266 b = buf;
01267 } else if (STREQ("suffix", f, fn)) {
01268 if ((b = strrchr(buf, '.')) != NULL)
01269 b++;
01270 } else if (STREQ("expand", f, fn)) {
01271 b = buf;
01272 } else if (STREQ("verbose", f, fn)) {
01273 #if defined(RPMLOG_MASK)
01274 if (negate)
01275 b = ((rpmlogSetMask(0) >= RPMLOG_MASK( RPMLOG_INFO )) ? NULL : buf);
01276 else
01277 b = ((rpmlogSetMask(0) >= RPMLOG_MASK( RPMLOG_INFO )) ? buf : NULL);
01278 #else
01279
01280 b = (negate) ? NULL : buf;
01281 #endif
01282 } else if (STREQ("url2path", f, fn) || STREQ("u2p", f, fn)) {
01283 int ut = urlPath(buf, (const char **)&b);
01284 ut = ut;
01285 if (*b == '\0') b = "/";
01286 } else if (STREQ("uncompress", f, fn)) {
01287 rpmCompressedMagic compressed = COMPRESSED_OTHER;
01288
01289 for (b = buf; (c = (int)*b) && isblank(c);)
01290 b++;
01291
01292 for (be = b; (c = (int)*be) && !isblank(c);)
01293 be++;
01294
01295 *be++ = '\0';
01296 (void) isCompressed(b, &compressed);
01297 switch(compressed) {
01298 default:
01299 case 0:
01300 sprintf(be, "%%__cat %s", b);
01301 break;
01302 case 1:
01303 sprintf(be, "%%__gzip -dc '%s'", b);
01304 break;
01305 case 2:
01306 sprintf(be, "%%__bzip2 -dc '%s'", b);
01307 break;
01308 case 3:
01309 sprintf(be, "%%__unzip -qq '%s'", b);
01310 break;
01311 case 4:
01312 sprintf(be, "%%__lzop -dc '%s'", b);
01313 break;
01314 case 5:
01315 sprintf(be, "%%__lzma -dc '%s'", b);
01316 break;
01317 }
01318 b = be;
01319 } else if (STREQ("mkstemp", f, fn)) {
01320
01321 for (b = buf; (c = (int)*b) && isblank(c);)
01322 b++;
01323
01324 for (be = b; (c = (int)*be) && !isblank(c);)
01325 be++;
01326
01327 #if defined(HAVE_MKSTEMP)
01328 (void) close(mkstemp(b));
01329 #else
01330 (void) mktemp(b);
01331 #endif
01332 } else if (STREQ("S", f, fn)) {
01333 for (b = buf; (c = (int)*b) && xisdigit(c);)
01334 b++;
01335 if (!c) {
01336 b++;
01337 sprintf(b, "%%SOURCE%s", buf);
01338 } else
01339 b = buf;
01340 } else if (STREQ("P", f, fn)) {
01341 for (b = buf; (c = (int) *b) && xisdigit(c);)
01342 b++;
01343 if (!c) {
01344 b++;
01345 sprintf(b, "%%PATCH%s", buf);
01346 } else
01347 b = buf;
01348 } else if (STREQ("F", f, fn)) {
01349 b = buf + strlen(buf) + 1;
01350 sprintf(b, "file%s.file", buf);
01351 }
01352
01353 if (b) {
01354 (void) expandT(mb, b, strlen(b));
01355 }
01356 }
01357
01358 static int expandFIFO(MacroBuf mb, MacroEntry me, const char *g, size_t gn)
01359
01360
01361 {
01362 int rc = 0;
01363
01364 if (me) {
01365 if (me->prev) {
01366 rc = expandFIFO(mb, me->prev, g, gn);
01367 rc = expandT(mb, g, gn);
01368 }
01369 rc = expandT(mb, me->body, strlen(me->body));
01370 }
01371 return rc;
01372 }
01373
01380 static int
01381 expandMacro(MacroBuf mb)
01382
01383
01384
01385
01386
01387
01388 {
01389 MacroEntry *mep;
01390 MacroEntry me;
01391 const char *s = mb->s, *se;
01392 const char *f, *fe;
01393 const char *g, *ge;
01394 size_t fn, gn;
01395 char *t = mb->t;
01396 int c;
01397 int rc = 0;
01398 int negate;
01399 int stackarray;
01400 const char * lastc;
01401 int chkexist;
01402
01403 if (++mb->depth > max_macro_depth) {
01404 rpmlog(RPMLOG_ERR,
01405 _("Recursion depth(%d) greater than max(%d)\n"),
01406 mb->depth, max_macro_depth);
01407 mb->depth--;
01408 mb->expand_trace = 1;
01409 return 1;
01410 }
01411
01412 while (rc == 0 && mb->nb > 0 && (c = (int)*s) != (int)'\0') {
01413 s++;
01414
01415 switch(c) {
01416 case '%':
01417 if (*s != '\0') {
01418 if (*s != '%')
01419 break;
01420 s++;
01421 }
01422
01423 default:
01424 SAVECHAR(mb, c);
01425 continue;
01426 break;
01427 }
01428
01429
01430 f = fe = NULL;
01431 g = ge = NULL;
01432 if (mb->depth > 1)
01433 t = mb->t;
01434 stackarray = chkexist = negate = 0;
01435 lastc = NULL;
01436 switch ((c = (int) *s)) {
01437 default:
01438 while (*s != '\0' && strchr("!?@", *s) != NULL) {
01439 switch(*s++) {
01440 case '@':
01441 stackarray = ((stackarray + 1) % 2);
01442 break;
01443 case '!':
01444 negate = ((negate + 1) % 2);
01445 break;
01446 case '?':
01447 chkexist++;
01448 break;
01449 }
01450 }
01451 f = se = s;
01452 if (*se == '-')
01453 se++;
01454 while((c = (int) *se) && (xisalnum(c) || c == (int) '_'))
01455 se++;
01456
01457 switch (*se) {
01458 case '*':
01459 se++;
01460 if (*se == '*') se++;
01461 break;
01462 case '#':
01463 se++;
01464 break;
01465 default:
01466 break;
01467 }
01468 fe = se;
01469
01470
01471 if ((c = (int) *fe) && isblank(c))
01472 if ((lastc = strchr(fe,'\n')) == NULL)
01473 lastc = strchr(fe, '\0');
01474
01475 break;
01476 case '(':
01477 if ((se = matchchar(s, (char)c, ')')) == NULL) {
01478 rpmlog(RPMLOG_ERR,
01479 _("Unterminated %c: %s\n"), (char)c, s);
01480 rc = 1;
01481 continue;
01482 }
01483 if (mb->macro_trace)
01484 printMacro(mb, s, se+1);
01485
01486 s++;
01487 rc = doShellEscape(mb, s, (se - s));
01488 se++;
01489
01490 s = se;
01491 continue;
01492 break;
01493 case '{':
01494 if ((se = matchchar(s, (char)c, '}')) == NULL) {
01495 rpmlog(RPMLOG_ERR,
01496 _("Unterminated %c: %s\n"), (char)c, s);
01497 rc = 1;
01498 continue;
01499 }
01500 f = s+1;
01501 se++;
01502 while (strchr("!?@", *f) != NULL) {
01503 switch(*f++) {
01504 case '@':
01505 stackarray = ((stackarray + 1) % 2);
01506 break;
01507 case '!':
01508 negate = ((negate + 1) % 2);
01509 break;
01510 case '?':
01511 chkexist++;
01512 break;
01513 }
01514 }
01515
01516 for (fe = f; (c = (int) *fe) && !strchr(" :}", c);)
01517 fe++;
01518 switch (c) {
01519 case ':':
01520 g = fe + 1;
01521 ge = se - 1;
01522 break;
01523 case ' ':
01524 lastc = se-1;
01525 break;
01526 default:
01527 break;
01528 }
01529 break;
01530 }
01531
01532
01533 fn = (fe - f);
01534 gn = (ge - g);
01535 if ((fe - f) <= 0) {
01536
01537 c = (int) '%';
01538 SAVECHAR(mb, c);
01539 #if 0
01540 rpmlog(RPMLOG_ERR,
01541 _("A %% is followed by an unparseable macro\n"));
01542 #endif
01543 s = se;
01544 continue;
01545 }
01546
01547 if (mb->macro_trace)
01548 printMacro(mb, s, se);
01549
01550
01551 if (STREQ("load", f, fn)) {
01552 if (g != NULL) {
01553 char * mfn = strncpy(alloca(gn + 1), g, gn);
01554 int xx;
01555 mfn[gn] = '\0';
01556 xx = rpmLoadMacroFile(NULL, mfn);
01557 }
01558 s = se;
01559 continue;
01560 }
01561 if (STREQ("global", f, fn)) {
01562 s = doDefine(mb, se, RMIL_GLOBAL, 1);
01563 continue;
01564 }
01565 if (STREQ("define", f, fn)) {
01566 s = doDefine(mb, se, mb->depth, 0);
01567 continue;
01568 }
01569 if (STREQ("undefine", f, fn)) {
01570 s = doUndefine(mb->mc, se);
01571 continue;
01572 }
01573
01574 if (STREQ("echo", f, fn) ||
01575 STREQ("warn", f, fn) ||
01576 STREQ("error", f, fn)) {
01577 int waserror = 0;
01578 if (STREQ("error", f, fn))
01579 waserror = 1, rc = 1;
01580 if (g != NULL && g < ge)
01581 doOutput(mb, waserror, g, gn);
01582 else
01583 doOutput(mb, waserror, f, fn);
01584 s = se;
01585 continue;
01586 }
01587
01588 if (STREQ("trace", f, fn)) {
01589
01590 mb->expand_trace = mb->macro_trace = (negate ? 0 : mb->depth);
01591 if (mb->depth == 1) {
01592 print_macro_trace = mb->macro_trace;
01593 print_expand_trace = mb->expand_trace;
01594 }
01595 s = se;
01596 continue;
01597 }
01598
01599 if (STREQ("dump", f, fn)) {
01600 rpmDumpMacroTable(mb->mc, NULL);
01601 while (iseol(*se))
01602 se++;
01603 s = se;
01604 continue;
01605 }
01606
01607 #ifdef WITH_LUA
01608 if (STREQ("lua", f, fn)) {
01609 rpmlua lua = rpmluaGetGlobalState();
01610 rpmlua olua = memcpy(alloca(sizeof(*olua)), lua, sizeof(*olua));
01611 const char *ls = s+sizeof("{lua:")-1;
01612 const char *lse = se-sizeof("}")+1;
01613 char *scriptbuf = (char *)xmalloc((lse-ls)+1);
01614 const char *printbuf;
01615
01616
01617 lua->storeprint = 1;
01618 lua->printbuf = NULL;
01619 lua->printbufsize = 0;
01620 lua->printbufused = 0;
01621
01622 memcpy(scriptbuf, ls, lse-ls);
01623 scriptbuf[lse-ls] = '\0';
01624 if (rpmluaRunScript(lua, scriptbuf, NULL) == -1)
01625 rc = 1;
01626 printbuf = rpmluaGetPrintBuffer(lua);
01627 if (printbuf) {
01628 size_t len = strlen(printbuf);
01629 if (len > mb->nb)
01630 len = mb->nb;
01631 memcpy(mb->t, printbuf, len);
01632 mb->t += len;
01633 mb->nb -= len;
01634 }
01635
01636
01637 lua->storeprint = olua->storeprint;
01638 lua->printbuf = olua->printbuf;
01639 lua->printbufsize = olua->printbufsize;
01640 lua->printbufused = olua->printbufused;
01641
01642 free(scriptbuf);
01643 s = se;
01644 continue;
01645 }
01646 #endif
01647
01648
01649 if (lastc && fn > 5 && STREQ("patch", f, 5) && xisdigit((int)f[5])) {
01650
01651 doFoo(mb, negate, f, (lastc - f), NULL, 0);
01652
01653 s = lastc;
01654 continue;
01655 }
01656
01657
01658 if (STREQ("basename", f, fn) ||
01659 STREQ("dirname", f, fn) ||
01660 STREQ("realpath", f, fn) ||
01661 STREQ("getenv", f, fn) ||
01662 STREQ("shrink", f, fn) ||
01663 STREQ("suffix", f, fn) ||
01664 STREQ("expand", f, fn) ||
01665 STREQ("verbose", f, fn) ||
01666 STREQ("uncompress", f, fn) ||
01667 STREQ("mkstemp", f, fn) ||
01668 STREQ("url2path", f, fn) ||
01669 STREQ("u2p", f, fn) ||
01670 STREQ("S", f, fn) ||
01671 STREQ("P", f, fn) ||
01672 STREQ("F", f, fn)) {
01673
01674 doFoo(mb, negate, f, fn, g, gn);
01675
01676 s = se;
01677 continue;
01678 }
01679
01680
01681 mep = findEntry(mb->mc, f, fn);
01682 me = (mep ? *mep : NULL);
01683
01684
01685 if (*f == '-') {
01686 if (me)
01687 me->used++;
01688 if ((me == NULL && !negate) ||
01689 (me != NULL && negate)) {
01690 s = se;
01691 continue;
01692 }
01693
01694 if (g && g < ge) {
01695 rc = expandT(mb, g, gn);
01696 } else
01697 if (me && me->body && *me->body) {
01698 rc = expandT(mb, me->body, strlen(me->body));
01699 }
01700 s = se;
01701 continue;
01702 }
01703
01704
01705 if (chkexist) {
01706 if ((me == NULL && !negate) ||
01707 (me != NULL && negate)) {
01708 s = se;
01709 continue;
01710 }
01711 if (g && g < ge) {
01712 rc = expandT(mb, g, gn);
01713 } else
01714 if (me && me->body && *me->body) {
01715 rc = expandT(mb, me->body, strlen(me->body));
01716 }
01717 s = se;
01718 continue;
01719 }
01720
01721 if (me == NULL) {
01722 #ifndef HACK
01723 #if DEAD
01724
01725 if (fn == 1 && *f == '*') {
01726 s = se;
01727 continue;
01728 }
01729 #endif
01730
01731 c = (int) '%';
01732 SAVECHAR(mb, c);
01733 #else
01734 if (!strncmp(f, "if", fn) ||
01735 !strncmp(f, "else", fn) ||
01736 !strncmp(f, "endif", fn)) {
01737 c = '%';
01738 SAVECHAR(mb, c);
01739 } else {
01740 rpmlog(RPMLOG_ERR,
01741 _("Macro %%%.*s not found, skipping\n"), fn, f);
01742 s = se;
01743 }
01744 #endif
01745 continue;
01746 }
01747
01748
01749 if (stackarray) {
01750 if (!(g && g < ge)) {
01751 g = "\n";
01752 gn = strlen(g);
01753 }
01754 rc = expandFIFO(mb, me, g, gn);
01755 s = se;
01756 continue;
01757 }
01758
01759
01760 if (me && me->opts != NULL) {
01761 if (lastc != NULL) {
01762 se = grabArgs(mb, me, fe, lastc);
01763 } else {
01764 addMacro(mb->mc, "**", NULL, "", mb->depth);
01765 addMacro(mb->mc, "*", NULL, "", mb->depth);
01766 addMacro(mb->mc, "#", NULL, "0", mb->depth);
01767 addMacro(mb->mc, "0", NULL, me->name, mb->depth);
01768 }
01769 }
01770
01771
01772 if (me->body && *me->body) {
01773 mb->s = me->body;
01774 rc = expandMacro(mb);
01775 if (rc == 0)
01776 me->used++;
01777 }
01778
01779
01780 if (me->opts != NULL)
01781 freeArgs(mb);
01782
01783 s = se;
01784 }
01785
01786 *mb->t = '\0';
01787 mb->s = s;
01788 mb->depth--;
01789 if (rc != 0 || mb->expand_trace)
01790 printExpansion(mb, t, mb->t);
01791 return rc;
01792 }
01793
01794 #if defined(RPM_VENDOR_OPENPKG)
01795 int rpmSecuritySaneFile(const char *filename)
01796 {
01797 struct stat sb;
01798 uid_t uid;
01799
01800 if (stat(filename, &sb) == -1)
01801 return (errno == ENOENT ? 1 : 0);
01802 uid = getuid();
01803 if (sb.st_uid != uid)
01804 return 0;
01805 if (!S_ISREG(sb.st_mode))
01806 return 0;
01807 if (sb.st_mode & (S_IWGRP|S_IWOTH))
01808 return 0;
01809 return 1;
01810 }
01811 #endif
01812
01813 #if !defined(DEBUG_MACROS)
01814
01815
01816
01817 #define POPT_ERROR_NOARG -10
01818 #define POPT_ERROR_BADQUOTE -15
01819 #define POPT_ERROR_MALLOC -21
01821 #define POPT_ARGV_ARRAY_GROW_DELTA 5
01822
01823 static int XpoptDupArgv(int argc, const char **argv,
01824 int * argcPtr, const char *** argvPtr)
01825
01826 {
01827 size_t nb = (argc + 1) * sizeof(*argv);
01828 const char ** argv2;
01829 char * dst;
01830 int i;
01831
01832 if (argc <= 0 || argv == NULL)
01833 return POPT_ERROR_NOARG;
01834 for (i = 0; i < argc; i++) {
01835 if (argv[i] == NULL)
01836 return POPT_ERROR_NOARG;
01837 nb += strlen(argv[i]) + 1;
01838 }
01839
01840 dst = malloc(nb);
01841 if (dst == NULL)
01842 return POPT_ERROR_MALLOC;
01843 argv2 = (void *) dst;
01844 dst += (argc + 1) * sizeof(*argv);
01845
01846 for (i = 0; i < argc; i++) {
01847 argv2[i] = dst;
01848 dst += strlen(strcpy(dst, argv[i])) + 1;
01849 }
01850 argv2[argc] = NULL;
01851
01852 if (argvPtr) {
01853 *argvPtr = argv2;
01854 } else {
01855 free(argv2);
01856 argv2 = NULL;
01857 }
01858 if (argcPtr)
01859 *argcPtr = argc;
01860 return 0;
01861 }
01862
01863 static int XpoptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
01864
01865 {
01866 const char * src;
01867 char quote = '\0';
01868 int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
01869 const char ** argv = malloc(sizeof(*argv) * argvAlloced);
01870 int argc = 0;
01871 size_t buflen = strlen(s) + 1;
01872 char * buf = memset(alloca(buflen), 0, buflen);
01873 int rc = POPT_ERROR_MALLOC;
01874
01875 if (argv == NULL) return rc;
01876 argv[argc] = buf;
01877
01878 for (src = s; *src != '\0'; src++) {
01879 if (quote == *src) {
01880 quote = '\0';
01881 } else if (quote != '\0') {
01882 if (*src == '\\') {
01883 src++;
01884 if (!*src) {
01885 rc = POPT_ERROR_BADQUOTE;
01886 goto exit;
01887 }
01888 if (*src != quote) *buf++ = '\\';
01889 }
01890 *buf++ = *src;
01891 } else if (isspace(*src)) {
01892 if (*argv[argc] != '\0') {
01893 buf++, argc++;
01894 if (argc == argvAlloced) {
01895 argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
01896 argv = realloc(argv, sizeof(*argv) * argvAlloced);
01897 if (argv == NULL) goto exit;
01898 }
01899 argv[argc] = buf;
01900 }
01901 } else switch (*src) {
01902 case '"':
01903 case '\'':
01904 quote = *src;
01905 break;
01906 case '\\':
01907 src++;
01908 if (!*src) {
01909 rc = POPT_ERROR_BADQUOTE;
01910 goto exit;
01911 }
01912
01913 default:
01914 *buf++ = *src;
01915 break;
01916 }
01917 }
01918
01919 if (strlen(argv[argc])) {
01920 argc++, buf++;
01921 }
01922
01923 rc = XpoptDupArgv(argc, argv, argcPtr, argvPtr);
01924
01925 exit:
01926 if (argv) free(argv);
01927 return rc;
01928 }
01929
01930
01931
01932 static int _debug = 0;
01933
01934 int rpmGlob(const char * patterns, int * argcPtr, const char *** argvPtr)
01935 {
01936 int ac = 0;
01937 const char ** av = NULL;
01938 int argc = 0;
01939 const char ** argv = NULL;
01940 char * globRoot = NULL;
01941 #ifdef ENABLE_NLS
01942 const char * old_collate = NULL;
01943 const char * old_ctype = NULL;
01944 const char * t;
01945 #endif
01946 size_t maxb, nb;
01947 int i, j;
01948 int rc;
01949
01950 rc = XpoptParseArgvString(patterns, &ac, &av);
01951 if (rc)
01952 return rc;
01953 #ifdef ENABLE_NLS
01954 t = setlocale(LC_COLLATE, NULL);
01955 if (t)
01956 old_collate = xstrdup(t);
01957 t = setlocale(LC_CTYPE, NULL);
01958 if (t)
01959 old_ctype = xstrdup(t);
01960 (void) setlocale(LC_COLLATE, "C");
01961 (void) setlocale(LC_CTYPE, "C");
01962 #endif
01963
01964 if (av != NULL)
01965 for (j = 0; j < ac; j++) {
01966 const char * globURL;
01967 const char * path;
01968 int ut = urlPath(av[j], &path);
01969 glob_t gl;
01970
01971 if (!Glob_pattern_p(av[j], 0) && strchr(path, '~') == NULL) {
01972 argv = xrealloc(argv, (argc+2) * sizeof(*argv));
01973 argv[argc] = xstrdup(av[j]);
01974 if (_debug)
01975 fprintf(stderr, "*** rpmGlob argv[%d] \"%s\"\n", argc, argv[argc]);
01976 argc++;
01977 continue;
01978 }
01979
01980 gl.gl_pathc = 0;
01981 gl.gl_pathv = NULL;
01982 rc = Glob(av[j], GLOB_TILDE, Glob_error, &gl);
01983 if (rc)
01984 goto exit;
01985
01986
01987 maxb = 0;
01988 for (i = 0; i < gl.gl_pathc; i++) {
01989 if ((nb = strlen(&(gl.gl_pathv[i][0]))) > maxb)
01990 maxb = nb;
01991 }
01992
01993 nb = ((ut == URL_IS_PATH) ? (path - av[j]) : 0);
01994 maxb += nb;
01995 maxb += 1;
01996 globURL = globRoot = xmalloc(maxb);
01997
01998 switch (ut) {
01999 case URL_IS_PATH:
02000 case URL_IS_DASH:
02001 strncpy(globRoot, av[j], nb);
02002 break;
02003 case URL_IS_HTTPS:
02004 case URL_IS_HTTP:
02005 case URL_IS_FTP:
02006 case URL_IS_HKP:
02007 case URL_IS_UNKNOWN:
02008 default:
02009 break;
02010 }
02011 globRoot += nb;
02012 *globRoot = '\0';
02013 if (_debug)
02014 fprintf(stderr, "*** GLOB maxb %d diskURL %d %*s globURL %p %s\n", (int)maxb, (int)nb, (int)nb, av[j], globURL, globURL);
02015
02016 argv = xrealloc(argv, (argc+gl.gl_pathc+1) * sizeof(*argv));
02017
02018 if (argv != NULL)
02019 for (i = 0; i < gl.gl_pathc; i++) {
02020 const char * globFile = &(gl.gl_pathv[i][0]);
02021 if (globRoot > globURL && globRoot[-1] == '/')
02022 while (*globFile == '/') globFile++;
02023 strcpy(globRoot, globFile);
02024 if (_debug)
02025 fprintf(stderr, "*** rpmGlob argv[%d] \"%s\"\n", argc, globURL);
02026 argv[argc++] = xstrdup(globURL);
02027 }
02028
02029 Globfree(&gl);
02030
02031 globURL = _free(globURL);
02032 }
02033
02034 if (argv != NULL && argc > 0) {
02035 argv[argc] = NULL;
02036 if (argvPtr)
02037 *argvPtr = argv;
02038 if (argcPtr)
02039 *argcPtr = argc;
02040 rc = 0;
02041 } else
02042 rc = 1;
02043
02044
02045 exit:
02046 #ifdef ENABLE_NLS
02047 if (old_collate) {
02048 (void) setlocale(LC_COLLATE, old_collate);
02049 old_collate = _free(old_collate);
02050 }
02051 if (old_ctype) {
02052 (void) setlocale(LC_CTYPE, old_ctype);
02053 old_ctype = _free(old_ctype);
02054 }
02055 #endif
02056 av = _free(av);
02057 if (rc || argvPtr == NULL) {
02058
02059 if (argv != NULL)
02060 for (i = 0; i < argc; i++)
02061 argv[i] = _free(argv[i]);
02062 argv = _free(argv);
02063
02064 }
02065 return rc;
02066 }
02067 #endif
02068
02069
02070
02071 int
02072 expandMacros(void * spec, MacroContext mc, char * sbuf, size_t slen)
02073 {
02074 MacroBuf mb = alloca(sizeof(*mb));
02075 char *tbuf;
02076 int rc;
02077
02078 if (sbuf == NULL || slen == 0)
02079 return 0;
02080 if (mc == NULL) mc = rpmGlobalMacroContext;
02081
02082 tbuf = alloca(slen + 1);
02083 memset(tbuf, 0, (slen + 1));
02084
02085 mb->s = sbuf;
02086 mb->t = tbuf;
02087 mb->nb = slen;
02088 mb->depth = 0;
02089 mb->macro_trace = print_macro_trace;
02090 mb->expand_trace = print_expand_trace;
02091
02092 mb->spec = spec;
02093 mb->mc = mc;
02094
02095 rc = expandMacro(mb);
02096
02097 tbuf[slen] = '\0';
02098 if (mb->nb == 0)
02099 rpmlog(RPMLOG_ERR, _("Macro expansion too big for target buffer\n"));
02100 else
02101 strncpy(sbuf, tbuf, (slen - mb->nb + 1));
02102
02103 return rc;
02104 }
02105
02106 void
02107 addMacro(MacroContext mc,
02108 const char * n, const char * o, const char * b, int level)
02109 {
02110 MacroEntry * mep;
02111 const char * name = n;
02112
02113 if (*name == '.')
02114 name++;
02115 if (*name == '.')
02116 name++;
02117
02118 if (mc == NULL) mc = rpmGlobalMacroContext;
02119
02120
02121 if ((mep = findEntry(mc, name, 0)) == NULL) {
02122 if (mc->firstFree == mc->macrosAllocated)
02123 expandMacroTable(mc);
02124 if (mc->macroTable != NULL)
02125 mep = mc->macroTable + mc->firstFree++;
02126 }
02127
02128 if (mep != NULL) {
02129
02130 if (*mep && (*mep)->flags && !(n[0] == '.' && n[1] == '.')) {
02131
02132 if (strcmp((*mep)->name, "buildroot"))
02133 rpmlog(RPMLOG_ERR, _("Macro '%s' is readonly and cannot be changed.\n"), n);
02134 return;
02135 }
02136
02137 pushMacro(mep, n, o, b, level);
02138
02139
02140 if ((*mep)->prev == NULL)
02141 sortMacroTable(mc);
02142 }
02143 }
02144
02145 void
02146 delMacro(MacroContext mc, const char * n)
02147 {
02148 MacroEntry * mep;
02149
02150 if (mc == NULL) mc = rpmGlobalMacroContext;
02151
02152 if ((mep = findEntry(mc, n, 0)) != NULL) {
02153 popMacro(mep);
02154
02155 if (!(mep && *mep))
02156 sortMacroTable(mc);
02157 }
02158 }
02159
02160
02161 int
02162 rpmDefineMacro(MacroContext mc, const char * macro, int level)
02163 {
02164 MacroBuf mb = alloca(sizeof(*mb));
02165
02166 memset(mb, 0, sizeof(*mb));
02167
02168 mb->mc = (mc ? mc : rpmGlobalMacroContext);
02169 (void) doDefine(mb, macro, level, 0);
02170 return 0;
02171 }
02172
02173
02174
02175 int
02176 rpmUndefineMacro(MacroContext mc, const char * macro)
02177 {
02178 (void) doUndefine(mc ? mc : rpmGlobalMacroContext, macro);
02179 return 0;
02180 }
02181
02182
02183 void
02184 rpmLoadMacros(MacroContext mc, int level)
02185 {
02186
02187 if (mc == NULL || mc == rpmGlobalMacroContext)
02188 return;
02189
02190 if (mc->macroTable != NULL) {
02191 int i;
02192 for (i = 0; i < mc->firstFree; i++) {
02193 MacroEntry *mep, me;
02194 mep = &mc->macroTable[i];
02195 me = *mep;
02196
02197 if (me == NULL)
02198 continue;
02199 addMacro(NULL, me->name, me->opts, me->body, (level - 1));
02200 }
02201 }
02202 }
02203
02204 #if defined(RPM_VENDOR_OPENPKG)
02205 static void expand_macrosfile_macro(const char *file_name, const char *buf, size_t bufn)
02206 {
02207 char *cp;
02208 size_t l, k;
02209 static const char *macro_name = "%{macrosfile}";
02210
02211 l = strlen(macro_name);
02212 k = strlen(file_name);
02213 while ((cp = strstr(buf, macro_name)) != NULL) {
02214 if (((strlen(buf) - l) + k) < bufn) {
02215 memmove(cp+k, cp+l, strlen(cp+l)+1);
02216 memcpy(cp, file_name, k);
02217 }
02218 }
02219 return;
02220 }
02221 #endif
02222
02223 int
02224 rpmLoadMacroFile(MacroContext mc, const char * fn)
02225 {
02226 FD_t fd = Fopen(fn, "r.fpio");
02227 size_t bufn = _macro_BUFSIZ;
02228 char *buf = alloca(bufn);
02229 int rc = -1;
02230
02231 if (fd == NULL || Ferror(fd)) {
02232 if (fd) (void) Fclose(fd);
02233 return rc;
02234 }
02235
02236
02237
02238 max_macro_depth = _MAX_MACRO_DEPTH;
02239
02240
02241 buf[0] = '\0';
02242 while(rdcl(buf, bufn, fd) != NULL) {
02243 char *n;
02244 int c;
02245
02246 n = buf;
02247 SKIPBLANK(n, c);
02248
02249 if (c != (int) '%')
02250 continue;
02251 n++;
02252 #if defined(RPM_VENDOR_OPENPKG)
02253 expand_macrosfile_macro(fn, buf, bufn);
02254 #endif
02255 rc = rpmDefineMacro(mc, n, RMIL_MACROFILES);
02256 }
02257 rc = Fclose(fd);
02258 return rc;
02259 }
02260
02261 void
02262 rpmInitMacros(MacroContext mc, const char * macrofiles)
02263 {
02264 char *mfiles, *m, *me;
02265
02266 if (macrofiles == NULL)
02267 return;
02268 #ifdef DYING
02269 if (mc == NULL) mc = rpmGlobalMacroContext;
02270 #endif
02271
02272 mfiles = xstrdup(macrofiles);
02273 for (m = mfiles; m && *m != '\0'; m = me) {
02274 const char ** av;
02275 int ac;
02276 int i;
02277
02278 for (me = m; (me = strchr(me, ':')) != NULL; me++) {
02279
02280 if (!(me[1] == '/' && me[2] == '/'))
02281 break;
02282 }
02283
02284 if (me && *me == ':')
02285 *me++ = '\0';
02286 else
02287 me = m + strlen(m);
02288
02289 #if defined(RPM_VENDOR_OPENPKG)
02290 if (m[0] == '@' ) {
02291 m++;
02292 if (!rpmSecuritySaneFile(m)) {
02293 rpmlog(RPMLOG_WARNING, "existing RPM macros file \"%s\" considered INSECURE -- not loaded\n", m);
02294 continue;
02295 }
02296 }
02297 #endif
02298
02299
02300 ac = 0;
02301 av = NULL;
02302 #if defined(DEBUG_MACROS)
02303 ac = 1;
02304 av = xmalloc((ac + 1) * sizeof(*av));
02305 av[0] = strdup(m);
02306 av[1] = NULL;
02307 #else
02308 i = rpmGlob(m, &ac, &av);
02309 if (i != 0)
02310 continue;
02311 #endif
02312
02313
02314
02315 for (i = 0; i < ac; i++) {
02316 size_t slen = strlen(av[i]);
02317
02318
02319 #define _suffix(_s, _x) \
02320 (slen >= sizeof(_x) && !strcmp((_s)+slen-(sizeof(_x)-1), (_x)))
02321 if (!(_suffix(av[i], "~")
02322 || _suffix(av[i], ".rpmnew")
02323 || _suffix(av[i], ".rpmorig")
02324 || _suffix(av[i], ".rpmsave"))
02325 )
02326 (void) rpmLoadMacroFile(mc, av[i]);
02327 #undef _suffix
02328
02329 av[i] = _free(av[i]);
02330 }
02331 av = _free(av);
02332 }
02333 mfiles = _free(mfiles);
02334
02335
02336
02337 rpmLoadMacros(rpmCLIMacroContext, RMIL_CMDLINE);
02338
02339 }
02340
02341
02342 void
02343 rpmFreeMacros(MacroContext mc)
02344 {
02345
02346 if (mc == NULL) mc = rpmGlobalMacroContext;
02347
02348 if (mc->macroTable != NULL) {
02349 int i;
02350 for (i = 0; i < mc->firstFree; i++) {
02351 MacroEntry me;
02352 while ((me = mc->macroTable[i]) != NULL) {
02353
02354
02355 if ((mc->macroTable[i] = me->prev) == NULL)
02356 me->name = _free(me->name);
02357
02358 me->opts = _free(me->opts);
02359 me->body = _free(me->body);
02360 me = _free(me);
02361 }
02362 }
02363 mc->macroTable = _free(mc->macroTable);
02364 }
02365 memset(mc, 0, sizeof(*mc));
02366 }
02367
02368
02369
02370 int isCompressed(const char * file, rpmCompressedMagic * compressed)
02371 {
02372 FD_t fd;
02373 ssize_t nb;
02374 int rc = -1;
02375 unsigned char magic[13];
02376
02377 *compressed = COMPRESSED_NOT;
02378
02379 fd = Fopen(file, "r");
02380 if (fd == NULL || Ferror(fd)) {
02381
02382 rpmlog(RPMLOG_ERR, _("File %s: %s\n"), file, Fstrerror(fd));
02383 if (fd) (void) Fclose(fd);
02384 return 1;
02385 }
02386 nb = Fread(magic, sizeof(magic[0]), sizeof(magic), fd);
02387 if (nb < 0) {
02388 rpmlog(RPMLOG_ERR, _("File %s: %s\n"), file, Fstrerror(fd));
02389 rc = 1;
02390 } else if (nb < sizeof(magic)) {
02391 rpmlog(RPMLOG_ERR, _("File %s is smaller than %u bytes\n"),
02392 file, (unsigned)sizeof(magic));
02393 rc = 0;
02394 }
02395 (void) Fclose(fd);
02396 if (rc >= 0)
02397 return rc;
02398
02399 rc = 0;
02400
02401 if (magic[0] == 'B' && magic[1] == 'Z')
02402 *compressed = COMPRESSED_BZIP2;
02403 else
02404 if (magic[0] == (unsigned char) 0120 && magic[1] == (unsigned char) 0113
02405 && magic[2] == (unsigned char) 0003 && magic[3] == (unsigned char) 0004)
02406 *compressed = COMPRESSED_ZIP;
02407 else
02408 if (magic[0] == (unsigned char) 0x89 && magic[1] == 'L'
02409 && magic[2] == 'Z' && magic[3] == 'O')
02410 *compressed = COMPRESSED_LZOP;
02411 else
02412
02413 if (magic[ 9] == (unsigned char) 0x00 && magic[10] == (unsigned char) 0x00 &&
02414 magic[11] == (unsigned char) 0x00 && magic[12] == (unsigned char) 0x00)
02415 *compressed = COMPRESSED_LZMA;
02416 else
02417 if ((magic[0] == (unsigned char) 0037 && magic[1] == (unsigned char) 0213)
02418 || (magic[0] == (unsigned char) 0037 && magic[1] == (unsigned char) 0236)
02419 || (magic[0] == (unsigned char) 0037 && magic[1] == (unsigned char) 0036)
02420 || (magic[0] == (unsigned char) 0037 && magic[1] == (unsigned char) 0240)
02421 || (magic[0] == (unsigned char) 0037 && magic[1] == (unsigned char) 0235))
02422 *compressed = COMPRESSED_OTHER;
02423
02424 return rc;
02425 }
02426
02427
02428
02429
02430 char *
02431 rpmExpand(const char *arg, ...)
02432 {
02433 const char *s;
02434 char *t, *te;
02435 size_t sn, tn;
02436 size_t bufn = 8 * _macro_BUFSIZ;
02437
02438 va_list ap;
02439
02440 if (arg == NULL)
02441 return xstrdup("");
02442
02443 t = xmalloc(bufn + strlen(arg) + 1);
02444 *t = '\0';
02445 te = stpcpy(t, arg);
02446
02447 va_start(ap, arg);
02448 while ((s = va_arg(ap, const char *)) != NULL) {
02449 sn = strlen(s);
02450 tn = (te - t);
02451 t = xrealloc(t, tn + sn + bufn + 1);
02452 te = t + tn;
02453 te = stpcpy(te, s);
02454 }
02455 va_end(ap);
02456
02457 *te = '\0';
02458 tn = (te - t);
02459 (void) expandMacros(NULL, NULL, t, tn + bufn + 1);
02460 t[tn + bufn] = '\0';
02461 t = xrealloc(t, strlen(t) + 1);
02462
02463 return t;
02464 }
02465
02466
02467 int
02468 rpmExpandNumeric(const char *arg)
02469 {
02470 const char *val;
02471 int rc;
02472
02473 if (arg == NULL)
02474 return 0;
02475
02476 val = rpmExpand(arg, NULL);
02477 if (!(val && *val != '%'))
02478 rc = 0;
02479 else if (*val == 'Y' || *val == 'y')
02480 rc = 1;
02481 else if (*val == 'N' || *val == 'n')
02482 rc = 0;
02483 else {
02484 char *end;
02485 rc = strtol(val, &end, 0);
02486 if (!(end && *end == '\0'))
02487 rc = 0;
02488 }
02489 val = _free(val);
02490
02491 return rc;
02492 }
02493
02494
02495 char *rpmCleanPath(char * path)
02496 {
02497 const char *s;
02498 char *se, *t, *te;
02499 int begin = 1;
02500
02501 if (path == NULL)
02502 return NULL;
02503
02504
02505 s = t = te = path;
02506 while (*s != '\0') {
02507
02508 switch(*s) {
02509 case ':':
02510 if (s[1] == '/' && s[2] == '/') {
02511 *t++ = *s++;
02512 *t++ = *s++;
02513
02514 if (s[0] == '/') *t++ = *s++;
02515 te = t;
02516 break;
02517 }
02518 begin=1;
02519 break;
02520 case '/':
02521
02522 for (se = te + 1; se < t && *se != '/'; se++)
02523 {};
02524 if (se < t && *se == '/') {
02525 te = se;
02526
02527 }
02528 while (s[1] == '/')
02529 s++;
02530 while (t > te && t[-1] == '/')
02531 t--;
02532 break;
02533 case '.':
02534
02535
02536
02537
02538
02539
02540 if (begin && s[1] == '.' && (s[2] == '/' || s[2] == '\0')) {
02541
02542 *t++ = *s++;
02543 break;
02544 }
02545
02546 if (begin && s[1] == '\0') {
02547 break;
02548 }
02549
02550 if ((t[-1] == '/' && s[1] == '\0') || (t > path && t[-1] == '/' && s[1] == '/')) {
02551 s++;
02552 continue;
02553 }
02554
02555 if (!begin && t > path && t[-1] == '/' && s[1] == '.' && (s[2] == '/' || s[2] == '\0')) {
02556 t = te;
02557
02558 if (te > path)
02559 for (--te; te > path && *te != '/'; te--)
02560 {};
02561
02562 s++;
02563 s++;
02564 continue;
02565 }
02566 break;
02567 default:
02568 begin = 0;
02569 break;
02570 }
02571 *t++ = *s++;
02572 }
02573
02574
02575 if (t > &path[1] && t[-1] == '/')
02576 t--;
02577 *t = '\0';
02578
02579
02580 return path;
02581 }
02582
02583
02584
02585 const char *
02586 rpmGetPath(const char *path, ...)
02587 {
02588 size_t bufn = _macro_BUFSIZ;
02589 char *buf = alloca(bufn);
02590 const char * s;
02591 char * t, * te;
02592 va_list ap;
02593
02594 if (path == NULL)
02595 return xstrdup("");
02596
02597 buf[0] = '\0';
02598 t = buf;
02599 te = stpcpy(t, path);
02600 *te = '\0';
02601
02602 va_start(ap, path);
02603 while ((s = va_arg(ap, const char *)) != NULL) {
02604 te = stpcpy(te, s);
02605 *te = '\0';
02606 }
02607 va_end(ap);
02608
02609 (void) expandMacros(NULL, NULL, buf, bufn);
02610
02611
02612 (void) rpmCleanPath(buf);
02613 return xstrdup(buf);
02614 }
02615
02616
02617
02618 const char * rpmGenPath(const char * urlroot, const char * urlmdir,
02619 const char *urlfile)
02620 {
02621 const char * xroot = rpmGetPath(urlroot, NULL);
02622 const char * root = xroot;
02623 const char * xmdir = rpmGetPath(urlmdir, NULL);
02624 const char * mdir = xmdir;
02625 const char * xfile = rpmGetPath(urlfile, NULL);
02626 const char * file = xfile;
02627 const char * result;
02628 const char * url = NULL;
02629 int nurl = 0;
02630 int ut;
02631
02632 #if 0
02633 if (_debug) fprintf(stderr, "*** RGP xroot %s xmdir %s xfile %s\n", xroot, xmdir, xfile);
02634 #endif
02635 ut = urlPath(xroot, &root);
02636 if (url == NULL && ut > URL_IS_DASH) {
02637 url = xroot;
02638 nurl = root - xroot;
02639 #if 0
02640 if (_debug) fprintf(stderr, "*** RGP ut %d root %s nurl %d\n", ut, root, nurl);
02641 #endif
02642 }
02643 if (root == NULL || *root == '\0') root = "/";
02644
02645 ut = urlPath(xmdir, &mdir);
02646 if (url == NULL && ut > URL_IS_DASH) {
02647 url = xmdir;
02648 nurl = mdir - xmdir;
02649 #if 0
02650 if (_debug) fprintf(stderr, "*** RGP ut %d mdir %s nurl %d\n", ut, mdir, nurl);
02651 #endif
02652 }
02653 if (mdir == NULL || *mdir == '\0') mdir = "/";
02654
02655 ut = urlPath(xfile, &file);
02656 if (url == NULL && ut > URL_IS_DASH) {
02657 url = xfile;
02658 nurl = file - xfile;
02659 #if 0
02660 if (_debug) fprintf(stderr, "*** RGP ut %d file %s nurl %d\n", ut, file, nurl);
02661 #endif
02662 }
02663
02664 if (url && nurl > 0) {
02665 char *t = strncpy(alloca(nurl+1), url, nurl);
02666 t[nurl] = '\0';
02667 url = t;
02668 } else
02669 url = "";
02670
02671 result = rpmGetPath(url, root, "/", mdir, "/", file, NULL);
02672
02673 xroot = _free(xroot);
02674 xmdir = _free(xmdir);
02675 xfile = _free(xfile);
02676 #if 0
02677 if (_debug) fprintf(stderr, "*** RGP result %s\n", result);
02678 #endif
02679 return result;
02680 }
02681
02682
02683
02684 #if defined(DEBUG_MACROS)
02685
02686 #if defined(EVAL_MACROS)
02687
02688 const char *rpmMacrofiles = MACROFILES;
02689
02690 int
02691 main(int argc, char *argv[])
02692 {
02693 int c;
02694 int errflg = 0;
02695 extern char *optarg;
02696 extern int optind;
02697
02698 while ((c = getopt(argc, argv, "f:")) != EOF ) {
02699 switch (c) {
02700 case 'f':
02701 rpmMacrofiles = optarg;
02702 break;
02703 case '?':
02704 default:
02705 errflg++;
02706 break;
02707 }
02708 }
02709 if (errflg || optind >= argc) {
02710 fprintf(stderr, "Usage: %s [-f macropath ] macro ...\n", argv[0]);
02711 exit(1);
02712 }
02713
02714 rpmInitMacros(NULL, rpmMacrofiles);
02715
02716 for ( ; optind < argc; optind++) {
02717 const char *val;
02718
02719 val = rpmExpand(argv[optind], NULL);
02720 if (val) {
02721 fprintf(stdout, "%s:\t%s\n", argv[optind], val);
02722 val = _free(val);
02723 }
02724 }
02725 rpmFreeMacros(NULL);
02726 return 0;
02727 }
02728
02729 #else
02730
02731 const char *rpmMacrofiles = "../macros:./testmacros";
02732 const char *testfile = "./test";
02733
02734 int
02735 main(int argc, char *argv[])
02736 {
02737 size_t bufn = _macro_BUFSIZ;
02738 char *buf = alloca(bufn);
02739 FILE *fp;
02740 int x;
02741
02742 rpmInitMacros(NULL, rpmMacrofiles);
02743
02744 if ((fp = fopen(testfile, "r")) != NULL) {
02745 while(rdcl(buf, bufn, fp)) {
02746 x = expandMacros(NULL, NULL, buf, bufn);
02747 fprintf(stderr, "%d->%s\n", x, buf);
02748 memset(buf, 0, bufn);
02749 }
02750 fclose(fp);
02751 }
02752
02753 while(rdcl(buf, bufn, stdin)) {
02754 x = expandMacros(NULL, NULL, buf, bufn);
02755 fprintf(stderr, "%d->%s\n <-\n", x, buf);
02756 memset(buf, 0, bufn);
02757 }
02758 rpmFreeMacros(NULL);
02759
02760 return 0;
02761 }
02762 #endif
02763 #endif