mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
With gcc 7 we get warnings like the following:
fdasd.c: In function 'main':
fdasd.c:3055:4: warning: this statement may fall through
[-Wimplicit-fallthrough=]
fdasd_exit(&anchor, 0);
^~~~~~~~~~~~~~~~~~~~~~
fdasd.c:3056:3: note: here
default:
^~~~~~~
Fix this by marking functions with "__noreturn" to help gcc.
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
162 lines
4.2 KiB
C
162 lines
4.2 KiB
C
/*
|
|
* ipl_tools - Linux for System z reipl and shutdown tools
|
|
*
|
|
* Command: chshut
|
|
*
|
|
* 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 "ipl_tools.h"
|
|
|
|
static const char *const usage_chshut =
|
|
"Usage: %s TRIGGER ACTION [COMMAND] [OPTIONS]\n"
|
|
"\n"
|
|
"Change the shutdown actions for Linux on System z.\n"
|
|
"\n"
|
|
"TRIGGER specifies when the action is performed:\n"
|
|
" halt System has been shut down (e.g. shutdown -h -H now)\n"
|
|
" poff System has been shut down for power off (e.g. shutdown -h -P now)\n"
|
|
" reboot System has been shut down for reboot (e.g. shutdown -r)\n"
|
|
" Note: Depending on the distribution, \"halt\" might be mapped to \"poff\".\n"
|
|
"\n"
|
|
"ACTION specifies the action to be performed:\n"
|
|
" ipl IPL with previous settings\n"
|
|
" reipl IPL with re-IPL settings (see chreipl)\n"
|
|
" stop Stop all CPUs\n"
|
|
" vmcmd Run z/VM CP command defined by COMMAND\n"
|
|
"\n"
|
|
"COMMAND defines the z/VM CP command to issue.\n"
|
|
"\n"
|
|
"OPTIONS:\n"
|
|
" -h, --help Print this help, then exit\n"
|
|
" -v, --version Print version information, then exit\n";
|
|
|
|
static void __noreturn print_usage_chshut_exit(void)
|
|
{
|
|
printf(usage_chshut, g.prog_name);
|
|
exit(0);
|
|
}
|
|
|
|
static void parse_chshut_options(int argc, char *argv[])
|
|
{
|
|
int opt, idx;
|
|
const struct option long_opts[] = {
|
|
{ "help", no_argument, NULL, 'h' },
|
|
{ "version", no_argument, NULL, 'v' },
|
|
{ NULL, 0, NULL, 0 }
|
|
};
|
|
while ((opt = getopt_long(argc, argv, "hv", long_opts, &idx)) != -1) {
|
|
switch (opt) {
|
|
case 'h':
|
|
print_usage_chshut_exit();
|
|
case 'v':
|
|
print_version_exit();
|
|
default:
|
|
print_help_hint_exit();
|
|
}
|
|
}
|
|
if (!is_root())
|
|
ERR_EXIT("You must be root to perform this operation");
|
|
}
|
|
|
|
static struct shutdown_trigger *shutdown_trigger_get(const char *trigger)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; shutdown_trigger_vec[i]; i++) {
|
|
if (strcmp(trigger, shutdown_trigger_vec[i]->name) != 0)
|
|
continue;
|
|
if (shutdown_trigger_vec[i]->available)
|
|
return shutdown_trigger_vec[i];
|
|
ERR_EXIT("Shutdown trigger \"%s\" is not available on "
|
|
"your system", trigger);
|
|
}
|
|
ERR_EXIT("Unknown shutdown trigger \"%s\" specified", trigger);
|
|
}
|
|
|
|
static struct shutdown_action *shutdown_action_get(const char *action)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; shutdown_action_vec[i]; i++) {
|
|
if (strcmp(action, shutdown_action_vec[i]->name) == 0)
|
|
return shutdown_action_vec[i];
|
|
}
|
|
ERR_EXIT("Unknown shutdown action \"%s\" specified", action);
|
|
}
|
|
|
|
/*
|
|
* Multiple CP commands can be specified via "vmcmd XY1 vmcmd XY2 ..."
|
|
*/
|
|
static void vmcmd_set(struct shutdown_trigger *st, int argc, char *argv[])
|
|
{
|
|
char vmcmd[1024], path[PATH_MAX];
|
|
int first = 1, i;
|
|
int vmcmd_length = 0;
|
|
|
|
if (is_lpar())
|
|
ERR_EXIT("vmcmd works only under z/VM");
|
|
memset(vmcmd, 0, sizeof(vmcmd));
|
|
for (i = 2; i < argc; i++) {
|
|
if (strcmp(argv[i], "vmcmd") != 0)
|
|
ERR_EXIT("Invalid vmcmd command specification");
|
|
if (i == argc - 1)
|
|
ERR_EXIT("vmcmd needs an additional argument");
|
|
if (!first) {
|
|
strcat(vmcmd, "\n");
|
|
vmcmd_length++;
|
|
} else {
|
|
first = 0;
|
|
}
|
|
vmcmd_length += strlen(argv[i + 1]);
|
|
if (vmcmd_length >= 127)
|
|
ERR_EXIT("The vmcmd command must not exceed 127 "
|
|
"characters");
|
|
|
|
strcat(vmcmd, argv[i + 1]);
|
|
i++;
|
|
}
|
|
|
|
sprintf(path, "vmcmd/%s", st->name_sysfs);
|
|
write_str(vmcmd, path);
|
|
}
|
|
|
|
void cmd_chshut(int argc, char *argv[])
|
|
{
|
|
struct shutdown_trigger *st;
|
|
struct shutdown_action *sa;
|
|
char path[PATH_MAX];
|
|
|
|
parse_chshut_options(argc, argv);
|
|
|
|
if (argc < 2) {
|
|
ERR("No trigger specified");
|
|
print_help_hint_exit();
|
|
}
|
|
shutdown_init();
|
|
st = shutdown_trigger_get(argv[1]);
|
|
if (st == &shutdown_trigger_panic ||
|
|
st == &shutdown_trigger_restart)
|
|
ERR_EXIT("Please use \"service dumpconf\" for "
|
|
"configuring the %s trigger",
|
|
st->name);
|
|
if (argc < 3) {
|
|
ERR("No action specified");
|
|
print_help_hint_exit();
|
|
}
|
|
sa = shutdown_action_get(argv[2]);
|
|
|
|
if (sa == &shutdown_action_vmcmd) {
|
|
vmcmd_set(st, argc, argv);
|
|
} else if (argc != 3) {
|
|
ERR("Too many parameters specified");
|
|
print_help_hint_exit();
|
|
}
|
|
sprintf(path, "shutdown_actions/%s", st->name_sysfs);
|
|
if (write_str_errno(argv[2], path))
|
|
ERR_EXIT_ERRNO("Could not set \"%s\"", path);
|
|
}
|