Files
s390-tools/iucvterm/src/getopt.c
Peter Oberparleiter 5ef1320a7b iucvconn/iucvtty: Direct --help output to stdout
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>
2018-09-17 14:23:47 +02:00

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"));
}