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