Bug Summary

File:xrdb.c
Location:line 197, column 12
Description:Call to 'realloc' has an allocation size of 0 bytes

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)
196 return NULL((void*)0);
197 return realloc(optr, n * s);
38
Call to 'realloc' has an allocation size of 0 bytes
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));
209 if (b->buff == NULL((void*)0))
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++) {
35
Loop condition is false. Execution continues on line 281
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) {
36
Taking true branch
282 e->entry = reallocarray(e->entry, e->room, 2 * sizeof(Entry));
37
Calling 'reallocarray'
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)
1
Assuming 'str' is non-null
2
Taking false branch
341 return;
342 for (; str < buff->buff + buff->used;
3
Loop condition is true. Entering loop body
10
Loop condition is true. Entering loop body
16
Loop condition is true. Entering loop body
22
Loop condition is true. Entering loop body
343 str = line + 1, lineno += lines_skipped) {
344 line = FindFirst(str, '\n', &lines_skipped);
345 lineno++;
346 if (!line)
4
Assuming 'line' is non-null
5
Taking false branch
11
Assuming 'line' is non-null
12
Taking false branch
17
Assuming 'line' is non-null
18
Taking false branch
23
Assuming 'line' is non-null
24
Taking false branch
347 line = buff->buff + buff->used;
348 if (*str == '!')
6
Taking false branch
13
Taking false branch
19
Taking false branch
25
Taking false branch
349 continue;
350 if (*str == '\n')
7
Taking false branch
14
Taking false branch
20
Taking false branch
26
Taking false branch
351 continue;
352 if (!bequiet && *str == '#') {
8
Assuming 'bequiet' is not equal to 0
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')
27
Taking false branch
364 continue;
9
Execution continues on line 343
15
Execution continues on line 343
21
Execution continues on line 343
365
366 colon = FindFirst(str, ':', NULL((void*)0));
367 if (!colon || colon > line) {
28
Assuming 'colon' is non-null
29
Assuming 'colon' is <= 'line'
30
Taking false branch
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')
31
Loop condition is false. Execution continues on line 378
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')
32
Loop condition is false. Execution continues on line 389
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;
33
'?' condition is true
394
395 AddEntry(entries, &entry);
34
Calling 'AddEntry'
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);
739 while (in) {
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++) {
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) {
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) {
1273 printf("%s\n", defines.val);
1274 }
1275 else if (oper == OPQUERY1) {
1276 if (xdefs)
1277 printf("%s", xdefs); /* fputs broken in SunOS 4.0 */
1278 }
1279 else if (oper == OPREMOVE2) {
1280 if (xdefs)
1281 XDeleteProperty(dpy, root, res_prop);
1282 }
1283 else if (oper == OPEDIT3) {
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)
1299 fatal("%s: can't open temporary file '%s'\n", ProgramName,
1300 template);
1301 GetEntriesString(&newDB, xdefs);
1302 EditFile(&newDB, input, output);
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}