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