如何使用fork()打开一个新的终端窗口?

问题描述:

在我的程序中,我调用函数fork(),然后我想要fork创建的子进程打开一个新的终端窗口。 这是我现在所拥有的代码:如何使用fork()打开一个新的终端窗口?

 /* 
    * Shows user info from local pwfile. 
    * 
    * Usage: userinfo username 
    */ 

    #define _XOPEN_SOURCE 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    #include "pwdblib.h" /* include header declarations for pwdblib.c */ 
    #include <pwd.h> 
    #include <unistd.h> 
    #define _XOPEN_SOURCE  /* See feature_test_macros(7) */ 
    #include <unistd.h> 



    /* Define some constants. */ 
    #define USERNAME_SIZE (32) 
    #define NOUSER (-1) 


    int print_info(const char *username) 
    { 
     struct pwdb_passwd *p = pwdb_getpwnam(username); 
     if (p != NULL) { 
     printf("Name: %s\n", p->pw_name); 
     printf("Passwd: %s\n", p->pw_passwd); 
     printf("Uid: %u\n", p->pw_uid); 
     printf("Gid: %u\n", p->pw_gid); 
     printf("Real name: %s\n", p->pw_gecos); 
     printf("Home dir: %s\n",p->pw_dir); 
     printf("Shell: %s\n", p->pw_shell); 
     return 0; 
     } else { 
     return NOUSER; 
     } 
    } 

    int user_authentication(const char *username , const char *password){ 

    struct pwdb_passwd *pw_entry; 
    char *salt = malloc(2);  // Allocate 2 bytes of memory for the salt variable 
    int pwdcmp; // return value after comparison 
    char *pwdcrypt; //the hashed password 
    pw_entry = pwdb_getpwnam(username); // get struct line for username in pwfile 

    if(pw_entry != NULL){  //If the structure exist 
    memcpy(salt, pw_entry->pw_passwd, 2); // Take the 2 first bits of password will be in salt 
    pwdcrypt = crypt(password, salt); // Hashed value 

    pwdcmp = strcmp(pwdcrypt , pw_entry->pw_passwd); // Compare the passwords 

    if(pwdcmp == 0){ // if passwords are correct return 1 
     return 1; 
    } else{ 
    return -1;  // passwords are incorrect 
    } 

    } 

    } 

    void read_username(char *username) 
    { 
     printf("login: "); 
     fgets(username, USERNAME_SIZE, stdin); 

     /* remove the newline included by getline() */ 
     username[strlen(username) - 1] = '\0'; 
    } 

    int main(int argc, char **argv) 
    { 
     char username[USERNAME_SIZE]; 
     char *inputpwd; 
    int login = 0; 
     int pwd_failed;  // Failed login counter 
     int pwd_age; // age of password counter 

     struct pwdb_passwd *pw_entry; 

    /*/ Until successful login, run this loop */ 

     while(login == 0){ 
     signal(2, SIG_IGN); 
     /* 
     * Write "login: " and read user input. Copies the username to the 
     * username variable. 
     */ 
     read_username(username); 





    /* Displays a propt to password, reads in the password */ 
     inputpwd = getpass("Password: "); 


    /*/ Gets the structure of specifik username */ 
     pw_entry = pwdb_getpwnam(username); 

    /*/ Return the age & failed passwords counter*/ 
    pwd_age = pw_entry->pw_age; 
    pwd_failed = pw_entry->pw_failed; 


    /* Check authentication, successful terminates program by login = 1 else 
    * run the program again 
    */ 
     if(user_authentication(username , inputpwd) == 1 && pwd_failed > -1){ 
      printf("User authenticated successfully\n"); 

      if(pwd_age > 2){ 
       printf("Time to change password\n"); 
      } 
      pwd_failed = 0;  // successful login resets failed     atempts 
      pwd_age++; 
      pw_entry->pw_age = pwd_age;  //Update age in file 
      pwdb_update_user(pw_entry);  
      login = 1; 
     pid_t pid; 
     int status; 

     pid = fork(); 

     if (pid==0) { 
      /* This is the child process. Run an xterm window */ 
      execl("/usr/bin/xterm", "xterm", "-e", "yourprogram", NULL); 

      /* if child returns we must inform parent. 
      * Always exit a child process with _exit() and not return() or exit(). 
      */ 
      _exit(-1); 
     } else if (pid < 0) { /* Fork failed */ 
      printf("Fork faild\n"); 
      status = -1; 
     } else { 
      /* This is parent process. Wait for child to complete */ 
      if (waitpid(pid, &status, 0) != pid) { 
      status = -1; 
      } 
     } 
     } 
     else if(user_authentication(username, inputpwd) == -1){ 
      pwd_failed++;  //increase counter by 1 of failedlogins 
      pw_entry->pw_failed = pwd_failed; //update failed counter in file 

      if(pwd_failed > 1){ 
       pwd_failed = -1; 


      } 
      printf("\nWrong password: %s\n", username); 
      pwdb_update_user(pw_entry); 
     return 0; 
     } 

     else{ 
      printf("Unknown user or incorrect password\n"); 
     return 0; 
     } 

     //pw_entry->pw_age = pwd_age;  //Update age in file 
     //pw_entry->pw_failed = pwd_failed; //update failed counter in file 

     pwdb_update_user(pw_entry);  //Update actual file 

    /* Show user info from our local pwfile. */ 
     if (print_info(username) == NOUSER) { 
      /* if there are no user with that usename... */ 
     printf("\nFound no user with name: %s\n", username); 
     return 0; 
    }}} 

我希望发生的是新的终端窗口中运行的功能,我已经实现了我自己。我不太确定如何去解决这个问题,任何人都有一些想法或方向来帮助?

编辑: 我现在编辑了这个问题,以便整个程序可见。以下是程序应该能够做的事情。我不知道如何去任何进一步的...

  • 用户的认证成功后,你的程序应该叉子和启动终端 窗口用户的首选外壳。父进程应该等到孩子 退出,然后再次显示“login:”提示符。
  • 在启动终端窗口之前,子进程应该设置合适的真实有效的 进程用户以及合适的真实有效组。
+0

在什么操作系统上? – 2015-03-02 10:51:22

+0

你可以显示你的完整代码...? – 2015-03-02 10:55:07

execl("/usr/bin/xterm", "xterm", "-e", "yourprogram", NULL);