#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
void prep_exe(char *sttp, char **path, char ***argv)
{
char *p;
char *endp;
char *commendp, *infile, *outfile;
int max, i;
int fd_in, fd_out;
int f_infile, f_outfile;
for (p = sttp; *p != '\0'; p++)
;
commendp = endp = p;
i = 0;
f_infile = f_outfile = 0;
p = sttp;
while (p < endp) {
if (*p == '<') {
if (p < commendp)
commendp = p;
*p = 0;
f_infile = 1;
for (p++; p < endp && *p == ' '; p++)
;
if (p < endp) {
infile = p;
for (; p < endp && *p != ' '; p++)
;
*p = 0;
}
p++;
} else if (*p == '>') {
if (p < commendp)
commendp = p;
*p = 0;
f_outfile = 1;
for (p++; p < endp && *p == ' '; p++)
;
if (p < endp) {
outfile = p;
for (; p < endp && *p != ' '; p++)
;
*p = 0;
}
p++;
} else if (!f_infile && !f_outfile && *p == ' ') {
*p = '\0';
p++;
i++;
for (;*p == ' '; p++)
;
} else {
p++;
}
}
max = i + 3;
*argv = malloc(sizeof(char *) * max);
*path = sttp;
(*argv)[0] = sttp;
i = 1;
for (p = sttp; p < commendp; p++) {
if (*p == '\0') {
p++;
for (;*p == ' '; p++)
;
if (p < commendp)
(*argv)[i++] = p;
}
}
(*argv)[i] = NULL;
if (f_infile) {
fd_in = open(infile, O_RDONLY);
if (fd_in) {
dup2(fd_in, 0);
close(fd_in);
}
}
if (f_outfile) {
fd_out = open(outfile, O_RDWR | O_CREAT, 0666);
if (fd_out) {
dup2(fd_out, 1);
close(fd_out);
}
}
return;
}
char *cut(char *comline, char *last)
{
char *p;
for (p = last; *p != '|' && p > comline; p--)
;
if (p > comline) {
*p = '\0';
for (p++; *p == ' '; p++)
;
return p;
} else {
return p;
}
}
struct list {
char *path;
struct list *next;
};
void task(char *comline, struct list *env)
{
struct list *n;
char *endpos, *p, *path, *fullpath, **argv, *q, **t;
int pid, status;
int fd[2];
for (p = comline; *p != '\0'; p++)
;
p = cut(comline, p);
endpos = p;
if (fork() == 0) {
for (;;) {
if (p < endpos) {
dup2(fd[1], 1);
close(fd[1]);
close(fd[0]);
}
if (p > comline) {
pipe(fd);
if ((pid = fork()) == 0) {
p = cut(comline, p);
continue;
} else {
dup2(fd[0], 0);
close(fd[0]);
close(fd[1]);
prep_exe(p, &path, &argv);
for (n = env; n; n = n->next) {
fullpath = malloc(strlen(n->path) + strlen(path) + 2);
strcpy(fullpath, n->path);
for (q = fullpath; *q; q++)
;
if (*--q != '/')
strcat(fullpath, "/");
strcat(fullpath, path);
execv(fullpath, argv);
/* not reached if no error */
free(fullpath);
}
fprintf(stderr, "cannot found(2) %s\n", path);
exit(-1);
}
} else {
prep_exe(p, &path, &argv);
for (n = env; n; n = n->next) {
fullpath = malloc(strlen(n->path) + strlen(path) + 2);
strcpy(fullpath, n->path);
for (q = fullpath; *q; q++)
;
if (*--q != '/')
strcat(fullpath, "/");
strcat(fullpath, path);
execv(fullpath, argv);
/* not reached if no error */
free(fullpath);
}
fprintf(stderr, "cannot found(1) %s\n", path);
exit(-1);
}
} /* for (;;) */
} else {
wait(&status);
fflush(stdout);
sleep(1);
putchar('\n');
}
}
#define BUFFSIZE 1024 /* >= 2 */
char *getline(FILE *fp)
{
static char inbuff[BUFFSIZE];
char *outbuff_malloc, *tmpbuff;
char *p, *q;
int fEOL;
if ((outbuff_malloc = malloc(1)) == NULL) {
return NULL;
}
*outbuff_malloc = '\0';
fEOL = 0;
do {
if ((q = fgets(inbuff, BUFFSIZE, fp)) == NULL)
break;
for (p = inbuff; *p != '\0'; p++)
;
if (*(p - 1) == '\n') {
*(p - 1) = '\0';
fEOL = 1;
}
if ((tmpbuff = realloc(outbuff_malloc, strlen(outbuff_malloc) + strlen(inbuff) + 1)) ==NULL) {
free(outbuff_malloc);
return NULL;
}
strcat(tmpbuff, inbuff);
outbuff_malloc = tmpbuff;
} while (!fEOL);
if (q == NULL) {
free(outbuff_malloc);
return NULL;
}
return outbuff_malloc;
}
void addlist(struct list **root, char *path) {
struct list *p;
p = malloc(sizeof(struct list));
p->path = malloc(strlen(path) + 1);
strcpy(p->path, path);
p->next = *root;
*root = p;
}
void release(struct list *root) {
if (root != NULL) {
free(root->path);
release(root->next);
free(root);
}
}
void setpath(FILE *fp, struct list **root) {
int s;
struct list *n;
char *p, *q, *r;
while ((p = getline(fp)) != NULL) {
s = strlen(p);
for (q = p; q < p + s; q++) {
for (r = q; *r && *r != ';'; r++)
;
*r = '\0';
addlist(root, q);
q = r;
}
free(p);
}
if (*root != NULL) {
for (n = *root; n != NULL; n = n->next) {
printf("path >%s\n", n->path);
}
}
}
void sigcatch(int sig) {
fprintf(stderr, "Ctrl+C entered.\n");
}
int main(int argc, char *argv[])
{
char *inputLine_malloc;
FILE *fp;
struct list *env = NULL;
if (argc == 1 && (fp = fopen(".path", "r")) != NULL)
setpath(fp, &env);
else if (argc == 2 && (fp = fopen(argv[1], "r")) != NULL)
setpath(fp, &env);
signal(SIGINT, sigcatch);
for (;;) {
fflush(stdout);
printf("> ");
if ((inputLine_malloc = getline(stdin)) == NULL) {
break;
}
if (strstr(inputLine_malloc, "exit") != NULL) {
free(inputLine_malloc);
break;
} else {
task(inputLine_malloc, env);
free(inputLine_malloc); /* NULL ok */
}
}
release(env);
return 0;
}
/* end */