--- /dev/null
+--- rpm-4.5/rpmio/macro.c.org 2009-08-08 15:42:25.574860247 +0200
++++ rpm-4.5/rpmio/macro.c 2009-08-08 15:47:20.495455961 +0200
+@@ -807,6 +807,41 @@
+ return se;
+ }
+
++/**
++ * Parse (and execute) macro undefinition.
++ * @param mc macro context
++ * @param se macro name to undefine
++ * @return address to continue parsing
++ */
++/*@dependent@*/ static const char *
++doUnglobal(MacroContext mc, /*@returned@*/ const char * se)
++ /*@globals rpmGlobalMacroContext @*/
++ /*@modifies mc, rpmGlobalMacroContext @*/
++{
++ const char *s = se;
++ char *buf = alloca(_macro_BUFSIZ);
++ char *n = buf, *ne = n;
++ int c;
++
++ COPYNAME(ne, s, c);
++
++ /* Move scan over body */
++ while (iseol(*s))
++ s++;
++ se = s;
++
++ /* Names must start with alphabetic or _ and be at least 3 chars */
++ if (!((c = *n) && (xisalpha(c) || c == '_') && (ne - n) > 2)) {
++ rpmError(RPMERR_BADSPEC,
++ _("Macro %%%s has illegal name (%%unglobal)\n"), n);
++ return se;
++ }
++
++ delMacroAll(mc, n);
++
++ return se;
++}
++
+ #ifdef DYING
+ static void
+ dumpME(const char * msg, MacroEntry me)
+@@ -1430,6 +1465,10 @@
+ s = doUndefine(mb->mc, se);
+ continue;
+ }
++ if (STREQ("unglobal", f, fn)) {
++ s = doUnglobal(mb->mc, se);
++ continue;
++ }
+
+ if (STREQ("echo", f, fn) ||
+ STREQ("warn", f, fn) ||
+@@ -1984,6 +2023,18 @@
+ }
+ }
+
++void
++delMacroAll(MacroContext mc, const char * n)
++{
++ MacroEntry * mep;
++
++ if (mc == NULL) mc = rpmGlobalMacroContext;
++ /* If name exists, pop entry */
++ while ((mep = findEntry(mc, n, 0)) != NULL) {
++ delMacro(mc, n);
++ }
++}
++
+ /*@-mustmod@*/ /* LCL: mc is modified through mb->mc, mb is abstract */
+ int
+ rpmDefineMacro(MacroContext mc, const char * macro, int level)