带有 C99 内联函数的 OpenBSD 5.9 header
OpenBSD 5.9 header with C99 inline function
我正在构建一个自定义 shell 并在我编译时看到 usr/include/ctype.h:92
似乎需要 c99 inline 函数,但编译器说 C99
内联函数不需要支持的。可以使用编译器的参数禁用警告,但它是一个需要修复的错误吗?
这是我的main.c
#define _XOPEN_SOURCE 500
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include "openshell.h"
#include "errors.h"
#include <errno.h>
#include <locale.h>
#include <readline/readline.h>
#include <getopt.h>
#include <unistd.h>
#include <assert.h>
#include <readline/history.h>
#ifdef SIGDET
#if SIGDET == 1
int isSignal = 1; /*Termination detected by signals*/
#endif
#endif
static int sourceCount = 0;
static FILE *sourcefiles[MAX_SOURCE];
/*
* The special maximum argument value which means that there is
* no limit to the number of arguments on the command line.
*/
#define INFINITE_ARGS 0x7fffffff
/*
* The table of built-in commands.
* A command is terminated wih an entry containing NULL values.
*/
static const CommandEntry commandEntryTable[] =
{
{
"checkenv", do_checkenv, 1, INFINITE_ARGS,
"Check environment variables",
""
},
{
"add2path", do_add2path, 3, INFINITE_ARGS,
"do_add2path",
"[txp]v arFileName fileName ..."
},
{
"cd", do_cd, 1, 2,
"Change current directory",
"[dirName]"
},
{
"exit", do_exit, 1, 2,
"Exit from shell",
"[exit value]"
},
{
"help", do_help, 1, 2,
"Print help about a command",
"[word]"
},
{
"kill", do_kill, 2, INFINITE_ARGS,
"Send a signal to the specified process",
"[-sig] pid ..."
},
{
NULL, 0, 0, 0,
NULL,
NULL
}
};
struct command {
char *const *argv;
};
char** str_split(char* a_str, const char a_delim)
{
char** result = 0;
size_t count = 0;
char* tmp = a_str;
char* last_comma = 0;
char delim[2];
delim[0] = a_delim;
delim[1] = 0;
/* Count how many elements will be extracted. */
while (*tmp)
{
if (a_delim == *tmp)
{
count++;
last_comma = tmp;
}
tmp++;
}
/* Add space for trailing token. */
count += last_comma < (a_str + strlen(a_str) - 1);
/* Add space for terminating null string so caller
knows where the list of returned strings ends. */
count++;
result = malloc(sizeof(char*) * count);
if (result)
{
size_t idx = 0;
char* token = strtok(a_str, delim);
while (token)
{
assert(idx < count);
*(result + idx++) = strdup(token);
token = strtok(0, delim);
}
assert(idx == count - 1);
*(result + idx) = 0;
}
return result;
}
char ** stripped;
char ** create_pipeline(int argc, char ** argv) {
if(!strstr(argv[argc], "|")) { /* && ! isBetweenquotes*/
stripped = argv;
return stripped;
}
else {
stripped = argv;
return create_pipeline(argc, argv);
}
}
static int runCmd(const char *cmd) {
const char *cp;
pid_t pid;
int status;
struct command shellcommand[4];
char **argv = 0;
int argc = 1;
bool pipe = false;
char *command[40];
char *cmd2[20] = {"cmd2", 0};
int numberofpipelines = 0;
unsigned long i3 = 0;
unsigned long i2 = 0;
unsigned long i1 = 0;
unsigned long n = 0;
char *string;
char *string1;
int max_args = 1; /* there's at least one argument or we wouldn't reach this */
cmd2[0] = NULL;
cmd2[1] = NULL;
cmd2[2] = NULL;
command[0] = NULL;
command[1] = NULL;
command[3] = NULL;
char *string2 = NULL;
char** tokens;
for (cp = cmd; *cp; cp++) {
if ((*cp >= 'a') && (*cp <= 'z')) {
continue;
}
if ((*cp >= 'A') && (*cp <= 'Z')) {
continue;
}
if (isDecimal(*cp)) {
continue;
}
if (isBlank(*cp)){
continue;
}
if ((*cp == '.') || (*cp == '/') || (*cp == '-') ||
(*cp == '+') || (*cp == '=') || (*cp == '_') ||
(*cp == ':') || (*cp == ',') || (*cp == '\'') ||
(*cp == '"')) {
continue;
}
}
makeArgs(cmd, &argc, (const char ***) &argv, pipe);
char a[20] = {0};
if (sscanf(cmd, "%*[^']'%[^']'", a) == 1) {
printf("<undefined>");
}
char cmdtmp[75];
strcpy(cmdtmp, cmd);
tokens = str_split( cmdtmp, '|');
if (tokens)
{
int i;
for (i = 0; *(tokens + i); i++)
{
printf("month=[%s]\n", *(tokens + i));
free(*(tokens + i));
}
printf("\n");
free(tokens);
}
for (int i = 0; i < argc; i++) {
if (argv[i] != NULL && strstr(argv[i], "|")) {
numberofpipelines++;
char subbuff[40];
i1 = 0;
i2 = 0;
i3 = 0;
subbuff[0]='[=11=]';
string = strstr(argv[i], "|");
if (string != NULL) {
i3 = string - argv[i];
printf("**** is null ***");
cmd2[1] = argv[argc - 1];
}
string1 = strstr(&argv[i][i3 + 2], "|");
if (string1 != NULL) {
i2 = string1 - argv[i3 + 1];
printf("i2: %lu", i2);
} else {
char *found3 = strstr(&argv[i][i3 + 1], " ");
if (found3 != NULL) {}
string2 = strstr(argv[1], "|");
if (string2 != NULL) {
i1 = string2 - argv[1];
}
n = strlen(argv[1]) - i1;
if (argc > 2) {
memcpy(subbuff, &argv[i][i3 + 1], n - 1);
subbuff[n - 1] = '[=11=]';
cmd2[0] = subbuff;
cmd2[1] = argv[argc - 1];
} else {
memcpy(subbuff, &argv[i][i3 + 1], n);
subbuff[n] = '[=11=]';
cmd2[0] = subbuff;
cmd2[1] = argv[argc - 1];
}
argc++;
argv[i + 1] = subbuff;
command[i] = "<undefined>";
argv[i + 2] = NULL;
max_args = i;
}
}
if (argv[i] != NULL) {
if (i < max_args) {
command[i] = argv[i];
command[i+1] = 0;
max_args++;
cmd2[1] = argv[argc - 1];
} else {
command[max_args] = argv[max_args];
command[max_args+1] = 0;
cmd2[1] = argv[argc - 1];
}
}
if (argv[i] != NULL) {
char *p = strchr(argv[i], '|');
if (!p) {
/* deal with error: / not present" */;
} else {
*p = 0;
}
}
}
dump_argv((const char *) "d", argc, argv);
/* makeArgs(cmd, &argc, &argv, pipe);*/
/* command[2]= 0;*/
shellcommand[0].argv = command;
shellcommand[1].argv = cmd2;
pid = fork();
if (pid < 0) {
perror("fork failed");
return -1;
}
/* If we are the child process, then go execute the program.*/
if (pid == 0) {
/* spawn(cmd);*/
fork_pipes(numberofpipelines, shellcommand);
}
/*
* We are the parent process.
* Wait for the child to complete.
*/
status = 0;
while (((pid = waitpid(pid, &status, 0)) < 0) && (errno == EINTR));
if (pid < 0) {
fprintf(stderr, "Error from waitpid: %s", strerror(errno));
return -1;
}
if (WIFSIGNALED(status)) {
fprintf(stderr, "pid %ld: killed by signal %d\n",
(long) pid, WTERMSIG(status));
return -1;
}
return WEXITSTATUS(status);
}
/* The shell performs wildcard expansion on each token it extracts while parsing the command line.
* Oftentimes, globbing will obviously not do anything (for example, ls just returns ls).
* When you want nullglob behavior you'll have to know whether the glob function actually found any glob characters, though
*/
static void expandVariable(char *shellcommand) {
char mystring[CMD_LEN];
char *cp;
char *ep;
strcpy(mystring, shellcommand);
cp = strstr(mystring, "$(");
if (cp) {
*cp++ = '[=11=]';
strcpy(shellcommand, mystring);
ep = ++cp;
while (*ep && (*ep != ')')) ep++;
if (*ep == ')') *ep++ = '[=11=]';
cp = getenv(cp);
if (cp) strcat(shellcommand, cp);
strcat(shellcommand, ep);
}
return;
}
int do_help(int argc, const char **argv) {
const CommandEntry *entry;
const char *str;
str = NULL;
if (argc == 2)
str = argv[1];
/*
* Check for an exact match, in which case describe the program.
*/
if (str) {
for (entry = commandEntryTable; entry->name; entry++) {
if (strcmp(str, entry->name) == 0) {
printf("%s\n", entry->description);
printf("usage: %s %s\n", entry->name,
entry->usage);
return 0;
}
}
}
/*
* Print short information about commands which contain the
* specified word.
*/
for (entry = commandEntryTable; entry->name; entry++) {
if ((str == NULL) || (strstr(entry->name, str) != NULL) ||
(strstr(entry->usage, str) != NULL)) {
printf("%-10s %s\n", entry->name, entry->usage);
}
}
return 0;
}
/*
* Try to execute a built-in command.
* Returns TRUE if the command is a built in, whether or not the
* command succeeds. Returns FALSE if this is not a built-in command.
*/
bool exec_builtin(const char *cmd) {
const char *endCmd;
const CommandEntry *entry;
int argc;
const char **argv;
char cmdName[CMD_LEN];
/*
* Look for the end of the command name and then copy the
* command name to a buffer so we can null terminate it.
*/
endCmd = cmd;
while (*endCmd && !isBlank(*endCmd))
endCmd++;
memcpy(cmdName, cmd, endCmd - cmd);
cmdName[endCmd - cmd] = '[=11=]';
/*
* Search the command table looking for the command name.
*/
for (entry = commandEntryTable; entry->name != NULL; entry++) {
if (strcmp(entry->name, cmdName) == 0)
break;
}
/*
* If the command is not a built-in, return indicating that.
*/
if (entry->name == NULL) {
return false;
}
bool bo = false;
/*
* The command is a built-in.
* Break the command up into arguments and expand wildcards.
*/
if (!makeArgs(cmd, &argc, &argv, bo)) {
return true;
}
/*
* Give a usage string if the number of arguments is too large
* or too small.
*/
if ((argc < entry->minArgs) || (argc > entry->maxArgs)) {
fprintf(stderr, "usage: %s %s\n", entry->name, entry->usage);
return true;
}
/*
* Call the built-in function with the argument list.
*/
entry->func(argc, argv);
return true;
}
/*
* Parse and execute one null-terminated command line string.
* This breaks the command line up into words, checks to see if the
* command is an alias, and expands wildcards.
*/
int command(const char *cmd) {
const char *endCmd;
char cmdName[CMD_LEN];
freeChunks();
/*
* Skip leading blanks.
*/
while (isBlank(*cmd))
cmd++;
/*
* If the command is empty or is a comment then ignore it.
*/
if ((*cmd == '[=11=]') || (*cmd == '#'))
return 0;
/*
* Look for the end of the command name and then copy the
* command name to a buffer so we can null terminate it.
*/
endCmd = cmd;
while (*endCmd && !isBlank(*endCmd))
endCmd++;
memcpy(cmdName, cmd, endCmd - cmd);
cmdName[endCmd - cmd] = '[=11=]';
/*
* Expand simple environment variables
*/
while (strstr(cmd, "$(")) expandVariable((char *) cmd);
/*
* Now look for the command in the builtin table, and execute
* the command if found.
*/
if (exec_builtin(cmd)) {
return 0;
}
/*
* The command is not a built-in, so run the program along
* the PATH list.
*/
return runCmd(cmd);
}
/*
* Execute the specified file or program
* A null name pointer indicates to read from stdin.
*/
int exec_program(const char *name) {
FILE *fp;
int r = 0;
char *input, shell_prompt[100];
if (sourceCount >= MAX_SOURCE) {
fprintf(stderr, "Too many source files\n");
return 1;
}
fp = stdin;
if (name) {
fp = fopen(name, "r");
if (fp == NULL) {
perror(name);
return 1;
}
}
sourcefiles[sourceCount++] = fp;
setlocale(LC_CTYPE, "");
/*Configure readline to auto-complete paths when the tab key is hit.*/
rl_bind_key('\t', rl_complete);
/*stifle_history(7);*/
for (; ;) {
/* Create prompt string from user name and current working directory.*/
snprintf(shell_prompt, sizeof(shell_prompt), "%s:%s $ ", getenv("USER"), getcwd(NULL, 1024));
// Display prompt and read input (NB: input must be freed after use)...
input = readline(shell_prompt);
// Check for EOF.
if (!input)
break;
add_history(input);
r = command(input);
free(input);
}
return r;
}
static struct option long_options[] = {
{"with_param", 1, 0, 'p'},
{"version", 0, 0, 'v'},
{"help", 0, 0, 'h'},
{0, 0, 0, 0}
};
char s[] = "Interrupt\n";
void int_handler(int signum) {
if (write(fileno(stdin), s, sizeof s - 1)) { } else { }
if (signum) { if (false); } else { }
}
int main(int argc, char *argv[]) {
struct sigaction sh;
sh.sa_handler = int_handler;
sigemptyset(&sh.sa_mask);
sh.sa_flags = 0;
sigaction(SIGINT, &sh, NULL);
sourceCount = 0;
const char *commandFile;
commandFile = NULL;
char *pathValue;
int option;
sh.sa_handler = int_handler;
sigemptyset(&sh.sa_mask);
sh.sa_flags = 0;
sigaction(SIGINT, &sh, NULL);
int option_index = 0;
while (1) {
option_index = 0;
option = getopt_long(argc, argv, "p:vh",
long_options, &option_index);
if (option == -1)
break;
switch (option) {
case 'p': {
/* store_parameter(optarg); */
break;
}
case 'v': {
printf("OpenShell version 0.1(a)\n");
printf("Version: %s\n", VERSION);
exit(EXIT_SUCCESS);
}
case 'h': {
printf("Usage: ./shell\n");
/*print_help();*/
exit(EXIT_SUCCESS);
}
default: {
/* fprintf(stderr, "Error (%s): unrecognized option.\n", __FUNCTION__);*/
/* print_help();*/
return 1;/*RETURN_FAILURE;*/
}
} /* end switch */
}
/* get the PATH environment to find if less is installed */
pathValue = getenv("PATH");
if (!pathValue || getenv("PATH") == NULL) {
printf("'%s' is not set.\n", "PATH");
/* Default our path if it is not set. */
putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc");
}
else {
printf("'%s' is set to %s.\n", "PATH", pathValue);
}
exec_program(commandFile);
return (0);
}
我的生成文件:
CC = gcc
GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags)
CFLAGS := $(CFLAGS) -L/usr/local/include/ -L/usr/include -pedantic -std=c99 -Wall -O3 -g -DVERSION=\"$(GIT_VERSION)\" -ledit -lncurses
LDIRS = -L/usr/local/lib -L/usr/lib
LIBS =su -lcurses
shell: main.o
$(CC) -o shell main.o errors.c util.c pipeline.c -ledit -lncurses -lcurses
main.o: main.c errors.c util.c
USERNAME := $(shell whoami >> username.txt)
GIT:= $(shell head -n -1 openshell.h > temp.txt ; mv temp.txt openshell.h;git describe --abbrev=4 --dirty --always --tags > VERSION; echo "\#define VERSION \"$(GIT_VERSION)\"" >> openshell.h)
.PHONY: clean
clean:
rm -f *.o
您应该使用 c99 或 c11 进行编译,并为 gcc 设置标志:
gcc -std=c99
或
gcc -std=c11
我正在构建一个自定义 shell 并在我编译时看到 usr/include/ctype.h:92
似乎需要 c99 inline 函数,但编译器说 C99
内联函数不需要支持的。可以使用编译器的参数禁用警告,但它是一个需要修复的错误吗?
这是我的main.c
#define _XOPEN_SOURCE 500
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include "openshell.h"
#include "errors.h"
#include <errno.h>
#include <locale.h>
#include <readline/readline.h>
#include <getopt.h>
#include <unistd.h>
#include <assert.h>
#include <readline/history.h>
#ifdef SIGDET
#if SIGDET == 1
int isSignal = 1; /*Termination detected by signals*/
#endif
#endif
static int sourceCount = 0;
static FILE *sourcefiles[MAX_SOURCE];
/*
* The special maximum argument value which means that there is
* no limit to the number of arguments on the command line.
*/
#define INFINITE_ARGS 0x7fffffff
/*
* The table of built-in commands.
* A command is terminated wih an entry containing NULL values.
*/
static const CommandEntry commandEntryTable[] =
{
{
"checkenv", do_checkenv, 1, INFINITE_ARGS,
"Check environment variables",
""
},
{
"add2path", do_add2path, 3, INFINITE_ARGS,
"do_add2path",
"[txp]v arFileName fileName ..."
},
{
"cd", do_cd, 1, 2,
"Change current directory",
"[dirName]"
},
{
"exit", do_exit, 1, 2,
"Exit from shell",
"[exit value]"
},
{
"help", do_help, 1, 2,
"Print help about a command",
"[word]"
},
{
"kill", do_kill, 2, INFINITE_ARGS,
"Send a signal to the specified process",
"[-sig] pid ..."
},
{
NULL, 0, 0, 0,
NULL,
NULL
}
};
struct command {
char *const *argv;
};
char** str_split(char* a_str, const char a_delim)
{
char** result = 0;
size_t count = 0;
char* tmp = a_str;
char* last_comma = 0;
char delim[2];
delim[0] = a_delim;
delim[1] = 0;
/* Count how many elements will be extracted. */
while (*tmp)
{
if (a_delim == *tmp)
{
count++;
last_comma = tmp;
}
tmp++;
}
/* Add space for trailing token. */
count += last_comma < (a_str + strlen(a_str) - 1);
/* Add space for terminating null string so caller
knows where the list of returned strings ends. */
count++;
result = malloc(sizeof(char*) * count);
if (result)
{
size_t idx = 0;
char* token = strtok(a_str, delim);
while (token)
{
assert(idx < count);
*(result + idx++) = strdup(token);
token = strtok(0, delim);
}
assert(idx == count - 1);
*(result + idx) = 0;
}
return result;
}
char ** stripped;
char ** create_pipeline(int argc, char ** argv) {
if(!strstr(argv[argc], "|")) { /* && ! isBetweenquotes*/
stripped = argv;
return stripped;
}
else {
stripped = argv;
return create_pipeline(argc, argv);
}
}
static int runCmd(const char *cmd) {
const char *cp;
pid_t pid;
int status;
struct command shellcommand[4];
char **argv = 0;
int argc = 1;
bool pipe = false;
char *command[40];
char *cmd2[20] = {"cmd2", 0};
int numberofpipelines = 0;
unsigned long i3 = 0;
unsigned long i2 = 0;
unsigned long i1 = 0;
unsigned long n = 0;
char *string;
char *string1;
int max_args = 1; /* there's at least one argument or we wouldn't reach this */
cmd2[0] = NULL;
cmd2[1] = NULL;
cmd2[2] = NULL;
command[0] = NULL;
command[1] = NULL;
command[3] = NULL;
char *string2 = NULL;
char** tokens;
for (cp = cmd; *cp; cp++) {
if ((*cp >= 'a') && (*cp <= 'z')) {
continue;
}
if ((*cp >= 'A') && (*cp <= 'Z')) {
continue;
}
if (isDecimal(*cp)) {
continue;
}
if (isBlank(*cp)){
continue;
}
if ((*cp == '.') || (*cp == '/') || (*cp == '-') ||
(*cp == '+') || (*cp == '=') || (*cp == '_') ||
(*cp == ':') || (*cp == ',') || (*cp == '\'') ||
(*cp == '"')) {
continue;
}
}
makeArgs(cmd, &argc, (const char ***) &argv, pipe);
char a[20] = {0};
if (sscanf(cmd, "%*[^']'%[^']'", a) == 1) {
printf("<undefined>");
}
char cmdtmp[75];
strcpy(cmdtmp, cmd);
tokens = str_split( cmdtmp, '|');
if (tokens)
{
int i;
for (i = 0; *(tokens + i); i++)
{
printf("month=[%s]\n", *(tokens + i));
free(*(tokens + i));
}
printf("\n");
free(tokens);
}
for (int i = 0; i < argc; i++) {
if (argv[i] != NULL && strstr(argv[i], "|")) {
numberofpipelines++;
char subbuff[40];
i1 = 0;
i2 = 0;
i3 = 0;
subbuff[0]='[=11=]';
string = strstr(argv[i], "|");
if (string != NULL) {
i3 = string - argv[i];
printf("**** is null ***");
cmd2[1] = argv[argc - 1];
}
string1 = strstr(&argv[i][i3 + 2], "|");
if (string1 != NULL) {
i2 = string1 - argv[i3 + 1];
printf("i2: %lu", i2);
} else {
char *found3 = strstr(&argv[i][i3 + 1], " ");
if (found3 != NULL) {}
string2 = strstr(argv[1], "|");
if (string2 != NULL) {
i1 = string2 - argv[1];
}
n = strlen(argv[1]) - i1;
if (argc > 2) {
memcpy(subbuff, &argv[i][i3 + 1], n - 1);
subbuff[n - 1] = '[=11=]';
cmd2[0] = subbuff;
cmd2[1] = argv[argc - 1];
} else {
memcpy(subbuff, &argv[i][i3 + 1], n);
subbuff[n] = '[=11=]';
cmd2[0] = subbuff;
cmd2[1] = argv[argc - 1];
}
argc++;
argv[i + 1] = subbuff;
command[i] = "<undefined>";
argv[i + 2] = NULL;
max_args = i;
}
}
if (argv[i] != NULL) {
if (i < max_args) {
command[i] = argv[i];
command[i+1] = 0;
max_args++;
cmd2[1] = argv[argc - 1];
} else {
command[max_args] = argv[max_args];
command[max_args+1] = 0;
cmd2[1] = argv[argc - 1];
}
}
if (argv[i] != NULL) {
char *p = strchr(argv[i], '|');
if (!p) {
/* deal with error: / not present" */;
} else {
*p = 0;
}
}
}
dump_argv((const char *) "d", argc, argv);
/* makeArgs(cmd, &argc, &argv, pipe);*/
/* command[2]= 0;*/
shellcommand[0].argv = command;
shellcommand[1].argv = cmd2;
pid = fork();
if (pid < 0) {
perror("fork failed");
return -1;
}
/* If we are the child process, then go execute the program.*/
if (pid == 0) {
/* spawn(cmd);*/
fork_pipes(numberofpipelines, shellcommand);
}
/*
* We are the parent process.
* Wait for the child to complete.
*/
status = 0;
while (((pid = waitpid(pid, &status, 0)) < 0) && (errno == EINTR));
if (pid < 0) {
fprintf(stderr, "Error from waitpid: %s", strerror(errno));
return -1;
}
if (WIFSIGNALED(status)) {
fprintf(stderr, "pid %ld: killed by signal %d\n",
(long) pid, WTERMSIG(status));
return -1;
}
return WEXITSTATUS(status);
}
/* The shell performs wildcard expansion on each token it extracts while parsing the command line.
* Oftentimes, globbing will obviously not do anything (for example, ls just returns ls).
* When you want nullglob behavior you'll have to know whether the glob function actually found any glob characters, though
*/
static void expandVariable(char *shellcommand) {
char mystring[CMD_LEN];
char *cp;
char *ep;
strcpy(mystring, shellcommand);
cp = strstr(mystring, "$(");
if (cp) {
*cp++ = '[=11=]';
strcpy(shellcommand, mystring);
ep = ++cp;
while (*ep && (*ep != ')')) ep++;
if (*ep == ')') *ep++ = '[=11=]';
cp = getenv(cp);
if (cp) strcat(shellcommand, cp);
strcat(shellcommand, ep);
}
return;
}
int do_help(int argc, const char **argv) {
const CommandEntry *entry;
const char *str;
str = NULL;
if (argc == 2)
str = argv[1];
/*
* Check for an exact match, in which case describe the program.
*/
if (str) {
for (entry = commandEntryTable; entry->name; entry++) {
if (strcmp(str, entry->name) == 0) {
printf("%s\n", entry->description);
printf("usage: %s %s\n", entry->name,
entry->usage);
return 0;
}
}
}
/*
* Print short information about commands which contain the
* specified word.
*/
for (entry = commandEntryTable; entry->name; entry++) {
if ((str == NULL) || (strstr(entry->name, str) != NULL) ||
(strstr(entry->usage, str) != NULL)) {
printf("%-10s %s\n", entry->name, entry->usage);
}
}
return 0;
}
/*
* Try to execute a built-in command.
* Returns TRUE if the command is a built in, whether or not the
* command succeeds. Returns FALSE if this is not a built-in command.
*/
bool exec_builtin(const char *cmd) {
const char *endCmd;
const CommandEntry *entry;
int argc;
const char **argv;
char cmdName[CMD_LEN];
/*
* Look for the end of the command name and then copy the
* command name to a buffer so we can null terminate it.
*/
endCmd = cmd;
while (*endCmd && !isBlank(*endCmd))
endCmd++;
memcpy(cmdName, cmd, endCmd - cmd);
cmdName[endCmd - cmd] = '[=11=]';
/*
* Search the command table looking for the command name.
*/
for (entry = commandEntryTable; entry->name != NULL; entry++) {
if (strcmp(entry->name, cmdName) == 0)
break;
}
/*
* If the command is not a built-in, return indicating that.
*/
if (entry->name == NULL) {
return false;
}
bool bo = false;
/*
* The command is a built-in.
* Break the command up into arguments and expand wildcards.
*/
if (!makeArgs(cmd, &argc, &argv, bo)) {
return true;
}
/*
* Give a usage string if the number of arguments is too large
* or too small.
*/
if ((argc < entry->minArgs) || (argc > entry->maxArgs)) {
fprintf(stderr, "usage: %s %s\n", entry->name, entry->usage);
return true;
}
/*
* Call the built-in function with the argument list.
*/
entry->func(argc, argv);
return true;
}
/*
* Parse and execute one null-terminated command line string.
* This breaks the command line up into words, checks to see if the
* command is an alias, and expands wildcards.
*/
int command(const char *cmd) {
const char *endCmd;
char cmdName[CMD_LEN];
freeChunks();
/*
* Skip leading blanks.
*/
while (isBlank(*cmd))
cmd++;
/*
* If the command is empty or is a comment then ignore it.
*/
if ((*cmd == '[=11=]') || (*cmd == '#'))
return 0;
/*
* Look for the end of the command name and then copy the
* command name to a buffer so we can null terminate it.
*/
endCmd = cmd;
while (*endCmd && !isBlank(*endCmd))
endCmd++;
memcpy(cmdName, cmd, endCmd - cmd);
cmdName[endCmd - cmd] = '[=11=]';
/*
* Expand simple environment variables
*/
while (strstr(cmd, "$(")) expandVariable((char *) cmd);
/*
* Now look for the command in the builtin table, and execute
* the command if found.
*/
if (exec_builtin(cmd)) {
return 0;
}
/*
* The command is not a built-in, so run the program along
* the PATH list.
*/
return runCmd(cmd);
}
/*
* Execute the specified file or program
* A null name pointer indicates to read from stdin.
*/
int exec_program(const char *name) {
FILE *fp;
int r = 0;
char *input, shell_prompt[100];
if (sourceCount >= MAX_SOURCE) {
fprintf(stderr, "Too many source files\n");
return 1;
}
fp = stdin;
if (name) {
fp = fopen(name, "r");
if (fp == NULL) {
perror(name);
return 1;
}
}
sourcefiles[sourceCount++] = fp;
setlocale(LC_CTYPE, "");
/*Configure readline to auto-complete paths when the tab key is hit.*/
rl_bind_key('\t', rl_complete);
/*stifle_history(7);*/
for (; ;) {
/* Create prompt string from user name and current working directory.*/
snprintf(shell_prompt, sizeof(shell_prompt), "%s:%s $ ", getenv("USER"), getcwd(NULL, 1024));
// Display prompt and read input (NB: input must be freed after use)...
input = readline(shell_prompt);
// Check for EOF.
if (!input)
break;
add_history(input);
r = command(input);
free(input);
}
return r;
}
static struct option long_options[] = {
{"with_param", 1, 0, 'p'},
{"version", 0, 0, 'v'},
{"help", 0, 0, 'h'},
{0, 0, 0, 0}
};
char s[] = "Interrupt\n";
void int_handler(int signum) {
if (write(fileno(stdin), s, sizeof s - 1)) { } else { }
if (signum) { if (false); } else { }
}
int main(int argc, char *argv[]) {
struct sigaction sh;
sh.sa_handler = int_handler;
sigemptyset(&sh.sa_mask);
sh.sa_flags = 0;
sigaction(SIGINT, &sh, NULL);
sourceCount = 0;
const char *commandFile;
commandFile = NULL;
char *pathValue;
int option;
sh.sa_handler = int_handler;
sigemptyset(&sh.sa_mask);
sh.sa_flags = 0;
sigaction(SIGINT, &sh, NULL);
int option_index = 0;
while (1) {
option_index = 0;
option = getopt_long(argc, argv, "p:vh",
long_options, &option_index);
if (option == -1)
break;
switch (option) {
case 'p': {
/* store_parameter(optarg); */
break;
}
case 'v': {
printf("OpenShell version 0.1(a)\n");
printf("Version: %s\n", VERSION);
exit(EXIT_SUCCESS);
}
case 'h': {
printf("Usage: ./shell\n");
/*print_help();*/
exit(EXIT_SUCCESS);
}
default: {
/* fprintf(stderr, "Error (%s): unrecognized option.\n", __FUNCTION__);*/
/* print_help();*/
return 1;/*RETURN_FAILURE;*/
}
} /* end switch */
}
/* get the PATH environment to find if less is installed */
pathValue = getenv("PATH");
if (!pathValue || getenv("PATH") == NULL) {
printf("'%s' is not set.\n", "PATH");
/* Default our path if it is not set. */
putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc");
}
else {
printf("'%s' is set to %s.\n", "PATH", pathValue);
}
exec_program(commandFile);
return (0);
}
我的生成文件:
CC = gcc
GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags)
CFLAGS := $(CFLAGS) -L/usr/local/include/ -L/usr/include -pedantic -std=c99 -Wall -O3 -g -DVERSION=\"$(GIT_VERSION)\" -ledit -lncurses
LDIRS = -L/usr/local/lib -L/usr/lib
LIBS =su -lcurses
shell: main.o
$(CC) -o shell main.o errors.c util.c pipeline.c -ledit -lncurses -lcurses
main.o: main.c errors.c util.c
USERNAME := $(shell whoami >> username.txt)
GIT:= $(shell head -n -1 openshell.h > temp.txt ; mv temp.txt openshell.h;git describe --abbrev=4 --dirty --always --tags > VERSION; echo "\#define VERSION \"$(GIT_VERSION)\"" >> openshell.h)
.PHONY: clean
clean:
rm -f *.o
您应该使用 c99 或 c11 进行编译,并为 gcc 设置标志:
gcc -std=c99
或
gcc -std=c11