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 FIND_IN_TABLE(f,t,c)\
20   f ((void*)(t), sizeof ((t)) / sizeof ((t)[0]), sizeof ((t)[0]), c)
21 
22 static const struct mail_command_entry mail_command_table[] = {
23   { "a",	"alias",	"a[lias] [alias [address...]]",	0,
24     mail_alias, alias_compl },
25   { "alt",	"alternates",	"alt[ernates] name...",		0,
26     mail_alt, NULL },
27   { "C",	"Copy",		"C[opy] [msglist]",		0,
28     mail_copy,  msglist_compl },
29   { "cd",	"cd",		"cd [directory]",		0,
30     mail_cd, dir_compl },
31   { "ch",	"chdir",	"ch[dir] directory",		0,
32     mail_cd, NULL },
33   { "c",	"copy",		"c[opy] [[msglist] file]",	0,
34     mail_copy, msglist_file_compl },
35   { "dec",	"decode",	"dec[ode] [msglist]",		0,
36     mail_decode, msglist_compl },
37   { "d",	"delete",	"d[elete] [msglist]",		0,
38     mail_delete, msglist_compl },
39   { "di",	"discard",	"di[scard] [header-field...]",	0,
40     mail_discard, no_compl },
41   { "dp",	"dp",		"dp [msglist]",			0,
42     mail_dp, msglist_compl },
43   { "dt",	"dt",		"dt [msglist]",			0,
44     mail_dp, msglist_compl },
45   { "ec",	"echo",		"ec[ho] string ...",		0,
46     mail_echo, no_compl },
47   { "e",	"edit",		"e[dit] [msglist]",		0,
48     mail_edit, msglist_compl },
49   { "el",	"else",		"el[se]",			EF_FLOW,
50     mail_else, no_compl },
51   { "en",	"endif",	"en[dif]",			EF_FLOW,
52     mail_endif, no_compl },
53   { "env",      "envelope",     "en[velope]",                   0,
54     mail_envelope, msglist_compl },
55   { "ex",	"exit",		"ex[it]",			0,
56     mail_exit, no_compl },
57   { "F",	"Followup",	"F[ollowup] [msglist]",		EF_SEND,
58     mail_followup, msglist_compl },
59   { "fi",	"file",		"fi[le] [file]",		0,
60     mail_file, file_compl },
61   { "fold",	"folder",	"fold[er] [file]",		0,
62     mail_file, file_compl },
63   { "folders",	"folders",	"folders",			0,
64     mail_folders, no_compl },
65   { "fo",	"followup",	"fo[llowup] [message]",		EF_SEND,
66     mail_followup, msglist_compl },
67   { "f",	"from",		"f[rom] [msglist]",		0,
68     mail_from, msglist_compl },
69   { "g",	"group",	"g[roup] [alias [address...]]",	0,
70     mail_alias, alias_compl },
71   { "h",	"headers",	"h[eaders] [msglist]",		0,
72     mail_headers, msglist_compl },
73   { "hel",	"help",		"hel[p] [command...]",		0,
74     mail_help, command_compl },
75   { "ho",	"hold",		"ho[ld] [msglist]",		0,
76     mail_hold, msglist_compl },
77   { "i",	"if",		"i[f] s|r|t",			EF_FLOW,
78     mail_if, no_compl },
79   { "ig",	"ignore",	"ig[nore] [header-field...]",	0,
80     mail_discard, no_compl },
81   { "inc",      "incorporate",	"inc[orporate]",		0,
82     mail_inc, no_compl },
83   { "l",	"list",		"l[ist]",			0,
84     mail_list, no_compl },
85   { "m",	"mail",		"m[ail] [address...]",		EF_SEND,
86     mail_send, alias_compl },
87   { "M",        "Mail",         "M[ail] [address...]",		EF_SEND,
88     mail_send, alias_compl },
89   { "mb",	"mbox",		"mb[ox] [msglist]",		0,
90     mail_mbox, msglist_compl },
91   { "n",	"next",		"n[ext] [message]",		0,
92     mail_next, no_compl },
93   { "nosender", "nos",          "nos[ender] [header-field...]", 0,
94     mail_nosender, no_compl },
95   { "nou",      "nounfold",     "nou[nfold] [header-field]",    0,
96     mail_nounfold, no_compl },
97   { "P",	"Print",	"P[rint] [msglist]",		0,
98     mail_print, msglist_compl },
99   { "pi",	"pipe",		"pi[pe] [[msglist] command]",	0,
100     mail_pipe, exec_compl },
101   { "pre",	"preserve",	"pre[serve] [msglist]",		0,
102     mail_hold, msglist_compl },
103   { "prev",	"previous",	"prev[ious] [message]",		0,
104     mail_previous, no_compl },
105   { "p",	"print",	"p[rint] [msglist]",		0,
106     mail_print, msglist_compl },
107   { "q",	"quit",		"q[uit]",			0,
108     mail_quit, no_compl },
109   { "R",	"Reply",	"R[eply] [msglist]",		EF_SEND,
110     mail_reply, msglist_compl },
111   { "R",	"Respond",	"R[espond] [msglist]",		EF_SEND,
112     mail_reply, msglist_compl },
113   { "r",	"reply",	"r[eply] [message]",		EF_SEND,
114     mail_reply, msglist_compl },
115   { "r",	"respond",	"r[espond] [message]",		EF_SEND,
116     mail_reply, msglist_compl },
117   { "ret",	"retain",	"ret[ain] [header-field]",	0,
118     mail_retain, no_compl },
119   { "S",	"Save",		"S[ave] [msglist]",		0,
120     mail_save, msglist_compl },
121   { "s",	"save",		"s[ave] [[msglist] file]",	0,
122     mail_save, msglist_file_compl },
123   { "sen",      "sendheader",   "sen[dheader] [[header][: value]]", EF_SEND,
124     mail_sendheader, no_compl },
125   { "se", "set", "se[t] [name[=[string]]...] [name=number...] [noname...]", 0,
126     mail_set, mailvar_set_compl },
127   { "setq",     "setq",         NULL,                           EF_HIDDEN,
128     mail_set, no_compl },
129   { "sender",   "sen",          "sen[der] [header-field...]",   0,
130     mail_sender, no_compl },
131   { "sete",     "setenv",       "sete[nv] [name[=value]]",      0,
132     mail_setenv, no_compl },
133   { "sh",	"shell",	"sh[ell] [command]",		0,
134     mail_shell, shell_compl },
135   { "si",	"size",		"si[ze] [msglist]",		0,
136     mail_size, msglist_compl },
137   { "so",	"source",	"so[urce] file",		0,
138     mail_source, NULL },
139   { "st",       "struct",       "st[ruct] [msglist]",           0,
140     mail_struct, NULL },
141   { "su",	"summary",	"su[mmary]",			0,
142     mail_summary, no_compl },
143   { "T",	"Type",		"T[ype] [msglist]",		0,
144     mail_print, msglist_compl },
145   { "ta",       "tag",		"ta[g] [msglist]",		0,
146     mail_tag, msglist_compl },
147   { "to",	"top",		"to[p] [msglist]",		0,
148     mail_top, msglist_compl },
149   { "tou",	"touch",        "tou[ch] [msglist]",  	        0,
150     mail_touch, msglist_compl },
151   { "t",	"type",		"t[ype] [msglist]",		0,
152     mail_print, msglist_compl },
153   { "una",	"unalias",	"una[lias] [alias]...",		0,
154     mail_unalias, NULL },
155   { "u",	"undelete",	"u[ndelete] [msglist]",		0,
156     mail_undelete, msglist_compl },
157   { "unf",      "unfold",       "unf[old] [header-field]",      0,
158     mail_unfold, no_compl },
159   { "uns",	"unset",	"uns[et] name...",		0,
160     mail_unset, mailvar_set_compl },
161   { "unt",      "untag",	"unt[ag] [msglist]",		0,
162     mail_tag, msglist_compl },
163   { "va",       "variable",     "variable [name...]",           0,
164     mail_variable, mailvar_set_compl },
165   { "ve",	"version",	"ve[rsion]",			0,
166     mail_version, no_compl },
167   { "v",	"visual",	"v[isual] [msglist]",		0,
168     mail_visual, msglist_compl },
169   { "wa",       "warranty",	"wa[rranty]",			0,
170     mail_warranty, no_compl },
171   { "W",	"Write",	"W[rite] [msglist]",		0,
172     mail_write, msglist_compl },
173   { "w",	"write",	"w[rite] [[msglist] file]",	0,
174     mail_write, msglist_file_compl },
175   { "x",	"xit",		"x[it]",			0,
176     mail_exit, no_compl },
177   { "z",	"",		"z[+|-|. [count]]",		0,
178     mail_z, no_compl },
179   { "?",	"?",		"? [command...]",		0,
180     mail_help, command_compl },
181   { "!",	"",		"![command]",			0,
182     mail_shell, shell_compl },
183   { "=",	"=",		"=",				0,
184     mail_eq, no_compl },
185   { "#",	"#",		"# comment",			0,
186     NULL, no_compl },
187   { "*",	"*",		"*",				0,
188     mail_list, no_compl },
189   { "+",	"+",		"+ [message]",			0,
190     mail_next, msglist_compl },
191   { "|",	"|",		"| [[msglist] command]",	0,
192     mail_pipe, exec_compl },
193   { "-",	"-",		"- [message]",			0,
194     mail_previous, msglist_compl },
195 };
196 
197 
198 const struct mail_command_entry *
mail_find_command(const char * cmd)199 mail_find_command (const char *cmd)
200 {
201   return FIND_IN_TABLE (util_find_entry, mail_command_table, cmd);
202 }
203 
204 int
mail_command_help(const char * cmd)205 mail_command_help (const char *cmd)
206 {
207   return FIND_IN_TABLE (util_help, mail_command_table, cmd);
208 }
209 
210 void
mail_command_list()211 mail_command_list ()
212 {
213   util_command_list ((void*)mail_command_table,
214 		     sizeof (mail_command_table) / sizeof (mail_command_table[0]),
215 		     sizeof (mail_command_table[0]));
216 }
217 
218 const struct mail_command *
mail_command_name(int i)219 mail_command_name (int i)
220 {
221   if (i < 0 || i >= sizeof (mail_command_table) / sizeof (mail_command_table[0]))
222     return NULL;
223   return (struct mail_command*) &mail_command_table[i];
224 }
225 
226 static const struct mail_escape_entry mail_escape_table[] = {
227   {"!",	"!",	"![shell-command]", escape_shell },
228   {":",	":",	":[mail-command]",  escape_command },
229   {"-",	"-",	"-[mail-command]",  escape_command },
230   {"+",	"+",	"+name [content-type [encoding]]", escape_attach },
231   {"^",	"^",	"^N",               escape_remove_attachment },
232   {"/", "/",    "/",                escape_toggle_multipart_type },
233   {"?",	"?",	"?",		    escape_help },
234   {"A",	"A",	"A",		    escape_sign },
235   {"a",	"a",	"a",		    escape_sign },
236   {"b",	"b",	"b[bcc-list]",	    escape_bcc },
237   {"c",	"c",	"c[cc-list]",	    escape_cc },
238   {"d",	"d",	"d",		    escape_deadletter },
239   {"e",	"e",	"e",		    escape_editor },
240   {"f",	"f",	"f[mesg-list]",	    escape_print },
241   {"F",	"F",	"F[mesg-list]",	    escape_print },
242   {"h",	"h",	"h",		    escape_headers },
243   {"i",	"i",	"i[var-name]",	    escape_insert },
244   {"l",	"l",	"l",                escape_list_attachments },
245   {"m",	"m",	"m[mesg-list]",	    escape_quote },
246   {"M",	"M",	"M[mesg-list]",	    escape_quote },
247   {"p",	"p",	"p",		    escape_type_input },
248   {"r",	"<",	"r[filename]",	    escape_read },
249   {"s",	"s",	"s[string]",	    escape_subj },
250   {"t",	"t",	"t[name-list]",	    escape_to },
251   {"v",	"v",	"v",		    escape_visual },
252   {"w",	"w",	"w[filename]",	    escape_write },
253   {"x", "x",    "x",                NULL }, /* Implemented directly in
254 					       send.c */
255   {"|",	"|",	"|[shell-command]", escape_pipe },
256 };
257 
258 const struct mail_escape_entry *
mail_find_escape(const char * cmd)259 mail_find_escape (const char *cmd)
260 {
261   return FIND_IN_TABLE (util_find_entry, mail_escape_table, cmd);
262 }
263 
264 int
mail_escape_help(const char * cmd)265 mail_escape_help (const char *cmd)
266 {
267   return FIND_IN_TABLE (util_help, mail_escape_table, cmd);
268 }
269 
270