1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | #include "smproxy.h" |
29 | #ifdef HAVE_MKSTEMP1 |
30 | #include <unistd.h> |
31 | #endif |
32 | |
33 | |
34 | static ProxyFileEntry *proxyFileHead = NULL((void*)0); |
35 | |
36 | static int write_byte ( FILE *file, unsigned char b ); |
37 | static int write_short ( FILE *file, unsigned short s ); |
38 | static int write_counted_string ( FILE *file, char *string ); |
39 | static int read_byte ( FILE *file, unsigned char *bp ); |
40 | static int read_short ( FILE *file, unsigned short *shortp ); |
41 | static int read_counted_string ( FILE *file, char **stringp ); |
42 | |
43 | #ifndef HAVE_ASPRINTF1 |
44 | # include <stdarg.h> |
45 | |
46 | |
47 | _X_HIDDEN__attribute__((visibility("hidden"))) int _X_ATTRIBUTE_PRINTF(2,3)__attribute__((__format__(__printf__,2,3))) |
48 | asprintf(char ** ret, const char *format, ...) |
49 | { |
50 | char buf[256]; |
51 | int len; |
52 | va_list ap; |
53 | |
54 | va_start(ap, format); |
55 | len = vsnprintf(buf, sizeof(buf), format, ap)__builtin___vsnprintf_chk (buf, sizeof(buf), 0, __builtin_object_size (buf, 2 > 1 ? 1 : 0), format, ap); |
56 | va_end(ap); |
57 | |
58 | if (len < 0) |
59 | return -1; |
60 | |
61 | if (len < sizeof(buf)) |
62 | { |
63 | *ret = strdup(buf); |
64 | } |
65 | else |
66 | { |
67 | *ret = malloc(len + 1); |
68 | if (*ret != NULL((void*)0)) |
69 | { |
70 | va_start(ap, format); |
71 | len = vsnprintf(*ret, len + 1, format, ap)__builtin___vsnprintf_chk (*ret, len + 1, 0, __builtin_object_size (*ret, 2 > 1 ? 1 : 0), format, ap); |
72 | va_end(ap); |
73 | if (len < 0) { |
74 | free(*ret); |
75 | *ret = NULL((void*)0); |
76 | } |
77 | } |
78 | } |
79 | |
80 | if (*ret == NULL((void*)0)) |
81 | return -1; |
82 | |
83 | return len; |
84 | } |
85 | #endif |
86 | |
87 | |
88 |
|
89 | static int |
90 | write_byte (FILE *file, unsigned char b) |
91 | { |
92 | if (fwrite ((char *) &b, 1, 1, file) != 1) |
93 | return 0; |
94 | return 1; |
95 | } |
96 | |
97 | |
98 | static int |
99 | write_short (FILE *file, unsigned short s) |
100 | { |
101 | unsigned char file_short[2]; |
102 | |
103 | file_short[0] = (s & (unsigned)0xff00) >> 8; |
104 | file_short[1] = s & 0xff; |
105 | if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) |
106 | return 0; |
107 | return 1; |
108 | } |
109 | |
110 | |
111 | static int |
112 | write_counted_string(FILE *file, char *string) |
113 | { |
114 | if (string) |
115 | { |
116 | unsigned char count = strlen (string); |
117 | |
118 | if (write_byte (file, count) == 0) |
119 | return 0; |
120 | if (fwrite (string, (int) sizeof (char), (int) count, file) != count) |
121 | return 0; |
122 | } |
123 | else |
124 | { |
125 | if (write_byte (file, 0) == 0) |
126 | return 0; |
127 | } |
128 | |
129 | return 1; |
130 | } |
131 | |
132 | |
133 |
|
134 | static int |
135 | read_byte(FILE *file, unsigned char *bp) |
136 | { |
137 | if (fread ((char *) bp, 1, 1, file) != 1) |
138 | return 0; |
139 | return 1; |
140 | } |
141 | |
142 | |
143 | static int |
144 | read_short(FILE *file, unsigned short *shortp) |
145 | { |
146 | unsigned char file_short[2]; |
147 | |
148 | if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) |
149 | return 0; |
150 | *shortp = file_short[0] * 256 + file_short[1]; |
151 | return 1; |
152 | } |
153 | |
154 | |
155 | static int |
156 | read_counted_string(FILE *file, char **stringp) |
157 | { |
158 | unsigned char len; |
159 | char *data; |
160 | |
161 | if (read_byte (file, &len) == 0) |
162 | return 0; |
163 | if (len == 0) { |
164 | data = NULL((void*)0); |
165 | } else { |
166 | data = (char *) malloc ((unsigned) len + 1); |
167 | if (!data) |
168 | return 0; |
169 | if (fread (data, (int) sizeof (char), (int) len, file) != len) { |
170 | free (data); |
171 | return 0; |
172 | } |
173 | data[len] = '\0'; |
174 | } |
175 | *stringp = data; |
176 | return 1; |
177 | } |
178 | |
179 | |
180 |
|
181 | |
182 | |
183 | |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | |
194 | |
195 | |
196 | |
197 | |
198 | |
199 | |
200 | int |
201 | WriteProxyFileEntry(FILE *proxyFile, WinInfo *theWindow) |
202 | { |
203 | int i; |
204 | |
205 | if (!write_counted_string (proxyFile, theWindow->client_id)) |
206 | return 0; |
207 | if (!write_counted_string (proxyFile, theWindow->class.res_name)) |
208 | return 0; |
209 | if (!write_counted_string (proxyFile, theWindow->class.res_class)) |
210 | return 0; |
211 | if (!write_counted_string (proxyFile, theWindow->wm_name)) |
212 | return 0; |
213 | |
214 | if (!theWindow->wm_command || theWindow->wm_command_count == 0) |
215 | { |
216 | if (!write_byte (proxyFile, 0)) |
217 | return 0; |
218 | } |
219 | else |
220 | { |
221 | if (!write_byte (proxyFile, (char) theWindow->wm_command_count)) |
222 | return 0; |
223 | for (i = 0; i < theWindow->wm_command_count; i++) |
224 | if (!write_counted_string (proxyFile, theWindow->wm_command[i])) |
225 | return 0; |
226 | } |
227 | |
228 | return 1; |
229 | } |
230 | |
231 | |
232 | int |
233 | ReadProxyFileEntry(FILE *proxyFile, ProxyFileEntry **pentry) |
234 | { |
235 | ProxyFileEntry *entry; |
236 | unsigned char byte; |
237 | int i; |
238 | |
239 | *pentry = entry = (ProxyFileEntry *) malloc ( |
240 | sizeof (ProxyFileEntry)); |
241 | if (!*pentry) |
| |
242 | return 0; |
243 | |
244 | entry->tag = 0; |
245 | entry->client_id = NULL((void*)0); |
246 | entry->class.res_name = NULL((void*)0); |
247 | entry->class.res_class = NULL((void*)0); |
248 | entry->wm_name = NULL((void*)0); |
249 | entry->wm_command = NULL((void*)0); |
250 | entry->wm_command_count = 0; |
251 | |
252 | if (!read_counted_string (proxyFile, &entry->client_id)) |
| |
253 | goto give_up; |
254 | if (!read_counted_string (proxyFile, &entry->class.res_name)) |
| |
255 | goto give_up; |
256 | if (!read_counted_string (proxyFile, &entry->class.res_class)) |
| |
257 | goto give_up; |
258 | if (!read_counted_string (proxyFile, &entry->wm_name)) |
| |
259 | goto give_up; |
260 | |
261 | if (!read_byte (proxyFile, &byte)) |
| |
262 | goto give_up; |
263 | entry->wm_command_count = byte; |
264 | |
265 | if (entry->wm_command_count == 0) |
| |
266 | entry->wm_command = NULL((void*)0); |
267 | else |
268 | { |
269 | entry->wm_command = (char **) malloc (entry->wm_command_count * |
270 | sizeof (char *)); |
271 | |
272 | if (!entry->wm_command) |
| |
273 | goto give_up; |
274 | |
275 | for (i = 0; i < entry->wm_command_count; i++) |
| 15 | | Loop condition is true. Entering loop body | |
|
276 | if (!read_counted_string (proxyFile, &entry->wm_command[i])) |
| |
277 | goto give_up; |
| 17 | | Control jumps to line 284 | |
|
278 | } |
279 | |
280 | return 1; |
281 | |
282 | give_up: |
283 | |
284 | if (entry->client_id) |
| |
285 | free (entry->client_id); |
286 | if (entry->class.res_name) |
| |
287 | free (entry->class.res_name); |
288 | if (entry->class.res_class) |
| |
289 | free (entry->class.res_class); |
290 | if (entry->wm_name) |
| |
291 | free (entry->wm_name); |
292 | if (entry->wm_command) |
| |
293 | { |
294 | if (entry->wm_command_count) |
| |
295 | { |
296 | for (i = 0; i < entry->wm_command_count; i++) |
| 24 | | Loop condition is true. Entering loop body | |
|
297 | if (entry->wm_command[i]) |
| 25 | | Branch condition evaluates to a garbage value |
|
298 | free (entry->wm_command[i]); |
299 | } |
300 | free ((char *) entry->wm_command); |
301 | } |
302 | |
303 | free ((char *) entry); |
304 | *pentry = NULL((void*)0); |
305 | |
306 | return 0; |
307 | } |
308 | |
309 | |
310 | void |
311 | ReadProxyFile(char *filename) |
312 | { |
313 | FILE *proxyFile; |
314 | ProxyFileEntry *entry; |
315 | int done = 0; |
316 | unsigned short version; |
317 | |
318 | proxyFile = fopen (filename, "rb"); |
319 | if (!proxyFile) |
| 1 | Assuming 'proxyFile' is non-null | |
|
| |
320 | return; |
321 | |
322 | if (!read_short (proxyFile, &version) || |
| |
323 | version > SAVEFILE_VERSION1) |
| 3 | | Assuming 'version' is <= 1 | |
|
324 | { |
325 | done = 1; |
326 | } |
327 | |
328 | while (!done) |
| 5 | | Loop condition is true. Entering loop body | |
|
329 | { |
330 | if (ReadProxyFileEntry (proxyFile, &entry)) |
| 6 | | Calling 'ReadProxyFileEntry' | |
|
331 | { |
332 | entry->next = proxyFileHead; |
333 | proxyFileHead = entry; |
334 | } |
335 | else |
336 | done = 1; |
337 | } |
338 | |
339 | fclose (proxyFile); |
340 | } |
341 | |
342 | |
343 |
|
344 | static char * |
345 | unique_filename(const char *path, const char *prefix, int *pFd) |
346 | { |
347 | char *tempFile = NULL((void*)0); |
348 | int tempFd = 0; |
349 | |
350 | #if defined(HAVE_MKSTEMP1) || defined(HAVE_MKTEMP1) |
351 | if (asprintf (&tempFile, "%s/%sXXXXXX", path, prefix) == -1) |
352 | return NULL((void*)0); |
353 | #endif |
354 | |
355 | #ifdef HAVE_MKSTEMP1 |
356 | tempFd = mkstemp(tempFile); |
357 | #else |
358 | |
359 | # ifdef HAVE_MKTEMP1 |
360 | if (mktemp(tempFile) == NULL((void*)0)) |
361 | tempFd = -1; |
362 | # else /* fallback to tempnam */ |
363 | tempFile = tempnam (path, prefix); |
364 | # endif /* HAVE_MKTEMP */ |
365 | |
366 | if (tempFd != -1 && tempFile != NULL((void*)0)) |
367 | tempFd = open(tempFile, O_RDWR | O_CREAT | O_EXCL, 0600); |
368 | #endif |
369 | |
370 | if (tempFd == -1) { |
371 | free(tempFile); |
372 | return (NULL((void*)0)); |
373 | } |
374 | |
375 | *pFd = tempFd; |
376 | return tempFile; |
377 | |
378 | } |
379 | |
380 | |
381 |
|
382 | char * |
383 | WriteProxyFile(void) |
384 | { |
385 | FILE *proxyFile = NULL((void*)0); |
386 | char *filename = NULL((void*)0); |
387 | int fd = -1; |
388 | const char *path; |
389 | WinInfo *winptr; |
390 | Boolint success = False0; |
391 | |
392 | path = getenv ("SM_SAVE_DIR"); |
393 | if (!path) |
394 | { |
395 | path = getenv ("HOME"); |
396 | if (!path) |
397 | path = "."; |
398 | } |
399 | |
400 | if ((filename = unique_filename (path, ".prx", &fd)) == NULL((void*)0)) |
401 | goto bad; |
402 | |
403 | if (!(proxyFile = fdopen(fd, "wb"))) |
404 | goto bad; |
405 | |
406 | if (!write_short (proxyFile, SAVEFILE_VERSION1)) |
407 | goto bad; |
408 | |
409 | success = True1; |
410 | winptr = win_head; |
411 | |
412 | while (winptr && success) |
413 | { |
414 | if (winptr->client_id) |
415 | if (!WriteProxyFileEntry (proxyFile, winptr)) |
416 | { |
417 | success = False0; |
418 | break; |
419 | } |
420 | |
421 | winptr = winptr->next; |
422 | } |
423 | |
424 | bad: |
425 | |
426 | if (proxyFile) |
427 | fclose (proxyFile); |
428 | else if (fd != -1) |
429 | close (fd); |
430 | |
431 | if (success) |
432 | return (filename); |
433 | else |
434 | { |
435 | if (filename) |
436 | free (filename); |
437 | return (NULL((void*)0)); |
438 | } |
439 | } |
440 | |
441 | |
442 |
|
443 | char * |
444 | LookupClientID(WinInfo *theWindow) |
445 | { |
446 | ProxyFileEntry *ptr; |
447 | int found = 0; |
448 | |
449 | ptr = proxyFileHead; |
450 | while (ptr && !found) |
451 | { |
452 | if (!ptr->tag && |
453 | strcmp (theWindow->class.res_name, ptr->class.res_name) == 0 && |
454 | strcmp (theWindow->class.res_class, ptr->class.res_class) == 0 && |
455 | strcmp (theWindow->wm_name, ptr->wm_name) == 0) |
456 | { |
457 | int i; |
458 | |
459 | if (theWindow->wm_command_count == ptr->wm_command_count) |
460 | { |
461 | for (i = 0; i < theWindow->wm_command_count; i++) |
462 | if (strcmp (theWindow->wm_command[i], |
463 | ptr->wm_command[i]) != 0) |
464 | break; |
465 | |
466 | if (i == theWindow->wm_command_count) |
467 | found = 1; |
468 | } |
469 | } |
470 | |
471 | if (!found) |
472 | ptr = ptr->next; |
473 | } |
474 | |
475 | if (found) |
476 | { |
477 | ptr->tag = 1; |
478 | return (ptr->client_id); |
479 | } |
480 | else |
481 | return NULL((void*)0); |
482 | } |