/* * iucvtty / iucvconn - IUCV Terminal Applications * * Processing of command line arguments * * Copyright IBM Corp. 2008, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include #include #include #include "lib/zt_common.h" #include "iucvterm/config.h" #include "iucvterm/functions.h" #include "iucvterm/gettext.h" static const char iucvtty_usage[] = N_( "Usage: %s [-h|--help] [-v|--version]\n" " %s [-a ] [-- []]\n\n" "Options:\n" " -h, --help Print this help, then exit.\n" " -v, --version Print version information, then exit.\n" " -a, --allow-from Permit connections from particular z/VM guests only.\n" " A z/VM guest is permitted if regex matches its name.\n" ); static const char iucvconn_usage[] = N_( "Usage: %s [-h|--help] [-v|--version]\n" " %s [-e esc] [-s ] \n\n" "Options:\n" " -h, --help Print this help, then exit.\n" " -v, --version Print version information, then exit.\n" " -s, --sessionlog Write terminal session to file.\n" " -e, --escape-char Escape character (can be one of: A-Y, ], ^ or _)\n" " Characters C, D, Q, S, Z and [ are not allowed.\n" ); static const struct option iucvterm_long_opts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "allow-from", required_argument, NULL, 'a' }, { "sessionlog", required_argument, NULL, 's' }, { "escape-char", required_argument, NULL, 'e' }, { NULL, no_argument, NULL, 0 } }; struct tool_info { char name[10]; char optstring[10]; const char *usage; unsigned char reqNonOpts; }; /* program specific command line settings */ static const struct tool_info iucv_tool[2] = { { .name = "iucvtty", .optstring = "-hva:", .usage = iucvtty_usage, .reqNonOpts = 1, }, { .name = "iucvconn", .optstring = "-hvs:e:", .usage = iucvconn_usage, .reqNonOpts = 2, } }; static void __noreturn usage_exit(const struct tool_info *prg, int is_error, const char *msg) { FILE *file = is_error ? stderr : stdout; if (msg != NULL) fprintf(file, _("%s: %s\n"), prg->name, msg); fprintf(file, _(prg->usage), prg->name, prg->name); exit(is_error ? 1 : 0); /* rc=1 .. invalid args */ } static void __noreturn version_exit(const struct tool_info *prg) { printf(_("%s: IUCV Terminal Applications, version %s\n"), prg->name, RELEASE_STRING); printf(_("Copyright IBM Corp. 2008, 2017\n")); exit(0); } static void cpy_or_exit(char *dest, const char *src, size_t size, const struct tool_info *prg, const char *param) { if (strlen(src) >= size){ fprintf(stderr, _("%s: %s exceeds the maximum of %zu characters\n"), prg->name, param, size - 1); exit(1); } strncpy(dest, src, size); dest[size - 1] = 0; } static void set_esc_or_exit(const struct tool_info *prg, const char val, unsigned char *esc) { unsigned char upval = toupper(val); /* range of valid escape keys: A-Z [ \ ] ^ _ */ if (upval < 'A' || upval > '_') usage_exit(prg, 1, _("The specified character is not a " "valid escape character")); switch (upval) { case 'C': /* interrupt (ISIG) */ case 'D': /* EoF / EoT */ case 'Q': /* XON */ case 'S': /* XOFF */ case 'Z': /* suspend (shell) */ case '[': /* ESC */ usage_exit(prg, 1, _("The specified character is not a " "valid escape character")); default: *esc = upval ^ 0100; /* see ascii(7) */ break; } } void parse_options(enum iucvterm_prg prg, struct iucvterm_cfg *config, int argc, char **argv) { int c; int index; int nonOpts = 0; config->cmd_parms = NULL; config->sessionlog = NULL; config->esc_char = '_' ^ 0100; /* Ctrl-_ (0x1f) */ config->flags = 0; while (1) { index = -1; c = getopt_long(argc, argv, iucv_tool[prg].optstring, iucvterm_long_opts, &index); if (c == -1) break; switch (c) { case 1: if (nonOpts >= iucv_tool[prg].reqNonOpts) { usage_exit(&iucv_tool[prg], 1, NULL); break; } switch (nonOpts) { case 0: if (prg == PROG_IUCV_CONN) cpy_or_exit(config->host, optarg, sizeof(config->host), &iucv_tool[prg], _("")); else cpy_or_exit(config->service, optarg, sizeof(config->service), &iucv_tool[prg], _("")); break; case 1: cpy_or_exit(config->service, optarg, sizeof(config->service), &iucv_tool[prg], _("")); break; default: usage_exit(&iucv_tool[prg], 1, NULL); break; } ++nonOpts; break; case 'a':/* max 80 */ cpy_or_exit(config->client_re, optarg, sizeof(config->client_re), &iucv_tool[prg], _("")); if (is_regex_valid(config->client_re)) exit(1); config->flags |= CFG_F_CHKCLNT; break; case 'e': switch (strlen(optarg)) { case 1: set_esc_or_exit(&iucv_tool[prg], optarg[0], &config->esc_char); break; case 4: if (memcmp(optarg, "none", 4) == 0) { config->esc_char = 0; break; } /* fall through */ default: usage_exit(&iucv_tool[prg], 1, _("The escape character must be a " "single character or 'none'")); } break; case 's': config->sessionlog = optarg; break; case 'h': usage_exit(&iucv_tool[prg], 0, NULL); case 'v': version_exit(&iucv_tool[prg]); case '?': printf(_("Try '%s --help' for more information.\n"), iucv_tool[prg].name); exit(1); break; } } if (optind < argc) /* save additional parameters */ config->cmd_parms = argv + optind; if (nonOpts < iucv_tool[prg].reqNonOpts) /* not enough args */ usage_exit(&iucv_tool[prg], 1, _("The command does not have enough arguments")); }