3 * Bare-bones Moira client
5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
10 #include <mit-copyright.h>
33 #define isatty _isatty
36 #define sigjmp_buf jmp_buf
37 #define siglongjmp longjmp
38 #define sigsetjmp(env, save) setjmp(env)
42 #include "readline/readline.h"
43 #include "readline/history.h"
48 int recursion = 0, quote_output = 0, interactive;
49 int count, quit = 0, cancel = 0;
56 void discard_input(int sig);
57 char *mr_gets(char *prompt, char *buf, size_t len);
58 void execute_line(char *cmdbuf);
59 int parse(char *buf, char *argv[MAXARGS]);
60 int print_reply(int argc, char **argv, void *help);
62 void test_connect(int argc, char **argv);
63 void test_disconnect(void);
66 void test_query(int argc, char **argv);
68 void test_proxy(int argc, char **argv);
69 void test_access(int argc, char **argv);
71 void test_script(int argc, char **argv);
72 void test_list_requests(void);
73 void test_version(int argc, char **argv);
74 void test_krb5_auth(void);
75 void set_signal_handler(int, void (*handler)(int));
76 void set_signal_blocking(int, int);
78 int main(int argc, char **argv)
84 interactive = (isatty(0) && isatty(1));
86 while ((c = getopt(argc, argv, "q")) != -1)
95 fprintf(stderr, "Usage: mrtest [-q]\n");
100 initialize_sms_error_table();
101 initialize_krb_error_table();
104 /* we don't want filename completion */
105 rl_bind_key('\t', rl_insert);
108 set_signal_handler(SIGINT, discard_input);
113 if (!mr_gets("moira: ", cmdbuf, BUFSIZ))
115 execute_line(cmdbuf);
121 void discard_input(int sig)
125 /* if we're inside a script, we have to clean up file descriptors,
126 so don't jump out yet */
133 char *mr_gets(char *prompt, char *buf, size_t len)
139 in = readline(prompt);
145 strncpy(buf, in, len - 1);
152 printf("%s", prompt);
154 in = fgets(buf, len, stdin);
157 if (strchr(buf, '\n'))
158 *(strchr(buf, '\n')) = '\0';
162 void execute_line(char *cmdbuf)
167 argc = parse(cmdbuf, argv);
170 if (!strcmp(argv[0], "noop"))
172 else if (!strcmp(argv[0], "connect") || !strcmp(argv[0], "c"))
173 test_connect(argc, argv);
174 else if (!strcmp(argv[0], "disconnect") || !strcmp(argv[0], "d"))
176 else if (!strcmp(argv[0], "host"))
178 else if (!strcmp(argv[0], "motd") || !strcmp(argv[0], "m"))
180 else if (!strcmp(argv[0], "query") || !strcmp(argv[0], "qy"))
181 test_query(argc, argv);
182 else if (!strcmp(argv[0], "auth") || !strcmp(argv[0], "a"))
184 else if (!strcmp(argv[0], "proxy") || !strcmp(argv[0], "p"))
185 test_proxy(argc, argv);
186 else if (!strcmp(argv[0], "access"))
187 test_access(argc, argv);
188 else if (!strcmp(argv[0], "dcm"))
190 else if (!strcmp(argv[0], "script") || !strcmp(argv[0], "s"))
191 test_script(argc, argv);
192 else if (!strcmp(argv[0], "list_requests") ||
193 !strcmp(argv[0], "lr") || !strcmp(argv[0], "?"))
194 test_list_requests();
195 else if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "Q"))
197 else if (!strcmp(argv[0], "version") || !strcmp(argv[0], "v"))
198 test_version(argc, argv);
199 else if (!strcmp(argv[0], "krb4_auth") || !strcmp(argv[0], "4"))
203 fprintf(stderr, "moira: Unknown request \"%s\". "
204 "Type \"?\" for a request list.\n", argv[0]);
208 int parse(char *buf, char *argv[MAXARGS])
216 for (p = buf, argc = 0, argv[0] = buf; *p && *p != '\n'; p++)
221 /* skip to close-quote, copying back over open-quote */
224 if (!*p || *p == '\n')
227 "moira: Unbalanced quotes in command line\n");
230 /* deal with \### or \\ */
233 if (*++p != '"' && (*p < '0' || *p > '9') && (*p != '\\'))
235 fprintf(stderr, "moira: Bad use of \\\n");
238 else if (*p >= '0' && *p <= '9')
240 num = (*p - '0') * 64 + (*++p - '0') * 8 + (*++p - '0');
257 if (*p == ' ' || *p == '\t')
259 /* skip whitespace */
260 for (*p++ = '\0'; *p == ' ' || *p == '\t'; p++)
262 if (*p && *p != '\n')
273 int status = mr_noop();
275 com_err("moira (noop)", status, "");
278 void test_connect(int argc, char *argv[])
285 status = mr_connect(server);
287 com_err("moira (connect)", status, "");
291 void test_disconnect(void)
293 int status = mr_disconnect();
295 com_err("moira (disconnect)", status, "");
303 memset(host, 0, sizeof(host));
305 if ((status = mr_host(host, sizeof(host) - 1)))
306 com_err("moira (host)", status, "");
308 printf("You are connected to host %s\n", host);
315 status = mr_auth("mrtest");
317 com_err("moira (auth)", status, "");
320 void test_krb5_auth(void)
324 status = mr_krb5_auth("mrtest");
326 com_err("moira (krb5_auth)", status, "");
329 void test_proxy(int argc, char *argv[])
335 com_err("moira (proxy)", 0, "Usage: proxy principal authtype");
338 status = mr_proxy(argv[1], argv[2]);
340 com_err("moira (proxy)", status, "");
343 void test_script(int argc, char *argv[])
346 char input[BUFSIZ], *cp;
347 int status, oldstdout, oldstderr;
351 com_err("moira (script)", 0, "too many levels deep in script files\n");
357 com_err("moira (script)", 0, "Usage: script input_file [ output_file ]");
361 inp = fopen(argv[1], "r");
364 sprintf(input, "Cannot open input file %s", argv[1]);
365 com_err("moira (script)", 0, input);
371 printf("Redirecting output to %s\n", argv[2]);
375 status = open(argv[2], O_CREAT|O_WRONLY|O_APPEND, 0664);
381 sprintf(input, "Unable to redirect output to %s\n", argv[2]);
382 com_err("moira (script)", errno, input);
397 if (!fgets(input, BUFSIZ, inp))
399 if ((cp = strchr(input, '\n')))
408 for (cp = &input[1]; *cp && isspace(*cp); cp++)
410 printf("Comment: %s\n", cp);
413 printf("Executing: %s\n", input);
435 int print_reply(int argc, char **argv, void *help)
438 for (i = 0; i < argc; i++)
442 if (quote_output && !*(int *)help)
446 for (p = (unsigned char *)argv[i]; *p; p++)
448 if (isprint(*p) && *p != '\\' && *p != ',')
451 printf("\\%03o", *p);
455 printf("%s", argv[i]);
462 void test_query(int argc, char **argv)
468 com_err("moira (query)", 0, "Usage: query handle [ args ... ]");
471 help = !strcmp(argv[1], "_help");
474 /* Don't allow ^C during the query: it will confuse libmoira's
475 internal state. (Yay static variables) */
476 set_signal_blocking(SIGINT, 1);
477 status = mr_query(argv[1], argc - 2, argv + 2, print_reply, &help);
478 set_signal_blocking(SIGINT, 0);
479 printf("%d tuple%s\n", count, ((count == 1) ? "" : "s"));
481 com_err("moira (query)", status, "");
484 void test_access(int argc, char **argv)
489 com_err("moira (access)", 0, "Usage: access handle [ args ... ]");
492 status = mr_access(argv[1], argc - 2, argv + 2);
494 com_err("moira (access)", status, "");
501 if ((status = mr_do_update()))
502 com_err("moira (dcm)", status, " while triggering dcm");
510 if ((status = mr_motd(&motd)))
511 com_err("moira (motd)", status, " while getting motd");
513 printf("%s\n", motd);
515 printf("No message of the day.\n");
518 void test_list_requests(void)
520 printf("Available moira requests:\n");
522 printf("noop\t\t\tAsk Moira to do nothing\n");
523 printf("connect, c\t\tConnect to Moira server\n");
524 printf("disconnect, d\t\tDisconnect from server\n");
525 printf("host\t\t\tIdentify the server host\n");
526 printf("motd, m\t\t\tGet the Message of the Day\n");
527 printf("query, qy\t\tMake a query.\n");
528 printf("auth, a\t\t\tAuthenticate to Moira.\n");
529 printf("proxy, p\t\tProxy authenticate to Moira.\n");
530 printf("access\t\t\tCheck access to a Moira query.\n");
531 printf("dcm\t\t\tTrigger the DCM\n");
532 printf("script, s\t\tRead commands from a script.\n");
533 printf("list_requests, lr, ?\tList available commands.\n");
534 printf("quit, Q\t\t\tLeave the subsystem.\n");
537 void test_version(int argc, char **argv)
543 com_err("moira (version)", 0, "Usage: version versionnumber");
546 status = mr_version(atoi(argv[1]));
548 com_err("moira (version)", status, "");
551 #ifdef HAVE_POSIX_SIGNALS
553 void set_signal_handler(int sig, void (*handler)(int))
555 struct sigaction action;
557 sigemptyset(&action.sa_mask);
559 action.sa_handler = handler;
560 sigaction(sig, &action, NULL);
563 void set_signal_blocking(int sig, int block)
567 sigaddset(&sigs, sig);
568 sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sigs, NULL);
573 void set_signal_handler(int sig, void (*handler)(int))
575 signal(sig, handler);
579 BOOL WINAPI blocking_handler(DWORD dwCtrlType)
584 void set_signal_blocking(int sig, int block)
586 SetConsoleCtrlHandler(blocking_handler, block ? TRUE : FALSE);
590 #endif /* HAVE_POSIX_SIGNALS */