]> andersk Git - moira.git/blame - clients/mrtest/mrtest.c
fix RCS IDs
[moira.git] / clients / mrtest / mrtest.c
CommitLineData
c441a31a 1/* $Id$
6e6374cb 2 *
7ac48069 3 * Bare-bones Moira client
6e6374cb 4 *
7ac48069 5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
7 * <mit-copyright.h>.
6e6374cb 8 */
9
c801de4c 10#include <mit-copyright.h>
8defc06b 11#include <moira.h>
7ac48069 12
13#include <errno.h>
14#include <fcntl.h>
f281aa29 15#include <setjmp.h>
16#include <signal.h>
7ac48069 17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
f281aa29 21
22#ifdef USE_READLINE
23#include "readline.h"
7ac48069 24#include "history.h"
f281aa29 25#endif
6e6374cb 26
7ac48069 27RCSID("$Header$");
28
fcb0b7fa 29int recursion = 0, interactive;
5eaef520 30int count, quit = 0, cancel = 0;
1a5c774c 31char *whoami;
74c84b52 32sigjmp_buf jb;
1a5c774c 33
34#define MAXARGS 20
6e6374cb 35
7ac48069 36void discard_input(void);
37char *mr_gets(char *prompt, char *buf, size_t len);
38void execute_line(char *cmdbuf);
39int parse(char *buf, char *argv[MAXARGS]);
40int print_reply(int argc, char **argv, void *hint);
41void test_noop(void);
42void test_connect(int argc, char **argv);
43void test_disconnect(void);
44void test_host(void);
7ac48069 45void test_motd(void);
46void test_query(int argc, char **argv);
47void test_auth(void);
48void test_access(int argc, char **argv);
49void test_dcm(void);
50void test_script(int argc, char **argv);
51void test_list_requests(void);
f281aa29 52
5eaef520 53int main(int argc, char **argv)
54{
55 char cmdbuf[BUFSIZ];
56 struct sigaction action;
6e6374cb 57
5eaef520 58 whoami = argv[0];
59 interactive = (isatty(0) && isatty(1));
3442308f 60
5eaef520 61 initialize_sms_error_table();
62 initialize_krb_error_table();
63
64#ifdef USE_READLINE
65 /* we don't want filename completion */
66 rl_bind_key('\t', rl_insert);
74c84b52 67#endif
f281aa29 68
5eaef520 69 action.sa_handler = discard_input;
70 action.sa_flags = 0;
71 sigemptyset(&action.sa_mask);
72 sigaction(SIGINT, &action, NULL);
73 sigsetjmp(jb, 1);
74
75 while (!quit)
76 {
77 if (!mr_gets("moira: ", cmdbuf, BUFSIZ))
78 break;
79 execute_line(cmdbuf);
80 }
81 mr_disconnect();
82 exit(0);
1a5c774c 83}
84
5eaef520 85void discard_input(void)
f281aa29 86{
87 putc('\n', stdout);
fcb0b7fa 88
89 /* if we're inside a script, we have to clean up file descriptors,
90 so don't jump out yet */
5eaef520 91 if (recursion)
92 cancel = 1;
93 else
fcb0b7fa 94 siglongjmp(jb, 1);
f281aa29 95}
96
5eaef520 97char *mr_gets(char *prompt, char *buf, size_t len)
f281aa29 98{
99 char *in;
100#ifdef USE_READLINE
5eaef520 101 if (interactive)
102 {
103 in = readline(prompt);
104
105 if (!in)
106 return NULL;
107 if (*in)
108 add_history(in);
109 strncpy(buf, in, len - 1);
110 buf[len] = 0;
111 free(in);
112
113 return buf;
f281aa29 114 }
f281aa29 115#endif
116 printf("%s", prompt);
117 fflush(stdout);
5eaef520 118 in = fgets(buf, len, stdin);
119 if (!in)
120 return in;
121 if (strchr(buf, '\n'))
122 *(strchr(buf, '\n')) = '\0';
f281aa29 123 return buf;
124}
125
7ac48069 126void execute_line(char *cmdbuf)
1a5c774c 127{
128 int argc;
129 char *argv[MAXARGS];
130
5eaef520 131 argc = parse(cmdbuf, argv);
132 if (argc == 0)
133 return;
134 if (!strcmp(argv[0], "noop"))
1a5c774c 135 test_noop();
5eaef520 136 else if (!strcmp(argv[0], "connect") || !strcmp(argv[0], "c"))
1a5c774c 137 test_connect(argc, argv);
5eaef520 138 else if (!strcmp(argv[0], "disconnect") || !strcmp(argv[0], "d"))
1a5c774c 139 test_disconnect();
5eaef520 140 else if (!strcmp(argv[0], "host"))
1a5c774c 141 test_host();
5eaef520 142 else if (!strcmp(argv[0], "motd"))
1a5c774c 143 test_motd();
5eaef520 144 else if (!strcmp(argv[0], "query") || !strcmp(argv[0], "qy"))
1a5c774c 145 test_query(argc, argv);
5eaef520 146 else if (!strcmp(argv[0], "auth") || !strcmp(argv[0], "a"))
7ac48069 147 test_auth();
5eaef520 148 else if (!strcmp(argv[0], "access"))
1a5c774c 149 test_access(argc, argv);
5eaef520 150 else if (!strcmp(argv[0], "dcm"))
1a5c774c 151 test_dcm();
5eaef520 152 else if (!strcmp(argv[0], "script") || !strcmp(argv[0], "s"))
1a5c774c 153 test_script(argc, argv);
5eaef520 154 else if (!strcmp(argv[0], "list_requests") ||
155 !strcmp(argv[0], "lr") || !strcmp(argv[0], "?"))
1a5c774c 156 test_list_requests();
5eaef520 157 else if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "Q"))
158 quit = 1;
159 else
160 {
161 fprintf(stderr, "moira: Unknown request \"%s\". "
162 "Type \"?\" for a request list.\n", argv[0]);
163 }
1a5c774c 164}
165
5eaef520 166int parse(char *buf, char *argv[MAXARGS])
1a5c774c 167{
168 char *p;
169 int argc, num;
5eaef520 170
171 if (!*buf)
172 return 0;
173
174 for (p = buf, argc = 0, argv[0] = buf; *p && *p != '\n'; p++)
175 {
176 if (*p == '"')
177 {
178 char *d = p++;
179 /* skip to close-quote, copying back over open-quote */
180 while (*p != '"')
181 {
182 if (!*p || *p == '\n')
183 {
184 fprintf(stderr,
185 "moira: Unbalanced quotes in command line\n");
186 return 0;
187 }
188 /* deal with \### or \\ */
189 if (*p == '\\')
190 {
191 if (*++p != '"' && (*p < '0' || *p > '9') && (*p != '\\'))
192 {
193 fprintf(stderr, "moira: Bad use of \\\n");
194 return 0;
195 }
196 else if (*p >= '0' && *p <= '9')
197 {
198 num = (*p - '0') * 64 + (*++p - '0') * 8 + (*++p - '0');
199 *p = num;
200 }
201 }
202 *d++ = *p++;
203 }
204 if (p == d + 1)
205 {
206 *d = '\0';
207 p++;
208 }
209 else
210 {
211 while (p >= d)
212 *p-- = ' ';
213 }
2c031a2a 214 }
5eaef520 215 if (*p == ' ' || *p == '\t')
216 {
217 /* skip whitespace */
218 for (*p++ = '\0'; *p == ' ' || *p == '\t'; p++)
219 ;
220 if (*p && *p != '\n')
221 argv[++argc] = p--;
6e6374cb 222 }
1a5c774c 223 }
5eaef520 224 if (*p == '\n')
225 *p = '\0';
226 return argc + 1;
6e6374cb 227}
228
7ac48069 229void test_noop(void)
6e6374cb 230{
5eaef520 231 int status = mr_noop();
232 if (status)
233 com_err("moira (noop)", status, "");
6e6374cb 234}
235
7ac48069 236void test_connect(int argc, char *argv[])
6e6374cb 237{
5eaef520 238 char *server = "";
239 int status;
240
241 if (argc > 1)
242 server = argv[1];
243 status = mr_connect(server);
244 if (status)
245 com_err("moira (connect)", status, "");
6e6374cb 246}
247
7ac48069 248void test_disconnect(void)
6e6374cb 249{
5eaef520 250 int status = mr_disconnect();
251 if (status)
252 com_err("moira (disconnect)", status, "");
6e6374cb 253}
254
7ac48069 255void test_host(void)
66848930 256{
5eaef520 257 char host[BUFSIZ];
258 int status;
66848930 259
5eaef520 260 memset(host, 0, sizeof(host));
66848930 261
5eaef520 262 if ((status = mr_host(host, sizeof(host) - 1)))
263 com_err("moira (host)", status, "");
264 else
265 printf("You are connected to host %s\n", host);
66848930 266}
267
7ac48069 268void test_auth(void)
6e6374cb 269{
5eaef520 270 int status;
59af7b90 271
5eaef520 272 status = mr_auth("mrtest");
273 if (status)
274 com_err("moira (auth)", status, "");
6e6374cb 275}
276
7ac48069 277void test_script(int argc, char *argv[])
58b825a4 278{
5eaef520 279 FILE *inp;
280 char input[BUFSIZ], *cp;
281 int status, oldstdout, oldstderr;
282
283 if (recursion > 8)
284 {
285 com_err("moira (script)", 0, "too many levels deep in script files\n");
286 return;
58b825a4 287 }
288
5eaef520 289 if (argc < 2)
290 {
291 com_err("moira (script)", 0, "Usage: script input_file [ output_file ]");
292 return;
58b825a4 293 }
294
5eaef520 295 inp = fopen(argv[1], "r");
296 if (!inp)
297 {
298 sprintf(input, "Cannot open input file %s", argv[1]);
299 com_err("moira (script)", 0, input);
300 return;
58b825a4 301 }
302
5eaef520 303 if (argc == 3)
304 {
305 printf("Redirecting output to %s\n", argv[2]);
306 fflush(stdout);
307 oldstdout = dup(1);
308 close(1);
309 status = open(argv[2], O_CREAT|O_WRONLY|O_APPEND, 0664);
310 if (status != 1)
311 {
312 close(status);
313 dup2(oldstdout, 1);
314 argc = 2;
315 sprintf(input, "Unable to redirect output to %s\n", argv[2]);
316 com_err("moira (script)", errno, input);
317 }
318 else
319 {
320 fflush(stderr);
321 oldstderr = dup(2);
322 close(2);
323 dup2(1, 2);
58b825a4 324 }
325 }
326
5eaef520 327 recursion++;
328
329 while (!cancel)
330 {
331 if (!fgets(input, BUFSIZ, inp))
332 break;
333 if ((cp = strchr(input, '\n')))
334 *cp = '\0';
335 if (input[0] == 0)
336 {
337 printf("\n");
338 continue;
6a592314 339 }
5eaef520 340 if (input[0] == '%')
341 {
342 for (cp = &input[1]; *cp && isspace(*cp); cp++)
343 ;
344 printf("Comment: %s\n", cp);
345 continue;
58b825a4 346 }
5eaef520 347 printf("Executing: %s\n", input);
348 execute_line(input);
58b825a4 349 }
350
5eaef520 351 recursion--;
352 if (!recursion)
353 cancel = 0;
354
355 fclose(inp);
356 if (argc == 3)
357 {
358 fflush(stdout);
359 close(1);
360 dup2(oldstdout, 1);
361 close(oldstdout);
362 fflush(stderr);
363 close(2);
364 dup2(oldstderr, 2);
365 close(oldstderr);
58b825a4 366 }
367}
368
7ac48069 369int print_reply(int argc, char **argv, void *hint)
6e6374cb 370{
5eaef520 371 int i;
372 for (i = 0; i < argc; i++)
373 {
374 if (i != 0)
375 printf(", ");
376 printf("%s", argv[i]);
377 }
378 printf("\n");
379 count++;
380 return MR_CONT;
6e6374cb 381}
382
7ac48069 383void test_query(int argc, char **argv)
6e6374cb 384{
5eaef520 385 int status;
386 sigset_t sigs;
fcb0b7fa 387
5eaef520 388 if (argc < 2)
389 {
390 com_err("moira (query)", 0, "Usage: query handle [ args ... ]");
391 return;
392 }
59af7b90 393
5eaef520 394 count = 0;
395 /* Don't allow ^C during the query: it will confuse libmoira's
396 internal state. (Yay static variables) */
397 sigemptyset(&sigs);
398 sigaddset(&sigs, SIGINT);
399 sigprocmask(SIG_BLOCK, &sigs, NULL);
400 status = mr_query(argv[1], argc - 2, argv + 2, print_reply, NULL);
401 sigprocmask(SIG_UNBLOCK, &sigs, NULL);
402 printf("%d tuple%s\n", count, ((count == 1) ? "" : "s"));
403 if (status)
404 com_err("moira (query)", status, "");
6e6374cb 405}
406
7ac48069 407void test_access(int argc, char **argv)
6e6374cb 408{
5eaef520 409 int status;
410 if (argc < 2)
411 {
412 com_err("moira (access)", 0, "Usage: access handle [ args ... ]");
413 return;
414 }
415 status = mr_access(argv[1], argc - 2, argv + 2);
416 if (status)
417 com_err("moira (access)", status, "");
6e6374cb 418}
fc3ac28e 419
7ac48069 420void test_dcm()
fc3ac28e 421{
5eaef520 422 int status;
fc3ac28e 423
5eaef520 424 if ((status = mr_do_update()))
425 com_err("moira (dcm)", status, " while triggering dcm");
fc3ac28e 426}
093b57b1 427
7ac48069 428void test_motd()
093b57b1 429{
5eaef520 430 int status;
431 char *motd;
432
433 if ((status = mr_motd(&motd)))
434 com_err("moira (motd)", status, " while getting motd");
435 if (motd)
436 printf("%s\n", motd);
437 else
438 printf("No message of the day.\n");
093b57b1 439}
1a5c774c 440
7ac48069 441void test_list_requests(void)
1a5c774c 442{
5eaef520 443 printf("Available moira requests:\n");
444 printf("\n");
445 printf("noop\t\t\tAsk Moira to do nothing\n");
446 printf("connect, c\t\tConnect to Moira server\n");
447 printf("disconnect, d\t\tDisconnect from server\n");
448 printf("host\t\t\tIdentify the server host\n");
5eaef520 449 printf("motd, m\t\t\tGet the Message of the Day\n");
450 printf("query, qy\t\tMake a query.\n");
451 printf("auth, a\t\t\tAuthenticate to Moira.\n");
452 printf("access\t\t\tCheck access to a Moira query.\n");
453 printf("dcm\t\t\tTrigger the DCM\n");
454 printf("script, s\t\tRead commands from a script.\n");
455 printf("list_requests, lr, ?\tList available commands.\n");
456 printf("quit, Q\t\t\tLeave the subsystem.\n");
1a5c774c 457}
This page took 0.160514 seconds and 5 git commands to generate.