2017-04-21 1 views
1

J'ai un projet pour copier des commandes shell sur C. L'une des commandes est | ce qui doit être fait en utilisant la tuyauterie. Mes autres commandes fonctionnent mais je n'ai pas réussi à faire fonctionner (ls | sort). Il dit que ls ne peuvent pas accéder |: Aucun fichier ou répertoire ls ne peuvent pas accéder tri: Aucun fichier ou répertoireTuyauterie sans création de descripteurs de tuyau spécifiques

J'espérais que quelqu'un pourrait me aider à comprendre comment résoudre le problème de la tuyauterie? Il a commencé par essayer de faire en sorte que je n'aurais pas à faire un tuyau séparé pour chaque commande, donc je l'ai couru à travers une boucle for.

La fonction qui exécute le plus de travail est exécutée. Runsource et Rundest font l'ouverture et le transfert de l'information dans le tuyau.

void execute(char *cmdline) 
{ 
    int pid, async; 
    char *args[MAX_ARGS]; 
    char *pargs[MAX_ARGS]; 
    int i = 1; 
    int j; 

    int nargs = get_args(cmdline, args); 
    if (nargs <= 0) 
     return; 

    if (!strcmp(args[0], "quit") || !strcmp(args[0], "exit")) 
    { 
     exit(0); 
    } 

    int npargs = get_pipe(cmdline, pargs); 
    if (npargs > 1) 
    { 
     int pdes[2]; 
     pipe(pdes); 

     for (j = 0; i < npargs; j++) 
     { 
      nargs = get_args(pargs[j], pargs); 
      runsource(pdes, j, pargs, npargs); 
      rundest(pdes, j + 1, pargs, npargs); 
      close(pdes[0]); 
      close(pdes[1]); 
     } 
    } 
    else 
    { 
     while (args[i] < args[nargs]) 
     { 
      if (strcmp(args[i], ">")) 
      { 
       freopen(args[i + 1], "w", stdout); 
       args[i] = NULL; 
      } 

      if (strcmp(args[i], ">>")) 
      { 
       freopen(args[i + 1], "a", stdout); 
       args[i] = NULL; 
      } 

      if (strcmp(args[i], "<")) 
      { 
       freopen(args[i + 1], "r", stdin); 
       args[i] = NULL; 
      } 
     } 
    } 


    /* check if async call */ 
    if (!strcmp(args[nargs - 1], "&")) 
    { 
     async = 1; 
     args[--nargs] = 0; 
    } 
    else 
     async = 0; 

    pid = fork(); 
    if (pid == 0) /* child process */ 
    { 
     execvp(args[0], args); 
/* return only when exec fails */ 
     perror("exec failed"); 
     exit(-1); 
    } 
    else if (pid > 0) /* parent process */ 
    { 
     if (!async) 
      waitpid(pid, NULL, 0); 
     else 
      printf("this is an async call\n"); 
    } 
    else /* error occurred */ 
    { 
     perror("fork failed"); 
     exit(1); 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    char cmdline[BUFFSIZE]; 

    for (; ;) 
    { 
     printf("COP4338$ "); 
     if (fgets(cmdline, BUFFSIZE, stdin) == NULL) 
     { 
      perror("fgets failed"); 
      exit(1); 
     } 
     execute(cmdline); 
    } 
    return 0; 
} 
+0

Assurez-vous que vous n'avez aucun onglet dans le code que vous copiez et collez puis indentez. Ça fait un gâchis. –

+0

Oui, vous devez connaître le canal avant de traiter la commande avant ou après le canal. Vous appelez une fonction 'get_pipe()' mais ne l'incluez pas dans la question. Il y a aussi d'autres fonctions manquantes. Ce n'est pas un MCVE ([MCVE]). Il est difficile de savoir ce que fait votre fonction 'get_pipe()'. Vous en avez besoin pour diviser 'ls -l | trier -k2n -k5n | sed 's/*// g' | less' en 4 ensembles distincts de commandes et d'arguments, et le pipe n'apparaîtra dans aucune des listes d'arguments. La commande 'sed' n'a besoin que de deux arguments, et pas de guillemets (les shells les suppriment). Vous pouvez ignorer les arguments argumentés. –

Répondre

0

Je vois que vous avez un code spécial pour gérer les symboles « < » et « > », mais je ne vois pas de code dans votre réponse qui gère « | », alors comment vous ont même été à attendre travail? Le problème maintenant est que vous passez "|" comme un argument à ls, alors qu'en fait vous devriez exécuter la chose après le tuyau en tant que commande envoyant la sortie standard de ls à l'entrée standard de cette commande. Pourquoi essayez-vous d'inventer un shell à partir de zéro en analysant les données et en configurant les tuyaux manuellement? Ne pouvez-vous pas simplement utiliser system() pour exécuter une commande shell à la place?

+0

N'auriez-vous pas à connaître le "|" était là avant que vous exécutiez ls parce que alors il courrait et enverrait à la norme dehors quand plutôt je voudrais l'envoyer à la commande suivante –

+0

Également un des points principaux des affectations était d'intégrer la tuyauterie dedans. J'ai juste du mal à faire du code qui peut être pipé quand il faut plutôt que de coder manuellement les pipes. –

+0

Non, tout le point de l'appel 'system()' est qu'il exécute la commande avec votre shell ('/ bin/sh 'Selon la documentation à laquelle je suis lié dans ma réponse. Votre shell va analyser le personnage de pipe et faire le truc approprié, parce que c'est l'une des choses principales que les shells sont censés faire. Si c'est un devoir, l'enseignant a-t-il explicitement dit que vous ne pouvez pas utiliser 'system()' ou exécuter un shell externe comme sh ou bash? –