mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Both iucvconn and iucvtty write output for --help to stderr. To be consistent with other s390-tools and GNU coding guide lines, fix this by using stdout for tool-generated usage help. Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com> Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
231 lines
5.9 KiB
C
231 lines
5.9 KiB
C
/*
|
|
* 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 <ctype.h>
|
|
#include <getopt.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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 <regex>] <terminal id> [-- <login program> [<args>]]\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 <file>] <vm guest> <terminal id>\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],
|
|
_("<vm guest>"));
|
|
else
|
|
cpy_or_exit(config->service, optarg,
|
|
sizeof(config->service),
|
|
&iucv_tool[prg],
|
|
_("<terminal id>"));
|
|
break;
|
|
case 1:
|
|
cpy_or_exit(config->service, optarg,
|
|
sizeof(config->service),
|
|
&iucv_tool[prg],
|
|
_("<terminal id>"));
|
|
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], _("<regex>"));
|
|
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"));
|
|
}
|