12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448 |
- /*
- * xrdb - X resource manager database utility
- *
- */
- /*
- * COPYRIGHT 1987, 1991
- * DIGITAL EQUIPMENT CORPORATION
- * MAYNARD, MASSACHUSETTS
- * MASSACHUSETTS INSTITUTE OF TECHNOLOGY
- * CAMBRIDGE, MASSACHUSETTS
- * ALL RIGHTS RESERVED.
- *
- * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
- * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
- * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
- * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
- *
- * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS,
- * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT
- * SET FORTH ABOVE.
- *
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Digital Equipment Corporation not be
- * used in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission.
- */
- /*
- * this program is used to load, or dump the resource manager database
- * in the server.
- *
- * Original Author: Jim Gettys, August 28, 1987
- * Extensively Modified: Phil Karlton, January 5, 1987
- * Modified a Bunch More: Bob Scheifler, February, 1991
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/Xatom.h>
- #include <X11/Xos.h>
- #include <X11/Xmu/SysUtil.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #ifdef NEED_SYS_PARAM_H
- # include <sys/param.h> /* defines MAXHOSTNAMELEN on BSD & Linux */
- #endif
- #ifdef NEED_NETDB_H
- # include <netdb.h> /* defines MAXHOSTNAMELEN on Solaris */
- #endif
- #define SCREEN_RESOURCES "SCREEN_RESOURCES"
- #ifndef CPP
- #ifdef __UNIXOS2__
- /* expected to be in path */
- #define CPP "cpp"
- #else
- #define CPP "/usr/lib/cpp"
- #endif /* __UNIXOS2__ */
- #endif /* CPP */
- #define INIT_BUFFER_SIZE 10000
- #define INIT_ENTRY_SIZE 500
- #define RALL 0
- #define RGLOBAL 1
- #define RSCREEN 2
- #define RSCREENS 3
- #define OPSYMBOLS 0
- #define OPQUERY 1
- #define OPREMOVE 2
- #define OPEDIT 3
- #define OPLOAD 4
- #define OPMERGE 5
- #define OPOVERRIDE 6
- #define RESOURCE_PROPERTY_NAME "RESOURCE_MANAGER"
- #define BACKUP_SUFFIX ".bak" /* for editting */
- typedef struct _Entry {
- char *tag, *value;
- int lineno;
- Bool usable;
- } Entry;
- typedef struct _Buffer {
- char *buff;
- int room, used;
- } Buffer;
- typedef struct _Entries {
- Entry *entry;
- int room, used;
- } Entries;
- /* dynamically allocated strings */
- #define CHUNK_SIZE 4096
- typedef struct _String {
- char *val;
- int room, used;
- } String;
- static char *ProgramName;
- static Bool quiet = False;
- static char tmpname[32];
- static char *filename = NULL;
- #ifdef PATHETICCPP
- static Bool need_real_defines = False;
- static char tmpname2[32];
- #endif
- #ifdef WIN32
- static char tmpname3[32];
- #endif
- static int oper = OPLOAD;
- static char *editFile = NULL;
- static const char *cpp_program = NULL;
- static const char* const cpp_locations[] = { CPP };
- static const char *backup_suffix = BACKUP_SUFFIX;
- static Bool dont_execute = False;
- static String defines;
- static int defines_base;
- #define MAX_CMD_DEFINES 512
- static char *cmd_defines[MAX_CMD_DEFINES];
- static int num_cmd_defines = 0;
- static String includes;
- static Display *dpy;
- static Buffer buffer;
- static Entries newDB;
- static void fatal(const char *, ...) _X_ATTRIBUTE_PRINTF(1,2) _X_NORETURN;
- static void addstring ( String *arg, const char *s );
- static void addescapedstring ( String *arg, const char *s );
- static void addtokstring ( String *arg, const char *s );
- static void FormatEntries ( Buffer *b, Entries *entries );
- static void StoreProperty ( Display *display, Window root, Atom res_prop );
- static void Process ( int scrno, Bool doScreen, Bool execute );
- static void ShuffleEntries ( Entries *db, Entries *dbs, int num );
- static void ReProcess ( int scrno, Bool doScreen );
- #ifndef HAVE_ASPRINTF
- /* sprintf variant found in newer libc's which allocates string to print to */
- static int _X_ATTRIBUTE_PRINTF(2,3)
- asprintf(char ** ret, const char *format, ...)
- {
- char buf[256];
- int len;
- va_list ap;
- va_start(ap, format);
- len = vsnprintf(buf, sizeof(buf), format, ap);
- va_end(ap);
- if (len < 0)
- return -1;
- if (len < sizeof(buf))
- {
- *ret = strdup(buf);
- }
- else
- {
- *ret = malloc(len + 1); /* snprintf doesn't count trailing '\0' */
- if (*ret != NULL)
- {
- va_start(ap, format);
- len = vsnprintf(*ret, len + 1, format, ap);
- va_end(ap);
- if (len < 0) {
- free(*ret);
- *ret = NULL;
- }
- }
- }
- if (*ret == NULL)
- return -1;
- return len;
- }
- #endif /* HAVE_ASPRINTF */
- static void
- InitBuffer(Buffer *b)
- {
- b->room = INIT_BUFFER_SIZE;
- b->used = 0;
- b->buff = malloc(INIT_BUFFER_SIZE*sizeof(char));
- }
- #ifdef notyet
- static void
- FreeBuffer(Buffer *b)
- {
- free(b->buff);
- }
- #endif
- static void
- AppendToBuffer(Buffer *b, const char *str, int len)
- {
- while (b->used + len > b->room) {
- b->buff = realloc(b->buff, 2*b->room*(sizeof(char)));
- b->room *= 2;
- }
- strncpy(b->buff + b->used, str, len);
- b->used += len;
- }
- static void
- InitEntries(Entries *e)
- {
- e->room = INIT_ENTRY_SIZE;
- e->used = 0;
- e->entry = malloc(INIT_ENTRY_SIZE*sizeof(Entry));
- }
- static void
- FreeEntries(Entries *e)
- {
- register int i;
- for (i = 0; i < e->used; i++) {
- if (e->entry[i].usable) {
- free(e->entry[i].tag);
- free(e->entry[i].value);
- }
- }
- free((char *)e->entry);
- }
- static void
- AddEntry(Entries *e, Entry *entry)
- {
- register int n;
- for (n = 0; n < e->used; n++) {
- if (!strcmp(e->entry[n].tag, entry->tag)) {
- /* overwrite old entry */
- if (e->entry[n].lineno && !quiet) {
- fprintf (stderr,
- "%s: \"%s\" on line %d overrides entry on line %d\n",
- ProgramName, entry->tag, entry->lineno,
- e->entry[n].lineno);
- }
- free(e->entry[n].tag);
- free(e->entry[n].value);
- entry->usable = True;
- e->entry[n] = *entry;
- return; /* ok to leave, now there's only one of each tag in db */
- }
- }
- if (e->used == e->room) {
- e->entry = realloc(e->entry, 2 * e->room * (sizeof(Entry)));
- e->room *= 2;
- }
- entry->usable = True;
- e->entry[e->used++] = *entry;
- }
- static int
- CompareEntries(const void *e1, const void *e2)
- {
- return strcmp(((const Entry *)e1)->tag, ((const Entry *)e2)->tag);
- }
- static void
- AppendEntryToBuffer(Buffer *b, Entry *entry)
- {
- AppendToBuffer(b, entry->tag, strlen(entry->tag));
- AppendToBuffer(b, ":\t", 2);
- AppendToBuffer(b, entry->value, strlen(entry->value));
- AppendToBuffer(b, "\n", 1);
- }
- /*
- * Return the position of the first unescaped occurrence of dest in string.
- * If lines is non-null, return the number of newlines skipped over.
- */
- static const char *
- FindFirst(const char *string, char dest, int *lines)
- {
- if (lines)
- *lines = 0;
- for (;;) {
- if (*string == '\0')
- return NULL;
- if (*string == '\\') {
- if (*++string == '\0')
- return NULL;
- } else if (*string == dest)
- return string;
- if (*string == '\n' && lines)
- (*lines)++;
- string++;
- }
- }
- static void
- GetEntries(Entries *entries, Buffer *buff, int bequiet)
- {
- const char *line, *colon, *temp, *str;
- Entry entry;
- register int length;
- int lineno = 0;
- int lines_skipped;
- str = buff->buff;
- if (!str) return;
- for ( ; str < buff->buff + buff->used;
- str = line + 1, lineno += lines_skipped) {
- line = FindFirst(str, '\n', &lines_skipped);
- lineno++;
- if (!line)
- line = buff->buff + buff->used;
- if (*str == '!')
- continue;
- if (*str == '\n')
- continue;
- if (!bequiet && *str == '#') {
- int dummy;
- if (sscanf (str, "# %d", &dummy) == 1 ||
- sscanf (str, "# line %d", &dummy) == 1)
- lineno = dummy - 1;
- continue;
- }
- for (temp = str;
- *temp && *temp != '\n' && isascii(*temp) && isspace(*temp);
- temp++) ;
- if (!*temp || *temp == '\n') continue;
- colon = FindFirst(str, ':', NULL);
- if (!colon || colon > line) {
- if (!bequiet && !quiet)
- fprintf (stderr,
- "%s: colon missing on line %d, ignoring line\n",
- ProgramName, lineno);
- continue;
- }
- /* strip leading and trailing blanks from name and store result */
- while (*str == ' ' || *str == '\t')
- str++;
- length = colon - str;
- while (length && (str[length-1] == ' ' || str[length-1] == '\t'))
- length--;
- entry.tag = malloc(length + 1);
- strncpy(entry.tag, str, length);
- entry.tag[length] = '\0';
- /* strip leading and trailing blanks from value and store result */
- colon++;
- while (*colon == ' ' || *colon == '\t')
- colon++;
- length = line - colon;
- entry.value = malloc(length + 1);
- strncpy(entry.value, colon, length);
- entry.value[length] = '\0';
- entry.lineno = bequiet ? 0 : lineno;
- AddEntry(entries, &entry);
- }
- }
- static void
- GetEntriesString(Entries *entries, char *str)
- {
- Buffer buff;
- if (str && *str) {
- buff.buff = str;
- buff.used = strlen(str);
- GetEntries(entries, &buff, 1);
- }
- }
- static void
- ReadFile(Buffer *b, FILE *input)
- {
- char buf[BUFSIZ + 1];
- register int bytes;
- b->used = 0;
- while (!feof(input) && (bytes = fread(buf, 1, BUFSIZ, input)) > 0) {
- #ifdef WIN32
- char *p;
- buf[bytes] = '\0';
- for (p = buf; p = strchr(p, '\r'); ) {
- if (p[-1] == '\\' && p[1] == '\n') {
- bytes -= 3;
- strcpy(p - 1, p + 2);
- }
- }
- #endif
- AppendToBuffer(b, buf, bytes);
- }
- AppendToBuffer(b, "", 1);
- }
- static void
- AddDef(String *buff, const char *title, const char *value)
- {
- #ifdef PATHETICCPP
- if (need_real_defines) {
- addstring(buff, "\n#define ");
- addtokstring(buff, title);
- if (value && (value[0] != '\0')) {
- addstring(buff, " ");
- addstring(buff, value);
- }
- return;
- }
- #endif
- if (buff->used) {
- if (oper == OPSYMBOLS)
- addstring(buff, "\n-D");
- else
- addstring(buff, " -D");
- } else
- addstring(buff, "-D");
- addtokstring(buff, title);
- if (value && (value[0] != '\0')) {
- addstring(buff, "=");
- addescapedstring(buff, value);
- }
- }
- static void
- AddSimpleDef(String *buff, const char *title)
- {
- AddDef(buff, title, (char *)NULL);
- }
- static void
- AddDefQ(String *buff, const char *title, const char *value)
- {
- #ifdef PATHETICCPP
- if (need_real_defines)
- AddDef(buff, title, value);
- else
- #endif
- if (value && (value[0] != '\0')) {
- AddSimpleDef(buff, title);
- addstring(buff, "=\"");
- addescapedstring(buff, value);
- addstring(buff, "\"");
- } else
- AddDef(buff, title, NULL);
- }
- static void
- AddNum(String *buff, const char *title, int value)
- {
- char num[20];
- snprintf(num, sizeof(num), "%d", value);
- AddDef(buff, title, num);
- }
- static void
- AddDefTok(String *buff, const char *prefix, char *title)
- {
- char name[512];
- snprintf(name, sizeof(name), "%s%s", prefix, title);
- AddSimpleDef(buff, name);
- }
- static void
- AddDefHostname(String *buff, const char *title, const char *value)
- {
- char *s;
- char name[512];
- char c;
- strncpy (name, value, sizeof(name)-1);
- name[sizeof(name)-1] = '\0';
- for (s = name; (c = *s); s++) {
- if (!isalpha(c) && !isdigit(c) && c != '_' && c != '.' && c != ':' && c != '-')
- *s = '_';
- }
- AddDef(buff, title, name);
- }
- static void
- AddUndef(String *buff, const char *title)
- {
- #ifdef PATHETICCPP
- if (need_real_defines) {
- addstring(buff, "\n#undef ");
- addstring(buff, title);
- return;
- }
- #endif
- if (buff->used) {
- if (oper == OPSYMBOLS)
- addstring(buff, "\n-U");
- else
- addstring(buff, " -U");
- } else
- addstring(buff, "-U");
- addtokstring(buff, title);
- }
- static void
- DoCmdDefines(String *buff)
- {
- int i;
- char *arg, *val;
- for (i = 0; i < num_cmd_defines; i++) {
- arg = cmd_defines[i];
- if (arg[1] == 'D') {
- val = strchr(arg, '=');
- if (val) {
- *val = '\0';
- AddDefQ(buff, arg + 2, val + 1);
- *val = '=';
- } else
- AddSimpleDef(buff, arg + 2);
- } else if (arg[1] == 'U') {
- AddUndef(buff, arg + 2);
- } else if (!strcmp(arg, "-undef") && oper != OPSYMBOLS) {
- addstring(buff, " -undef");
- }
- }
- }
- static int
- Resolution(int pixels, int mm)
- {
- if (mm == 0)
- return 0;
- else
- return ((pixels * 100000 / mm) + 50) / 100;
- }
- static void
- DoDisplayDefines(Display *display, String *defs, char *host)
- {
- #ifndef MAXHOSTNAMELEN
- #define MAXHOSTNAMELEN 255
- #endif
- char client[MAXHOSTNAMELEN], server[MAXHOSTNAMELEN], *colon;
- char **extnames;
- int n;
- XmuGetHostname(client, MAXHOSTNAMELEN);
- strncpy(server, XDisplayName(host), sizeof(server));
- server[sizeof(server) - 1] = '\0';
- /* search for final colon to skip over any embedded colons in IPv6
- numeric address forms */
- colon = strrchr(server, ':');
- n = 0;
- if (colon) {
- /* remove extra colon if there are exactly two, since it indicates
- DECnet. Three colons is an IPv6 address ending in :: though. */
- if ((colon > server) && (*(colon-1) == ':') &&
- ( ((colon - 1) == server) || (*(colon-2) != ':') ) ) {
- *(colon-1) = ':';
- }
- *colon++ = '\0';
- sscanf(colon, "%d", &n);
- }
- if (!*server || !strcmp(server, "unix") || !strcmp(server, "localhost"))
- strcpy(server, client);
- AddDefHostname(defs, "HOST", server); /* R3 compatibility */
- AddDefHostname(defs, "SERVERHOST", server);
- AddDefTok(defs, "SRVR_", server);
- AddNum(defs, "DISPLAY_NUM", n);
- AddDefHostname(defs, "CLIENTHOST", client);
- AddDefTok(defs, "CLNT_", client);
- AddNum(defs, "VERSION", ProtocolVersion(display));
- AddNum(defs, "REVISION", ProtocolRevision(display));
- AddDefQ(defs, "VENDOR", ServerVendor(display));
- AddDefTok(defs, "VNDR_", ServerVendor(display));
- AddNum(defs, "RELEASE", VendorRelease(display));
- AddNum(defs, "NUM_SCREENS", ScreenCount(display));
- extnames = XListExtensions(display, &n);
- while (--n >= 0)
- AddDefTok(defs, "EXT_", extnames[n]);
- XFreeExtensionList(extnames);
- }
- static const char *ClassNames[] = {
- "StaticGray",
- "GrayScale",
- "StaticColor",
- "PseudoColor",
- "TrueColor",
- "DirectColor"
- };
- #define NUM_CLASS_NAMES (int)(sizeof(ClassNames) / sizeof(ClassNames[0]))
- static void
- DoScreenDefines(Display *display, int scrno, String *defs)
- {
- Screen *screen;
- Visual *visual;
- XVisualInfo vinfo, *vinfos;
- int nv, i, j;
- char name[50];
- screen = ScreenOfDisplay(display, scrno);
- visual = DefaultVisualOfScreen(screen);
- vinfo.screen = scrno;
- vinfos = XGetVisualInfo(display, VisualScreenMask, &vinfo, &nv);
- AddNum(defs, "SCREEN_NUM", scrno);
- AddNum(defs, "WIDTH", screen->width);
- AddNum(defs, "HEIGHT", screen->height);
- AddNum(defs, "X_RESOLUTION", Resolution(screen->width,screen->mwidth));
- AddNum(defs, "Y_RESOLUTION", Resolution(screen->height,screen->mheight));
- AddNum(defs, "PLANES", DisplayPlanes(display, scrno));
- AddNum(defs, "BITS_PER_RGB", visual->bits_per_rgb);
- if (visual->class >= 0 && visual->class < NUM_CLASS_NAMES) {
- AddDefQ(defs, "CLASS", ClassNames[visual->class]);
- snprintf(name, sizeof(name), "CLASS_%s", ClassNames[visual->class]);
- AddNum(defs, name, (int)visual->visualid);
- }
- else {
- fprintf(stderr,
- "%s: unknown visual type %d for default visual id 0x%lx\n",
- ProgramName, visual->class, visual->visualid);
- }
- switch(visual->class) {
- case StaticColor:
- case PseudoColor:
- case TrueColor:
- case DirectColor:
- AddSimpleDef(defs, "COLOR");
- break;
- }
- for (i = 0; i < nv; i++) {
- for (j = i; --j >= 0; ) {
- if (vinfos[j].class == vinfos[i].class &&
- vinfos[j].depth == vinfos[i].depth)
- break;
- }
- if (j < 0) {
- if (vinfos[i].class >= 0 && vinfos[i].class < NUM_CLASS_NAMES) {
- snprintf(name, sizeof(name), "CLASS_%s_%d",
- ClassNames[vinfos[i].class], vinfos[i].depth);
- AddNum(defs, name, (int)vinfos[i].visualid);
- }
- else {
- fprintf(stderr,
- "%s: unknown visual type %d for visual id 0x%lx\n",
- ProgramName, vinfos[i].class, vinfos[i].visualid);
- }
- }
- }
- XFree((char *)vinfos);
- }
- static Entry *
- FindEntry(Entries *db, Buffer *b)
- {
- int i;
- register Entry *e;
- Entries phoney;
- Entry entry;
- entry.usable = False;
- entry.tag = NULL;
- entry.value = NULL;
- phoney.used = 0;
- phoney.room = 1;
- phoney.entry = &entry;
- GetEntries(&phoney, b, 1);
- if (phoney.used < 1)
- return NULL;
- for (i = 0; i < db->used; i++) {
- e = &db->entry[i];
- if (!e->usable)
- continue;
- if (strcmp(e->tag, entry.tag))
- continue;
- e->usable = False;
- if (strcmp(e->value, entry.value))
- return e;
- return NULL;
- }
- return NULL;
- }
- static void
- EditFile(Entries *new, FILE *in, FILE *out)
- {
- Buffer b;
- char buff[BUFSIZ];
- register Entry *e;
- register char *c;
- int i;
- InitBuffer(&b);
- while (in) {
- b.used = 0;
- while (1) {
- buff[0] ='\0';
- if (!fgets(buff, BUFSIZ, in))
- goto cleanup;
- AppendToBuffer(&b, buff, strlen(buff));
- c = &b.buff[b.used - 1];
- if ((*(c--) == '\n') && (b.used == 1 || *c != '\\'))
- break;
- }
- if ((e = FindEntry(new, &b)))
- fprintf(out, "%s:\t%s\n", e->tag, e->value);
- else
- fwrite(b.buff, 1, b.used, out);
- }
- cleanup:
- for (i = 0; i < new->used; i++) {
- e = &new->entry[i];
- if (e->usable)
- fprintf(out, "%s:\t%s\n", e->tag, e->value);
- }
- }
- static void _X_NORETURN
- Syntax (void)
- {
- fprintf (stderr,
- "usage: %s [-options ...] [filename]\n\n"
- "where options include:\n"
- " -help print this help message\n"
- " -version print the program version\n"
- " -display host:dpy display to use\n"
- " -all do all resources [default]\n"
- " -global do screen-independent resources\n"
- " -screen do screen-specific resources for one screen\n"
- " -screens do screen-specific resources for all screens\n"
- " -n show but don't do changes\n"
- " -cpp filename preprocessor to use [%s]\n"
- " -nocpp do not use a preprocessor\n"
- " -query query resources\n"
- " -load load resources from file [default]\n"
- " -override add in resources from file\n"
- " -merge merge resources from file & sort\n"
- " -edit filename edit resources into file\n"
- " -backup string backup suffix for -edit [%s]\n"
- " -symbols show preprocessor symbols\n"
- " -remove remove resources\n"
- " -retain avoid server reset (avoid using this)\n"
- " -quiet don't warn about duplicates\n"
- " -Dname[=value], -Uname, -Idirectory passed to preprocessor\n"
- "\n"
- "A - or no input filename represents stdin.\n",
- ProgramName, cpp_program ? cpp_program : "", BACKUP_SUFFIX);
- exit (1);
- }
- /*
- * The following is a hack until XrmParseCommand is ready. It determines
- * whether or not the given string is an abbreviation of the arg.
- */
- static Bool
- isabbreviation(const char *arg, const char *s, int minslen)
- {
- int arglen;
- int slen;
- /* exact match */
- if (!strcmp (arg, s)) return (True);
- arglen = strlen (arg);
- slen = strlen (s);
- /* too long or too short */
- if (slen >= arglen || slen < minslen) return (False);
- /* abbreviation */
- if (strncmp (arg, s, slen) == 0) return (True);
- /* bad */
- return (False);
- }
- static void
- addstring(String *arg, const char *s)
- {
- if(arg->used + strlen(s) + 1 >= arg->room) {
- if(arg->val)
- arg->val = realloc(arg->val, arg->room + CHUNK_SIZE);
- else
- arg->val = malloc(arg->room + CHUNK_SIZE);
- if(arg->val == NULL)
- fatal("%s: Not enough memory\n", ProgramName);
- arg->room += CHUNK_SIZE;
- }
- if(arg->used)
- strcat(arg->val, s);
- else
- strcpy(arg->val, s);
- arg->used += strlen(s);
- }
- static void
- addescapedstring(String *arg, const char *s)
- {
- char copy[512], *c;
- for (c = copy; *s && c < ©[sizeof(copy)-1]; s++) {
- switch (*s) {
- case '"': case '\'': case '`':
- case '$': case '\\':
- *c++ = '_';
- break;
- default:
- *c++ = *s;
- }
- }
- *c = 0;
- addstring (arg, copy);
- }
- static void
- addtokstring(String *arg, const char *s)
- {
- char copy[512], *c;
- for (c = copy; *s && c < ©[sizeof(copy)-1]; s++) {
- if (!isalpha(*s) && !isdigit(*s) && *s != '_')
- *c++ = '_';
- else
- *c++ = *s;
- }
- *c = 0;
- addstring (arg, copy);
- }
- int
- main(int argc, char *argv[])
- {
- int i;
- char *displayname = NULL;
- int whichResources = RALL;
- int retainProp = 0;
- FILE *fp = NULL;
- Bool need_newline;
- ProgramName = argv[0];
- defines.room = defines.used = includes.room = includes.used = 0;
- /* initialize the includes String struct */
- addstring(&includes, "");
- /* Pick the default cpp to use. This needs to be done before
- * we parse the command line in order to honor -nocpp which sets
- * it back to NULL.
- */
- if (cpp_program == NULL) {
- int number_of_elements
- = (sizeof cpp_locations) / (sizeof cpp_locations[0]);
- int j;
- for (j = 0; j < number_of_elements; j++) {
- char *end, *dup;
- /* cut off arguments */
- dup = strdup(cpp_locations[j]);
- end = strchr(dup,' ');
- if (end)
- *end = '\0';
- if (access(dup, X_OK) == 0) {
- cpp_program = cpp_locations[j];
- free(dup);
- break;
- }
- free(dup);
- }
- }
- /* needs to be replaced with XrmParseCommand */
- for (i = 1; i < argc; i++) {
- char *arg = argv[i];
- if (arg[0] == '-') {
- if (arg[1] == '\0') {
- filename = NULL;
- continue;
- } else if (isabbreviation ("-help", arg, 2)) {
- Syntax ();
- /* doesn't return */
- } else if (isabbreviation ("-version", arg, 2)) {
- printf("%s\n", PACKAGE_STRING);
- exit(0);
- } else if (isabbreviation ("-display", arg, 2)) {
- if (++i >= argc) Syntax ();
- displayname = argv[i];
- continue;
- } else if (isabbreviation ("-geometry", arg, 3)) {
- if (++i >= argc) Syntax ();
- /* ignore geometry */
- continue;
- } else if (isabbreviation ("-cpp", arg, 2)) {
- if (++i >= argc) Syntax ();
- cpp_program = argv[i];
- continue;
- } else if (!strcmp ("-n", arg)) {
- dont_execute = True;
- continue;
- } else if (isabbreviation ("-nocpp", arg, 3)) {
- cpp_program = NULL;
- continue;
- } else if (isabbreviation ("-query", arg, 2)) {
- oper = OPQUERY;
- continue;
- } else if (isabbreviation ("-load", arg, 2)) {
- oper = OPLOAD;
- continue;
- } else if (isabbreviation ("-merge", arg, 2)) {
- oper = OPMERGE;
- continue;
- } else if (isabbreviation ("-override", arg, 2)) {
- oper = OPOVERRIDE;
- continue;
- } else if (isabbreviation ("-symbols", arg, 3)) {
- oper = OPSYMBOLS;
- continue;
- } else if (isabbreviation ("-remove", arg, 4)) {
- oper = OPREMOVE;
- continue;
- } else if (isabbreviation ("-edit", arg, 2)) {
- if (++i >= argc) Syntax ();
- oper = OPEDIT;
- editFile = argv[i];
- continue;
- } else if (isabbreviation ("-backup", arg, 2)) {
- if (++i >= argc) Syntax ();
- backup_suffix = argv[i];
- continue;
- } else if (isabbreviation ("-all", arg, 2)) {
- whichResources = RALL;
- continue;
- } else if (isabbreviation ("-global", arg, 3)) {
- whichResources = RGLOBAL;
- continue;
- } else if (isabbreviation ("-screen", arg, 3)) {
- whichResources = RSCREEN;
- continue;
- } else if (!strcmp ("-screens", arg)) {
- whichResources = RSCREENS;
- continue;
- } else if (isabbreviation ("-retain", arg, 4)) {
- retainProp = 1;
- continue;
- } else if (isabbreviation ("-quiet", arg, 2)) {
- quiet = True;
- continue;
- } else if (arg[1] == 'I') {
- addstring(&includes, " ");
- addescapedstring(&includes, arg);
- continue;
- } else if (arg[1] == 'U' || arg[1] == 'D') {
- if (num_cmd_defines < MAX_CMD_DEFINES) {
- cmd_defines[num_cmd_defines++] = arg;
- } else {
- fatal("%s: Too many -U/-D arguments\n", ProgramName);
- }
- continue;
- } else if (!strcmp ("-undef", arg)) {
- if (num_cmd_defines < MAX_CMD_DEFINES) {
- cmd_defines[num_cmd_defines++] = "-undef";
- } else {
- fatal("%s: Too many cpp arguments\n", ProgramName);
- }
- continue;
- }
- Syntax ();
- } else if (arg[0] == '=')
- continue;
- else
- filename = arg;
- } /* end for */
- #ifndef WIN32
- while ((i = open("/dev/null", O_RDONLY)) < 3)
- ; /* make sure later freopen won't clobber things */
- (void) close(i);
- #endif
- /* Open display */
- if (!(dpy = XOpenDisplay (displayname)))
- fatal("%s: Can't open display '%s'\n", ProgramName,
- XDisplayName (displayname));
- if (whichResources == RALL && ScreenCount(dpy) == 1)
- whichResources = RGLOBAL;
- #ifdef PATHETICCPP
- if (cpp_program &&
- (oper == OPLOAD || oper == OPMERGE || oper == OPOVERRIDE)) {
- need_real_defines = True;
- #ifdef WIN32
- strcpy(tmpname2, "xrdbD_XXXXXX");
- strcpy(tmpname3, "\\temp\\xrdbD_XXXXXX");
- #else
- #ifdef __UNIXOS2__
- { char *tmpdir=getenv("TMP");
- if (!tmpdir) tmpdir="/";
- sprintf(tmpname2, "%s/xrdbD_XXXXXX",tmpdir);
- }
- #else
- strcpy(tmpname2, "/tmp/xrdbD_XXXXXX");
- #endif
- #endif
- (void) mktemp(tmpname2);
- }
- #endif
- if (!filename &&
- #ifdef PATHETICCPP
- need_real_defines
- #else
- (oper == OPLOAD || oper == OPMERGE || oper == OPOVERRIDE) &&
- (whichResources == RALL || whichResources == RSCREENS)
- #endif
- ) {
- char inputbuf[1024];
- #ifdef WIN32
- strcpy(tmpname, "\\temp\\xrdb_XXXXXX");
- #else
- #ifdef __UNIXOS2__
- { char *tmpdir=getenv("TMP");
- if (!tmpdir) tmpdir="/";
- sprintf(tmpname, "%s/xrdb_XXXXXX",tmpdir);
- }
- #else
- strcpy(tmpname, "/tmp/xrdb_XXXXXX");
- #endif
- #endif
- #ifndef HAVE_MKSTEMP
- (void) mktemp(tmpname);
- filename = tmpname;
- fp = fopen(filename, "w");
- #else
- {
- int fd = mkstemp(tmpname);
- filename = tmpname;
- fp = fdopen(fd, "w");
- }
- #endif /* MKSTEMP */
- if (!fp)
- fatal("%s: Failed to open temp file: %s\n", ProgramName,
- filename);
- while (fgets(inputbuf, sizeof(inputbuf), stdin) != NULL)
- fputs(inputbuf, fp);
- fclose(fp);
- }
- DoDisplayDefines(dpy, &defines, displayname);
- defines_base = defines.used;
- need_newline = (oper == OPQUERY || oper == OPSYMBOLS ||
- (dont_execute && oper != OPREMOVE));
- InitBuffer(&buffer);
- if (whichResources == RGLOBAL)
- Process(DefaultScreen(dpy), False, True);
- else if (whichResources == RSCREEN)
- Process(DefaultScreen(dpy), True, True);
- else if (whichResources == RSCREENS ||
- (oper != OPLOAD && oper != OPMERGE && oper != OPOVERRIDE)) {
- if (whichResources == RALL && oper != OPSYMBOLS) {
- if (need_newline)
- printf("! screen-independent resources\n");
- Process(0, False, True);
- if (need_newline)
- printf("\n");
- }
- for (i = 0; i < ScreenCount(dpy); i++) {
- if (need_newline) {
- if (oper == OPSYMBOLS)
- printf("# screen %d symbols\n", i);
- else {
- printf("! screen %d resources\n", i);
- printf("#if SCREEN_NUM == %d\n", i);
- }
- }
- Process(i, True, True);
- if (need_newline) {
- if (oper != OPSYMBOLS)
- printf("#endif\n");
- if (i+1 != ScreenCount(dpy))
- printf("\n");
- }
- }
- }
- else {
- Entries *dbs;
- dbs = malloc(ScreenCount(dpy) * sizeof(Entries));
- for (i = 0; i < ScreenCount(dpy); i++) {
- Process(i, True, False);
- dbs[i] = newDB;
- }
- InitEntries(&newDB);
- if (oper == OPMERGE || oper == OPOVERRIDE)
- GetEntriesString(&newDB, XResourceManagerString(dpy));
- ShuffleEntries(&newDB, dbs, ScreenCount(dpy));
- if (need_newline)
- printf("! screen-independent resources\n");
- ReProcess(0, False);
- if (need_newline)
- printf("\n");
- for (i = 0; i < ScreenCount(dpy); i++) {
- newDB = dbs[i];
- if (need_newline) {
- printf("! screen %d resources\n", i);
- printf("#if SCREEN_NUM == %d\n", i);
- }
- ReProcess(i, True);
- if (need_newline) {
- printf("#endif\n");
- if (i+1 != ScreenCount(dpy))
- printf("\n");
- }
- }
- }
- if (fp)
- unlink(filename);
- if (retainProp)
- XSetCloseDownMode(dpy, RetainPermanent);
- XCloseDisplay(dpy);
- exit (0);
- }
- static void
- FormatEntries(Buffer *b, Entries *entries)
- {
- register int i;
- b->used = 0;
- if (!entries->used)
- return;
- if (oper == OPMERGE)
- qsort(entries->entry, entries->used, sizeof(Entry),
- CompareEntries);
- for (i = 0; i < entries->used; i++) {
- if (entries->entry[i].usable)
- AppendEntryToBuffer(b, &entries->entry[i]);
- }
- }
- static void
- StoreProperty(Display *display, Window root, Atom res_prop)
- {
- int len = buffer.used;
- int mode = PropModeReplace;
- unsigned char *buf = (unsigned char *)buffer.buff;
- int max = (XMaxRequestSize(display) << 2) - 28;
- if (len > max) {
- XGrabServer(display);
- do {
- XChangeProperty(display, root, res_prop, XA_STRING, 8, mode, buf, max);
- buf += max;
- len -= max;
- mode = PropModeAppend;
- } while (len > max);
- }
- XChangeProperty(display, root, res_prop, XA_STRING, 8, mode, buf, len);
- if (mode != PropModeReplace)
- XUngrabServer(display);
- }
- static void
- Process(int scrno, Bool doScreen, Bool execute)
- {
- char *xdefs;
- Window root;
- Atom res_prop;
- FILE *input, *output;
- char *cmd;
- defines.val[defines_base] = '\0';
- defines.used = defines_base;
- buffer.used = 0;
- InitEntries(&newDB);
- DoScreenDefines(dpy, scrno, &defines);
- DoCmdDefines(&defines);
- if (doScreen) {
- xdefs = XScreenResourceString (ScreenOfDisplay(dpy, scrno));
- root = RootWindow(dpy, scrno);
- res_prop = XInternAtom(dpy, SCREEN_RESOURCES, False);
- } else {
- xdefs = XResourceManagerString (dpy);
- root = RootWindow(dpy, 0);
- res_prop = XA_RESOURCE_MANAGER;
- }
- if (oper == OPSYMBOLS) {
- printf ("%s\n", defines.val);
- } else if (oper == OPQUERY) {
- if (xdefs)
- printf ("%s", xdefs); /* fputs broken in SunOS 4.0 */
- } else if (oper == OPREMOVE) {
- if (xdefs)
- XDeleteProperty(dpy, root, res_prop);
- } else if (oper == OPEDIT) {
- char template[100], old[100];
- input = fopen(editFile, "r");
- snprintf(template, sizeof(template), "%sXXXXXX", editFile);
- #ifndef HAVE_MKSTEMP
- (void) mktemp(template);
- output = fopen(template, "w");
- #else
- {
- int fd = mkstemp(template);
- output = fdopen(fd, "w");
- }
- #endif
- if (!output)
- fatal("%s: can't open temporary file '%s'\n", ProgramName, template);
- GetEntriesString(&newDB, xdefs);
- EditFile(&newDB, input, output);
- if (input)
- fclose(input);
- fclose(output);
- snprintf(old, sizeof(old), "%s%s", editFile, backup_suffix);
- if (dont_execute) { /* then write to standard out */
- char buf[BUFSIZ];
- int n;
- output = fopen (template, "r");
- if (output) {
- while ((n = fread (buf, 1, sizeof buf, output)) > 0) {
- fwrite (buf, 1, n, stdout);
- }
- fclose (output);
- }
- unlink (template);
- } else {
- rename (editFile, old);
- if (rename (template, editFile))
- fatal("%s: can't rename file '%s' to '%s'\n", ProgramName,
- template, editFile);
- }
- } else {
- const char *cpp_addflags = "";
- if (oper == OPMERGE || oper == OPOVERRIDE)
- GetEntriesString(&newDB, xdefs);
- /* Add -P flag only if using cpp, not another preprocessor */
- if (cpp_program) {
- const char *cp = strstr(cpp_program, "cpp");
- if (cp && ((cp[3] == '\0') || cp[3] == ' '))
- cpp_addflags = "-P";
- }
- #ifdef PATHETICCPP
- if (need_real_defines) {
- #ifdef WIN32
- if (!(input = fopen(tmpname2, "w")))
- fatal("%s: can't open file '%s'\n", ProgramName, tmpname2);
- fputs(defines.val, input);
- fprintf(input, "\n#include \"%s\"\n", filename);
- fclose(input);
- (void) mktemp(tmpname3);
- if (asprintf(&cmd, "%s %s %s %s > %s", cpp_program, cpp_addflags,
- includes.val, tmpname2, tmpname3) == -1)
- fatal("%s: Out of memory\n", ProgramName);
- if (system(cmd) < 0)
- fatal("%s: cannot run '%s'\n", ProgramName, cmd);
- free(cmd);
- if (!(input = fopen(tmpname3, "r")))
- fatal("%s: can't open file '%s'\n", ProgramName, tmpname3);
- #else
- if (!freopen(tmpname2, "w+", stdin))
- fatal("%s: can't open file '%s'\n", ProgramName, tmpname2);
- fputs(defines.val, stdin);
- fprintf(stdin, "\n#include \"%s\"\n", filename);
- fflush(stdin);
- fseek(stdin, 0, 0);
- if (asprintf(&cmd, "%s %s %s", cpp_program, cpp_addflags,
- includes.val) == -1)
- fatal("%s: Out of memory\n", ProgramName);
- if (!(input = popen(cmd, "r")))
- fatal("%s: cannot run '%s'\n", ProgramName, cmd);
- free(cmd);
- #endif
- } else {
- #endif
- if (filename) {
- if (!freopen (filename, "r", stdin))
- fatal("%s: can't open file '%s'\n", ProgramName, filename);
- }
- if (cpp_program) {
- #ifdef WIN32
- (void) mktemp(tmpname3);
- if (asprintf(&cmd, "%s %s %s %s %s > %s", cpp_program,
- cpp_addflags, includes.val, defines.val,
- filename ? filename : "", tmpname3) == -1)
- fatal("%s: Out of memory\n", ProgramName);
- if (system(cmd) < 0)
- fatal("%s: cannot run '%s'\n", ProgramName, cmd);
- free(cmd);
- if (!(input = fopen(tmpname3, "r")))
- fatal("%s: can't open file '%s'\n", ProgramName, tmpname3);
- #else
- if (asprintf(&cmd, "%s %s %s %s %s", cpp_program,
- cpp_addflags, includes.val, defines.val,
- filename ? filename : "") == -1)
- fatal("%s: Out of memory\n", ProgramName);
- if (!(input = popen(cmd, "r")))
- fatal("%s: cannot run '%s'\n", ProgramName, cmd);
- free(cmd);
- #endif
- } else {
- input = stdin;
- }
- #ifdef PATHETICCPP
- }
- #endif
- ReadFile(&buffer, input);
- if (cpp_program) {
- #ifdef WIN32
- fclose(input);
- #else
- pclose(input);
- #endif
- }
- #ifdef PATHETICCPP
- if (need_real_defines) {
- unlink(tmpname2);
- #ifdef WIN32
- if (tmpname3[strlen(tmpname3) - 1] != 'X')
- unlink(tmpname3);
- #endif
- }
- #endif
- GetEntries(&newDB, &buffer, 0);
- if (execute) {
- FormatEntries(&buffer, &newDB);
- if (dont_execute) {
- if (buffer.used > 0) {
- fwrite (buffer.buff, 1, buffer.used, stdout);
- if (buffer.buff[buffer.used - 1] != '\n') putchar ('\n');
- }
- } else if (buffer.used > 1 || !doScreen)
- StoreProperty (dpy, root, res_prop);
- else
- XDeleteProperty (dpy, root, res_prop);
- }
- }
- if (execute)
- FreeEntries(&newDB);
- if (doScreen && xdefs)
- XFree(xdefs);
- }
- static void
- ShuffleEntries(Entries *db, Entries *dbs, int num)
- {
- int *hits;
- register int i, j, k;
- Entries cur, cmp;
- char *curtag, *curvalue;
- hits = malloc(num * sizeof(int));
- cur = dbs[0];
- for (i = 0; i < cur.used; i++) {
- curtag = cur.entry[i].tag;
- curvalue = cur.entry[i].value;
- for (j = 1; j < num; j++) {
- cmp = dbs[j];
- for (k = 0; k < cmp.used; k++) {
- if (cmp.entry[k].usable &&
- !strcmp(curtag, cmp.entry[k].tag) &&
- !strcmp(curvalue, cmp.entry[k].value))
- {
- hits[j] = k;
- break;
- }
- }
- if (k == cmp.used)
- break;
- }
- if (j == num) {
- AddEntry(db, &cur.entry[i]);
- hits[0] = i;
- for (j = 0; j < num; j++)
- dbs[j].entry[hits[j]].usable = False;
- }
- }
- free((char *)hits);
- }
- static void
- ReProcess(int scrno, Bool doScreen)
- {
- Window root;
- Atom res_prop;
- FormatEntries(&buffer, &newDB);
- if (doScreen) {
- root = RootWindow(dpy, scrno);
- res_prop = XInternAtom(dpy, SCREEN_RESOURCES, False);
- } else {
- root = RootWindow(dpy, 0);
- res_prop = XA_RESOURCE_MANAGER;
- }
- if (dont_execute) {
- if (buffer.used > 0) {
- fwrite (buffer.buff, 1, buffer.used, stdout);
- if (buffer.buff[buffer.used - 1] != '\n') putchar ('\n');
- }
- } else {
- if (buffer.used > 1 || !doScreen)
- StoreProperty (dpy, root, res_prop);
- else
- XDeleteProperty (dpy, root, res_prop);
- }
- FreeEntries(&newDB);
- }
- static void
- fatal(const char *msg, ...)
- {
- va_list args;
- if (errno != 0)
- perror(ProgramName);
- va_start(args, msg);
- vfprintf(stderr, msg, args);
- va_end(args);
- exit(1);
- }
|