1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
/* Definitions of test shell functions for GNU Mailutils.
Copyright (C) 2019 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
/* Test shell commands are implemented via mu_tesh_function_t functions.
Arguments:
argc - argument count
argv - argument vector
options - assoc of options
env - evaluation environment (closure)
*/
typedef int (*mu_tesh_function_t)(int argc, char **argv, mu_assoc_t options,
void *env);
/* Option argument types */
enum mu_tesh_arg
{
mu_tesh_noarg, /* No argument allowed */
mu_tesh_arg_required, /* Argument is required */
mu_tesh_arg_optional /* Argument is optional */
};
/* Test shell command definition */
struct mu_tesh_command
{
/* The following fields must be filled by the caller */
char *verb; /* Command verb [1] */
char *args; /* Description of command arguments [2] */
mu_tesh_function_t func; /* Command handler function */
/* The fields below are computed and used by the shell itself.
The caller MAY NOT initialize them.
*/
int param_min; /* Minimum number of parameters */
int param_max; /* Maximum number of parameters. -1 for variadic */
mu_assoc_t options; /* Assoc array of the allowed options, indexed by
option names without the leading dash. Values
are of enum mu_tesh_arg type. */
};
/* Notes:
[1] The command verb "help" is implicitly defined. It produces a short
summary of the available shell commands. The special commands
The following special command verbs can be used:
__LINEPROC__
Called before word splitting. The entire command line is passed
as argv[0]. The argc is 1, and the options argument is NULL.
The function returns 0 to indicate that it has processed the
input. In this case, no further input handing will be performed
and the shell will proceed to next line from the input.
Otherwise, the shell will perform word splitting and initiate
further processing.
The function is free to modify or reassign argv[0] if it needs
so. The modified value will serve as input for further processing.
If the function chooses to reassing argv[0], it may not free the
current value, and the caller remains responsible for any memory
management needed. For example, if a newly allocated memory is
assigned to argv[0], this pointer must be saved somewhere in the
'env' to be subsequently freed by the __ENVFINI__ handler.
__NOCMD__
Called if the first token in the command line does not match
any defined command. The result of word splitting is passed in
argc and argv. The options argument is NULL. The function must
return 0 if it was able to process the input, and any non-zero
value otherwise. In the latter case, the shell will issue the
"no such command" diagnostics.
__ENVINIT__
Initialize the environment prior to running the command. The
argc, argv, and options arguments contain the result of command
line parsing.
The command must return 0 on success.
__ENVFINI__
Do any post-command cleanup of the environment. Arguments are
the same as to __ENVINIT__.
Return value is ignored.
__HELPINIT__
Print initial part of the help output. This function is called
by mu_tesh_help prior to printing the command summary.
The argc parameter is 0, argv and options are NULL.
Return value is ignored.
__HELPFINI__
Print final part of the help output. This function is called
by mu_tesh_help prior after printing the command summary.
Arguments are the same as for __HELPINIT__. Return value is
ignored.
Apart from these, no command verbs may begin and end with two
underscore characters.
[2] The args field in the above structure serves two purposes. First,
it describes the options and arguments to the shell command in
unambiguous way and is used during command line parsing. Secondly,
it is output by mu_tesh_help as a human-readable command line
syntax summary.
The syntax of this field is described by the BNF below:
<args> ::= <arglist> | <arglist> <ws> "..." |
<arglist> "..."
<arglist> ::= <argdef> | <arglist> <ws> <argdef>
<argdef> ::= <optdef> | <optarg> | STRING
<optdef> ::= "[-" STRING "]" |
"[-" STRING "=" STRING "]" |
"[-" STRING "[=" STRING "]]"
<optarg> ::= "[" string-list "]"
<string-list> ::= STRING | <string-list> <ws> STRING
<ws> ::= 1*WS
STRING is any contiguous sequence of printable characters, other
than whitespace, '[', or ']'. WS is horizontal space or tab
character.
Ellipis can appear immediately before the closing "]" of an <optdef>
or <optarg>.
The <optdef> token defines options that can be supplied to the
command. The <optdef>s can be intermixed with other tokens in an
<args> string. However, in actual command invocation, options must
precede positional arguments. The "--" argument can be given to
explicitly stop option processing.
Both trailing ellipsis and <optarg> indicate variable number of
arguments to the command.
*/
/* Initialize the shell. */
void mu_tesh_init (char const *argv0);
/* Main command evaluation loop.
If argc > 0, commands are read from argv. They must be delimited by
semicolons (obviously, if argc,argv are obtained from the shell command
line, the user must take care to escape each ';' to prevent it from
being processed by the shell). A semicolon may appear either as a separate
argument or as a last character of command's argument, e.g. supposing that
't' is a command line utility using tesh, both invocations below are valid:
t foo bar \; baz qux
t foo 'bar;' baz qux
If argc == 0, commands are read from the standard input. The '#' character
begins an inline comment.
*/
void mu_tesh_read_and_eval (int argc, char **argv,
struct mu_tesh_command *cmd,
void *env);
/* Print a short summary of shell commands. */
void mu_tesh_help (struct mu_tesh_command *cmd, void *env);
|