Bug Summary

File:xrdb.c
Location:line 756, column 14
Description:Potential leak of memory pointed to by 'b.buff'

Annotated Source Code

1/*
2 * xrdb - X resource manager database utility
3 *
4 */
5
6/*
7 * COPYRIGHT 1987, 1991
8 * DIGITAL EQUIPMENT CORPORATION
9 * MAYNARD, MASSACHUSETTS
10 * MASSACHUSETTS INSTITUTE OF TECHNOLOGY
11 * CAMBRIDGE, MASSACHUSETTS
12 * ALL RIGHTS RESERVED.
13 *
14 * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
15 * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
16 * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
17 * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
18 *
19 * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS,
20 * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT
21 * SET FORTH ABOVE.
22 *
23 *
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation for any purpose and without fee is hereby granted, provided
26 * that the above copyright notice appear in all copies and that both that
27 * copyright notice and this permission notice appear in supporting
28 * documentation, and that the name of Digital Equipment Corporation not be
29 * used in advertising or publicity pertaining to distribution of the software
30 * without specific, written prior permission.
31 */
32
33/*
34 * this program is used to load, or dump the resource manager database
35 * in the server.
36 *
37 * Original Author: Jim Gettys, August 28, 1987
38 * Extensively Modified: Phil Karlton, January 5, 1987
39 * Modified a Bunch More: Bob Scheifler, February, 1991
40 */
41
42#ifdef HAVE_CONFIG_H1
43#include <config.h>
44#endif
45
46#include <X11/Xlib.h>
47#include <X11/Xutil.h>
48#include <X11/Xatom.h>
49#include <X11/Xos.h>
50#include <X11/Xmu/SysUtil.h>
51#include <stdio.h>
52#include <ctype.h>
53#include <errno(*__error()).h>
54#include <stdlib.h>
55#include <stdarg.h>
56#include <stdint.h>
57
58#ifdef NEED_SYS_PARAM_H1
59# include <sys/param.h> /* defines MAXHOSTNAMELEN on BSD & Linux */
60#endif
61
62#ifdef NEED_NETDB_H
63# include <netdb.h> /* defines MAXHOSTNAMELEN on Solaris */
64#endif
65
66#define SCREEN_RESOURCES"SCREEN_RESOURCES" "SCREEN_RESOURCES"
67
68#ifndef CPP"/usr/bin/cpp"
69#define CPP"/usr/bin/cpp" "/usr/lib/cpp"
70#endif /* CPP */
71
72#define INIT_BUFFER_SIZE10000 10000
73#define INIT_ENTRY_SIZE500 500
74
75#define RALL0 0
76#define RGLOBAL1 1
77#define RSCREEN2 2
78#define RSCREENS3 3
79
80#define OPSYMBOLS0 0
81#define OPQUERY1 1
82#define OPREMOVE2 2
83#define OPEDIT3 3
84#define OPLOAD4 4
85#define OPMERGE5 5
86#define OPOVERRIDE6 6
87
88#define BACKUP_SUFFIX".bak" ".bak" /* for editing */
89
90typedef struct _Entry {
91 char *tag, *value;
92 int lineno;
93 Boolint usable;
94} Entry;
95
96typedef struct _Buffer {
97 char *buff;
98 size_t room, used;
99} Buffer;
100
101typedef struct _Entries {
102 Entry *entry;
103 size_t room, used;
104} Entries;
105
106/* dynamically allocated strings */
107#define CHUNK_SIZE4096 4096
108typedef struct _String {
109 char *val;
110 size_t room, used;
111} String;
112
113static char *ProgramName;
114static Boolint quiet = False0;
115static char tmpname[32];
116static char *filename = NULL((void*)0);
117#ifdef PATHETICCPP
118static Boolint need_real_defines = False0;
119static char tmpname2[32];
120#endif
121#ifdef WIN32
122static char tmpname3[32];
123#endif
124static int oper = OPLOAD4;
125static char *editFile = NULL((void*)0);
126static const char *cpp_program = NULL((void*)0);
127static const char * const cpp_locations[] = { CPP"/usr/bin/cpp" };
128static const char *backup_suffix = BACKUP_SUFFIX".bak";
129static Boolint dont_execute = False0;
130static String defines;
131static size_t defines_base;
132#define MAX_CMD_DEFINES512 512
133static char *cmd_defines[MAX_CMD_DEFINES512];
134static int num_cmd_defines = 0;
135static String includes;
136static Display *dpy;
137static Buffer buffer;
138static Entries newDB;
139
140static void fatal(const char *, ...)
141 _X_ATTRIBUTE_PRINTF(1, 2)__attribute__((__format__(__printf__,1,2)))_X_NORETURN__attribute((noreturn)) _X_COLD__attribute__((__cold__));
142static void addstring(String *arg, const char *s);
143static void addescapedstring(String *arg, const char *s);
144static void addtokstring(String *arg, const char *s);
145static void FormatEntries(Buffer *b, Entries * entries);
146static void StoreProperty(Display *display, Window root, Atom res_prop);
147static void Process(int scrno, Boolint doScreen, Boolint execute);
148static void ShuffleEntries(Entries *db, Entries *dbs, unsigned int num);
149static void ReProcess(int scrno, Boolint doScreen);
150
151#ifndef HAVE_ASPRINTF1
152/* sprintf variant found in newer libc's which allocates string to print to */
153static int _X_ATTRIBUTE_PRINTF(2, 3)__attribute__((__format__(__printf__,2,3)))
154asprintf(char **ret, const char *format, ...)
155{
156 char buf[256];
157 int len;
158 va_list ap;
159
160 va_start(ap, format)__builtin_va_start(ap, format);
161 len = vsnprintf(buf, sizeof(buf), format, ap)__builtin___vsnprintf_chk (buf, sizeof(buf), 0, __builtin_object_size
(buf, 2 > 1 ? 1 : 0), format, ap)
;
162 va_end(ap)__builtin_va_end(ap);
163
164 if (len < 0)
165 return -1;
166
167 if (len < sizeof(buf)) {
168 *ret = strdup(buf);
169 }
170 else {
171 *ret = malloc(len + 1); /* snprintf doesn't count trailing '\0' */
172 if (*ret != NULL((void*)0)) {
173 va_start(ap, format)__builtin_va_start(ap, format);
174 len = vsnprintf(*ret, len + 1, format, ap)__builtin___vsnprintf_chk (*ret, len + 1, 0, __builtin_object_size
(*ret, 2 > 1 ? 1 : 0), format, ap)
;
175 va_end(ap)__builtin_va_end(ap);
176 if (len < 0) {
177 free(*ret);
178 *ret = NULL((void*)0);
179 }
180 }
181 }
182
183 if (*ret == NULL((void*)0))
184 return -1;
185
186 return len;
187}
188#endif /* HAVE_ASPRINTF */
189
190#ifndef HAVE_REALLOCARRAY
191/* overflow checking realloc API from OpenBSD libc */
192static inline void *
193reallocarray(void *optr, size_t n, size_t s)
194{
195 if (n > 0 && (SIZE_MAX18446744073709551615ULL / n) < s)
16
Taking false branch
196 return NULL((void*)0);
197 return realloc(optr, n * s);
17
Memory is allocated
198}
199#endif
200
201# define mallocarray(n, s)reallocarray(((void*)0), n, s) reallocarray(NULL((void*)0), n, s)
202
203static void
204InitBuffer(Buffer *b)
205{
206 b->room = INIT_BUFFER_SIZE10000;
207 b->used = 0;
208 b->buff = mallocarray(INIT_BUFFER_SIZE, sizeof(char))reallocarray(((void*)0), 10000, sizeof(char));
15
Within the expansion of the macro 'mallocarray':
a
Calling 'reallocarray'
b
Returned allocated memory
209 if (b->buff == NULL((void*)0))
18
Taking false branch
210 fatal("%s: Can't allocate memory in %s\n", ProgramName, __func__);
211}
212
213#ifdef notyet
214static void
215FreeBuffer(Buffer *b)
216{
217 free(b->buff);
218}
219#endif
220
221static void
222AppendToBuffer(Buffer *b, const char *str, size_t len)
223{
224 while (b->used + len > b->room) {
225 b->buff = reallocarray(b->buff, b->room, 2 * sizeof(char));
226 if (b->buff == NULL((void*)0))
227 fatal("%s: Can't allocate memory in %s\n", ProgramName, __func__);
228 b->room *= 2;
229 }
230 strncpy(b->buff + b->used, str, len)__builtin___strncpy_chk (b->buff + b->used, str, len, __builtin_object_size
(b->buff + b->used, 2 > 1 ? 1 : 0))
;
231 b->used += len;
232}
233
234static void
235InitEntries(Entries *e)
236{
237 e->room = INIT_ENTRY_SIZE500;
238 e->used = 0;
239 e->entry = mallocarray(INIT_ENTRY_SIZE, sizeof(Entry))reallocarray(((void*)0), 500, sizeof(Entry));
240 if (e->entry == NULL((void*)0))
241 fatal("%s: Can't allocate memory in %s\n", ProgramName, __func__);
242
243}
244
245static void
246FreeEntries(Entries *e)
247{
248 size_t i;
249
250 for (i = 0; i < e->used; i++) {
251 if (e->entry[i].usable) {
252 free(e->entry[i].tag);
253 free(e->entry[i].value);
254 }
255 }
256 free(e->entry);
257}
258
259static void
260AddEntry(Entries *e, Entry *entry)
261{
262 size_t n;
263
264 for (n = 0; n < e->used; n++) {
265 if (!strcmp(e->entry[n].tag, entry->tag)) {
266 /* overwrite old entry */
267 if (e->entry[n].lineno && !quiet) {
268 fprintf(stderr__stderrp,
269 "%s: \"%s\" on line %d overrides entry on line %d\n",
270 ProgramName, entry->tag, entry->lineno,
271 e->entry[n].lineno);
272 }
273 free(e->entry[n].tag);
274 free(e->entry[n].value);
275 entry->usable = True1;
276 e->entry[n] = *entry;
277 return; /* ok to leave, now there's only one of each tag in db */
278 }
279 }
280
281 if (e->used == e->room) {
282 e->entry = reallocarray(e->entry, e->room, 2 * sizeof(Entry));
283 if (e->entry == NULL((void*)0))
284 fatal("%s: Can't allocate memory in %s\n", ProgramName, __func__);
285 e->room *= 2;
286 }
287 entry->usable = True1;
288 e->entry[e->used++] = *entry;
289}
290
291static int
292CompareEntries(const void *e1, const void *e2)
293{
294 return strcmp(((const Entry *) e1)->tag, ((const Entry *) e2)->tag);
295}
296
297static void
298AppendEntryToBuffer(Buffer *b, Entry *entry)
299{
300 AppendToBuffer(b, entry->tag, strlen(entry->tag));
301 AppendToBuffer(b, ":\t", 2);
302 AppendToBuffer(b, entry->value, strlen(entry->value));
303 AppendToBuffer(b, "\n", 1);
304}
305
306/*
307 * Return the position of the first unescaped occurrence of dest in string.
308 * If lines is non-null, return the number of newlines skipped over.
309 */
310static const char *
311FindFirst(const char *string, char dest, int *lines)
312{
313 if (lines)
314 *lines = 0;
315 for (;;) {
316 if (*string == '\0')
317 return NULL((void*)0);
318 if (*string == '\\') {
319 if (*++string == '\0')
320 return NULL((void*)0);
321 }
322 else if (*string == dest)
323 return string;
324 if (*string == '\n' && lines)
325 (*lines)++;
326 string++;
327 }
328}
329
330static void
331GetEntries(Entries *entries, Buffer *buff, int bequiet)
332{
333 const char *line, *colon, *temp, *str;
334 Entry entry;
335 size_t length;
336 int lineno = 0;
337 int lines_skipped;
338
339 str = buff->buff;
340 if (!str)
341 return;
342 for (; str < buff->buff + buff->used;
343 str = line + 1, lineno += lines_skipped) {
344 line = FindFirst(str, '\n', &lines_skipped);
345 lineno++;
346 if (!line)
347 line = buff->buff + buff->used;
348 if (*str == '!')
349 continue;
350 if (*str == '\n')
351 continue;
352 if (!bequiet && *str == '#') {
353 int dummy;
354
355 if (sscanf(str, "# %d", &dummy) == 1 ||
356 sscanf(str, "# line %d", &dummy) == 1)
357 lineno = dummy - 1;
358 continue;
359 }
360 for (temp = str;
361 *temp && *temp != '\n' && isascii(*temp) && isspace(*temp);
362 temp++);
363 if (!*temp || *temp == '\n')
364 continue;
365
366 colon = FindFirst(str, ':', NULL((void*)0));
367 if (!colon || colon > line) {
368 if (!bequiet && !quiet)
369 fprintf(stderr__stderrp,
370 "%s: colon missing on line %d, ignoring line\n",
371 ProgramName, lineno);
372 continue;
373 }
374
375 /* strip leading and trailing blanks from name and store result */
376 while (*str == ' ' || *str == '\t')
377 str++;
378 length = colon - str;
379 while (length && (str[length - 1] == ' ' || str[length - 1] == '\t'))
380 length--;
381 entry.tag = malloc(length + 1);
382 strncpy(entry.tag, str, length)__builtin___strncpy_chk (entry.tag, str, length, __builtin_object_size
(entry.tag, 2 > 1 ? 1 : 0))
;
383 entry.tag[length] = '\0';
384
385 /* strip leading and trailing blanks from value and store result */
386 colon++;
387 while (*colon == ' ' || *colon == '\t')
388 colon++;
389 length = line - colon;
390 entry.value = malloc(length + 1);
391 strncpy(entry.value, colon, length)__builtin___strncpy_chk (entry.value, colon, length, __builtin_object_size
(entry.value, 2 > 1 ? 1 : 0))
;
392 entry.value[length] = '\0';
393 entry.lineno = bequiet ? 0 : lineno;
394
395 AddEntry(entries, &entry);
396 }
397}
398
399static void
400GetEntriesString(Entries *entries, char *str)
401{
402 Buffer buff;
403
404 if (str && *str) {
405 buff.buff = str;
406 buff.used = strlen(str);
407 GetEntries(entries, &buff, 1);
408 }
409}
410
411static void
412ReadFile(Buffer *b, FILE *input)
413{
414 char buf[BUFSIZ1024 + 1];
415 size_t bytes;
416
417 b->used = 0;
418 while (!feof(input) && (bytes = fread(buf, 1, BUFSIZ1024, input)) > 0) {
419#ifdef WIN32
420 char *p;
421
422 buf[bytes] = '\0';
423 for (p = buf; p = strchr(p, '\r');) {
424 if (p[-1] == '\\' && p[1] == '\n') {
425 bytes -= 3;
426 strcpy(p - 1, p + 2)__builtin___strcpy_chk (p - 1, p + 2, __builtin_object_size (
p - 1, 2 > 1 ? 1 : 0))
;
427 }
428 }
429#endif
430 AppendToBuffer(b, buf, bytes);
431 }
432 AppendToBuffer(b, "", 1);
433}
434
435static void
436AddDef(String *buff, const char *title, const char *value)
437{
438#ifdef PATHETICCPP
439 if (need_real_defines) {
440 addstring(buff, "\n#define ");
441 addtokstring(buff, title);
442 if (value && (value[0] != '\0')) {
443 addstring(buff, " ");
444 addstring(buff, value);
445 }
446 return;
447 }
448#endif
449 if (buff->used) {
450 if (oper == OPSYMBOLS0)
451 addstring(buff, "\n-D");
452 else
453 addstring(buff, " -D");
454 }
455 else
456 addstring(buff, "-D");
457 addtokstring(buff, title);
458 if (value && (value[0] != '\0')) {
459 addstring(buff, "=");
460 addescapedstring(buff, value);
461 }
462}
463
464static void
465AddSimpleDef(String *buff, const char *title)
466{
467 AddDef(buff, title, (char *) NULL((void*)0));
468}
469
470static void
471AddDefQ(String *buff, const char *title, const char *value)
472{
473#ifdef PATHETICCPP
474 if (need_real_defines)
475 AddDef(buff, title, value);
476 else
477#endif
478 if (value && (value[0] != '\0')) {
479 AddSimpleDef(buff, title);
480 addstring(buff, "=\"");
481 addescapedstring(buff, value);
482 addstring(buff, "\"");
483 }
484 else
485 AddDef(buff, title, NULL((void*)0));
486}
487
488static void
489AddNum(String *buff, const char *title, int value)
490{
491 char num[20];
492
493 snprintf(num, sizeof(num), "%d", value)__builtin___snprintf_chk (num, sizeof(num), 0, __builtin_object_size
(num, 2 > 1 ? 1 : 0), "%d", value)
;
494 AddDef(buff, title, num);
495}
496
497static void
498AddDefTok(String *buff, const char *prefix, char *title)
499{
500 char name[512];
501
502 snprintf(name, sizeof(name), "%s%s", prefix, title)__builtin___snprintf_chk (name, sizeof(name), 0, __builtin_object_size
(name, 2 > 1 ? 1 : 0), "%s%s", prefix, title)
;
503 AddSimpleDef(buff, name);
504}
505
506static void
507AddDefHostname(String *buff, const char *title, const char *value)
508{
509 char *s;
510 char name[512];
511 char c;
512
513 strncpy(name, value, sizeof(name) - 1)__builtin___strncpy_chk (name, value, sizeof(name) - 1, __builtin_object_size
(name, 2 > 1 ? 1 : 0))
;
514 name[sizeof(name) - 1] = '\0';
515 for (s = name; (c = *s); s++) {
516 if (!isalpha(c) && !isdigit(c) &&
517 c != '_' && c != '.' && c != ':' && c != '-')
518 *s = '_';
519 }
520 AddDef(buff, title, name);
521}
522
523static void
524AddUndef(String *buff, const char *title)
525{
526#ifdef PATHETICCPP
527 if (need_real_defines) {
528 addstring(buff, "\n#undef ");
529 addstring(buff, title);
530 return;
531 }
532#endif
533 if (buff->used) {
534 if (oper == OPSYMBOLS0)
535 addstring(buff, "\n-U");
536 else
537 addstring(buff, " -U");
538 }
539 else
540 addstring(buff, "-U");
541 addtokstring(buff, title);
542}
543
544static void
545DoCmdDefines(String *buff)
546{
547 int i;
548 char *arg, *val;
549
550 for (i = 0; i < num_cmd_defines; i++) {
551 arg = cmd_defines[i];
552 if (arg[1] == 'D') {
553 val = strchr(arg, '=');
554 if (val) {
555 *val = '\0';
556 AddDefQ(buff, arg + 2, val + 1);
557 *val = '=';
558 }
559 else
560 AddSimpleDef(buff, arg + 2);
561 }
562 else if (arg[1] == 'U') {
563 AddUndef(buff, arg + 2);
564 }
565 else if (!strcmp(arg, "-undef") && oper != OPSYMBOLS0) {
566 addstring(buff, " -undef");
567 }
568 }
569}
570
571static int
572Resolution(int pixels, int mm)
573{
574 if (mm == 0)
575 return 0;
576 else
577 return ((pixels * 100000 / mm) + 50) / 100;
578}
579
580static void
581DoDisplayDefines(Display *display, String *defs, char *host)
582{
583#ifndef MAXHOSTNAMELEN256
584#define MAXHOSTNAMELEN256 255
585#endif
586 char client[MAXHOSTNAMELEN256], server[MAXHOSTNAMELEN256], *colon;
587 char **extnames;
588 int n;
589
590 XmuGetHostname(client, MAXHOSTNAMELEN256);
591 strncpy(server, XDisplayName(host), sizeof(server))__builtin___strncpy_chk (server, XDisplayName(host), sizeof(server
), __builtin_object_size (server, 2 > 1 ? 1 : 0))
;
592 server[sizeof(server) - 1] = '\0';
593 /* search for final colon to skip over any embedded colons in IPv6
594 numeric address forms */
595 colon = strrchr(server, ':');
596 n = 0;
597 if (colon) {
598 /* remove extra colon if there are exactly two, since it indicates
599 DECnet. Three colons is an IPv6 address ending in :: though. */
600 if ((colon > server) && (*(colon - 1) == ':') &&
601 (((colon - 1) == server) || (*(colon - 2) != ':'))) {
602 *(colon - 1) = ':';
603 }
604 *colon++ = '\0';
605 sscanf(colon, "%d", &n);
606 }
607 if (!*server || !strcmp(server, "unix") || !strcmp(server, "localhost"))
608 strcpy(server, client)__builtin___strcpy_chk (server, client, __builtin_object_size
(server, 2 > 1 ? 1 : 0))
;
609 AddDefHostname(defs, "HOST", server); /* R3 compatibility */
610 AddDefHostname(defs, "SERVERHOST", server);
611 AddDefTok(defs, "SRVR_", server);
612 AddNum(defs, "DISPLAY_NUM", n);
613 AddDefHostname(defs, "CLIENTHOST", client);
614 AddDefTok(defs, "CLNT_", client);
615 AddNum(defs, "VERSION", ProtocolVersion(display)(((_XPrivDisplay)(display))->proto_major_version));
616 AddNum(defs, "REVISION", ProtocolRevision(display)(((_XPrivDisplay)(display))->proto_minor_version));
617 AddDefQ(defs, "VENDOR", ServerVendor(display)(((_XPrivDisplay)(display))->vendor));
618 AddDefTok(defs, "VNDR_", ServerVendor(display)(((_XPrivDisplay)(display))->vendor));
619 AddNum(defs, "RELEASE", VendorRelease(display)(((_XPrivDisplay)(display))->release));
620 AddNum(defs, "NUM_SCREENS", ScreenCount(display)(((_XPrivDisplay)(display))->nscreens));
621 extnames = XListExtensions(display, &n);
622 while (--n >= 0)
623 AddDefTok(defs, "EXT_", extnames[n]);
624 XFreeExtensionList(extnames);
625}
626
627static const char *ClassNames[] = {
628 "StaticGray",
629 "GrayScale",
630 "StaticColor",
631 "PseudoColor",
632 "TrueColor",
633 "DirectColor"
634};
635
636#define NUM_CLASS_NAMES(int)(sizeof(ClassNames) / sizeof(ClassNames[0])) (int)(sizeof(ClassNames) / sizeof(ClassNames[0]))
637
638static void
639DoScreenDefines(Display *display, int scrno, String *defs)
640{
641 Screen *screen;
642 Visual *visual;
643 XVisualInfo vinfo, *vinfos;
644 int nv, i, j;
645 char name[50];
646
647 screen = ScreenOfDisplay(display, scrno)(&((_XPrivDisplay)(display))->screens[scrno]);
648 visual = DefaultVisualOfScreen(screen)((screen)->root_visual);
649 vinfo.screen = scrno;
650 vinfos = XGetVisualInfo(display, VisualScreenMask0x2, &vinfo, &nv);
651 AddNum(defs, "SCREEN_NUM", scrno);
652 AddNum(defs, "WIDTH", screen->width);
653 AddNum(defs, "HEIGHT", screen->height);
654 AddNum(defs, "X_RESOLUTION", Resolution(screen->width, screen->mwidth));
655 AddNum(defs, "Y_RESOLUTION", Resolution(screen->height, screen->mheight));
656 AddNum(defs, "PLANES", DisplayPlanes(display, scrno)((&((_XPrivDisplay)(display))->screens[scrno])->root_depth
)
);
657 AddNum(defs, "BITS_PER_RGB", visual->bits_per_rgb);
658 if (visual->class >= 0 && visual->class < NUM_CLASS_NAMES(int)(sizeof(ClassNames) / sizeof(ClassNames[0]))) {
659 AddDefQ(defs, "CLASS", ClassNames[visual->class]);
660 snprintf(name, sizeof(name), "CLASS_%s", ClassNames[visual->class])__builtin___snprintf_chk (name, sizeof(name), 0, __builtin_object_size
(name, 2 > 1 ? 1 : 0), "CLASS_%s", ClassNames[visual->
class])
;
661 AddNum(defs, name, (int) visual->visualid);
662 }
663 else {
664 fprintf(stderr__stderrp,
665 "%s: unknown visual type %d for default visual id 0x%lx\n",
666 ProgramName, visual->class, visual->visualid);
667 }
668 switch (visual->class) {
669 case StaticColor2:
670 case PseudoColor3:
671 case TrueColor4:
672 case DirectColor5:
673 AddSimpleDef(defs, "COLOR");
674 break;
675 }
676 for (i = 0; i < nv; i++) {
677 for (j = i; --j >= 0;) {
678 if (vinfos[j].class == vinfos[i].class &&
679 vinfos[j].depth == vinfos[i].depth)
680 break;
681 }
682 if (j < 0) {
683 if (vinfos[i].class >= 0 && vinfos[i].class < NUM_CLASS_NAMES(int)(sizeof(ClassNames) / sizeof(ClassNames[0]))) {
684 snprintf(name, sizeof(name), "CLASS_%s_%d",__builtin___snprintf_chk (name, sizeof(name), 0, __builtin_object_size
(name, 2 > 1 ? 1 : 0), "CLASS_%s_%d", ClassNames[vinfos[i
].class], vinfos[i].depth)
685 ClassNames[vinfos[i].class], vinfos[i].depth)__builtin___snprintf_chk (name, sizeof(name), 0, __builtin_object_size
(name, 2 > 1 ? 1 : 0), "CLASS_%s_%d", ClassNames[vinfos[i
].class], vinfos[i].depth)
;
686 AddNum(defs, name, (int) vinfos[i].visualid);
687 }
688 else {
689 fprintf(stderr__stderrp,
690 "%s: unknown visual type %d for visual id 0x%lx\n",
691 ProgramName, vinfos[i].class, vinfos[i].visualid);
692 }
693 }
694 }
695 XFree(vinfos);
696}
697
698static Entry *
699FindEntry(Entries *db, Buffer *b)
700{
701 size_t i;
702 register Entry *e;
703 Entries phoney;
704 Entry entry;
705
706 entry.usable = False0;
707 entry.tag = NULL((void*)0);
708 entry.value = NULL((void*)0);
709 phoney.used = 0;
710 phoney.room = 1;
711 phoney.entry = &entry;
712 GetEntries(&phoney, b, 1);
713 if (phoney.used < 1)
714 return NULL((void*)0);
715 for (i = 0; i < db->used; i++) {
716 e = &db->entry[i];
717 if (!e->usable)
718 continue;
719 if (strcmp(e->tag, entry.tag))
720 continue;
721 e->usable = False0;
722 if (strcmp(e->value, entry.value))
723 return e;
724 return NULL((void*)0);
725 }
726 return NULL((void*)0);
727}
728
729static void
730EditFile(Entries *new, FILE *in, FILE *out)
731{
732 Buffer b;
733 char buff[BUFSIZ1024];
734 register Entry *e;
735 register char *c;
736 size_t i;
737
738 InitBuffer(&b);
14
Calling 'InitBuffer'
19
Returned allocated memory
739 while (in) {
20
Loop condition is false. Execution continues on line 756
740 b.used = 0;
741 while (1) {
742 buff[0] = '\0';
743 if (!fgets(buff, BUFSIZ1024, in))
744 goto cleanup;
745 AppendToBuffer(&b, buff, strlen(buff));
746 c = &b.buff[b.used - 1];
747 if ((*(c--) == '\n') && (b.used == 1 || *c != '\\'))
748 break;
749 }
750 if ((e = FindEntry(new, &b)))
751 fprintf(out, "%s:\t%s\n", e->tag, e->value);
752 else
753 fwrite(b.buff, 1, b.used, out);
754 }
755 cleanup:
756 for (i = 0; i < new->used; i++) {
21
Potential leak of memory pointed to by 'b.buff'
757 e = &new->entry[i];
758 if (e->usable)
759 fprintf(out, "%s:\t%s\n", e->tag, e->value);
760 }
761}
762
763static void _X_NORETURN__attribute((noreturn)) _X_COLD__attribute__((__cold__))
764Syntax(const char *errmsg)
765{
766 if (errmsg != NULL((void*)0))
767 fprintf(stderr__stderrp, "%s: %s\n", ProgramName, errmsg);
768
769 fprintf(stderr__stderrp,
770 "usage: %s [-options ...] [filename]\n\n"
771 "where options include:\n"
772 " -help print this help message\n"
773 " -version print the program version\n"
774 " -display host:dpy display to use\n"
775 " -all do all resources [default]\n"
776 " -global do screen-independent resources\n"
777 " -screen do screen-specific resources for one screen\n"
778 " -screens do screen-specific resources for all screens\n"
779 " -n show but don't do changes\n"
780 " -cpp filename preprocessor to use [%s]\n"
781 " -nocpp do not use a preprocessor\n"
782 " -query query resources\n"
783 " -load load resources from file [default]\n"
784 " -override add in resources from file\n"
785 " -merge merge resources from file & sort\n"
786 " -edit filename edit resources into file\n"
787 " -backup string backup suffix for -edit [%s]\n"
788 " -symbols show preprocessor symbols\n"
789 " -remove remove resources\n"
790 " -retain avoid server reset (avoid using this)\n"
791 " -quiet don't warn about duplicates\n"
792 " -Dname[=value], -Uname, -Idirectory passed to preprocessor\n"
793 "\n"
794 "A - or no input filename represents stdin.\n",
795 ProgramName, cpp_program ? cpp_program : "", BACKUP_SUFFIX".bak");
796 exit(1);
797}
798
799/*
800 * The following is a hack until XrmParseCommand is ready. It determines
801 * whether or not the given string is an abbreviation of the arg.
802 */
803
804static Boolint
805isabbreviation(const char *arg, const char *s, size_t minslen)
806{
807 size_t arglen;
808 size_t slen;
809
810 /* exact match */
811 if (!strcmp(arg, s))
812 return (True1);
813
814 arglen = strlen(arg);
815 slen = strlen(s);
816
817 /* too long or too short */
818 if (slen >= arglen || slen < minslen)
819 return (False0);
820
821 /* abbreviation */
822 if (strncmp(arg, s, slen) == 0)
823 return (True1);
824
825 /* bad */
826 return (False0);
827}
828
829static void
830addstring(String *arg, const char *s)
831{
832 if (arg->used + strlen(s) + 1 >= arg->room) {
833 if (arg->val)
834 arg->val = realloc(arg->val, arg->room + CHUNK_SIZE4096);
835 else
836 arg->val = malloc(arg->room + CHUNK_SIZE4096);
837 if (arg->val == NULL((void*)0))
838 fatal("%s: Not enough memory\n", ProgramName);
839 arg->room += CHUNK_SIZE4096;
840 }
841 if (arg->used)
842 strcat(arg->val, s)__builtin___strcat_chk (arg->val, s, __builtin_object_size
(arg->val, 2 > 1 ? 1 : 0))
;
843 else
844 strcpy(arg->val, s)__builtin___strcpy_chk (arg->val, s, __builtin_object_size
(arg->val, 2 > 1 ? 1 : 0))
;
845 arg->used += strlen(s);
846}
847
848static void
849addescapedstring(String *arg, const char *s)
850{
851 char copy[512], *c;
852
853 for (c = copy; *s && c < &copy[sizeof(copy) - 1]; s++) {
854 switch (*s) {
855 case '"':
856 case '\'':
857 case '`':
858 case '$':
859 case '\\':
860 *c++ = '_';
861 break;
862 default:
863 *c++ = *s;
864 }
865 }
866 *c = 0;
867 addstring(arg, copy);
868}
869
870static void
871addtokstring(String *arg, const char *s)
872{
873 char copy[512], *c;
874
875 for (c = copy; *s && c < &copy[sizeof(copy) - 1]; s++) {
876 if (!isalpha(*s) && !isdigit(*s) && *s != '_')
877 *c++ = '_';
878 else
879 *c++ = *s;
880 }
881 *c = 0;
882 addstring(arg, copy);
883}
884
885
886int
887main(int argc, char *argv[])
888{
889 int i;
890 char *displayname = NULL((void*)0);
891 int whichResources = RALL0;
892 int retainProp = 0;
893 FILE *fp = NULL((void*)0);
894 Boolint need_newline;
895
896 ProgramName = argv[0];
897
898 defines.room = defines.used = includes.room = includes.used = 0;
899
900 /* initialize the includes String struct */
901 addstring(&includes, "");
902
903 /* Pick the default cpp to use. This needs to be done before
904 * we parse the command line in order to honor -nocpp which sets
905 * it back to NULL.
906 */
907 if (cpp_program == NULL((void*)0)) {
908 int number_of_elements
909 = (sizeof cpp_locations) / (sizeof cpp_locations[0]);
910 int j;
911
912 for (j = 0; j < number_of_elements; j++) {
913 char *end, *dup;
914
915 /* cut off arguments */
916 dup = strdup(cpp_locations[j]);
917 end = strchr(dup, ' ');
918 if (end)
919 *end = '\0';
920 if (access(dup, X_OK(1<<0)) == 0) {
921 cpp_program = cpp_locations[j];
922 free(dup);
923 break;
924 }
925 free(dup);
926 }
927 }
928
929 /* needs to be replaced with XrmParseCommand */
930
931 for (i = 1; i < argc; i++) {
932 char *arg = argv[i];
933
934 if (arg[0] == '-') {
935 if (arg[1] == '\0') {
936 filename = NULL((void*)0);
937 continue;
938 }
939 else if (isabbreviation("-help", arg, 2)) {
940 Syntax(NULL((void*)0));
941 /* doesn't return */
942 }
943 else if (isabbreviation("-version", arg, 2)) {
944 printf("%s\n", PACKAGE_STRING"xrdb 1.1.0");
945 exit(0);
946 }
947 else if (isabbreviation("-display", arg, 2)) {
948 if (++i >= argc)
949 Syntax("-display requires an argument");
950 displayname = argv[i];
951 continue;
952 }
953 else if (isabbreviation("-geometry", arg, 3)) {
954 if (++i >= argc)
955 Syntax("-geometry requires an argument");
956 /* ignore geometry */
957 continue;
958 }
959 else if (isabbreviation("-cpp", arg, 2)) {
960 if (++i >= argc)
961 Syntax("-cpp requires an argument");
962 cpp_program = argv[i];
963 continue;
964 }
965 else if (!strcmp("-n", arg)) {
966 dont_execute = True1;
967 continue;
968 }
969 else if (isabbreviation("-nocpp", arg, 3)) {
970 cpp_program = NULL((void*)0);
971 continue;
972 }
973 else if (isabbreviation("-query", arg, 2)) {
974 oper = OPQUERY1;
975 continue;
976 }
977 else if (isabbreviation("-load", arg, 2)) {
978 oper = OPLOAD4;
979 continue;
980 }
981 else if (isabbreviation("-merge", arg, 2)) {
982 oper = OPMERGE5;
983 continue;
984 }
985 else if (isabbreviation("-override", arg, 2)) {
986 oper = OPOVERRIDE6;
987 continue;
988 }
989 else if (isabbreviation("-symbols", arg, 3)) {
990 oper = OPSYMBOLS0;
991 continue;
992 }
993 else if (isabbreviation("-remove", arg, 4)) {
994 oper = OPREMOVE2;
995 continue;
996 }
997 else if (isabbreviation("-edit", arg, 2)) {
998 if (++i >= argc)
999 Syntax("-edit requires an argument");
1000 oper = OPEDIT3;
1001 editFile = argv[i];
1002 continue;
1003 }
1004 else if (isabbreviation("-backup", arg, 2)) {
1005 if (++i >= argc)
1006 Syntax("-backup requires an argument");
1007 backup_suffix = argv[i];
1008 continue;
1009 }
1010 else if (isabbreviation("-all", arg, 2)) {
1011 whichResources = RALL0;
1012 continue;
1013 }
1014 else if (isabbreviation("-global", arg, 3)) {
1015 whichResources = RGLOBAL1;
1016 continue;
1017 }
1018 else if (isabbreviation("-screen", arg, 3)) {
1019 whichResources = RSCREEN2;
1020 continue;
1021 }
1022 else if (!strcmp("-screens", arg)) {
1023 whichResources = RSCREENS3;
1024 continue;
1025 }
1026 else if (isabbreviation("-retain", arg, 4)) {
1027 retainProp = 1;
1028 continue;
1029 }
1030 else if (isabbreviation("-quiet", arg, 2)) {
1031 quiet = True1;
1032 continue;
1033 }
1034 else if (arg[1] == 'I') {
1035 addstring(&includes, " ");
1036 addescapedstring(&includes, arg);
1037 continue;
1038 }
1039 else if (arg[1] == 'U' || arg[1] == 'D') {
1040 if (num_cmd_defines < MAX_CMD_DEFINES512) {
1041 cmd_defines[num_cmd_defines++] = arg;
1042 }
1043 else {
1044 fatal("%s: Too many -U/-D arguments\n", ProgramName);
1045 }
1046 continue;
1047 }
1048 else if (!strcmp("-undef", arg)) {
1049 if (num_cmd_defines < MAX_CMD_DEFINES512) {
1050 cmd_defines[num_cmd_defines++] = "-undef";
1051 }
1052 else {
1053 fatal("%s: Too many cpp arguments\n", ProgramName);
1054 }
1055 continue;
1056 }
1057 fprintf(stderr__stderrp, "%s: unrecognized argument '%s'\n",
1058 ProgramName, arg);
1059 Syntax(NULL((void*)0));
1060 }
1061 else if (arg[0] == '=')
1062 continue;
1063 else
1064 filename = arg;
1065 } /* end for */
1066
1067#ifndef WIN32
1068 while ((i = open("/dev/null", O_RDONLY0x0000)) < 3)
1069 ; /* make sure later freopen won't clobber things */
1070 (void) close(i);
1071#endif
1072 /* Open display */
1073 if (!(dpy = XOpenDisplay(displayname)))
1074 fatal("%s: Can't open display '%s'\n", ProgramName,
1075 XDisplayName(displayname));
1076
1077 if (whichResources == RALL0 && ScreenCount(dpy)(((_XPrivDisplay)(dpy))->nscreens) == 1)
1078 whichResources = RGLOBAL1;
1079
1080#ifdef PATHETICCPP
1081 if (cpp_program &&
1082 (oper == OPLOAD4 || oper == OPMERGE5 || oper == OPOVERRIDE6)) {
1083 need_real_defines = True1;
1084#ifdef WIN32
1085 strcpy(tmpname2, "xrdbD_XXXXXX")__builtin___strcpy_chk (tmpname2, "xrdbD_XXXXXX", __builtin_object_size
(tmpname2, 2 > 1 ? 1 : 0))
;
1086 strcpy(tmpname3, "\\temp\\xrdbD_XXXXXX")__builtin___strcpy_chk (tmpname3, "\\temp\\xrdbD_XXXXXX", __builtin_object_size
(tmpname3, 2 > 1 ? 1 : 0))
;
1087#else
1088 strcpy(tmpname2, "/tmp/xrdbD_XXXXXX")__builtin___strcpy_chk (tmpname2, "/tmp/xrdbD_XXXXXX", __builtin_object_size
(tmpname2, 2 > 1 ? 1 : 0))
;
1089#endif
1090 (void) mktemp(tmpname2);
1091 }
1092#endif
1093
1094 if (!filename &&
1095#ifdef PATHETICCPP
1096 need_real_defines
1097#else
1098 (oper == OPLOAD4 || oper == OPMERGE5 || oper == OPOVERRIDE6) &&
1099 (whichResources == RALL0 || whichResources == RSCREENS3)
1100#endif
1101 ) {
1102 char inputbuf[1024];
1103
1104#ifdef WIN32
1105 strcpy(tmpname, "\\temp\\xrdb_XXXXXX")__builtin___strcpy_chk (tmpname, "\\temp\\xrdb_XXXXXX", __builtin_object_size
(tmpname, 2 > 1 ? 1 : 0))
;
1106#else
1107 strcpy(tmpname, "/tmp/xrdb_XXXXXX")__builtin___strcpy_chk (tmpname, "/tmp/xrdb_XXXXXX", __builtin_object_size
(tmpname, 2 > 1 ? 1 : 0))
;
1108#endif
1109#ifndef HAVE_MKSTEMP1
1110 (void) mktemp(tmpname);
1111 filename = tmpname;
1112 fp = fopen(filename, "w");
1113#else
1114 {
1115 int fd = mkstemp(tmpname);
1116
1117 filename = tmpname;
1118 fp = fdopen(fd, "w");
1119 }
1120#endif /* MKSTEMP */
1121 if (!fp)
1122 fatal("%s: Failed to open temp file: %s\n", ProgramName, filename);
1123 while (fgets(inputbuf, sizeof(inputbuf), stdin__stdinp) != NULL((void*)0))
1124 fputs(inputbuf, fp);
1125 fclose(fp);
1126 }
1127
1128 DoDisplayDefines(dpy, &defines, displayname);
1129 defines_base = defines.used;
1130 need_newline = (oper == OPQUERY1 || oper == OPSYMBOLS0 ||
1131 (dont_execute && oper != OPREMOVE2));
1132 InitBuffer(&buffer);
1133 if (whichResources == RGLOBAL1)
1134 Process(DefaultScreen(dpy)(((_XPrivDisplay)(dpy))->default_screen), False0, True1);
1135 else if (whichResources == RSCREEN2)
1136 Process(DefaultScreen(dpy)(((_XPrivDisplay)(dpy))->default_screen), True1, True1);
1137 else if (whichResources == RSCREENS3 ||
1138 (oper != OPLOAD4 && oper != OPMERGE5 && oper != OPOVERRIDE6)) {
1139 if (whichResources == RALL0 && oper != OPSYMBOLS0) {
1140 if (need_newline)
1141 printf("! screen-independent resources\n");
1142 Process(0, False0, True1);
1143 if (need_newline)
1144 printf("\n");
1145 }
1146 for (i = 0; i < ScreenCount(dpy)(((_XPrivDisplay)(dpy))->nscreens); i++) {
1147 if (need_newline) {
1148 if (oper == OPSYMBOLS0)
1149 printf("# screen %d symbols\n", i);
1150 else {
1151 printf("! screen %d resources\n", i);
1152 printf("#if SCREEN_NUM == %d\n", i);
1153 }
1154 }
1155 Process(i, True1, True1);
1156 if (need_newline) {
1157 if (oper != OPSYMBOLS0)
1158 printf("#endif\n");
1159 if (i + 1 != ScreenCount(dpy)(((_XPrivDisplay)(dpy))->nscreens))
1160 printf("\n");
1161 }
1162 }
1163 }
1164 else {
1165 Entries *dbs;
1166
1167 dbs = mallocarray(ScreenCount(dpy), sizeof(Entries))reallocarray(((void*)0), (((_XPrivDisplay)(dpy))->nscreens
), sizeof(Entries))
;
1168 if (dbs == NULL((void*)0))
1169 fatal("%s: Can't allocate memory in %s\n", ProgramName, __func__);
1170 for (i = 0; i < ScreenCount(dpy)(((_XPrivDisplay)(dpy))->nscreens); i++) {
1171 Process(i, True1, False0);
1172 dbs[i] = newDB;
1173 }
1174 InitEntries(&newDB);
1175 if (oper == OPMERGE5 || oper == OPOVERRIDE6)
1176 GetEntriesString(&newDB, XResourceManagerString(dpy));
1177 ShuffleEntries(&newDB, dbs, (unsigned) ScreenCount(dpy)(((_XPrivDisplay)(dpy))->nscreens));
1178 if (need_newline)
1179 printf("! screen-independent resources\n");
1180 ReProcess(0, False0);
1181 if (need_newline)
1182 printf("\n");
1183 for (i = 0; i < ScreenCount(dpy)(((_XPrivDisplay)(dpy))->nscreens); i++) {
1184 newDB = dbs[i];
1185 if (need_newline) {
1186 printf("! screen %d resources\n", i);
1187 printf("#if SCREEN_NUM == %d\n", i);
1188 }
1189 ReProcess(i, True1);
1190 if (need_newline) {
1191 printf("#endif\n");
1192 if (i + 1 != ScreenCount(dpy)(((_XPrivDisplay)(dpy))->nscreens))
1193 printf("\n");
1194 }
1195 }
1196 }
1197
1198 if (fp)
1199 unlink(filename);
1200 if (retainProp)
1201 XSetCloseDownMode(dpy, RetainPermanent1);
1202 XCloseDisplay(dpy);
1203 exit(0);
1204}
1205
1206
1207static void
1208FormatEntries(Buffer *b, Entries *entries)
1209{
1210 size_t i;
1211
1212 b->used = 0;
1213 if (!entries->used)
1214 return;
1215 if (oper == OPMERGE5)
1216 qsort(entries->entry, entries->used, sizeof(Entry), CompareEntries);
1217 for (i = 0; i < entries->used; i++) {
1218 if (entries->entry[i].usable)
1219 AppendEntryToBuffer(b, &entries->entry[i]);
1220 }
1221}
1222
1223static void
1224StoreProperty(Display *display, Window root, Atom res_prop)
1225{
1226 size_t len = buffer.used;
1227 int mode = PropModeReplace0;
1228 unsigned char *buf = (unsigned char *) buffer.buff;
1229 size_t max = ((unsigned) XMaxRequestSize(display) << 2) - 28;
1230
1231 if (len > max) {
1232 XGrabServer(display);
1233 do {
1234 XChangeProperty(display, root, res_prop, XA_STRING((Atom) 31), 8, mode, buf,
1235 (int) max);
1236 buf += max;
1237 len -= max;
1238 mode = PropModeAppend2;
1239 } while (len > max);
1240 }
1241 XChangeProperty(display, root, res_prop, XA_STRING((Atom) 31), 8, mode, buf,
1242 (int) len);
1243 if (mode != PropModeReplace0)
1244 XUngrabServer(display);
1245}
1246
1247static void
1248Process(int scrno, Boolint doScreen, Boolint execute)
1249{
1250 char *xdefs;
1251 Window root;
1252 Atom res_prop;
1253 FILE *input, *output;
1254 char *cmd;
1255
1256 defines.val[defines_base] = '\0';
1257 defines.used = defines_base;
1258 buffer.used = 0;
1259 InitEntries(&newDB);
1260 DoScreenDefines(dpy, scrno, &defines);
1261 DoCmdDefines(&defines);
1262 if (doScreen) {
1
Assuming 'doScreen' is 0
2
Taking false branch
1263 xdefs = XScreenResourceString(ScreenOfDisplay(dpy, scrno)(&((_XPrivDisplay)(dpy))->screens[scrno]));
1264 root = RootWindow(dpy, scrno)((&((_XPrivDisplay)(dpy))->screens[scrno])->root);
1265 res_prop = XInternAtom(dpy, SCREEN_RESOURCES"SCREEN_RESOURCES", False0);
1266 }
1267 else {
1268 xdefs = XResourceManagerString(dpy);
1269 root = RootWindow(dpy, 0)((&((_XPrivDisplay)(dpy))->screens[0])->root);
1270 res_prop = XA_RESOURCE_MANAGER((Atom) 23);
1271 }
1272 if (oper == OPSYMBOLS0) {
3
Assuming 'oper' is not equal to 0
4
Taking false branch
1273 printf("%s\n", defines.val);
1274 }
1275 else if (oper == OPQUERY1) {
5
Assuming 'oper' is not equal to 1
6
Taking false branch
1276 if (xdefs)
1277 printf("%s", xdefs); /* fputs broken in SunOS 4.0 */
1278 }
1279 else if (oper == OPREMOVE2) {
7
Assuming 'oper' is not equal to 2
8
Taking false branch
1280 if (xdefs)
1281 XDeleteProperty(dpy, root, res_prop);
1282 }
1283 else if (oper == OPEDIT3) {
9
Assuming 'oper' is equal to 3
10
Taking true branch
1284 char template[100], old[100];
1285
1286 input = fopen(editFile, "r");
1287 snprintf(template, sizeof(template), "%sXXXXXX", editFile)__builtin___snprintf_chk (template, sizeof(template), 0, __builtin_object_size
(template, 2 > 1 ? 1 : 0), "%sXXXXXX", editFile)
;
1288#ifndef HAVE_MKSTEMP1
1289 (void) mktemp(template);
1290 output = fopen(template, "w");
1291#else
1292 {
1293 int fd = mkstemp(template);
1294
1295 output = fdopen(fd, "w");
1296 }
1297#endif
1298 if (!output)
11
Assuming 'output' is non-null
12
Taking false branch
1299 fatal("%s: can't open temporary file '%s'\n", ProgramName,
1300 template);
1301 GetEntriesString(&newDB, xdefs);
1302 EditFile(&newDB, input, output);
13
Calling 'EditFile'
1303 if (input)
1304 fclose(input);
1305 fclose(output);
1306 snprintf(old, sizeof(old), "%s%s", editFile, backup_suffix)__builtin___snprintf_chk (old, sizeof(old), 0, __builtin_object_size
(old, 2 > 1 ? 1 : 0), "%s%s", editFile, backup_suffix)
;
1307 if (dont_execute) { /* then write to standard out */
1308 char buf[BUFSIZ1024];
1309 size_t n;
1310
1311 output = fopen(template, "r");
1312 if (output) {
1313 while ((n = fread(buf, 1, sizeof buf, output)) > 0) {
1314 fwrite(buf, 1, n, stdout__stdoutp);
1315 }
1316 fclose(output);
1317 }
1318 unlink(template);
1319 }
1320 else {
1321 rename(editFile, old);
1322 if (rename(template, editFile))
1323 fatal("%s: can't rename file '%s' to '%s'\n", ProgramName,
1324 template, editFile);
1325 }
1326 }
1327 else {
1328 const char *cpp_addflags = "";
1329
1330 if (oper == OPMERGE5 || oper == OPOVERRIDE6)
1331 GetEntriesString(&newDB, xdefs);
1332
1333 /* Add -P flag only if using cpp, not another preprocessor */
1334 if (cpp_program) {
1335 const char *cp = strstr(cpp_program, "cpp");
1336
1337 if (cp && ((cp[3] == '\0') || cp[3] == ' '))
1338 cpp_addflags = "-P";
1339 }
1340#ifdef PATHETICCPP
1341 if (need_real_defines) {
1342#ifdef WIN32
1343 if (!(input = fopen(tmpname2, "w")))
1344 fatal("%s: can't open file '%s'\n", ProgramName, tmpname2);
1345 fputs(defines.val, input);
1346 fprintf(input, "\n#include \"%s\"\n", filename);
1347 fclose(input);
1348 (void) mktemp(tmpname3);
1349 if (asprintf(&cmd, "%s %s %s %s > %s", cpp_program, cpp_addflags,
1350 includes.val, tmpname2, tmpname3) == -1)
1351 fatal("%s: Out of memory\n", ProgramName);
1352 if (system(cmd) < 0)
1353 fatal("%s: cannot run '%s'\n", ProgramName, cmd);
1354 free(cmd);
1355 if (!(input = fopen(tmpname3, "r")))
1356 fatal("%s: can't open file '%s'\n", ProgramName, tmpname3);
1357#else
1358 if (!freopen(tmpname2, "w+", stdin__stdinp))
1359 fatal("%s: can't open file '%s'\n", ProgramName, tmpname2);
1360 fputs(defines.val, stdin__stdinp);
1361 fprintf(stdin__stdinp, "\n#include \"%s\"\n", filename);
1362 fflush(stdin__stdinp);
1363 fseek(stdin__stdinp, 0, SEEK_SET0);
1364 if (asprintf(&cmd, "%s %s %s", cpp_program, cpp_addflags,
1365 includes.val) == -1)
1366 fatal("%s: Out of memory\n", ProgramName);
1367 if (!(input = popen(cmd, "r")))
1368 fatal("%s: cannot run '%s'\n", ProgramName, cmd);
1369 free(cmd);
1370#endif
1371 }
1372 else {
1373#endif
1374 if (filename) {
1375 if (!freopen(filename, "r", stdin__stdinp))
1376 fatal("%s: can't open file '%s'\n", ProgramName, filename);
1377 }
1378 if (cpp_program) {
1379#ifdef WIN32
1380 (void) mktemp(tmpname3);
1381 if (asprintf(&cmd, "%s %s %s %s %s > %s", cpp_program,
1382 cpp_addflags, includes.val, defines.val,
1383 filename ? filename : "", tmpname3) == -1)
1384 fatal("%s: Out of memory\n", ProgramName);
1385 if (system(cmd) < 0)
1386 fatal("%s: cannot run '%s'\n", ProgramName, cmd);
1387 free(cmd);
1388 if (!(input = fopen(tmpname3, "r")))
1389 fatal("%s: can't open file '%s'\n", ProgramName, tmpname3);
1390#else
1391 if (asprintf(&cmd, "%s %s %s %s %s", cpp_program,
1392 cpp_addflags, includes.val, defines.val,
1393 filename ? filename : "") == -1)
1394 fatal("%s: Out of memory\n", ProgramName);
1395 if (!(input = popen(cmd, "r")))
1396 fatal("%s: cannot run '%s'\n", ProgramName, cmd);
1397 free(cmd);
1398#endif
1399 }
1400 else {
1401 input = stdin__stdinp;
1402 }
1403#ifdef PATHETICCPP
1404 }
1405#endif
1406 ReadFile(&buffer, input);
1407 if (cpp_program) {
1408#ifdef WIN32
1409 fclose(input);
1410#else
1411 pclose(input);
1412#endif
1413 }
1414#ifdef PATHETICCPP
1415 if (need_real_defines) {
1416 unlink(tmpname2);
1417#ifdef WIN32
1418 if (tmpname3[strlen(tmpname3) - 1] != 'X')
1419 unlink(tmpname3);
1420#endif
1421 }
1422#endif
1423 GetEntries(&newDB, &buffer, 0);
1424 if (execute) {
1425 FormatEntries(&buffer, &newDB);
1426 if (dont_execute) {
1427 if (buffer.used > 0) {
1428 fwrite(buffer.buff, 1, buffer.used, stdout__stdoutp);
1429 if (buffer.buff[buffer.used - 1] != '\n')
1430 putchar('\n');
1431 }
1432 }
1433 else if (buffer.used > 1 || !doScreen)
1434 StoreProperty(dpy, root, res_prop);
1435 else
1436 XDeleteProperty(dpy, root, res_prop);
1437 }
1438 }
1439 if (execute)
1440 FreeEntries(&newDB);
1441 if (doScreen && xdefs)
1442 XFree(xdefs);
1443}
1444
1445static void
1446ShuffleEntries(Entries *db, Entries *dbs, unsigned int num)
1447{
1448 unsigned int *hits;
1449 unsigned int i, j, k;
1450 Entries cur, cmp;
1451 char *curtag, *curvalue;
1452
1453 hits = mallocarray(num, sizeof(int))reallocarray(((void*)0), num, sizeof(int));
1454 if (hits == NULL((void*)0))
1455 fatal("%s: Can't allocate memory in %s\n", ProgramName, __func__);
1456 cur = dbs[0];
1457 for (i = 0; i < cur.used; i++) {
1458 curtag = cur.entry[i].tag;
1459 curvalue = cur.entry[i].value;
1460 for (j = 1; j < num; j++) {
1461 cmp = dbs[j];
1462 for (k = 0; k < cmp.used; k++) {
1463 if (cmp.entry[k].usable &&
1464 !strcmp(curtag, cmp.entry[k].tag) &&
1465 !strcmp(curvalue, cmp.entry[k].value)) {
1466 hits[j] = k;
1467 break;
1468 }
1469 }
1470 if (k == cmp.used)
1471 break;
1472 }
1473 if (j == num) {
1474 AddEntry(db, &cur.entry[i]);
1475 hits[0] = i;
1476 for (j = 0; j < num; j++)
1477 dbs[j].entry[hits[j]].usable = False0;
1478 }
1479 }
1480 free(hits);
1481}
1482
1483static void
1484ReProcess(int scrno, Boolint doScreen)
1485{
1486 Window root;
1487 Atom res_prop;
1488
1489 FormatEntries(&buffer, &newDB);
1490 if (doScreen) {
1491 root = RootWindow(dpy, scrno)((&((_XPrivDisplay)(dpy))->screens[scrno])->root);
1492 res_prop = XInternAtom(dpy, SCREEN_RESOURCES"SCREEN_RESOURCES", False0);
1493 }
1494 else {
1495 root = RootWindow(dpy, 0)((&((_XPrivDisplay)(dpy))->screens[0])->root);
1496 res_prop = XA_RESOURCE_MANAGER((Atom) 23);
1497 }
1498 if (dont_execute) {
1499 if (buffer.used > 0) {
1500 fwrite(buffer.buff, 1, buffer.used, stdout__stdoutp);
1501 if (buffer.buff[buffer.used - 1] != '\n')
1502 putchar('\n');
1503 }
1504 }
1505 else {
1506 if (buffer.used > 1 || !doScreen)
1507 StoreProperty(dpy, root, res_prop);
1508 else
1509 XDeleteProperty(dpy, root, res_prop);
1510 }
1511 FreeEntries(&newDB);
1512}
1513
1514static void
1515fatal(const char *msg, ...)
1516{
1517 va_list args;
1518
1519 if (errno(*__error()) != 0)
1520 perror(ProgramName);
1521 va_start(args, msg)__builtin_va_start(args, msg);
1522 vfprintf(stderr__stderrp, msg, args);
1523 va_end(args)__builtin_va_end(args);
1524 exit(1);
1525}