Rewritten internal environment functions.
Environment variables are now typed, so setting "set folder=1" won't cause coredumps anymore. The function util_getenv() is used to retrieve a variable of given data type. util_find_env() takes second argument specifying whether it should create a missing variable. This function is used only in util.c and var.c.
Showing
1 changed file
with
193 additions
and
67 deletions
... | @@ -51,7 +51,7 @@ util_ll_add (node *c, int data) | ... | @@ -51,7 +51,7 @@ util_ll_add (node *c, int data) |
51 | c->data = data; | 51 | c->data = data; |
52 | c->next->env_entry.var = NULL; | 52 | c->next->env_entry.var = NULL; |
53 | c->next->env_entry.set = 0; | 53 | c->next->env_entry.set = 0; |
54 | c->next->env_entry.value = NULL; | 54 | c->next->env_entry.value.number = 0; |
55 | c->next->next = NULL; | 55 | c->next->next = NULL; |
56 | return c->next; | 56 | return c->next; |
57 | } | 57 | } |
... | @@ -314,11 +314,11 @@ util_getlines (void) | ... | @@ -314,11 +314,11 @@ util_getlines (void) |
314 | int | 314 | int |
315 | util_screen_lines () | 315 | util_screen_lines () |
316 | { | 316 | { |
317 | struct mail_env_entry *ep = util_find_env ("screen"); | 317 | int screen; |
318 | size_t n; | 318 | size_t n; |
319 | 319 | ||
320 | if (ep && ep->set && (n = strtoul (ep->value, NULL, 10)) != 0) | 320 | if (util_getenv (&screen, "screen", Mail_env_number, 0) == 0) |
321 | return n; | 321 | return screen; |
322 | n = util_getlines(); | 322 | n = util_getlines(); |
323 | util_do_command ("set screen=%d", n); | 323 | util_do_command ("set screen=%d", n); |
324 | return n; | 324 | return n; |
... | @@ -327,25 +327,70 @@ util_screen_lines () | ... | @@ -327,25 +327,70 @@ util_screen_lines () |
327 | int | 327 | int |
328 | util_screen_columns () | 328 | util_screen_columns () |
329 | { | 329 | { |
330 | struct mail_env_entry *ep = util_find_env("columns"); | 330 | int cols; |
331 | size_t n; | 331 | size_t n; |
332 | 332 | ||
333 | if (ep && ep->set && (n = strtoul (ep->value, NULL, 10)) != 0) | 333 | if (util_getenv (&cols, "columns", Mail_env_number, 0) == 0) |
334 | return n; | 334 | return cols; |
335 | n = util_getcols(); | 335 | n = util_getcols(); |
336 | util_do_command ("set columns=%d", n); | 336 | util_do_command ("set columns=%d", n); |
337 | return n; | 337 | return n; |
338 | } | 338 | } |
339 | 339 | ||
340 | /* Functions for dealing with internal environment variables */ | ||
340 | 341 | ||
341 | /* | 342 | /* Retrieve the value of a specified variable of given type. |
342 | * Find environment entry var | 343 | The value is stored in the location pointed to by PTR variable. |
344 | VARIABLE and TYPE specify the variable name and type. If the | ||
345 | variable is not found and WARN is not null, the warning message | ||
346 | is issued. | ||
343 | 347 | ||
344 | FIXME: We should probably call this util_getenv to be consitent with | 348 | Return value is 0 if the variable is found, 1 otherwise. |
345 | util_printenv(), util_setenv() etc .. | 349 | If PTR is not NULL, it must point to |
346 | */ | 350 | |
351 | int if TYPE is Mail_env_number or Mail_env_boolean | ||
352 | const char * if TYPE is Mail_env_string. | ||
353 | |||
354 | Passing PTR=NULL may be used to check whether the variable is set | ||
355 | without retrieving its value. */ | ||
356 | |||
357 | int | ||
358 | util_getenv (void *ptr, const char *variable, mail_env_data_t type, int warn) | ||
359 | { | ||
360 | struct mail_env_entry *env = util_find_env (variable, 0); | ||
361 | |||
362 | if (!mail_env_entry_is_set (env) || env->type != type) | ||
363 | { | ||
364 | if (warn) | ||
365 | util_error ("No value set for \"%s\"", variable); | ||
366 | return 1; | ||
367 | } | ||
368 | if (ptr) | ||
369 | switch (type) | ||
370 | { | ||
371 | case Mail_env_string: | ||
372 | *(char**)ptr = env->value.string; | ||
373 | break; | ||
374 | |||
375 | case Mail_env_number: | ||
376 | *(int*)ptr = env->value.number; | ||
377 | break; | ||
378 | |||
379 | case Mail_env_boolean: | ||
380 | *(int*)ptr = env->set; | ||
381 | break; | ||
382 | |||
383 | default: | ||
384 | break; | ||
385 | } | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | /* Find environment entry var. If not found and CREATE is not null, then | ||
391 | create the (unset and untyped) variable */ | ||
347 | struct mail_env_entry * | 392 | struct mail_env_entry * |
348 | util_find_env (const char *variable) | 393 | util_find_env (const char *variable, int create) |
349 | { | 394 | { |
350 | /* Annoying, variable "ask" is equivalent to "asksub". */ | 395 | /* Annoying, variable "ask" is equivalent to "asksub". */ |
351 | static const char *asksub = "asksub"; | 396 | static const char *asksub = "asksub"; |
... | @@ -365,34 +410,33 @@ util_find_env (const char *variable) | ... | @@ -365,34 +410,33 @@ util_find_env (const char *variable) |
365 | 410 | ||
366 | if (environment == NULL) | 411 | if (environment == NULL) |
367 | { | 412 | { |
413 | if (!create) | ||
414 | return 0; | ||
368 | environment = xmalloc (sizeof (node)); | 415 | environment = xmalloc (sizeof (node)); |
369 | environment->env_entry.var = NULL; | 416 | environment->env_entry.var = NULL; |
370 | environment->env_entry.set = 0; | 417 | environment->env_entry.set = 0; |
371 | environment->env_entry.value = NULL; | 418 | environment->env_entry.value.number = 0; |
372 | environment->next = NULL; | 419 | environment->next = NULL; |
373 | } | 420 | } |
374 | 421 | ||
375 | for (env_cursor = environment; env_cursor->next != NULL; | 422 | for (env_cursor = environment; env_cursor->next; |
376 | env_cursor = env_cursor->next) | 423 | env_cursor = env_cursor->next) |
377 | { | 424 | { |
378 | if (strlen (env_cursor->env_entry.var) == len && | 425 | if (strlen (env_cursor->env_entry.var) == len && |
379 | !strcmp (var, env_cursor->env_entry.var)) | 426 | !strcmp (var, env_cursor->env_entry.var)) |
380 | { | 427 | return &env_cursor->env_entry; |
381 | return &(env_cursor->env_entry); | ||
382 | } | ||
383 | } | 428 | } |
384 | 429 | ||
385 | env_cursor->env_entry.var = strdup (var); | 430 | env_cursor->env_entry.var = strdup (var); |
386 | env_cursor->env_entry.set = 0; | 431 | env_cursor->env_entry.set = 0; |
387 | env_cursor->env_entry.value = NULL; | 432 | env_cursor->env_entry.type = Mail_env_whatever; |
433 | env_cursor->env_entry.value.number = 0; | ||
388 | t = env_cursor; | 434 | t = env_cursor; |
389 | env_cursor = util_ll_add (env_cursor, 0); | 435 | env_cursor = util_ll_add (env_cursor, 0); |
390 | return &(t->env_entry); | 436 | return &t->env_entry; |
391 | } | 437 | } |
392 | 438 | ||
393 | /* | 439 | /* print the environment */ |
394 | * print the environment | ||
395 | */ | ||
396 | int | 440 | int |
397 | util_printenv (int set) | 441 | util_printenv (int set) |
398 | { | 442 | { |
... | @@ -402,54 +446,96 @@ util_printenv (int set) | ... | @@ -402,54 +446,96 @@ util_printenv (int set) |
402 | if (env_cursor->env_entry.set == set) | 446 | if (env_cursor->env_entry.set == set) |
403 | { | 447 | { |
404 | fprintf (ofile, "%s", env_cursor->env_entry.var); | 448 | fprintf (ofile, "%s", env_cursor->env_entry.var); |
405 | if (env_cursor->env_entry.value != NULL) | 449 | switch (env_cursor->env_entry.type) |
406 | fprintf (ofile, "=\"%s\"", env_cursor->env_entry.value); | 450 | { |
451 | case Mail_env_number: | ||
452 | fprintf (ofile, "=%d", env_cursor->env_entry.value.number); | ||
453 | break; | ||
454 | |||
455 | case Mail_env_string: | ||
456 | fprintf (ofile, "=\"%s\"", env_cursor->env_entry.value.string); | ||
457 | break; | ||
458 | |||
459 | case Mail_env_boolean: | ||
460 | break; | ||
461 | |||
462 | case Mail_env_whatever: | ||
463 | fprintf (ofile, "oops?"); | ||
464 | } | ||
407 | fprintf (ofile, "\n"); | 465 | fprintf (ofile, "\n"); |
408 | } | 466 | } |
409 | } | 467 | } |
410 | return 0; | 468 | return 0; |
411 | } | 469 | } |
412 | 470 | ||
413 | /* | 471 | /* Initialize environment entry: clear set indicator and free any memory |
414 | * Set environement | 472 | associated with the data */ |
415 | * The util_setenv() function adds the variable name to the envi- | 473 | void |
416 | * ronment with the value value, if name does not already | 474 | util_mail_env_free (struct mail_env_entry *ep) |
417 | * exist. If name does exist in the environment, then its | ||
418 | * value is changed to value if overwrite is non-zero; if | ||
419 | * overwrite is zero, then the value of name is not changed. | ||
420 | * | ||
421 | * A side effect of the code is if value is null the variable name | ||
422 | * will be unset. | ||
423 | */ | ||
424 | int | ||
425 | util_setenv (const char *variable, const char *value, int overwrite) | ||
426 | { | 475 | { |
427 | struct mail_env_entry *ep = util_find_env (variable); | 476 | if (!mail_env_entry_is_set (ep)) |
428 | if (ep->set) | 477 | return; |
478 | |||
479 | switch (ep->type) | ||
429 | { | 480 | { |
430 | if (overwrite) | 481 | case Mail_env_string: |
431 | { | 482 | free (ep->value.string); |
432 | ep->set = 0; | 483 | ep->value.string = NULL; |
433 | if (ep->value) | 484 | break; |
434 | free (ep->value); | 485 | |
435 | ep->value = NULL; | 486 | default: |
436 | if (value) | 487 | break; |
437 | { | ||
438 | ep->set = 1; | ||
439 | ep->value = strdup (value); | ||
440 | } | ||
441 | } | ||
442 | } | 488 | } |
443 | else | 489 | ep->set = 0; |
490 | } | ||
491 | |||
492 | /* Set environement | ||
493 | The util_setenv() function adds the variable name to the envi- | ||
494 | ronment with the value value, if name does not already | ||
495 | exist. If name does exist in the environment, then its | ||
496 | value is changed to value if overwrite is non-zero; if | ||
497 | overwrite is zero, then the value of name is not changed. | ||
498 | |||
499 | A side effect of the code is if value is null the variable name | ||
500 | will be unset. */ | ||
501 | int | ||
502 | util_setenv (const char *variable, void *value, mail_env_data_t type, | ||
503 | int overwrite) | ||
504 | { | ||
505 | struct mail_env_entry *ep = util_find_env (variable, 1); | ||
506 | |||
507 | if (ep->set && !overwrite) | ||
508 | return 0; | ||
509 | |||
510 | util_mail_env_free (ep); | ||
511 | |||
512 | ep->type = type; | ||
513 | if (value) | ||
444 | { | 514 | { |
445 | ep->set = 1; | 515 | ep->set = 1; |
446 | if (ep->value) | 516 | switch (type) |
447 | free (ep->value); | 517 | { |
448 | ep->value = strdup (value); | 518 | case Mail_env_number: |
519 | ep->value.number = *(int*)value; | ||
520 | break; | ||
521 | |||
522 | case Mail_env_string: | ||
523 | ep->value.string = strdup (value); | ||
524 | break; | ||
525 | |||
526 | case Mail_env_boolean: | ||
527 | break; | ||
528 | |||
529 | default: | ||
530 | abort(); | ||
531 | } | ||
449 | } | 532 | } |
533 | |||
450 | return 0; | 534 | return 0; |
451 | } | 535 | } |
452 | 536 | ||
537 | /* ************************* */ | ||
538 | |||
453 | /* | 539 | /* |
454 | * return 1 if a message is deleted | 540 | * return 1 if a message is deleted |
455 | */ | 541 | */ |
... | @@ -480,12 +566,45 @@ util_get_homedir() | ... | @@ -480,12 +566,45 @@ util_get_homedir() |
480 | } | 566 | } |
481 | 567 | ||
482 | char * | 568 | char * |
483 | util_fullpath(const char *inpath) | 569 | util_fullpath (const char *inpath) |
484 | { | 570 | { |
485 | return mu_tilde_expansion(inpath, "/", NULL); | 571 | return mu_tilde_expansion(inpath, "/", NULL); |
486 | } | 572 | } |
487 | 573 | ||
488 | char * | 574 | char * |
575 | util_folder_path (const char *name) | ||
576 | { | ||
577 | char *folder; | ||
578 | char *tmp; | ||
579 | |||
580 | if (util_getenv (&folder, "folder", Mail_env_string, 1)) | ||
581 | return NULL; | ||
582 | |||
583 | if (!name) | ||
584 | return NULL; | ||
585 | if (name[0] == '+') | ||
586 | name++; | ||
587 | |||
588 | if (folder[0] != '/' && folder[1] != '~') | ||
589 | { | ||
590 | char *home = mu_get_homedir (); | ||
591 | tmp = xmalloc (strlen (home) + 1 + | ||
592 | strlen (folder) + 1 + | ||
593 | strlen (name) + 1); | ||
594 | sprintf (tmp, "%s/%s/%s", home, folder, name); | ||
595 | } | ||
596 | else | ||
597 | { | ||
598 | tmp = xmalloc (strlen (folder) + 1 + | ||
599 | strlen (name) + 1); | ||
600 | sprintf (tmp, "%s/%s", folder, name); | ||
601 | } | ||
602 | name = tmp; | ||
603 | |||
604 | return (char*) name; | ||
605 | } | ||
606 | |||
607 | char * | ||
489 | util_get_sender(int msgno, int strip) | 608 | util_get_sender(int msgno, int strip) |
490 | { | 609 | { |
491 | header_t header = NULL; | 610 | header_t header = NULL; |
... | @@ -690,21 +809,27 @@ util_escape_percent (char **str) | ... | @@ -690,21 +809,27 @@ util_escape_percent (char **str) |
690 | char * | 809 | char * |
691 | util_outfolder_name (char *str) | 810 | util_outfolder_name (char *str) |
692 | { | 811 | { |
693 | struct mail_env_entry *ep = util_find_env("outfolder"); | 812 | char *outfolder; |
694 | 813 | ||
814 | if (!str) | ||
815 | return NULL; | ||
816 | |||
695 | switch (*str) | 817 | switch (*str) |
696 | { | 818 | { |
697 | case '/': | 819 | case '/': |
698 | case '~': | 820 | case '~': |
699 | case '+': | ||
700 | str = util_fullpath (str); | 821 | str = util_fullpath (str); |
701 | break; | 822 | break; |
823 | |||
824 | case '+': | ||
825 | str = util_folder_path (str); | ||
826 | break; | ||
702 | 827 | ||
703 | default: | 828 | default: |
704 | if (ep && ep->set) | 829 | if (util_getenv (&outfolder, "outfolder", Mail_env_string, 0) == 0) |
705 | { | 830 | { |
706 | char *ns = NULL; | 831 | char *ns = NULL; |
707 | asprintf (&ns, "%s/%s", ep->value, str); | 832 | asprintf (&ns, "%s/%s", outfolder, str); |
708 | str = util_fullpath (ns); | 833 | str = util_fullpath (ns); |
709 | free (ns); | 834 | free (ns); |
710 | } | 835 | } |
... | @@ -712,7 +837,7 @@ util_outfolder_name (char *str) | ... | @@ -712,7 +837,7 @@ util_outfolder_name (char *str) |
712 | 837 | ||
713 | } | 838 | } |
714 | 839 | ||
715 | return str; | 840 | return strdup (str); |
716 | } | 841 | } |
717 | 842 | ||
718 | /* Save an outgoing message. "savefile" allows to override the setting | 843 | /* Save an outgoing message. "savefile" allows to override the setting |
... | @@ -720,11 +845,12 @@ util_outfolder_name (char *str) | ... | @@ -720,11 +845,12 @@ util_outfolder_name (char *str) |
720 | void | 845 | void |
721 | util_save_outgoing (message_t msg, char *savefile) | 846 | util_save_outgoing (message_t msg, char *savefile) |
722 | { | 847 | { |
723 | struct mail_env_entry *ep = util_find_env("record"); | 848 | char *record; |
724 | if (ep->set) | 849 | |
850 | if (util_getenv (&record, "record", Mail_env_string, 0) == 0) | ||
725 | { | 851 | { |
726 | FILE *outfile; | 852 | FILE *outfile; |
727 | char *filename = util_outfolder_name (savefile ? savefile : ep->value); | 853 | char *filename = util_outfolder_name (savefile ? savefile : record); |
728 | 854 | ||
729 | outfile = fopen (filename, "a"); | 855 | outfile = fopen (filename, "a"); |
730 | if (!outfile) | 856 | if (!outfile) |
... | @@ -810,8 +936,8 @@ util_help (const struct mail_command_entry *table, char *word) | ... | @@ -810,8 +936,8 @@ util_help (const struct mail_command_entry *table, char *word) |
810 | int i = 0; | 936 | int i = 0; |
811 | FILE *out = stdout; | 937 | FILE *out = stdout; |
812 | 938 | ||
813 | if ((util_find_env("crt"))->set) | 939 | if (util_getenv (NULL, "crt", Mail_env_boolean, 0) == 0) |
814 | out = popen (getenv("PAGER"), "w"); | 940 | out = popen (getenv ("PAGER"), "w"); |
815 | 941 | ||
816 | while (table[i].synopsis != 0) | 942 | while (table[i].synopsis != 0) |
817 | fprintf (out, "%s\n", table[i++].synopsis); | 943 | fprintf (out, "%s\n", table[i++].synopsis); | ... | ... |
-
Please register or sign in to post a comment