command.c 7.82 KB
Newer Older
1
/* command.c
Niels Möller's avatar
Niels Möller committed
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 *
 * $Id$ */

/* lsh, an implementation of the ssh protocol
 *
 * Copyright (C) 1998 Niels Mller
 *
 * This program 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 2 of the
 * License, or (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "command.h"

26
27
#include "connection.h"
#include "io.h"
28
#include "werror.h"
29
30
#include "xalloc.h"

31
32
#include <assert.h>

33
#define GABA_DEFINE
34
#include "command.h.x"
35
#undef GABA_DEFINE
36
37
38

#include "command.c.x"

39
40
41
static int
do_discard_continuation(struct command_continuation *ignored UNUSED,
			struct lsh_object *x UNUSED)
42
43
44
45
46
47
48
{
  return LSH_OK | LSH_GOON;
}

struct command_continuation discard_continuation =
{ STATIC_HEADER, do_discard_continuation};

49
50
51
52
53
54
55
struct command_context *
make_command_context(struct command_continuation *c,
		     struct exception_handler *e)
{
  NEW(command_context, self);
  self->c = c;
  self->e = e;
56

57
58
59
  return self;
}
  
60
/* GABA:
61
62
63
64
65
66
67
68
69
70
71
   (class
     (name command_apply)
     (super command_frame)
     (vars
       (f object command)))
*/

static int do_command_apply(struct command_continuation *s,
			    struct lsh_object *value)
{
  CAST(command_apply, self, s);
72
73
  return COMMAND_CALL(self->f, value,
		      self->super.up, self->super.e);
74
75
76
}

struct command_continuation *
77
78
make_apply(struct command *f,
	   struct command_continuation *c, struct exception_handler *e)
79
80
{
  NEW(command_apply, res);
81

82
83
  res->f = f;
  res->super.up = c;
84
  res->super.e = e;
85
86
87
88
  res->super.super.c = do_command_apply;

  return &res->super.super;
}
89

Niels Möller's avatar
Niels Möller committed
90
91
struct lsh_object *gaba_apply(struct lsh_object *f,
			      struct lsh_object *x)
92
93
94
95
96
{
  CAST_SUBTYPE(command_simple, cf, f);
  return COMMAND_SIMPLE(cf, x);
}

97
int do_call_simple_command(struct command *s,
98
			   struct lsh_object *arg,
99
100
			   struct command_continuation *c,
			   struct exception_handler *e UNUSED)
101
{
102
  CAST_SUBTYPE(command_simple, self, s);
103
104
105
  return COMMAND_RETURN(c, COMMAND_SIMPLE(self, arg));
}

106

107
108
109
110
/* Unimplemented command */
static int
do_command_unimplemented(struct command *s UNUSED,
			 struct lsh_object *o UNUSED,
111
112
			 struct command_continuation *c UNUSED,
			 struct exception_handler *e UNUSED)
113
{ fatal("command.c: Unimplemented command.\n"); }
Niels Möller's avatar
Niels Möller committed
114

115
116
117
118
static struct lsh_object *
do_command_simple_unimplemented(struct command_simple *s UNUSED,
				struct lsh_object *o UNUSED)
{ fatal("command.c: Unimplemented simple command.\n"); }
Niels Möller's avatar
Niels Möller committed
119

120
121
122
struct command_simple command_unimplemented =
{ { STATIC_HEADER, do_command_unimplemented}, do_command_simple_unimplemented};

123

Niels Möller's avatar
Niels Möller committed
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* Tracing
 *
 * For now, trace only function entry. */

/* GABA:
   (class
     (name trace_command)
     (super command)
     (vars
       (name . "const char *")
       (real object command)))
*/

static int do_trace_command(struct command *s,
			    struct lsh_object *x,
139
140
			    struct command_continuation *c,
			    struct exception_handler *e)
Niels Möller's avatar
Niels Möller committed
141
142
143
144
{
  CAST(trace_command, self, s);

  trace("Entering %z\n", self->name);
145
  return COMMAND_CALL(self->real, x, c, e);
Niels Möller's avatar
Niels Möller committed
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
}

struct command *make_trace(const char *name, struct command *real)
{
  NEW(trace_command, self);
  self->super.call = do_trace_command;
  self->name = name;
  self->real = real;

  return &self->super;
}

struct lsh_object *collect_trace(const char *name, struct lsh_object *c)
{
  CAST_SUBTYPE(command, real, c);
  return &make_trace(name, real)->super;
}

164
165
#if 0
/* This command should be obsoleted by the exception mechanism */
166
167
168
169
170
/* Fail if NULL. This commands returns its argument unchanged. Unless
 * it is NULL, in which case it doesn't return at all, but instead
 * returns an LSH_FAIL status to the mainloop. */

static int
Niels Möller's avatar
Niels Möller committed
171
do_command_die_on_null(struct command *s UNUSED,
172
		       struct lsh_object *x,
173
174
		       struct command_continuation *c,
		       struct exception_handler *e)
175
176
177
178
179
180
{
  return x ? COMMAND_RETURN(c, x) : LSH_FAIL | LSH_DIE;
}

struct command command_die_on_null =
{ STATIC_HEADER, do_command_die_on_null};
181
#endif
182
183

/* Collecting arguments */
Niels Möller's avatar
Niels Möller committed
184
struct lsh_object *
185
186
187
188
189
do_collect_1(struct command_simple *s, struct lsh_object *a)
{
  CAST(collect_info_1, self, s);
  return self->f(self, a);
}
Niels Möller's avatar
Niels Möller committed
190
191
192

/* GABA:
   (class
193
194
     (name collect_state_1)
     (super command_simple)
Niels Möller's avatar
Niels Möller committed
195
     (vars
196
       (info object collect_info_2)
Niels Möller's avatar
Niels Möller committed
197
198
199
200
201
       (a object lsh_object)))
*/

/* GABA:
   (class
202
203
     (name collect_state_2)
     (super command_simple)
Niels Möller's avatar
Niels Möller committed
204
     (vars
205
206
       (info object collect_info_3)
       (a object lsh_object)
Niels Möller's avatar
Niels Möller committed
207
208
       (b object lsh_object)))
*/
209

Niels Möller's avatar
Niels Möller committed
210
211
/* GABA:
   (class
212
213
     (name collect_state_3)
     (super command_simple)
Niels Möller's avatar
Niels Möller committed
214
     (vars
215
216
217
       (info object collect_info_4)
       (a object lsh_object)
       (b object lsh_object)
Niels Möller's avatar
Niels Möller committed
218
219
220
       (c object lsh_object)))
*/

221
222
223
static struct lsh_object *
do_collect_2(struct command_simple *s,
	     struct lsh_object *x)
Niels Möller's avatar
Niels Möller committed
224
{
225
226
  CAST(collect_state_1, self, s);
  return self->info->f(self->info, self->a, x);
Niels Möller's avatar
Niels Möller committed
227
228
}

229
230
231
struct lsh_object *
make_collect_state_1(struct collect_info_1 *info,
		     struct lsh_object *a)
Niels Möller's avatar
Niels Möller committed
232
{
233
234
235
236
237
238
  NEW(collect_state_1, self);
  self->info = info->next;
  self->a = a;

  self->super.call_simple = do_collect_2;
  self->super.super.call = do_call_simple_command;
Niels Möller's avatar
Niels Möller committed
239
  
240
  return &self->super.super.super;
Niels Möller's avatar
Niels Möller committed
241
242
243
}

static struct lsh_object *
244
245
do_collect_3(struct command_simple *s,
	     struct lsh_object *x)
Niels Möller's avatar
Niels Möller committed
246
{
247
248
  CAST(collect_state_2, self, s);
  return self->info->f(self->info, self->a, self->b, x);
Niels Möller's avatar
Niels Möller committed
249
250
}

251
252
253
254
struct lsh_object *
make_collect_state_2(struct collect_info_2 *info,
		     struct lsh_object *a,
		     struct lsh_object *b)
255
{
256
257
258
259
  NEW(collect_state_2, self);
  self->info = info->next;
  self->a = a;
  self->b = b;
Niels Möller's avatar
Niels Möller committed
260
  
261
262
263
264
  self->super.call_simple = do_collect_3;
  self->super.super.call = do_call_simple_command;
  
  return &self->super.super.super;
265
}
Niels Möller's avatar
Niels Möller committed
266

267
268
269
static struct lsh_object *
do_collect_4(struct command_simple *s,
	     struct lsh_object *x)
Niels Möller's avatar
Niels Möller committed
270
{
271
272
273
  CAST(collect_state_3, self, s);
  return self->info->f(self->info, self->a, self->b, self->c, x);
}
Niels Möller's avatar
Niels Möller committed
274

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
struct lsh_object *
make_collect_state_3(struct collect_info_3 *info,
		     struct lsh_object *a,
		     struct lsh_object *b,
		     struct lsh_object *c)
{
  NEW(collect_state_3, self);
  self->info = info->next;
  self->a = a;
  self->b = b;
  self->c = c;
  
  self->super.call_simple = do_collect_4;
  self->super.super.call = do_call_simple_command;
  
  return &self->super.super.super;
Niels Möller's avatar
Niels Möller committed
291
292
}

293
294
295
296
297
298
299
300
301
302
/* GABA:
   (class
     (name parallell_progn)
     (super command)
     (vars
       (body object object_list)))
*/

static int do_parallell_progn(struct command *s,
			      struct lsh_object *x,
303
304
			      struct command_continuation *c,
			      struct exception_handler *e)
305
306
307
308
309
310
311
312
{
  CAST(parallell_progn, self, s);
  unsigned i;
  int res = 0;
  
  for (i=0; i < LIST_LENGTH(self->body) - 1; i++)
    {
      CAST_SUBTYPE(command, command, LIST(self->body)[i]);
313
      res |= COMMAND_CALL(command, x, &discard_continuation, e);
314
315
316
317
318
319
      if (LSH_CLOSEDP(res))
	return res;
    }
  {
    CAST_SUBTYPE(command, command, LIST(self->body)[i]);
    
320
    return res | COMMAND_CALL(command, x, c, e);
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  }
}

struct command *make_parallell_progn(struct object_list *body)
{
  assert(LIST_LENGTH(body));
  {
    NEW(parallell_progn, self);
    self->body = body;
    self->super.call = do_parallell_progn;

    return &self->super;
  }
}
Niels Möller's avatar
Niels Möller committed
335
336
337
338
339

static struct lsh_object *do_progn(struct command_simple *s UNUSED,
				   struct lsh_object *x)
{
  CAST(object_list, body, x);
340
  return &make_parallell_progn(body)->super;
Niels Möller's avatar
Niels Möller committed
341
342
343
344
345
}

struct command_simple progn_command =
STATIC_COMMAND_SIMPLE(do_progn);