command.c 9.29 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"

Niels Möller's avatar
Niels Möller committed
39
static void
40
41
do_discard_continuation(struct command_continuation *ignored UNUSED,
			struct lsh_object *x UNUSED)
Niels Möller's avatar
Niels Möller committed
42
{}
43
44
45
46

struct command_continuation discard_continuation =
{ STATIC_HEADER, do_discard_continuation};

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

55
56
57
  return self;
}
  
58
/* GABA:
59
60
61
62
63
64
65
   (class
     (name command_apply)
     (super command_frame)
     (vars
       (f object command)))
*/

Niels Möller's avatar
Niels Möller committed
66
67
68
static void
do_command_apply(struct command_continuation *s,
		 struct lsh_object *value)
69
70
{
  CAST(command_apply, self, s);
Niels Möller's avatar
Niels Möller committed
71
72
  COMMAND_CALL(self->f, value,
	       self->super.up, self->super.e);
73
74
75
}

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

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

  return &res->super.super;
}
88

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

Niels Möller's avatar
Niels Möller committed
96
97
98
99
100
void
do_call_simple_command(struct command *s,
		       struct lsh_object *arg,
		       struct command_continuation *c,
		       struct exception_handler *e UNUSED)
101
{
102
  CAST_SUBTYPE(command_simple, self, s);
Niels Möller's avatar
Niels Möller committed
103
  COMMAND_RETURN(c, COMMAND_SIMPLE(self, arg));
104
105
}

106

107
/* Unimplemented command */
Niels Möller's avatar
Niels Möller committed
108
static void
109
110
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
/* Tracing
 *
 * For now, trace only function entry. */

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

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

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

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;
}

165
166
#if 0
/* This command should be obsoleted by the exception mechanism */
167
168
169
170
171
/* 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
172
do_command_die_on_null(struct command *s UNUSED,
173
		       struct lsh_object *x,
174
175
		       struct command_continuation *c,
		       struct exception_handler *e)
176
177
178
179
180
181
{
  return x ? COMMAND_RETURN(c, x) : LSH_FAIL | LSH_DIE;
}

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

/* Collecting arguments */
Niels Möller's avatar
Niels Möller committed
185
struct lsh_object *
186
187
188
189
190
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
191
192
193

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

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

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

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

230
231
232
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
233
{
234
235
236
237
238
239
  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
240
  
241
  return &self->super.super.super;
Niels Möller's avatar
Niels Möller committed
242
243
244
}

static struct lsh_object *
245
246
do_collect_3(struct command_simple *s,
	     struct lsh_object *x)
Niels Möller's avatar
Niels Möller committed
247
{
248
249
  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
250
251
}

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

268
269
270
static struct lsh_object *
do_collect_4(struct command_simple *s,
	     struct lsh_object *x)
Niels Möller's avatar
Niels Möller committed
271
{
272
273
274
  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
275

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
292
293
}

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

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

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
334
335
336
337
338

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

struct command_simple progn_command =
STATIC_COMMAND_SIMPLE(do_progn);

Niels Möller's avatar
Niels Möller committed
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429

/* A continuation that passes on its value only the first time it is
 * invoked. */
/* GABA:
   (class
     (name once_continuation)
     (super command_continuation)
     (vars
       (invoked . int)
       (msg . "const char *")
       (up object command_continuation)))
*/

static void
do_once_continuation(struct command_continuation *s,
		     struct lsh_object *value)
{
  CAST(once_continuation, self, s);

  if (!self->invoked)
    {
      self->invoked = 1;
      COMMAND_RETURN(self->up, value);
    }
  else if (self->msg)
    debug("%z", self->msg);
}

struct command_continuation *
make_once_continution(const char *msg,
		      struct command_continuation *up)
{
  NEW(once_continuation, self);
  self->super.c = do_once_continuation;
  self->invoked = 0;
  self->msg = msg;
  self->up = up;

  return &self->super;
}


/* Delayed application */

struct delayed_apply *
make_delayed_apply(struct command *f,
		   struct lsh_object *a)
{
  NEW(delayed_apply, self);
  self->f = f;
  self->a = a;
  return self;
}

/* GABA:
   (class
     (name delay_continuation)
     (super command_continuation)
     (vars
       (f object command)
       (up object command_continuation)))
*/

static void
do_delay_continuation(struct command_continuation *c,
		      struct lsh_object *o)
{
  CAST(delay_continuation, self, c);

  COMMAND_RETURN(self->up, make_delayed_apply(self->f, o));
}

struct command_continuation *
make_delay_continuation(struct command *f,
			struct command_continuation *c)
{
  NEW(delay_continuation, self);
  self->super.c = do_delay_continuation;
  self->up = c;
  self->f = f;

  return &self->super;
}