2017-05-14 16 views
0

J'ai une question concernant execlp() dans c.L'utilisation de execlp() dans un c-programme

Je le programm suivant:

#include <stdio.h> 
#include <unistd.h> 
#include <sys/unistd.h> 
#include <sys/types.h> 
#include <pwd.h> 
#include <stdlib.h> 
#include <limits.h> 
#include <signal.h> 

void INThandler(int); 

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

    struct passwd *pwd; 
    char *lgn; 
    char *cwd; 
    char buff[PATH_MAX + 1]; 
    char s1[10], s2[10]; 

    /*Um den Namen zu bekommen*/ 
    lgn = getlogin(); 
    pwd = getpwnam(lgn); 

    /*Um den Hostnamen zu bekommen*/ 
    char hostname[128]; 
    gethostname(hostname, sizeof hostname); 

    /*Um das Arbeitsverzeichnis zu bekommen*/ 
    cwd = getcwd(buff, PATH_MAX + 1); 
    if((cwd!=NULL)&& hostname!=NULL && ((lgn=getlogin())!=NULL || 
(pwd!=NULL))) 
    { 
     signal(SIGINT, INThandler); 
     while(1) 
     { 
      printf("%[email protected]%s %s$", pwd->pw_name, hostname, cwd); 
      if(scanf("%s %s",s1, s2)<1) 
      return 1; 
      printf("Befehl: %s\nArgument: %s\n",s1,s2); 
      execlp(s1, s1, NULL); 
      printf("Zhopa"); 
      return 1; 
     } 

    } 
    return 0; 
} 

void INThandler(int sig) { 
    char c; 

    signal(sig, SIG_IGN); 
    printf("Wollen Sie Program Verlassen? [y/n]"); 

    c = getchar(); 
    if(c == 'y' || c=='Y') 
    exit(0); 
    else 
    signal(SIGINT, INThandler); 
    getchar(); 
} 

il doit imprimer le utilisateur nom @ dossier hostname $ et prendre une commande linux comme argument « ls -al » après qu'il devrait commencer avec execlp (), mais cela ne fonctionne pas comme je le pense.

J'ai lu tous les articles ici concernant cette commande, mais je suppose, je ne comprends toujours pas, comment l'utiliser.

J'apprécierais l'aide de quelqu'un.

+2

* "ça ne marche pas comme je le pense" * signifie quoi exactement? - Notez que execlp * remplace * l'image de processus. Il ne retourne jamais à votre programme. Jetez un oeil à http://stackoverflow.com/questions/16206961/c-program-exits-on-executing-execlp-fonction –

+0

autant que je comprends, si je donne à execlp() ces chaînes s1, s2 (que serait execlp (s1, s2, NULL), s1 = "ls", s2 = "-al"), alors il devrait lancer ls -al – Natalya

+0

Est-ce correct? – Natalya

Répondre

1

Vous devez créer un nouveau processus avec fork() puis, dans le nouveau processus (enfant), utiliser le execlp. Voici l exemple de code. Il ne gère pas d'erreur et il fonctionne avec une commande avec exactement 1 paramètre parce que ce que je l'ai compris (par exemple. ls -all)

#include <stdio.h> 
#include <unistd.h> 
#include <sys/unistd.h> 
#include <sys/wait.h> /*Lib for waitpid*/ 
#include <sys/types.h> 
#include <pwd.h> 
#include <stdlib.h> 
#include <limits.h> 
#include <signal.h> 

void INThandler(int); 

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

    int pid = 0; /*PROCESS ID*/ 
    struct passwd *pwd; 
    char *lgn; 
    char *cwd; 
    char buff[PATH_MAX + 1]; 
    char s1[10], s2[10]; 

    /*Um den Namen zu bekommen*/ 
    lgn = getlogin(); 
    pwd = getpwnam(lgn); 

    /*Um den Hostnamen zu bekommen*/ 
    char hostname[128]; 
    gethostname(hostname, sizeof hostname); 

    /*Um das Arbeitsverzeichnis zu bekommen*/ 
    cwd = getcwd(buff, PATH_MAX + 1); 
    if((cwd!=NULL)&& hostname!=NULL && ((lgn=getlogin())!=NULL || 
(pwd!=NULL))) 
    { 
     signal(SIGINT, INThandler); 
     while(1) 
     { 
      printf("%[email protected]%s %s$", pwd->pw_name, hostname, cwd); 
      if(scanf("%s %s",s1, s2)<1) 
      return 1; 
      printf("Befehl: %s\nArgument: %s\n",s1,s2); 
      pid = fork(); 
      if(pid == 0){ /*Child*/ 
      execlp(s1, s1, s2,(char*) NULL); 
      }else if(pid > 0){ /*Father*/ 
      /*father waiting for the child*/ 
      waitpid(pid,NULL,0); 
      } 
      printf("Zhopa"); 
     } 

    } 
    return 0; 
} 

void INThandler(int sig) { 
    char c; 

    signal(sig, SIG_IGN); 
    printf("Wollen Sie Program Verlassen? [y/n]"); 

    c = getchar(); 
    if(c == 'y' || c=='Y') 
    exit(0); 
    else 
    signal(SIGINT, INThandler); 
    getchar(); 
} 
1

Votre gestionnaire de signal appelle un comportement non défini.

Vous pouvez uniquement appeler des fonctions de signal asynchrone à partir d'un gestionnaire de signal. Per the POSIX standard:

... le comportement est indéfini ... si le gestionnaire appelle une fonction de signal défini dans cette autre norme que l'une des fonctions énumérés dans le tableau suivant.

Le tableau suivant définit un ensemble de fonctions qui doivent être async-safe-signal. Par conséquent, les applications peuvent les appeler, sans restriction , à partir de fonctions de capture de signaux. ...

[Table des fonctions signaux asynchrones de sécurité]

Toute fonction pas dans le tableau ci-dessus peut être dangereux par rapport aux signaux. ...

Ce gestionnaire signal de

void INThandler(int sig) { 
    char c; 

    signal(sig, SIG_IGN); 
    printf("Wollen Sie Program Verlassen? [y/n]"); 

    c = getchar(); 
    if(c == 'y' || c=='Y') 
    exit(0); 
    else 
    signal(SIGINT, INThandler); 
    getchar(); 
} 

a de multiples fonctions non-async signal sûr en elle:

  • printf()
  • getchar()
  • exit()

Ces fonctions ne peuvent pas être appelées en toute sécurité depuis un gestionnaire de signal.

Compte tenu de votre code, un endroit probable pour que ce gestionnaire de signal soit appelé serait lorsque le processus est bloqué en scanf() - en essayant de lire stdin. Cela implique probablement une serrure ou un mutex quelconque. Pourtant, votre gestionnaire de signal appelle getchar() qui essaie également de lire à stdin, qui peut être verrouillé ou dans un état indéterminé.Si le thread principal est bloqué dans scanf(), l'appel asynchrone à getchar() dans le gestionnaire de signal peut bloquer ou corrompre les structures internes utilisées pour stdin.