1 /* GNU Mailutils -- a suite of utilities for electronic mail
2    Copyright (C) 1999-2021 Free Software Foundation, Inc.
3 
4    GNU Mailutils is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3, or (at your option)
7    any later version.
8 
9    GNU Mailutils is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #include "mail.h"
18 
19 #define COND_STK_SIZE 64
20 #define COND_STK_INCR 16
21 static int *_cond_stack;     /* Stack of conditions */
22 static int _cond_stack_size; /* Number of elements allocated this far */
23 static int _cond_level;      /* Number of nested `if' blocks */
24 
25 static void _cond_push(int val);
26 static int _cond_pop(void);
27 
28 int
if_cond()29 if_cond()
30 {
31   if (_cond_level == 0)
32     return 1;
33   return _cond_stack[_cond_level-1];
34 }
35 
36 void
_cond_push(int val)37 _cond_push(int val)
38 {
39   if (!_cond_stack)
40     {
41       _cond_stack = calloc(COND_STK_SIZE, sizeof(_cond_stack[0]));
42       _cond_stack_size = COND_STK_SIZE;
43       _cond_level = 0;
44     }
45   else if (_cond_level >= _cond_stack_size)
46     {
47       _cond_stack_size += COND_STK_INCR;
48       _cond_stack = realloc(_cond_stack,
49 			    sizeof(_cond_stack[0])*_cond_stack_size);
50     }
51 
52   if (!_cond_stack)
53     {
54       mu_error(_("Not enough memory"));
55       exit (EXIT_FAILURE);
56     }
57   _cond_stack[_cond_level++] = val;
58 }
59 
60 int
_cond_pop()61 _cond_pop()
62 {
63   if (_cond_level == 0)
64     {
65       mu_error(_("Internal error: condition stack underflow"));
66       abort();
67     }
68   return _cond_stack[--_cond_level];
69 }
70 
71 /*
72  * i[f] s|r|t
73  * mail-commands
74  * el[se]
75  * mail-commands
76  * en[dif]
77  */
78 
79 int
mail_if(int argc,char ** argv)80 mail_if (int argc, char **argv)
81 {
82   char *mode;
83   int cond;
84 
85   if (argc != 2)
86     {
87       /* TRANSLATORS: 'if' is the function name. Do not translate it */
88       mu_error(_("if requires an argument: s | r | t"));
89       return 1;
90     }
91 
92   if (argv[1][1] != 0)
93     {
94       mu_error(_("Valid if arguments are: s | r | t"));
95       return 1;
96     }
97 
98   if (mailvar_get (&mode, mailvar_name_mode, mailvar_type_string, 1))
99     exit (EXIT_FAILURE);
100 
101   if (if_cond() == 0)
102     /* Propagate negative condition */
103     cond = 0;
104   else
105     {
106       switch (argv[1][0])
107 	{
108 	case 's': /* Send mode */
109 	  cond = strcmp(mode, "send") == 0;
110 	  break;
111 	case 'r': /* Read mode */
112 	  cond = strcmp(mode, "read") == 0;
113 	  break;
114 	case 't': /* Stdout is a terminal device? */
115 	  cond = isatty (fileno (stdout));
116 	  break;
117 	default:
118 	  mu_error(_("Valid if arguments are: s | r | t"));
119 	  return 1;
120 	}
121     }
122   _cond_push(cond);
123   return 0;
124 }
125 
126 
127 int
mail_else(int argc MU_ARG_UNUSED,char ** argv MU_ARG_UNUSED)128 mail_else (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
129 {
130   int cond;
131 
132   if (_cond_level == 0)
133     {
134       /* TRANSLATORS: 'else' and 'if' are function names. Do not translate them */
135       mu_error(_("else without matching if"));
136       return 1;
137     }
138   cond = _cond_pop();
139   if (if_cond ())
140     cond = !cond;
141   _cond_push(cond);
142   return 0;
143 }
144 
145 int
mail_endif(int argc MU_ARG_UNUSED,char ** argv MU_ARG_UNUSED)146 mail_endif (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
147 {
148   if (_cond_level == 0)
149     {
150       /* TRANSLATORS: 'endif' and 'if' are function names. Do not translate them */
151       mu_error (_("endif without matching if"));
152       return 1;
153     }
154   _cond_pop();
155   return 1;
156 }
157 
158