source: trunk/third/gnome-core/panel/conditional.c @ 17152

Revision 17152, 11.5 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17151, which included commits to RCS files with non-trunk default branches.
Line 
1/* Gnome conditional: conditional loading
2 * (C) 2001 George Lebl
3 */
4
5#include "config.h"
6#include <string.h>
7#include <signal.h>
8#include <limits.h>
9#include <unistd.h>
10#include <sys/types.h>
11#include <sys/wait.h>
12#include <gnome.h>
13
14#include "panel-include.h"
15
16#include "conditional.h"
17
18static gboolean
19linux_battery_exists (void)
20{
21        FILE *fp;
22        char buf[200] = "";
23        int foo;
24
25        if ( ! panel_file_exists("/proc/apm"))
26                return FALSE;
27
28        fp = fopen ("/proc/apm", "r");
29        if (fp == NULL)
30                return FALSE;
31
32        if (fgets (buf, sizeof (buf), fp) == NULL) {
33                fclose (fp);
34                return FALSE;
35        }
36        fclose (fp);
37
38        foo = -1;
39        sscanf (buf,
40                "%*s %*d.%*d %*x %*x %*x %*x %d%% %*d %*s\n",
41                &foo);
42
43        if (foo >= 0)
44                return TRUE;
45        else
46                return FALSE;
47}
48
49static gboolean
50battery_exists (void)
51{
52#ifndef __linux__
53        return FALSE;
54#else
55        /* This is MUUUUCHO ugly, but apparently RH 7.0 with segv the program
56         * reading /proc/apm on some laptops, and we don't want to crash, thus
57         * we do the check in a forked process */
58        int status;
59        pid_t pid;
60
61        pid = fork ();
62        if (pid == 0) {
63                struct sigaction sa = {{NULL}};
64
65                sa.sa_handler = SIG_DFL;
66
67                sigaction(SIGSEGV, &sa, NULL);
68                sigaction(SIGFPE, &sa, NULL);
69                sigaction(SIGBUS, &sa, NULL);
70
71                if (linux_battery_exists ())
72                        _exit (0);
73                else
74                        _exit (1);
75        }
76
77        status = 0;
78        waitpid (pid, &status, 0);
79
80        if ( ! WIFSIGNALED (status) &&
81            WIFEXITED (status) &&
82            WEXITSTATUS (status) == 0) {
83                return TRUE;
84        } else {
85                return FALSE;
86        }
87#endif
88}
89
90static gboolean
91is_tokchar (char c)
92{
93        return ((c >= 'a' && c <= 'z') ||
94                (c >= 'A' && c <= 'Z') ||
95                (c >= '0' && c <= '9') ||
96                c == '_');
97}
98
99static int
100get_string (char const *buffer, int len)
101{
102        int llen = 0;
103        const char *p;
104
105        for (p = buffer, llen = 0;
106             *p != '\0' && len > 0;
107             p++, llen++) {
108                if (*p == '\'') {
109                        return llen;
110                }
111                len --;
112        }
113        return llen;
114}
115
116static const char *
117get_word (char const **retbuf, int *len, int *rlen)
118{
119        const char *buffer = *retbuf;
120
121        *rlen = 0;
122
123        if (buffer == NULL || *buffer == '\0' || *len == 0)
124                return NULL;
125
126        while ((*buffer == '\t' ||
127                *buffer == ' ' ||
128                *buffer == '\r') &&
129               *len > 0) {
130                buffer ++;
131                (*len) --;
132                (*retbuf) ++;
133        }
134
135        if (*buffer == '\0' || *len == 0)
136                return NULL;
137
138        /* some simple thingies */
139        if (*len >= 2 &&
140            (strncmp (buffer, "==", 2) == 0 ||
141             strncmp (buffer, ">=", 2) == 0 ||
142             strncmp (buffer, "<=", 2) == 0 ||
143             strncmp (buffer, "!=", 2) == 0 ||
144             strncmp (buffer, "||", 2) == 0 ||
145             strncmp (buffer, "&&", 2) == 0)) {
146                *len -= 2;
147                *rlen = 2;
148                (*retbuf) += 2;
149                return buffer;
150        }
151
152        if (is_tokchar (*buffer)) {
153                const char *p = buffer;
154                *rlen = 0;
155                do {
156                        (*rlen) ++;
157                        p ++;
158                        (*len) --;
159                } while (is_tokchar (*p) && *len > 0);
160                (*retbuf) += *rlen;
161                return buffer;
162        }
163
164        /* well, this is just a single token thingie */
165        (*len) --;
166        *rlen = 1;
167        (*retbuf) ++;
168        return buffer;
169}
170
171static int
172get_paren (char const *buffer, int len, char open, char close)
173{
174        int llen = 0;
175        const char *p;
176        int depth = 0;
177
178        for (p = buffer, llen = 0;
179             *p != '\0' && len > 0;
180             p++, llen++) {
181                if (*p == open) {
182                        depth++;
183                } else if (*p == close) {
184                        depth--;
185                        if (depth < 0)
186                                return llen+1;
187                }
188                len --;
189        }
190        return llen;
191}
192
193#define IS_KWORD(kword,word,len) ((len) == strlen (kword) && \
194                                  strncmp ((word), (kword), (len)) == 0)
195
196static gboolean
197have_cond (const char *word, int len)
198{
199        if (IS_KWORD ("battery", word, len)) {
200                static int got = -1;
201                if (got > -1)
202                        return got;
203                got = battery_exists ();
204                return got;
205        }
206        return FALSE;
207}
208
209static int
210get_value (const char *val, int len)
211{
212        if (IS_KWORD ("screen_width", val, len)) {
213                return gdk_screen_width ();
214        } else if (IS_KWORD ("screen_height", val, len)) {
215                return gdk_screen_height ();
216        } else if (val[0] >= '0' && val[0] <= '9') {
217                return atoi (val);
218        } else {
219                char *str = g_strndup (val, len);
220                g_warning ("Unknown value %s", str);
221                g_free (str);
222                return FALSE;
223        }
224}
225
226static gboolean
227eval_comp (const char *comp, int complen, int value1, int value2)
228{
229        if (IS_KWORD (">", comp, complen))
230                return value1 > value2;
231        else if (IS_KWORD ("<", comp, complen))
232                return value1 < value2;
233        else if (IS_KWORD (">=", comp, complen))
234                return value1 >= value2;
235        else if (IS_KWORD ("<=", comp, complen))
236                return value1 <= value2;
237        else if (IS_KWORD ("==", comp, complen) ||
238                 IS_KWORD ("=", comp, complen))
239                return value1 == value2;
240        else if (IS_KWORD ("!=", comp, complen))
241                return value1 != value2;
242        else {
243                g_warning ("Unknown comparison %c%c",
244                           *comp,
245                           *(comp+1) /* in the worst case this is '\0'*/);
246                return FALSE;
247        }
248}
249
250enum {
251        CONN_AND,
252        CONN_OR
253};
254
255static gboolean
256eval_cond (int connector, gboolean a, gboolean b)
257{
258        if (connector == CONN_AND) {
259                return a && b;
260        } else {
261                return a || b;
262        }
263}
264
265gboolean
266conditional_parse (const char *conditional, int len)
267{
268        int llen;
269        const char *word;
270        gboolean last_cond = TRUE;
271        int last_connector = CONN_AND;
272        gboolean invert = FALSE;
273
274        if (conditional == NULL)
275                return TRUE;
276
277        if (len <= 0) {
278                len = strlen (conditional);
279        }
280
281#if 0
282        /* Some debugging */
283        {
284                char *foo = g_strndup (conditional, len);
285                g_print ("Conditional: '%s'\n", foo);
286                g_free (foo);
287        }
288#endif
289
290
291        word = conditional;
292        while ((word = get_word (&conditional, &len, &llen))) {
293                /* ignore trailing )'s */
294                if (*word == ')' && len == 0) {
295                        break;
296                } else if (*word == '(') {
297                        int plen = get_paren (conditional, len, '(', ')');
298                        gboolean cond = conditional_parse (conditional, plen);
299                        conditional += plen;
300                        len -= plen;
301                        last_cond = eval_cond (last_connector,
302                                               last_cond,
303                                               invert ? !cond : cond);
304                        invert = FALSE;
305                } else if (IS_KWORD ("not", word, llen) ||
306                           *word == '!') {
307                        invert = TRUE;
308                } else if (IS_KWORD ("true", word, llen)) {
309                        last_cond = eval_cond (last_connector,
310                                               last_cond,
311                                               invert ? !TRUE : TRUE);
312                        invert = FALSE;
313                } else if (IS_KWORD ("false", word, llen)) {
314                        last_cond = eval_cond (last_connector,
315                                               last_cond,
316                                               invert ? !FALSE : FALSE);
317                        invert = FALSE;
318                } else if (IS_KWORD ("||", word, llen) ||
319                           IS_KWORD ("or", word, llen)) {
320                        invert = FALSE;
321                        last_connector = CONN_OR;
322                } else if (IS_KWORD ("&&", word, llen) ||
323                           IS_KWORD ("and", word, llen)) {
324                        invert = FALSE;
325                        last_connector = CONN_AND;
326                } else if (IS_KWORD ("have", word, llen)) {
327                        gboolean cond;
328                        word = get_word (&conditional, &len, &llen);
329                        if (word == NULL) {
330                                g_warning ("Conditional parse error");
331                                return FALSE;
332                        }
333                        cond = have_cond (word, llen);
334                        last_cond = eval_cond (last_connector,
335                                               last_cond,
336                                               invert ? !cond : cond);
337                        invert = FALSE;
338                } else if (IS_KWORD ("exists", word, llen)) {
339                        char *file;
340                        gboolean cond;
341                        word = get_word (&conditional, &len, &llen);
342                        if (word == NULL) {
343                                g_warning ("Conditional parse error");
344                                return FALSE;
345                        }
346                        if (*word == '\'') {
347                                int slen = get_string (conditional, len);
348                                file = g_strndup (conditional, slen);
349                                conditional += slen;
350                                len -= slen;
351                                if (*conditional == '\'') {
352                                        conditional ++;
353                                        len--;
354                                }
355                        } else {
356                                file = g_strndup (word, llen);
357                        }
358
359                        cond = FALSE;
360                        if (panel_file_exists (file)) {
361                                cond = TRUE;
362                        } else {
363                                char *full = gnome_datadir_file (file);
364                                if (full != NULL)
365                                        cond = TRUE;
366                                g_free (full);
367                        }
368                        last_cond = eval_cond (last_connector,
369                                               last_cond,
370                                               invert ? !cond : cond);
371                        invert = FALSE;
372                        g_free (file);
373                } else if (is_tokchar (*word)) {
374                        int value1 = get_value (word, llen);
375                        int value2;
376                        gboolean cond;
377                        const char *comp;
378                        int complen;
379                        word = get_word (&conditional, &len, &llen);
380                        if (word == NULL) {
381                                g_warning ("Conditional parse error");
382                                return FALSE;
383                        }
384                        comp = word;
385                        complen = llen;
386                        word = get_word (&conditional, &len, &llen);
387                        if (word == NULL) {
388                                g_warning ("Conditional parse error");
389                                return FALSE;
390                        }
391                        value2 = get_value (word, llen);
392                        cond = eval_comp (comp, complen, value1, value2);
393                        last_cond = eval_cond (last_connector,
394                                               last_cond,
395                                               invert ? !cond : cond);
396                        invert = FALSE;
397                } else {
398                        g_warning ("Conditional parse error");
399                        return FALSE;
400                }
401
402        }
403        return last_cond;
404}
405
406static char *
407get_conditional_value (const char *string, const char *ifempty)
408{
409        int condlen;
410        const char *cond;
411
412        if (*string == '\0')
413                return g_strdup (ifempty);
414        if (*string != '{')
415                return g_strdup (string);
416
417        string ++;
418        condlen = get_paren (string, strlen (string), '{', '}');
419        cond = string;
420        string += condlen; /* full condlen, including the '}' */
421
422        if (*(cond+condlen-1) == '}')
423                condlen --; /* wipe the trailing } */
424        if (condlen <= 0 /* empty condition means go */ ||
425            conditional_parse (cond, condlen)) {
426                int i;
427                for (i = 0; string[i] != '\0' && string[i] != '{'; i++)
428                        ;
429                if (i > 0)
430                        return g_strndup (string, i);
431                else
432                        return g_strdup (ifempty);
433        } else {
434                while (*string != '{' &&
435                       *string != '\0')
436                        string++;
437                return get_conditional_value (string, ifempty);
438        }
439}
440
441char *
442conditional_get_string (const char *key, const char *def, gboolean *isdef)
443{
444        gboolean lisdef;
445        char *fullkey;
446        char *ret;
447
448        if (def != NULL)
449                fullkey = g_strdup_printf ("%s=%s", key, def);
450        else
451                fullkey = g_strdup (key);
452
453        if (isdef != NULL)
454                *isdef = FALSE;
455
456        ret = gnome_config_get_string_with_default (fullkey, &lisdef);
457        g_free (fullkey);
458        if (lisdef) {
459                char *cond;
460                g_free (ret);
461                fullkey = g_strdup_printf ("%s:Conditional", key);
462                cond = gnome_config_get_string_with_default (fullkey, &lisdef);
463                g_free (fullkey);
464                if (lisdef) {
465                        if (isdef != NULL)
466                                *isdef = TRUE;
467                        g_free (cond);
468                        return g_strdup (def);
469                }
470                ret = get_conditional_value (cond, "");
471                g_free (cond);
472        }
473        return ret;
474}
475
476gboolean
477conditional_get_bool (const char *key, gboolean def, gboolean *isdef)
478{
479        gboolean lisdef;
480        char *fullkey;
481        gboolean ret;
482
483        fullkey = g_strdup_printf ("%s=%s", key,
484                                   def ? "true" : "false");
485
486        if (isdef != NULL)
487                *isdef = FALSE;
488
489        ret = gnome_config_get_bool_with_default (fullkey, &lisdef);
490        g_free (fullkey);
491        if (lisdef) {
492                char *cond, *str;
493                fullkey = g_strdup_printf ("%s:Conditional", key);
494                cond = gnome_config_get_string_with_default (fullkey, &lisdef);
495                g_free (fullkey);
496                if (lisdef) {
497                        if (isdef != NULL)
498                                *isdef = TRUE;
499                        g_free (cond);
500                        return def;
501                }
502                str = get_conditional_value (cond, "false");
503                g_free (cond);
504                if (*str == 'T' || *str == 't' ||
505                    *str == 'Y' || *str == 'y' ||
506                    atoi (str) != 0) {
507                        ret = TRUE;
508                } else {
509                        ret = FALSE;
510                }
511                g_free (str);
512        }
513        return ret;
514}
515
516int
517conditional_get_int (const char *key, int def, gboolean *isdef)
518{
519        gboolean lisdef;
520        char *fullkey;
521        int ret;
522
523        fullkey = g_strdup_printf ("%s=%d", key, def);
524
525        if (isdef != NULL)
526                *isdef = FALSE;
527
528        ret = gnome_config_get_int_with_default (fullkey, &lisdef);
529        g_free (fullkey);
530        if (lisdef) {
531                char *cond, *str;
532                fullkey = g_strdup_printf ("%s:Conditional", key);
533                cond = gnome_config_get_string_with_default (fullkey, &lisdef);
534                g_free (fullkey);
535                if (lisdef) {
536                        if (isdef != NULL)
537                                *isdef = TRUE;
538                        g_free (cond);
539                        return def;
540                }
541                str = get_conditional_value (cond, "");
542                g_free (cond);
543                if (*str == '\0') {
544                        ret = def;
545                } else {
546                        ret = atoi (str);
547                }
548                g_free (str);
549        }
550        return ret;
551}
552
553/* get key and treat it as a conditional */
554gboolean
555conditional_true (const char *key)
556{
557        gboolean isdef;
558        char *cond;
559        cond = gnome_config_get_string_with_default (key, &isdef);
560        if (string_empty (cond) || isdef) {
561                g_free (cond);
562                return TRUE;
563        } else {
564                gboolean ret = conditional_parse (cond, strlen (cond));
565                g_free (cond);
566                return ret;
567        }
568}
Note: See TracBrowser for help on using the repository browser.