]> andersk Git - moira.git/blame - clients/mrtest/mrtest.c
Document "4" command to perform v4 authentication; auth/a command now
[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>
533bacb3 20#ifdef HAVE_UNISTD_H
7ac48069 21#include <unistd.h>
533bacb3 22#endif
23
24#ifdef HAVE_GETOPT_H
25#include <getopt.h>
26#endif
27
28#ifdef _WIN32
29#include <windows.h>
30#include <io.h>
31#define dup _dup
32#define dup2 _dup2
33#define isatty _isatty
34#define close _close
35#define open _open
36#define sigjmp_buf jmp_buf
37#define siglongjmp longjmp
38#define sigsetjmp(env, save) setjmp(env)
39#endif /* _WIN32 */
f281aa29 40
ea0caf4a 41#ifdef HAVE_READLINE
c5c5a18d 42#include "readline/readline.h"
43#include "readline/history.h"
f281aa29 44#endif
6e6374cb 45
7ac48069 46RCSID("$Header$");
47
71da1922 48int recursion = 0, quote_output = 0, interactive;
5eaef520 49int count, quit = 0, cancel = 0;
1a5c774c 50char *whoami;
533bacb3 51
74c84b52 52sigjmp_buf jb;
1a5c774c 53
54#define MAXARGS 20
6e6374cb 55
533bacb3 56void discard_input(int sig);
7ac48069 57char *mr_gets(char *prompt, char *buf, size_t len);
58void execute_line(char *cmdbuf);
59int parse(char *buf, char *argv[MAXARGS]);
8c9b31a9 60int print_reply(int argc, char **argv, void *help);
7ac48069 61void test_noop(void);
62void test_connect(int argc, char **argv);
63void test_disconnect(void);
64void test_host(void);
7ac48069 65void test_motd(void);
66void test_query(int argc, char **argv);
67void test_auth(void);
e7138c1c 68void test_proxy(int argc, char **argv);
7ac48069 69void test_access(int argc, char **argv);
70void test_dcm(void);
71void test_script(int argc, char **argv);
72void test_list_requests(void);
acde26f0 73void test_version(int argc, char **argv);
991417e4 74void test_krb5_auth(void);
533bacb3 75void set_signal_handler(int, void (*handler)(int));
76void set_signal_blocking(int, int);
f281aa29 77
5eaef520 78int main(int argc, char **argv)
79{
80 char cmdbuf[BUFSIZ];
71da1922 81 int c;
6e6374cb 82
5eaef520 83 whoami = argv[0];
84 interactive = (isatty(0) && isatty(1));
3442308f 85
71da1922 86 while ((c = getopt(argc, argv, "q")) != -1)
87 {
88 switch (c)
89 {
90 case 'q':
91 quote_output = 1;
92 break;
93
94 default:
95 fprintf(stderr, "Usage: mrtest [-q]\n");
96 exit (1);
97 }
98 }
99
5eaef520 100 initialize_sms_error_table();
101 initialize_krb_error_table();
102
ea0caf4a 103#ifdef HAVE_READLINE
5eaef520 104 /* we don't want filename completion */
105 rl_bind_key('\t', rl_insert);
74c84b52 106#endif
f281aa29 107
533bacb3 108 set_signal_handler(SIGINT, discard_input);
5eaef520 109 sigsetjmp(jb, 1);
110
111 while (!quit)
112 {
113 if (!mr_gets("moira: ", cmdbuf, BUFSIZ))
114 break;
115 execute_line(cmdbuf);
116 }
117 mr_disconnect();
118 exit(0);
1a5c774c 119}
120
533bacb3 121void discard_input(int sig)
f281aa29 122{
123 putc('\n', stdout);
fcb0b7fa 124
125 /* if we're inside a script, we have to clean up file descriptors,
126 so don't jump out yet */
5eaef520 127 if (recursion)
128 cancel = 1;
129 else
fcb0b7fa 130 siglongjmp(jb, 1);
f281aa29 131}
132
5eaef520 133char *mr_gets(char *prompt, char *buf, size_t len)
f281aa29 134{
135 char *in;
ea0caf4a 136#ifdef HAVE_READLINE
5eaef520 137 if (interactive)
138 {
139 in = readline(prompt);
140
141 if (!in)
142 return NULL;
143 if (*in)
144 add_history(in);
145 strncpy(buf, in, len - 1);
146 buf[len] = 0;
147 free(in);
148
149 return buf;
f281aa29 150 }
f281aa29 151#endif
152 printf("%s", prompt);
153 fflush(stdout);
5eaef520 154 in = fgets(buf, len, stdin);
155 if (!in)
156 return in;
157 if (strchr(buf, '\n'))
158 *(strchr(buf, '\n')) = '\0';
f281aa29 159 return buf;
160}
161
7ac48069 162void execute_line(char *cmdbuf)
1a5c774c 163{
164 int argc;
165 char *argv[MAXARGS];
166
5eaef520 167 argc = parse(cmdbuf, argv);
168 if (argc == 0)
169 return;
170 if (!strcmp(argv[0], "noop"))
1a5c774c 171 test_noop();
5eaef520 172 else if (!strcmp(argv[0], "connect") || !strcmp(argv[0], "c"))
1a5c774c 173 test_connect(argc, argv);
5eaef520 174 else if (!strcmp(argv[0], "disconnect") || !strcmp(argv[0], "d"))
1a5c774c 175 test_disconnect();
5eaef520 176 else if (!strcmp(argv[0], "host"))
1a5c774c 177 test_host();
059d3dc2 178 else if (!strcmp(argv[0], "motd") || !strcmp(argv[0], "m"))
1a5c774c 179 test_motd();
5eaef520 180 else if (!strcmp(argv[0], "query") || !strcmp(argv[0], "qy"))
1a5c774c 181 test_query(argc, argv);
5eaef520 182 else if (!strcmp(argv[0], "auth") || !strcmp(argv[0], "a"))
991417e4 183 test_krb5_auth();
e7138c1c 184 else if (!strcmp(argv[0], "proxy") || !strcmp(argv[0], "p"))
185 test_proxy(argc, argv);
5eaef520 186 else if (!strcmp(argv[0], "access"))
1a5c774c 187 test_access(argc, argv);
5eaef520 188 else if (!strcmp(argv[0], "dcm"))
1a5c774c 189 test_dcm();
5eaef520 190 else if (!strcmp(argv[0], "script") || !strcmp(argv[0], "s"))
1a5c774c 191 test_script(argc, argv);
5eaef520 192 else if (!strcmp(argv[0], "list_requests") ||
193 !strcmp(argv[0], "lr") || !strcmp(argv[0], "?"))
1a5c774c 194 test_list_requests();
5eaef520 195 else if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "Q"))
196 quit = 1;
acde26f0 197 else if (!strcmp(argv[0], "version") || !strcmp(argv[0], "v"))
198 test_version(argc, argv);
991417e4 199 else if (!strcmp(argv[0], "krb4_auth") || !strcmp(argv[0], "4"))
200 test_auth();
5eaef520 201 else
202 {
203 fprintf(stderr, "moira: Unknown request \"%s\". "
204 "Type \"?\" for a request list.\n", argv[0]);
205 }
1a5c774c 206}
207
5eaef520 208int parse(char *buf, char *argv[MAXARGS])
1a5c774c 209{
210 char *p;
211 int argc, num;
5eaef520 212
213 if (!*buf)
214 return 0;
215
216 for (p = buf, argc = 0, argv[0] = buf; *p && *p != '\n'; p++)
217 {
218 if (*p == '"')
219 {
220 char *d = p++;
221 /* skip to close-quote, copying back over open-quote */
222 while (*p != '"')
223 {
224 if (!*p || *p == '\n')
225 {
226 fprintf(stderr,
227 "moira: Unbalanced quotes in command line\n");
228 return 0;
229 }
230 /* deal with \### or \\ */
231 if (*p == '\\')
232 {
233 if (*++p != '"' && (*p < '0' || *p > '9') && (*p != '\\'))
234 {
235 fprintf(stderr, "moira: Bad use of \\\n");
236 return 0;
237 }
238 else if (*p >= '0' && *p <= '9')
239 {
240 num = (*p - '0') * 64 + (*++p - '0') * 8 + (*++p - '0');
241 *p = num;
242 }
243 }
244 *d++ = *p++;
245 }
246 if (p == d + 1)
247 {
248 *d = '\0';
249 p++;
250 }
251 else
252 {
253 while (p >= d)
254 *p-- = ' ';
255 }
2c031a2a 256 }
5eaef520 257 if (*p == ' ' || *p == '\t')
258 {
259 /* skip whitespace */
260 for (*p++ = '\0'; *p == ' ' || *p == '\t'; p++)
261 ;
262 if (*p && *p != '\n')
263 argv[++argc] = p--;
6e6374cb 264 }
1a5c774c 265 }
5eaef520 266 if (*p == '\n')
267 *p = '\0';
268 return argc + 1;
6e6374cb 269}
270
7ac48069 271void test_noop(void)
6e6374cb 272{
5eaef520 273 int status = mr_noop();
274 if (status)
275 com_err("moira (noop)", status, "");
6e6374cb 276}
277
7ac48069 278void test_connect(int argc, char *argv[])
6e6374cb 279{
5eaef520 280 char *server = "";
281 int status;
282
283 if (argc > 1)
284 server = argv[1];
285 status = mr_connect(server);
286 if (status)
287 com_err("moira (connect)", status, "");
acde26f0 288 mr_version(-1);
6e6374cb 289}
290
7ac48069 291void test_disconnect(void)
6e6374cb 292{
5eaef520 293 int status = mr_disconnect();
294 if (status)
295 com_err("moira (disconnect)", status, "");
6e6374cb 296}
297
7ac48069 298void test_host(void)
66848930 299{
5eaef520 300 char host[BUFSIZ];
301 int status;
66848930 302
5eaef520 303 memset(host, 0, sizeof(host));
66848930 304
5eaef520 305 if ((status = mr_host(host, sizeof(host) - 1)))
306 com_err("moira (host)", status, "");
307 else
308 printf("You are connected to host %s\n", host);
66848930 309}
310
7ac48069 311void test_auth(void)
6e6374cb 312{
5eaef520 313 int status;
59af7b90 314
5eaef520 315 status = mr_auth("mrtest");
316 if (status)
317 com_err("moira (auth)", status, "");
6e6374cb 318}
319
991417e4 320void test_krb5_auth(void)
321{
322 int status;
323
324 status = mr_krb5_auth("mrtest");
325 if (status)
326 com_err("moira (krb5_auth)", status, "");
327}
328
e7138c1c 329void test_proxy(int argc, char *argv[])
330{
331 int status;
332
333 if (argc != 3)
334 {
335 com_err("moira (proxy)", 0, "Usage: proxy principal authtype");
336 return;
337 }
338 status = mr_proxy(argv[1], argv[2]);
339 if (status)
340 com_err("moira (proxy)", status, "");
341}
342
7ac48069 343void test_script(int argc, char *argv[])
58b825a4 344{
5eaef520 345 FILE *inp;
346 char input[BUFSIZ], *cp;
347 int status, oldstdout, oldstderr;
348
349 if (recursion > 8)
350 {
351 com_err("moira (script)", 0, "too many levels deep in script files\n");
352 return;
58b825a4 353 }
354
5eaef520 355 if (argc < 2)
356 {
357 com_err("moira (script)", 0, "Usage: script input_file [ output_file ]");
358 return;
58b825a4 359 }
360
5eaef520 361 inp = fopen(argv[1], "r");
362 if (!inp)
363 {
364 sprintf(input, "Cannot open input file %s", argv[1]);
365 com_err("moira (script)", 0, input);
366 return;
58b825a4 367 }
368
5eaef520 369 if (argc == 3)
370 {
371 printf("Redirecting output to %s\n", argv[2]);
372 fflush(stdout);
373 oldstdout = dup(1);
374 close(1);
375 status = open(argv[2], O_CREAT|O_WRONLY|O_APPEND, 0664);
376 if (status != 1)
377 {
378 close(status);
379 dup2(oldstdout, 1);
380 argc = 2;
381 sprintf(input, "Unable to redirect output to %s\n", argv[2]);
382 com_err("moira (script)", errno, input);
383 }
384 else
385 {
386 fflush(stderr);
387 oldstderr = dup(2);
388 close(2);
389 dup2(1, 2);
58b825a4 390 }
391 }
392
5eaef520 393 recursion++;
394
395 while (!cancel)
396 {
397 if (!fgets(input, BUFSIZ, inp))
398 break;
399 if ((cp = strchr(input, '\n')))
400 *cp = '\0';
401 if (input[0] == 0)
402 {
403 printf("\n");
404 continue;
6a592314 405 }
5eaef520 406 if (input[0] == '%')
407 {
408 for (cp = &input[1]; *cp && isspace(*cp); cp++)
409 ;
410 printf("Comment: %s\n", cp);
411 continue;
58b825a4 412 }
5eaef520 413 printf("Executing: %s\n", input);
414 execute_line(input);
58b825a4 415 }
416
5eaef520 417 recursion--;
418 if (!recursion)
419 cancel = 0;
420
421 fclose(inp);
422 if (argc == 3)
423 {
424 fflush(stdout);
425 close(1);
426 dup2(oldstdout, 1);
427 close(oldstdout);
428 fflush(stderr);
429 close(2);
430 dup2(oldstderr, 2);
431 close(oldstderr);
58b825a4 432 }
433}
434
8c9b31a9 435int print_reply(int argc, char **argv, void *help)
6e6374cb 436{
5eaef520 437 int i;
438 for (i = 0; i < argc; i++)
439 {
440 if (i != 0)
441 printf(", ");
8c9b31a9 442 if (quote_output && !*(int *)help)
71da1922 443 {
444 unsigned char *p;
445
446 for (p = (unsigned char *)argv[i]; *p; p++)
447 {
448 if (isprint(*p) && *p != '\\' && *p != ',')
449 putc(*p, stdout);
450 else
451 printf("\\%03o", *p);
452 }
453 }
454 else
455 printf("%s", argv[i]);
5eaef520 456 }
457 printf("\n");
458 count++;
459 return MR_CONT;
6e6374cb 460}
461
7ac48069 462void test_query(int argc, char **argv)
6e6374cb 463{
6fedb0a4 464 int status, help;
fcb0b7fa 465
5eaef520 466 if (argc < 2)
467 {
468 com_err("moira (query)", 0, "Usage: query handle [ args ... ]");
469 return;
470 }
6fedb0a4 471 help = !strcmp(argv[1], "_help");
59af7b90 472
5eaef520 473 count = 0;
474 /* Don't allow ^C during the query: it will confuse libmoira's
475 internal state. (Yay static variables) */
533bacb3 476 set_signal_blocking(SIGINT, 1);
8c9b31a9 477 status = mr_query(argv[1], argc - 2, argv + 2, print_reply, &help);
533bacb3 478 set_signal_blocking(SIGINT, 0);
5eaef520 479 printf("%d tuple%s\n", count, ((count == 1) ? "" : "s"));
480 if (status)
481 com_err("moira (query)", status, "");
6e6374cb 482}
483
7ac48069 484void test_access(int argc, char **argv)
6e6374cb 485{
5eaef520 486 int status;
487 if (argc < 2)
488 {
489 com_err("moira (access)", 0, "Usage: access handle [ args ... ]");
490 return;
491 }
492 status = mr_access(argv[1], argc - 2, argv + 2);
493 if (status)
494 com_err("moira (access)", status, "");
6e6374cb 495}
fc3ac28e 496
7ac48069 497void test_dcm()
fc3ac28e 498{
5eaef520 499 int status;
fc3ac28e 500
5eaef520 501 if ((status = mr_do_update()))
502 com_err("moira (dcm)", status, " while triggering dcm");
fc3ac28e 503}
093b57b1 504
7ac48069 505void test_motd()
093b57b1 506{
5eaef520 507 int status;
508 char *motd;
509
510 if ((status = mr_motd(&motd)))
511 com_err("moira (motd)", status, " while getting motd");
512 if (motd)
513 printf("%s\n", motd);
514 else
515 printf("No message of the day.\n");
093b57b1 516}
1a5c774c 517
7ac48069 518void test_list_requests(void)
1a5c774c 519{
5eaef520 520 printf("Available moira requests:\n");
521 printf("\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");
5eaef520 526 printf("motd, m\t\t\tGet the Message of the Day\n");
527 printf("query, qy\t\tMake a query.\n");
bb38293f 528 printf("auth, a\t\t\tAuthenticate to Moira via krb5.\n");
529 printf("krb4_auth, 4\t\tAuthenticate to Moira via krb4.\n");
e7138c1c 530 printf("proxy, p\t\tProxy authenticate to Moira.\n");
5eaef520 531 printf("access\t\t\tCheck access to a Moira query.\n");
532 printf("dcm\t\t\tTrigger the DCM\n");
533 printf("script, s\t\tRead commands from a script.\n");
534 printf("list_requests, lr, ?\tList available commands.\n");
535 printf("quit, Q\t\t\tLeave the subsystem.\n");
1a5c774c 536}
acde26f0 537
538void test_version(int argc, char **argv)
539{
540 int status;
541
542 if (argc != 2)
543 {
544 com_err("moira (version)", 0, "Usage: version versionnumber");
545 return;
546 }
547 status = mr_version(atoi(argv[1]));
548 if (status)
549 com_err("moira (version)", status, "");
550}
533bacb3 551
552#ifdef HAVE_POSIX_SIGNALS
553
554void set_signal_handler(int sig, void (*handler)(int))
555{
556 struct sigaction action;
557
558 sigemptyset(&action.sa_mask);
559 action.sa_flags = 0;
560 action.sa_handler = handler;
561 sigaction(sig, &action, NULL);
562}
563
564void set_signal_blocking(int sig, int block)
565{
566 sigset_t sigs;
567 sigemptyset(&sigs);
568 sigaddset(&sigs, sig);
569 sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sigs, NULL);
570}
571
572#else
573
574void set_signal_handler(int sig, void (*handler)(int))
575{
576 signal(sig, handler);
577}
578
579#ifdef _WIN32
580BOOL WINAPI blocking_handler(DWORD dwCtrlType)
581{
582 return(TRUE);
583}
584
585void set_signal_blocking(int sig, int block)
586{
587 SetConsoleCtrlHandler(blocking_handler, block ? TRUE : FALSE);
588}
589#endif /* _WIN32 */
590
591#endif /* HAVE_POSIX_SIGNALS */
This page took 0.264242 seconds and 5 git commands to generate.