[ create a new paste ] login | about

Link: http://codepad.org/hBrx6VoE    [ raw code | output | fork ]

C, pasted on Jan 16:
#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 */


Output:
1
> 


Create a new paste based on this one


Comments: