File: | xrdb.c |
Location: | line 197, column 12 |
Description: | Call to 'realloc' has an allocation size of 0 bytes |
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 | ||||
90 | typedef struct _Entry { | |||
91 | char *tag, *value; | |||
92 | int lineno; | |||
93 | Boolint usable; | |||
94 | } Entry; | |||
95 | ||||
96 | typedef struct _Buffer { | |||
97 | char *buff; | |||
98 | size_t room, used; | |||
99 | } Buffer; | |||
100 | ||||
101 | typedef struct _Entries { | |||
102 | Entry *entry; | |||
103 | size_t room, used; | |||
104 | } Entries; | |||
105 | ||||
106 | /* dynamically allocated strings */ | |||
107 | #define CHUNK_SIZE4096 4096 | |||
108 | typedef struct _String { | |||
109 | char *val; | |||
110 | size_t room, used; | |||
111 | } String; | |||
112 | ||||
113 | static char *ProgramName; | |||
114 | static Boolint quiet = False0; | |||
115 | static char tmpname[32]; | |||
116 | static char *filename = NULL((void*)0); | |||
117 | #ifdef PATHETICCPP | |||
118 | static Boolint need_real_defines = False0; | |||
119 | static char tmpname2[32]; | |||
120 | #endif | |||
121 | #ifdef WIN32 | |||
122 | static char tmpname3[32]; | |||
123 | #endif | |||
124 | static int oper = OPLOAD4; | |||
125 | static char *editFile = NULL((void*)0); | |||
126 | static const char *cpp_program = NULL((void*)0); | |||
127 | static const char * const cpp_locations[] = { CPP"/usr/bin/cpp" }; | |||
128 | static const char *backup_suffix = BACKUP_SUFFIX".bak"; | |||
129 | static Boolint dont_execute = False0; | |||
130 | static String defines; | |||
131 | static size_t defines_base; | |||
132 | #define MAX_CMD_DEFINES512 512 | |||
133 | static char *cmd_defines[MAX_CMD_DEFINES512]; | |||
134 | static int num_cmd_defines = 0; | |||
135 | static String includes; | |||
136 | static Display *dpy; | |||
137 | static Buffer buffer; | |||
138 | static Entries newDB; | |||
139 | ||||
140 | static void fatal(const char *, ...) | |||
141 | _X_ATTRIBUTE_PRINTF(1, 2)__attribute__((__format__(__printf__,1,2)))_X_NORETURN__attribute((noreturn)) _X_COLD__attribute__((__cold__)); | |||
142 | static void addstring(String *arg, const char *s); | |||
143 | static void addescapedstring(String *arg, const char *s); | |||
144 | static void addtokstring(String *arg, const char *s); | |||
145 | static void FormatEntries(Buffer *b, Entries * entries); | |||
146 | static void StoreProperty(Display *display, Window root, Atom res_prop); | |||
147 | static void Process(int scrno, Boolint doScreen, Boolint execute); | |||
148 | static void ShuffleEntries(Entries *db, Entries *dbs, unsigned int num); | |||
149 | static 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 */ | |||
153 | static int _X_ATTRIBUTE_PRINTF(2, 3)__attribute__((__format__(__printf__,2,3))) | |||
154 | asprintf(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 */ | |||
192 | static inline void * | |||
193 | reallocarray(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); | |||
| ||||
198 | } | |||
199 | #endif | |||
200 | ||||
201 | # define mallocarray(n, s)reallocarray(((void*)0), n, s) reallocarray(NULL((void*)0), n, s) | |||
202 | ||||
203 | static void | |||
204 | InitBuffer(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 | |||
214 | static void | |||
215 | FreeBuffer(Buffer *b) | |||
216 | { | |||
217 | free(b->buff); | |||
218 | } | |||
219 | #endif | |||
220 | ||||
221 | static void | |||
222 | AppendToBuffer(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 | ||||
234 | static void | |||
235 | InitEntries(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 | ||||
245 | static void | |||
246 | FreeEntries(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 | ||||
259 | static void | |||
260 | AddEntry(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 | ||||
291 | static int | |||
292 | CompareEntries(const void *e1, const void *e2) | |||
293 | { | |||
294 | return strcmp(((const Entry *) e1)->tag, ((const Entry *) e2)->tag); | |||
295 | } | |||
296 | ||||
297 | static void | |||
298 | AppendEntryToBuffer(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 | */ | |||
310 | static const char * | |||
311 | FindFirst(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 | ||||
330 | static void | |||
331 | GetEntries(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 | ||||
399 | static void | |||
400 | GetEntriesString(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 | ||||
411 | static void | |||
412 | ReadFile(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 | ||||
435 | static void | |||
436 | AddDef(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 | ||||
464 | static void | |||
465 | AddSimpleDef(String *buff, const char *title) | |||
466 | { | |||
467 | AddDef(buff, title, (char *) NULL((void*)0)); | |||
468 | } | |||
469 | ||||
470 | static void | |||
471 | AddDefQ(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 | ||||
488 | static void | |||
489 | AddNum(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 | ||||
497 | static void | |||
498 | AddDefTok(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 | ||||
506 | static void | |||
507 | AddDefHostname(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 | ||||
523 | static void | |||
524 | AddUndef(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 | ||||
544 | static void | |||
545 | DoCmdDefines(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 | ||||
571 | static int | |||
572 | Resolution(int pixels, int mm) | |||
573 | { | |||
574 | if (mm == 0) | |||
575 | return 0; | |||
576 | else | |||
577 | return ((pixels * 100000 / mm) + 50) / 100; | |||
578 | } | |||
579 | ||||
580 | static void | |||
581 | DoDisplayDefines(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 | ||||
627 | static 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 | ||||
638 | static void | |||
639 | DoScreenDefines(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 | ||||
698 | static Entry * | |||
699 | FindEntry(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 | ||||
729 | static void | |||
730 | EditFile(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 | ||||
763 | static void _X_NORETURN__attribute((noreturn)) _X_COLD__attribute__((__cold__)) | |||
764 | Syntax(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 | ||||
804 | static Boolint | |||
805 | isabbreviation(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 | ||||
829 | static void | |||
830 | addstring(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 | ||||
848 | static void | |||
849 | addescapedstring(String *arg, const char *s) | |||
850 | { | |||
851 | char copy[512], *c; | |||
852 | ||||
853 | for (c = copy; *s && c < ©[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 | ||||
870 | static void | |||
871 | addtokstring(String *arg, const char *s) | |||
872 | { | |||
873 | char copy[512], *c; | |||
874 | ||||
875 | for (c = copy; *s && c < ©[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 | ||||
886 | int | |||
887 | main(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 | ||||
1207 | static void | |||
1208 | FormatEntries(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 | ||||
1223 | static void | |||
1224 | StoreProperty(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 | ||||
1247 | static void | |||
1248 | Process(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 | ||||
1445 | static void | |||
1446 | ShuffleEntries(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 | ||||
1483 | static void | |||
1484 | ReProcess(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 | ||||
1514 | static void | |||
1515 | fatal(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 | } |