command.c 7.28 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
42
43
44
45
46
47
48
int do_discard_continuation(struct command_continuation *ignored UNUSED,
			    struct lsh_object *x UNUSED)
{
  return LSH_OK | LSH_GOON;
}

struct command_continuation discard_continuation =
{ STATIC_HEADER, do_discard_continuation};


49
/* GABA:
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
   (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);
  return COMMAND_CALL(self->f, value, self->super.up);
}

struct command_continuation *
make_apply(struct command *f, struct command_continuation *c)
{
  NEW(command_apply, res);
68

69
70
71
72
73
74
  res->f = f;
  res->super.up = c;
  res->super.super.c = do_command_apply;

  return &res->super.super;
}
75

Niels Möller's avatar
Niels Möller committed
76
77
struct lsh_object *gaba_apply(struct lsh_object *f,
			      struct lsh_object *x)
78
79
80
81
82
{
  CAST_SUBTYPE(command_simple, cf, f);
  return COMMAND_SIMPLE(cf, x);
}

83
int do_call_simple_command(struct command *s,
84
85
86
			   struct lsh_object *arg,
			   struct command_continuation *c)
{
87
  CAST_SUBTYPE(command_simple, self, s);
88
89
90
  return COMMAND_RETURN(c, COMMAND_SIMPLE(self, arg));
}

91

92
93
94
95
96
97
/* Unimplemented command */
static int
do_command_unimplemented(struct command *s UNUSED,
			 struct lsh_object *o UNUSED,
			 struct command_continuation *c UNUSED)
{ fatal("command.c: Unimplemented command.\n"); }
Niels Möller's avatar
Niels Möller committed
98

99
100
101
102
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
103

104
105
106
struct command_simple command_unimplemented =
{ { STATIC_HEADER, do_command_unimplemented}, do_command_simple_unimplemented};

107

Niels Möller's avatar
Niels Möller committed
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
/* 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,
			    struct command_continuation *c)
{
  CAST(trace_command, self, s);

  trace("Entering %z\n", self->name);
  return COMMAND_CALL(self->real, x, c);
}

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


148
149
150
151
152
/* 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
153
do_command_die_on_null(struct command *s UNUSED,
154
155
156
157
158
159
160
161
162
163
164
		       struct lsh_object *x,
		       struct command_continuation *c)
{
  return x ? COMMAND_RETURN(c, x) : LSH_FAIL | LSH_DIE;
}

struct command command_die_on_null =
{ STATIC_HEADER, do_command_die_on_null};


/* Collecting arguments */
Niels Möller's avatar
Niels Möller committed
165
struct lsh_object *
166
167
168
169
170
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
171
172
173

/* GABA:
   (class
174
175
     (name collect_state_1)
     (super command_simple)
Niels Möller's avatar
Niels Möller committed
176
     (vars
177
       (info object collect_info_2)
Niels Möller's avatar
Niels Möller committed
178
179
180
181
182
       (a object lsh_object)))
*/

/* GABA:
   (class
183
184
     (name collect_state_2)
     (super command_simple)
Niels Möller's avatar
Niels Möller committed
185
     (vars
186
187
       (info object collect_info_3)
       (a object lsh_object)
Niels Möller's avatar
Niels Möller committed
188
189
       (b object lsh_object)))
*/
190

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

202
203
204
static struct lsh_object *
do_collect_2(struct command_simple *s,
	     struct lsh_object *x)
Niels Möller's avatar
Niels Möller committed
205
{
206
207
  CAST(collect_state_1, self, s);
  return self->info->f(self->info, self->a, x);
Niels Möller's avatar
Niels Möller committed
208
209
}

210
211
212
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
213
{
214
215
216
217
218
219
  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
220
  
221
  return &self->super.super.super;
Niels Möller's avatar
Niels Möller committed
222
223
224
}

static struct lsh_object *
225
226
do_collect_3(struct command_simple *s,
	     struct lsh_object *x)
Niels Möller's avatar
Niels Möller committed
227
{
228
229
  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
230
231
}

232
233
234
235
struct lsh_object *
make_collect_state_2(struct collect_info_2 *info,
		     struct lsh_object *a,
		     struct lsh_object *b)
236
{
237
238
239
240
  NEW(collect_state_2, self);
  self->info = info->next;
  self->a = a;
  self->b = b;
Niels Möller's avatar
Niels Möller committed
241
  
242
243
244
245
  self->super.call_simple = do_collect_3;
  self->super.super.call = do_call_simple_command;
  
  return &self->super.super.super;
246
}
Niels Möller's avatar
Niels Möller committed
247

248
249
250
static struct lsh_object *
do_collect_4(struct command_simple *s,
	     struct lsh_object *x)
Niels Möller's avatar
Niels Möller committed
251
{
252
253
254
  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
255

256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
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
272
273
}

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
/* GABA:
   (class
     (name parallell_progn)
     (super command)
     (vars
       (body object object_list)))
*/

static int do_parallell_progn(struct command *s,
			      struct lsh_object *x,
			      struct command_continuation *c)
{
  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]);
293
      res |= COMMAND_CALL(command, x, &discard_continuation);
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
      if (LSH_CLOSEDP(res))
	return res;
    }
  {
    CAST_SUBTYPE(command, command, LIST(self->body)[i]);
    
    return res | COMMAND_CALL(command, x, c);
  }
}

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
315
316
317
318
319

static struct lsh_object *do_progn(struct command_simple *s UNUSED,
				   struct lsh_object *x)
{
  CAST(object_list, body, x);
320
  return &make_parallell_progn(body)->super;
Niels Möller's avatar
Niels Möller committed
321
322
323
324
325
}

struct command_simple progn_command =
STATIC_COMMAND_SIMPLE(do_progn);