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

时间:2015-03-02 10:49:33

标签: c terminal 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;
    }}}

我想要发生的是新终端窗口运行我自己实现的功能。我不太确定如何解决这个问题,任何人都有一些想法或指示可以提供帮助吗?

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

  • 成功验证用户后,您的程序应该分叉并启动终端 窗口与用户的首选shell。父进程应该等到孩子 退出然后显示&#34;登录:&#34;再次提示。
  • 在启动终端窗口之前,子进程应该设置正确有效 流程的用户,以及正确的真实有效群体。

1 个答案:

答案 0 :(得分:1)

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