我正在写一个定制的外壳,我希望它执行一个脚本:shebang for custom shell?
if [ type less > /dev/null ];then PAGER=less; fi
echo $PAGER
printenv|grep $1|$PAGER
如果我从bash和我的定制外壳运行它的工作原理:
$ ./shell -f ../checkenv.sh GNOME
[13607]
[13606]
GNOME_KEYRING_CONTROL=
GNOME_KEYRING_PID=
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
INSTANCE=GNOME
XDG_CURRENT_DESKTOP=GNOME
(END)
但是,如果我启动我的shell,然后尝试运行该脚本,我收到一条错误消息。
$ ./shell
'PATH' is set to /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/go/bin.
$ ../checkenv.sh GNOME
14786: executing ../checkenv.sh
../checkenv.sh: 2: [: type: unexpected operator
14786: executed
$
这似乎是因为我没有shebang,但我不知道如何使用shebang作为自定义shell。我应该在/usr/bin/
中安装我的自定义外壳还是进行其他安排?
我的主要功能和我readline的功能有:
int main(int argc, char *argv[]) {
bool donotrun = false;
struct sigaction new_action, old_action;
hashtable_t *hashtable = ht_create(65536);
/* Set up the structure to specify the new action. */
new_action.sa_handler = termination_handler;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGINT, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGINT, &new_action, NULL);
sigaction(SIGHUP, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGHUP, &new_action, NULL);
sigaction(SIGTERM, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGTERM, &new_action, NULL);
bool background = false;
int index = 0;
int i;
char *cvalue = NULL;
const char *commandFile = NULL;
while (1) {
index = 0;
i = getopt_long(argc, argv, "pc:fvh",
options, &index);
if (i == -1)
break;
switch (i) {
case 'p': {
exit(EXIT_SUCCESS);
}
case 'v': {
printf("sh OpenShell version 0.1(a)\n");
printf("Version: %s\n", VERSION);
// printf ("%s/%s/%s/%s\n",
// program_name, version,
// build_date, build_git_sha);
exit(EXIT_SUCCESS);
}
case 'h': {
usage();
exit(EXIT_SUCCESS);
}
case 'c': {
cvalue = optarg;
command(cvalue, hashtable, background);
exit(EXIT_SUCCESS);
}
case 'f': {
/*
* Execute commands from file.
* This is used for osh script files.
* The quiet flag is also set.
*/
//if ((argc != 1) || commandFile)
//usage();
//quietFlag = TRUE;
printf("case f\n");
//commandFile = *argv++;
argc--;
*argv++;
*argv++;
readFile(*argv++, argc, argv, hashtable, background);
//free(line);
exit(0);
//break;
}
case '?':
if (optopt == 'c')
fprintf(stderr, "Option -%c requires an argument.\n", optopt);
else if (isprint (optopt))
fprintf(stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf(stderr,
"Unknown option character `\\x%x'.\n",
optopt);
default: {
return 1;
}
}
}
getPath();
char *copy = "";
for (; ;) {
bool scanning = true;
while (scanning) {
char *line = NULL;
line = readline("$ ");
if (line == NULL) {
/* No more lines, so exit the loop. */
break;
}
if (line)
copy = strdup(line);
if (line && !strstr(line, "for") && !strstr(line, "==") && !strstr(line, "if") && strstr(line, "=")) {
donotrun = true;
char str[128];
char *ptr;
strcpy(str, line);
strtok_r (str, "=", &ptr);
ht_set(hashtable, str, ptr);
}
if (!scanning)
break;
if (commandFile!=NULL || !isatty(fileno(stdin))) {
*argv++;
readFile(*argv++, argc, argv, hashtable, background);
free(line);
exit(0);
}
else {
if (!donotrun) {
line = strrep(line, " | ", "|");
line = strrep(line, " |", "|");
background = testFn2(line);
if (background)
line[strlen(line) - 1] = '\0';
command(line, hashtable, background);
}
donotrun = false;
add_history(copy);
}
free(copy);
}
}
// ParseFree(pParser, free);FIXME: where should this go?
return 0;
}
/*
* Read commands from the specified file.
* A null name pointer indicates to read from stdin.
*/
static int readFile(const char *name, int argc, char ** argv, hashtable_t *hashtable, bool background) {
FILE *fp;
int cc;
bool ttyFlag;
char buf[CMD_LEN];
int r = 0;
if (sourceCount >= MAX_SOURCE) {
fprintf(stderr, "Too many source files\n");
return 1;
}
fp = stdin;
printf("name %s\n", name);
if (name) {
fp = fopen(name, "r");
if (fp == NULL) {
perror(name);
return 1;
}
}
sourcefiles[sourceCount++] = fp;
ttyFlag = isatty(fileno(fp));
int i = 0;
while (true) {
if (ttyFlag)
showPrompt();
if (intFlag && !ttyFlag && (fp != stdin)) {
fclose(fp);
sourceCount--;
return 1;
}
if (fgets(buf, CMD_LEN - 1, fp) == NULL) {
if (ferror(fp) && (errno == EINTR)) {
clearerr(fp);
continue;
}
break;
}
cc = strlen(buf);
if (buf[cc - 1] == '\n')
cc--;
while ((cc > 0) && isBlank(buf[cc - 1]))
cc--;
buf[cc] = '\0';
//printf("buf %s\n", argv[0]);
strreplace(buf, "$1", argv[0]);
//printf("arg %s\n", ++argv);
if (strstr(buf, "=")) {
char str[128];
char *ptr;
strcpy(str, buf);
strtok_r (str, "=", &ptr);
ht_set(hashtable, str, ptr);
}
//printf("the command is %s\n", buf);
r = command(buf, hashtable, background);
i++;
}
if (ferror(fp)) {
perror("Reading command line");
if (fp == stdin)
exit(1);
}
clearerr(fp);
if (fp != stdin)
fclose(fp);
sourceCount--;
return r;
}
目前还不清楚这是如何与C或您的shell的源代码相关。 She-bang是执行环境的一个特性,并且与C无关。 – Olaf
为什么不试试'#!/ path/to/my/shell'并查看会发生什么? – a3f
顺便说一句,'[]'不是'if'语法的一部分。这与分组运营商的对手或花括号不同。从字面上看,'['是'test'命令的别名; '如果[2-gt 1]'在任何方面**都是**,相当于'if test 2 -gt 1'(每个我读过的源代码的shell都使用相同的函数实现它们)你会发现你的操作系统提供了一个'/ usr/bin/['就像它做了一个'/ usr/bin/test'一样(尽管现代shell会有一个内建版本,而且启动速度更快,因此上面描述的内置版本)。 –