blob: 5f35dd9d1c3e65f409dcb1fe0eec52719a581271 [file] [log] [blame]
/*
* Copyright(c) 2015-2017 Intel Corporation. All rights reserved.
* Copyright(c) 2006 Linus Torvalds. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
/* originally copied from perf and git */
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <builtin.h>
#include <util/strbuf.h>
#include <util/util.h>
int main_handle_options(const char ***argv, int *argc, const char *usage_msg,
struct cmd_struct *cmds, int num_cmds)
{
int handled = 0;
while (*argc > 0) {
const char *cmd = (*argv)[0];
if (cmd[0] != '-')
break;
if (!strcmp(cmd, "--version") || !strcmp(cmd, "--help"))
break;
/*
* Shortcut for '-h' and '-v' options to invoke help
* and version command.
*/
if (!strcmp(cmd, "-h")) {
(*argv)[0] = "--help";
break;
}
if (!strcmp(cmd, "-v")) {
(*argv)[0] = "--version";
break;
}
if (!strcmp(cmd, "--list-cmds")) {
int i;
for (i = 0; i < num_cmds; i++) {
struct cmd_struct *p = cmds+i;
/* filter out commands from auto-complete */
if (strcmp(p->cmd, "create-nfit") == 0)
continue;
if (strcmp(p->cmd, "test") == 0)
continue;
if (strcmp(p->cmd, "bat") == 0)
continue;
printf("%s\n", p->cmd);
}
exit(0);
} else {
fprintf(stderr, "Unknown option: %s\n", cmd);
usage(usage_msg);
}
(*argv)++;
(*argc)--;
handled++;
}
return handled;
}
static int run_builtin(struct cmd_struct *p, int argc, const char **argv,
void *ctx)
{
int status;
struct stat st;
status = p->fn(argc, argv, ctx);
if (status)
return status & 0xff;
/* Somebody closed stdout? */
if (fstat(fileno(stdout), &st))
return 0;
/* Ignore write errors for pipes and sockets.. */
if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
return 0;
status = 1;
/* Check for ENOSPC and EIO errors.. */
if (fflush(stdout)) {
fprintf(stderr, "write failure on standard output: %s", strerror(errno));
goto out;
}
if (ferror(stdout)) {
fprintf(stderr, "unknown write failure on standard output");
goto out;
}
if (fclose(stdout)) {
fprintf(stderr, "close failed on standard output: %s", strerror(errno));
goto out;
}
status = 0;
out:
return status;
}
void main_handle_internal_command(int argc, const char **argv, void *ctx,
struct cmd_struct *cmds, int num_cmds)
{
const char *cmd = argv[0];
int i;
/* Turn "<binary> cmd --help" into "<binary> help cmd" */
if (argc > 1 && !strcmp(argv[1], "--help")) {
argv[1] = argv[0];
argv[0] = cmd = "help";
}
for (i = 0; i < num_cmds; i++) {
struct cmd_struct *p = cmds+i;
if (strcmp(p->cmd, cmd))
continue;
exit(run_builtin(p, argc, argv, ctx));
}
}