command.c 6.26 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
/* GABA:
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
   (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);
  res->f = f;
  res->super.up = c;
  res->super.super.c = do_command_apply;

  return &res->super.super;
}
64

Niels Möller's avatar
Niels Möller committed
65
66
struct lsh_object *gaba_apply(struct lsh_object *f,
			      struct lsh_object *x)
67
68
69
70
71
{
  CAST_SUBTYPE(command_simple, cf, f);
  return COMMAND_SIMPLE(cf, x);
}

72
int do_call_simple_command(struct command *s,
73
74
75
			   struct lsh_object *arg,
			   struct command_continuation *c)
{
76
  CAST_SUBTYPE(command_simple, self, s);
77
78
79
  return COMMAND_RETURN(c, COMMAND_SIMPLE(self, arg));
}

80

81
82
83
84
85
86
/* 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
87

88
89
90
91
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
92

93
94
95
struct command_simple command_unimplemented =
{ { STATIC_HEADER, do_command_unimplemented}, do_command_simple_unimplemented};

96
97
98
99
100
101

/* 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
102
do_command_die_on_null(struct command *s UNUSED,
103
104
105
106
107
108
109
110
111
112
113
		       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
114
struct lsh_object *
115
116
117
118
119
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
120
121
122

/* GABA:
   (class
123
124
     (name collect_state_1)
     (super command_simple)
Niels Möller's avatar
Niels Möller committed
125
     (vars
126
       (info object collect_info_2)
Niels Möller's avatar
Niels Möller committed
127
128
129
130
131
       (a object lsh_object)))
*/

/* GABA:
   (class
132
133
     (name collect_state_2)
     (super command_simple)
Niels Möller's avatar
Niels Möller committed
134
     (vars
135
136
       (info object collect_info_3)
       (a object lsh_object)
Niels Möller's avatar
Niels Möller committed
137
138
       (b object lsh_object)))
*/
139

Niels Möller's avatar
Niels Möller committed
140
141
/* GABA:
   (class
142
143
     (name collect_state_3)
     (super command_simple)
Niels Möller's avatar
Niels Möller committed
144
     (vars
145
146
147
       (info object collect_info_4)
       (a object lsh_object)
       (b object lsh_object)
Niels Möller's avatar
Niels Möller committed
148
149
150
       (c object lsh_object)))
*/

151
152
153
static struct lsh_object *
do_collect_2(struct command_simple *s,
	     struct lsh_object *x)
Niels Möller's avatar
Niels Möller committed
154
{
155
156
  CAST(collect_state_1, self, s);
  return self->info->f(self->info, self->a, x);
Niels Möller's avatar
Niels Möller committed
157
158
}

159
160
161
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
162
{
163
164
165
166
167
168
  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
169
  
170
  return &self->super.super.super;
Niels Möller's avatar
Niels Möller committed
171
172
173
}

static struct lsh_object *
174
175
do_collect_3(struct command_simple *s,
	     struct lsh_object *x)
Niels Möller's avatar
Niels Möller committed
176
{
177
178
  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
179
180
}

181
182
183
184
struct lsh_object *
make_collect_state_2(struct collect_info_2 *info,
		     struct lsh_object *a,
		     struct lsh_object *b)
185
{
186
187
188
189
  NEW(collect_state_2, self);
  self->info = info->next;
  self->a = a;
  self->b = b;
Niels Möller's avatar
Niels Möller committed
190
  
191
192
193
194
  self->super.call_simple = do_collect_3;
  self->super.super.call = do_call_simple_command;
  
  return &self->super.super.super;
195
}
Niels Möller's avatar
Niels Möller committed
196

197
198
199
static struct lsh_object *
do_collect_4(struct command_simple *s,
	     struct lsh_object *x)
Niels Möller's avatar
Niels Möller committed
200
{
201
202
203
  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
204

205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
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
221
222
}

223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/* 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]);
      res |= COMMAND_CALL(command, x, NULL);
      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
264
265
266
267
268

static struct lsh_object *do_progn(struct command_simple *s UNUSED,
				   struct lsh_object *x)
{
  CAST(object_list, body, x);
269
  return &make_parallell_progn(body)->super;
Niels Möller's avatar
Niels Möller committed
270
271
272
273
274
}

struct command_simple progn_command =
STATIC_COMMAND_SIMPLE(do_progn);