Commit 0b7f9863 0b7f9863de9277d28aed937694243d9d29ae6e7b by Sergey Poznyakoff

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.
1 parent 7ce36d80
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);
......