#include <string.h>
#include "builtin.h"
-#include "input.h"
#include "context.h"
+#include "input.h"
#include "parse.h"
#include "utils.h"
size_t size;
} aliases;
-void applyaliases(struct cmd *cmd) {
- struct cmd *p;
+void applyaliases(struct command *command) {
+ struct command *c;
char **end;
size_t i, l, a;
struct context *context;
- p = cmd;
+ c = command;
- end = p->args;
- while ((p = p->next)) if (p->args) end = p->args;
+ end = c->args;
+ while ((c = c->next)) if (c->args) end = c->args;
if (end) while (*end) ++end;
- while ((p = cmd = cmd->next)) {
- if (!cmd->args) continue;
+ while ((c = command = command->next)) {
+ if (!command->args) continue;
for (i = 0; i < aliases.size; ++i)
- if (strcmp(aliases.entries[i].lhs, *cmd->args) == 0) break;
+ if (strcmp(aliases.entries[i].lhs, *command->args) == 0) break;
if (i == aliases.size) continue;
context = &aliases.entries[i].context;
parse(context);
for (a = 0; context->tokens[a]; ++a);
- memmove(cmd->args + a, cmd->args + 1, (end - cmd->args + 1) * sizeof*cmd->args);
- memcpy(cmd->args, context->tokens, a * sizeof*cmd->args);
- while ((p = p->next)) p->args += a - 1;
+ memmove(command->args + a, command->args + 1,
+ (end - command->args + 1) * sizeof*command->args);
+ memcpy(command->args, context->tokens, a * sizeof*command->args);
+ while ((c = c->next)) c->args += a - 1;
}
}
-void applyaliases(struct cmd *cmd);
+void applyaliases(struct command *command);
int listfd, l;
DIR *dir;
size_t i, offset;
- struct cbsfile files[1 + MAXBUILTINS + 1];
+
+ /* The three extra files correspond to:
+ * 1) output file (../libbuiltin.a)
+ * 2) list.c
+ * 3) builtin.c */
+ struct cbsfile files[3 + MAXBUILTINS + 1];
+
struct dirent *entry;
char *name, *identifier;
if (strcmp(entry->d_name, "build.c") == 0) continue;
if (!(name = strrchr(entry->d_name, '.')) || strcmp(name, ".c") != 0)
continue;
- if (i == 1 + MAXBUILTINS + 1)
+ if (i == 3 + MAXBUILTINS + 1)
errx(EXIT_FAILURE, "Unable to add built-in `%s', maximum reached (%d)",
name, MAXBUILTINS);
if (!(name = strdup(entry->d_name)))
}
if (errno) err(EXIT_FAILURE, "Unable to read from current directory");
files[i] = (struct cbsfile){NULL};
-
+
identifier = "struct builtin builtins[] = {";
l = (int)strlen(identifier);
dprintf(listfd, "\n%s", identifier);
-#include <err.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include "utils.h"
static int fgstatus;
+struct termios canonical;
+static struct termios raw;
struct sigaction sigchld, sigdfl;
-struct termios raw, canonical;
static int setconfig(struct termios *mode) {
if (tcsetattr(STDIN_FILENO, TCSANOW, mode) == -1) {
fatal("Unable to install SIGCHLD handler");
}
-void initterm(void) {
+void initfg(void) {
if (tcgetattr(STDIN_FILENO, &canonical) == -1)
- err(EXIT_FAILURE, "Unable to get default termios config");
+ fatal("Unable to get default termios config");
cfmakeraw(&raw);
if (!setconfig(&raw)) exit(EXIT_FAILURE);
* the waitpid() below is just to block the current thread of execution until
* the foreground process has been reaped */
setsigchld(&sigchld);
- while (waitpid(job.id, NULL, 0) != -1);
- errno = 0;
+ waitpid(job.id, NULL, 0);
+ errno = 0; // waitpid() will set errno
setsigchld(&sigdfl);
if (sigaction(SIGTTOU, &(struct sigaction){{SIG_IGN}}, NULL) == -1
|| tcsetpgrp(STDIN_FILENO, getpgrp()) == -1
|| sigaction(SIGTTOU, &sigdfl, NULL) == -1) {
note("Unable to reclaim foreground; terminating");
- deinitialize();
+ deinit();
exit(EXIT_FAILURE);
}
if (tcgetattr(STDIN_FILENO, &job.config) == -1)
}
}
-void deinitterm(void) {
+void deinitfg(void) {
setconfig(&canonical);
}
return EXIT_FAILURE;
}
- return setfg(*job) ? (waitfg(*job), EXIT_SUCCESS) : EXIT_FAILURE;
+ if (!setfg(*job)) return EXIT_FAILURE;
+ waitfg(*job);
+
+ return EXIT_SUCCESS;
}
+extern struct termios canonical;
extern struct sigaction sigchld, sigdfl;
-extern struct termios raw, canonical;
void setsigchld(struct sigaction *act);
-void initterm(void);
+void initfg(void);
int setfg(struct job job);
void waitfg(struct job job);
-void deinitterm(void);
+void deinitfg(void);
#include <stdlib.h>
#include "builtin.h"
-#include "input.h"
#include "context.h"
+#include "input.h"
#include "parse.h"
#include "run.h"
#include "utils.h"
-#define MAXCHARS 500
-#define MAXCMDS (MAXCHARS + 1) / 2
-#define MAXRDS (MAXCHARS / 3)
+#define MAXCHARS 1000
+#define MAXCOMMANDS (MAXCHARS + 1) / 2
+#define MAXREDIRECTS (MAXCHARS / 3)
-enum accessmode {
- END,
+#define PIPELINE(name) struct context *name(struct context *context)
+
+enum access {
+ NONE,
READ = '<',
READWRITE,
WRITE = '>',
};
struct redirect {
- enum accessmode mode;
+ enum access mode;
int oldfd, newfd;
char *oldname;
+ struct redirect *next;
};
enum terminator {
OR,
};
-struct cmd {
+struct command {
char **args;
- struct redirect *r, rds[MAXRDS + 1];
+ struct redirect *r;
enum terminator term;
int pipe[2];
- struct cmd *prev, *next;
+ struct command *prev, *next;
};
struct context {
- char buffer[MAXCHARS + 1 + 1], *tokens[MAXCMDS + 1], *script, *string;
struct {
- char *m;
- size_t l;
- } map;
- struct cmd cmds[MAXCMDS + 1];
- Input input;
+ char *string, *script;
+ struct {
+ char *map;
+ size_t len;
+ };
+ PIPELINE((*input));
+ };
+ char buffer[MAXCHARS + 1 + 1], *tokens[MAXCOMMANDS + 1];
+ struct redirect redirects[MAXREDIRECTS + 1];
+ struct command commands[1 + MAXCOMMANDS];
};
#include <string.h>
#include <sys/errno.h>
-#include "input.h"
#include "context.h"
+#include "input.h"
#include "utils.h"
#define MAXHIST 100
+
#define INC(v) (history.v = (history.v + 1) % (MAXHIST + 1))
#define DEC(v) (history.v = (history.v + MAXHIST) % (MAXHIST + 1))
size_t b, c, t;
} history;
-void readhistory(void) {
+void inithistory(void) {
FILE *file;
-
+
if (!catpath(home, ".ashhistory", history.path)) exit(EXIT_FAILURE);
if (!(file = fopen(history.path, "r"))) {
if (errno == ENOENT) return;
*history.entries[history.t] = '\0';
}
-void writehistory(void) {
+void deinithistory(void) {
FILE *file;
if (!(file = fopen(history.path, "w"))) {
-void readhistory(void);
+void inithistory(void);
int gethistory(char direction, char *buffer);
void sethistory(char *buffer);
-void writehistory(void);
+void deinithistory(void);
#include <sys/stat.h>
#include <unistd.h>
+#include "context.h"
#include "history.h"
#include "input.h"
-#include "context.h"
#include "utils.h"
-#define DEFAULTPROMPT ">"
-
-INPUT(stringinput) {
+PIPELINE(stringinput) {
char *start;
size_t l;
if (!*context->string) {
- if (context->script && munmap(context->map.m, context->map.l) == -1)
+ if (context->script && munmap(context->map, context->len) == -1)
note("Unable to unmap memory associated with `%s'", context->script);
return NULL;
}
+
start = context->string;
while (*context->string && *context->string != '\n') ++context->string;
l = context->string - start;
note("Line too long, exceeds %d character limit", MAXCHARS);
return NULL;
}
+
strncpy(context->buffer, start, l);
context->buffer[l] = ';';
context->buffer[l + 1] = '\0';
return context;
}
-INPUT(scriptinput) {
+PIPELINE(scriptinput) {
int fd;
struct stat sstat;
note("Unable to stat `%s'", context->script);
return NULL;
}
- if ((context->map.l = sstat.st_size) == 0) return NULL;
- if ((context->string = context->map.m = mmap(NULL, context->map.l, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
+ if ((context->len = sstat.st_size) == 0) return NULL;
+ if ((context->map = mmap(NULL, context->len, PROT_READ, MAP_PRIVATE, fd, 0))
+ == MAP_FAILED) {
note("Unable to memory map `%s'", context->script);
return NULL;
}
note("Unable to close `%s'", context->script);
return NULL;
}
+
+ context->string = context->map;
context->input = stringinput;
return context->input(context);
}
-static size_t prompt(void) {
+static void prompt(void) {
char *p;
- if (!(p = getenv("PROMPT")) && setenv("PROMPT", p = DEFAULTPROMPT, 1) == -1)
+ if (!(p = getenv("PROMPT")) && setenv("PROMPT", p = ">", 1) == -1)
note("Unable to update $PROMPT$ environment variable");
- printf("%s ", p);
- return strlen(p) + 1;
+ printf("\r%s ", p);
}
-INPUT(userinput) {
+PIPELINE(userinput) {
char *start, *cursor, *end;
unsigned int c;
int i;
size_t oldlen, newlen;
end = cursor = start = context->buffer;
- *start = '\0';
+ *context->buffer = '\0';
while (start == end) {
prompt();
while ((c = getchar()) != '\r') switch (c) {
break;
case CTRLC:
puts("^C\r");
- *start = '\0';
+ *context->buffer = '\0';
return context;
case CTRLD:
puts("^D\r");
case CLEAR:
fputs("\033[H\033[J", stdout);
prompt();
- fputs(start, stdout);
+ fputs(context->buffer, stdout);
continue;
case ESCAPE:
switch ((c = getchar())) {
switch ((c = getchar())) {
case UP:
case DOWN:
- oldlen = strlen(start);
- if (!gethistory(c, start)) continue;
- newlen = strlen(start);
+ oldlen = strlen(context->buffer);
+ if (!gethistory(c, context->buffer)) continue;
+ newlen = strlen(context->buffer);
end = cursor = start + newlen;
putchar('\r');
prompt();
- fputs(start, stdout);
+ fputs(context->buffer, stdout);
for (i = oldlen - newlen; i > 0; --i) putchar(' ');
for (i = oldlen - newlen; i > 0; --i) putchar('\b');
+
break;
case LEFT:
if (cursor > start) putchar((--cursor, '\b'));
}
puts("\r");
}
- sethistory(start);
+
+ while (*start == ' ') ++start;
+ if (start == end) {
+ *context->buffer = '\0';
+ return context;
+ }
+
+ sethistory(context->buffer);
*end++ = ';';
*end = '\0';
-#define INPUT(name) struct context *name(struct context *context)
-
-typedef INPUT((*Input));
-
enum {
CTRLC = '\003',
CTRLD,
DEL = '\177',
};
-INPUT(stringinput);
-INPUT(scriptinput);
-INPUT(userinput);
+PIPELINE(stringinput);
+PIPELINE(scriptinput);
+PIPELINE(userinput);
#include <string.h>
#include <termios.h>
-// #include <stdio.h> // XXX
#include "job.h"
#include "utils.h"
struct joblink entries[MAXJOBS + 1], *active, *free;
} jobs;
+void initjobs(void) {
+ size_t i;
+
+ for (i = 0; i < MAXJOBS - 1; ++i) jobs.entries[i].next = &jobs.entries[i + 1];
+ jobs.free = jobs.entries;
+}
+
struct job *pushjob(struct job *job) {
struct joblink *p;
return &p->job;
}
-struct job *peekjob(void) {
- return jobs.active ? &jobs.active->job : NULL;
-}
-
struct job *pulljob(void) {
struct joblink *p;
return &p->job;
}
+struct job *peekjob(void) {
+ return jobs.active ? &jobs.active->job : NULL;
+}
+
struct job *searchjobid(pid_t id) {
struct joblink *p;
return &p->job;
}
-
-void initjobs(void) {
- size_t i;
-
- for (i = 0; i < MAXJOBS - 1; ++i) jobs.entries[i].next = &jobs.entries[i + 1];
- jobs.free = jobs.entries;
-}
enum jobtype type;
};
+void initjobs(void);
struct job *pushjob(struct job *job);
-struct job *peekjob(void);
struct job *pulljob(void);
+struct job *peekjob(void);
struct job *searchjobid(pid_t id);
struct job *searchjobtype(enum jobtype);
struct job *deletejobid(pid_t id);
-void initjobs(void);
#include <stdlib.h>
-#include "input.h"
#include "context.h"
+#include "input.h"
#include "options.h"
#include "parse.h"
#include "run.h"
options();
- initialize();
+ init();
if (login) config(".ashlogin");
- if (interactive) config(".ashint");
+ if (interactive) config(".ashrc");
while (run(parse(context.input(&context))));
- deinitialize();
+ deinit();
return EXIT_SUCCESS;
}
-#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include "input.h"
#include "context.h"
+#include "input.h"
+#include "utils.h"
int login, interactive, argc;
char **argv;
-
struct context context;
static void usage(char *program, int code) {
login = 1;
break;
case ':':
- warnx("Expected argument following `-%c'\n", optopt);
+ note("Expected argument following `-%c'\n", optopt);
usage(*argv, EXIT_FAILURE);
case '?':
default:
- warnx("Unknown command line option `-%c'\n", optopt);
+ note("Unknown command line option `-%c'\n", optopt);
usage(*argv, EXIT_FAILURE);
}
if (opt == 'c') break;
#include <stdlib.h>
#include <string.h>
-#include "input.h"
#include "context.h"
+#include "input.h"
#include "options.h"
#include "utils.h"
-static void initcmd(struct cmd *cmd) {
- cmd->args = NULL;
- cmd->r = cmd->rds;
- cmd->r->mode = END;
- cmd->prev = cmd - 1;
- cmd->next = NULL;
+static void initcommand(struct command *c) {
+ c->args = NULL;
+ c->r = NULL;
+ c->prev = c - 1;
+ c->next = NULL;
}
-struct context *parse(struct context *context) {
+PIPELINE(parse) {
char *b, **t, *name, *value, *stlend, *p, *end, *env;
- struct cmd *c;
+ struct redirect *r, *q;
+ struct command *c;
long l;
int e, offset;
if (!context) return NULL;
+
b = context->buffer;
t = context->tokens;
- c = context->cmds + 1;
- context->cmds->next = NULL;
+ r = context->redirects;
+ c = context->commands + 1;
+ context->commands->next = NULL;
*t = value = name = NULL;
- for (initcmd(c); *b; ++b) switch (*b) {
+ r->mode = NONE;
+ for (initcommand(c); *b; ++b) switch (*b) {
default:
- if (c->r->mode) break;
+ if (r->mode) break;
if (!c->args) c->args = t;
if (!*(b - 1)) {
if (!name) *t++ = b; else if (!value) value = b;
break;
case '<':
case '>':
- if (c->r->mode) {
+ if (r->mode) {
note("File redirections should be separated by spaces");
return context;
}
- c->r->newfd = *b == '>';
+ if (r - context->redirects == MAXREDIRECTS) {
+ note("Too many file redirects, exceeds %d redirect limit", MAXREDIRECTS);
+ return context;
+ }
+ if (!c->r) c->r = r;
if (*(b - 1)) {
if (c->args == --t) c->args = NULL;
if ((l = strtol(*t, &stlend, 10)) < 0 || l > INT_MAX || stlend != b) {
note("Invalid value for a file redirection");
return context;
}
- c->r->newfd = l;
- }
- c->r->mode = *b;
+ r->newfd = l;
+ } else r->newfd = *b == '>';
+ r->mode = *b;
if (*(b + 1) == '>') {
- ++c->r->mode;
+ ++r->mode;
++b;
}
- c->r->oldname = b + 1;
+ r->oldname = b + 1;
if (*(b + 1) == '&') ++b;
break;
case '"':
*end = '\0';
memmove(p, p + 1, end - p);
--b;
+
break;
case '=':
name = *--t;
memmove(b + offset, b, end - b + 1);
strncpy(p, env, e);
b += offset - 1;
+
break;
case '~':
if (!*(b - 1)) {
case '|':
case ';':
if (name && *c->args == name) c->args = NULL;
- if (c->args || c->rds->mode) {
+ if (c->args || c->r) {
if ((c->term = *b) == *(b + 1) && (*b == '&' || *b == '|')) {
++c->term;
*b++ = '\0';
}
*b = '\0';
- if (c->r->mode) (++c->r)->mode = END;
- for (c->r = c->rds; c->r->mode; ++c->r) if (*c->r->oldname == '&') {
- if ((l = strtol(++c->r->oldname, &stlend, 10)) < 0
- || l > INT_MAX || *stlend) {
+
+ if (r->mode) {
+ r++->next = NULL;
+ r->mode = NONE;
+ } else if (c->r) (r - 1)->next = NULL;
+ for (q = c->r; q; q = q->next) if (*q->oldname == '&') {
+ if ((l = strtol(++q->oldname, &stlend, 10)) < 0 || l > INT_MAX || *stlend) {
note("Incorrect syntax for file redirection");
return context;
}
- c->r->oldfd = l;
- c->r->oldname = NULL;
+ q->oldfd = l;
+ q->oldname = NULL;
}
- c->r = c->rds;
- c->next = c + 1;
- initcmd(++c);
+ initcommand(c = c->next = c + 1);
*t++ = NULL;
}
case ' ':
}
value = name = NULL;
}
- if (c->r->mode) (++c->r)->mode = END;
+ if (r->mode) {
+ r = r->next = r + 1;
+ r->mode = NONE;
+ }
}
(--c)->next = NULL;
break;
}
- context->cmds->next = context->cmds + 1;
+ context->commands->next = context->commands + 1;
+
return context;
}
-struct context *parse(struct context *context);
+PIPELINE(parse);
#include <signal.h>
#include <stdlib.h>
#include <sys/errno.h>
+#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
-// #include <stdio.h> // XXX
#include "builtin.h"
-#include "input.h"
#include "context.h"
#include "alias.h"
+#include "input.h"
#include "job.h"
#include "fg.h"
#include "utils.h"
-static int closepipe(struct cmd *cmd) {
+static int closepipe(struct command *command) {
int result;
- result = close(cmd->pipe[0]) == 0;
- result &= close(cmd->pipe[1]) == 0;
- if (!result) note("Unable to close `%s' pipe", *cmd->args);
+ result = close(command->pipe[0]) == 0;
+ result &= close(command->pipe[1]) == 0;
+ if (!result) note("Unable to close `%s' pipe", *command->args);
+
return result;
}
static void redirectfiles(struct redirect *r) {
int mode, fd;
- for (; r->mode; ++r) {
+ for (; r; r = r->next) {
if (r->oldname) {
switch (r->mode) {
case READ:
}
}
-static void exec(struct cmd *cmd) {
+static void exec(struct command *c) {
char cwd[PATH_MAX];
- redirectfiles(cmd->rds);
- if (isbuiltin(cmd->args)) exit(status);
- execvp(*cmd->args, cmd->args);
+ redirectfiles(c->r);
+
+ if (isbuiltin(c->args)) exit(status);
+ execvp(*c->args, c->args);
if (!getcwd(cwd, PATH_MAX)) fatal("Unable to check current working directory");
- execvP(*cmd->args, cwd, cmd->args);
- fatal("Couldn't find `%s' command", *cmd->args);
+ execvP(*c->args, cwd, c->args);
+
+ fatal("Couldn't find `%s' command", *c->args);
}
-int run(struct context *context) {
- struct cmd *cmd;
+PIPELINE(run) {
+ struct command *c;
int ispipe, ispipestart, ispipeend;
pid_t cpid, jobid;
struct job job;
- if (!context) return 0;
+ if (!context) return NULL;
- applyaliases(cmd = context->cmds);
+ applyaliases(c = context->commands);
setsigchld(&sigdfl);
- while ((cmd = cmd->next)) {
- if (!cmd->args) {
- if (!cmd->r->mode) break;
- if ((cpid = fork()) == -1) {
- note("Unable to create child process");
- break;
- } else if (cpid == 0) {
- redirectfiles(cmd->r);
- exit(EXIT_SUCCESS);
- }
- continue;
- }
-
- ispipe = cmd->term == PIPE || cmd->prev->term == PIPE;
- ispipestart = ispipe && cmd->prev->term != PIPE;
- ispipeend = ispipe && cmd->term != PIPE;
+ while ((c = c->next)) if (c->args) {
+ ispipe = c->term == PIPE || c->prev->term == PIPE;
+ ispipestart = ispipe && c->prev->term != PIPE;
+ ispipeend = ispipe && c->term != PIPE;
if (ispipe) {
- if (!ispipeend && pipe(cmd->pipe) == -1) {
+ if (!ispipeend && pipe(c->pipe) == -1) {
note("Unable to create pipe");
- if (!ispipestart) closepipe(cmd->prev);
+ if (!ispipestart) closepipe(c->prev);
break;
}
if ((jobid = cpid = fork()) == -1) {
- note("Unable to create child process");
+ note("Unable to fork child process");
break;
} else if (cpid == 0) {
if (!ispipestart) {
- if (dup2(cmd->prev->pipe[0], 0) == -1)
- fatal("Unable to duplicate read end of `%s' pipe", *cmd->prev->args);
- if (!closepipe(cmd->prev)) exit(EXIT_FAILURE);
+ if (dup2(c->prev->pipe[0], 0) == -1)
+ fatal("Unable to duplicate read end of `%s' pipe", *c->prev->args);
+ if (!closepipe(c->prev)) exit(EXIT_FAILURE);
}
if (!ispipeend) {
- if (dup2(cmd->pipe[1], 1) == -1)
- fatal("Unable to duplicate write end of `%s' pipe", *cmd->args);
- if (!closepipe(cmd)) exit(EXIT_FAILURE);
+ if (dup2(c->pipe[1], 1) == -1)
+ fatal("Unable to duplicate write end of `%s' pipe", *c->args);
+ if (!closepipe(c)) exit(EXIT_FAILURE);
}
- exec(cmd);
+ exec(c);
}
if (!ispipestart) {
- closepipe(cmd->prev);
+ closepipe(c->prev);
jobid = (ispipeend ? pulljob : peekjob)()->id;
}
- } else if (!cmd->rds->mode && isbuiltin(cmd->args)) cpid = 0;
+ } else if (!c->r && isbuiltin(c->args)) cpid = 0;
else if ((jobid = cpid = fork()) == -1) {
- note("Unable to create child process");
+ note("Unable to fork child process");
break;
- } else if (cpid == 0) exec(cmd);
+ } else if (cpid == 0) exec(c);
if (cpid) {
if (setpgid(cpid, jobid) == -1) {
if (errno != ESRCH) {
- note("Unable to set pgid of `%s' command to %d", *cmd->args, jobid);
+ note("Unable to set pgid of `%s' command to %d", *c->args, jobid);
if (kill(cpid, SIGKILL) == -1)
note("Unable to kill process %d; may need to manually terminate", cpid);
}
break;
}
job = (struct job){.id = jobid, .config = canonical, .type = BACKGROUND};
- if (ispipestart || cmd->term == BG) {
+ if (ispipestart || c->term == BG) {
if (!pushjob(&job)) {
note("Unable to add job to background; too many background jobs");
- if (ispipestart) closepipe(cmd);
+ if (ispipestart) closepipe(c);
break;
}
- } else if (cmd->term != PIPE) {
+ } else if (c->term != PIPE) {
if (!setfg(job)) break;
waitfg(job);
}
}
- if (cmd->term == AND && status != EXIT_SUCCESS) break;
- if (cmd->term == OR && status == EXIT_SUCCESS) break;
+ if (c->term == AND && status != EXIT_SUCCESS) break;
+ if (c->term == OR && status == EXIT_SUCCESS) break;
+ } else {
+ if (c->term == AND || c->term == PIPE || c->term == OR) {
+ note("Expected command");
+ break;
+ }
+ if (!c->r) break;
+
+ if ((cpid = fork()) == -1) {
+ note("Unable to fork child process");
+ break;
+ } else if (cpid == 0) {
+ redirectfiles(c->r);
+ exit(EXIT_SUCCESS);
+ }
+ waitpid(cpid, NULL, 0);
+ errno = 0; // waitpid() might set errno
}
setsigchld(&sigchld);
- return 1;
+ return context;
}
extern int status;
-int run(struct context *context);
+PIPELINE(run);
va_start(args, fmt);
(errno ? vwarn : vwarnx)(fmt, args);
va_end(args);
- putchar('\r');
+ putc('\r', stderr);
errno = 0;
}
va_start(args, fmt);
(errno ? vwarn : vwarnx)(fmt, args);
va_end(args);
- putchar('\r');
+ putc('\r', stderr);
exit(EXIT_FAILURE);
}
-void initialize(void) {
+void init(void) {
char *shlvlstr, buffer[19 + 1];
long shlvl;
- initterm();
-
if (!(home = getenv("HOME")))
fatal("Unable to locate user's home directory, $HOME$ not set");
if (!(shlvlstr = getenv("SHLVL"))) shlvlstr = "0";
if ((shlvl = strtol(shlvlstr, NULL, 10)) < 0) shlvl = 0;
- sprintf(shlvlstr = buffer, "%ld", shlvl + 1);
- if (setenv("SHLVL", shlvlstr, 1) == -1)
+ sprintf(buffer, "%ld", shlvl + 1);
+ if (setenv("SHLVL", buffer, 1) == -1)
note("Unable to update $SHLVL$ environment variable");
- if (interactive) readhistory();
+ initfg();
initjobs();
+ if (interactive) inithistory();
}
char *catpath(char *dir, char *filename, char *buffer) {
return buffer;
}
-void deinitialize(void) {
- deinitterm();
-
- if (interactive) writehistory();
+void deinit(void) {
+ if (interactive) deinithistory();
+ deinitfg();
}
void note(char *fmt, ...);
void fatal(char *fmt, ...);
-void initialize(void);
+void init(void);
char *catpath(char *dir, char *filename, char *buffer);
-void deinitialize(void);
+void deinit(void);