Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何使用fork()打开新的终端窗口?_C_Terminal_Fork - Fatal编程技术网

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

C 如何使用fork()打开新的终端窗口?,c,terminal,fork,C,Terminal,Fork,在我的程序中,我调用函数fork(),然后我希望fork创建的子进程打开一个新的终端窗口。 这是我现在掌握的代码: /* * Shows user info from local pwfile. * * Usage: userinfo username */ #define _XOPEN_SOURCE #include <stdio.h> #include <stdlib.h>

在我的程序中,我调用函数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;
    }}}
/*
*显示本地文件中的用户信息。
*  
*用法:userinfo用户名
*/
#定义_XOPEN_源
#包括
#包括
#包括
#include“pwdlib.h”/*包含pwdlib.c的头声明*/
#包括
#包括
#定义XOPEN\uSource/*参见功能测试宏(7)*/
#包括
/*定义一些常量*/
#定义用户名大小(32)
#定义NOUSER(-1)
整数打印信息(常量字符*用户名)
{
结构pwdb_passwd*p=pwdb_getpwnam(用户名);
如果(p!=NULL){
printf(“名称:%s\n”,p->pw\u名称);
printf(“密码:%s\n”,p->pw\u密码);
printf(“Uid:%u\n”,p->pw\u Uid);
printf(“Gid:%u\n”,p->pw_Gid);
printf(“实名:%s\n”,p->pw_gecos);
printf(“主目录:%s\n”,p->pw_目录);
printf(“外壳:%s\n”,p->pw_外壳);
返回0;
}否则{
返回零;
}
}
int user_身份验证(常量字符*用户名,常量字符*密码){
结构pwdb_passwd*pw_条目;
char*salt=malloc(2);//为salt变量分配2字节的内存
int pwdcmp;//比较后返回值
char*pwdcrypt;//哈希密码
pw_entry=pwdb_getpwnam(username);//获取pwfile中用户名的结构行
if(pw_entry!=NULL){//如果结构存在
memcpy(salt,pw_entry->pw_passwd,2);//获取密码的前2位将在salt中
pwdcrypt=crypt(密码,salt);//散列值
pwdcmp=strcmp(pwdcrypt,pw_entry->pw_passwd);//比较密码
如果(pwdcmp==0){//如果密码正确,则返回1
返回1;
}否则{
return-1;//密码不正确
}
}
}
无效读取用户名(字符*用户名)
{
printf(“登录:”);
fgets(用户名、用户名大小、标准输入);
/*删除getline()包含的换行符*/
用户名[strlen(username)-1]='\0';
}
int main(int argc,字符**argv)
{
字符用户名[用户名大小];
字符*inputpwd;
int login=0;
int pwd_失败;//登录计数器失败
int pwd_age;//密码计数器的年龄
结构pwdb_passwd*pw_条目;
/*/在成功登录之前,请运行此循环*/
while(login==0){
信号(2,信号);
/* 
*写“登录:”并读取用户输入。将用户名复制到
*用户名变量。
*/
读取用户名(用户名);
/*显示密码提示,读取密码*/
inputpwd=getpass(“密码:”);
/*/获取指定用户名的结构*/
pw_entry=pwdb_getpwnam(用户名);
/*/返回密码过期和失败计数器*/
pwd_年龄=pw_条目->pw_年龄;
pwd_failed=pw_条目->pw_失败;
/*检查身份验证,成功通过login=1终止程序
*再次运行程序
*/
if(用户身份验证(用户名,输入密码)==1&&pwd\u失败>-1){
printf(“用户身份验证成功\n”);
如果(pwd_年龄>2){
printf(“更改密码的时间”);
}
pwd_failed=0;//成功登录重置失败的atempts
pwd_age++;
pw_entry->pw_age=pwd_age;//更新文件中的年龄
pwdb_更新_用户(pw_条目);
登录=1;
pid_t pid;
智力状态;
pid=fork();
如果(pid==0){
/*这是子进程。请运行xterm窗口*/
execl(“/usr/bin/xterm”,“xterm”,“-e”,“yourprogram”,NULL);
/*如果孩子回来,我们必须通知家长。
*始终使用_exit()退出子进程,而不使用return()或exit()。
*/
_出口(-1);
}如果(pid<0){/*Fork失败,则为else*/
printf(“Fork faild\n”);
状态=-1;
}否则{
/*这是父进程。请等待子进程完成*/
if(waitpid(pid,&状态,0)!=pid){
状态=-1;
}
}
}   
else if(用户身份验证(用户名,输入密码)=-1){
pwd_failed++//将计数器增加失败登录的1
pw_entry->pw_failed=pwd_failed;//更新文件中的失败计数器
如果(pwd_失败>1){
pwd_失败=-1;
}
printf(“\n错误密码:%s\n”,用户名);
pwdb_更新_用户(pw_条目);
返回0;
}
否则{
printf(“未知用户或不正确的密码”);
返回0;
}
//pw_entry->pw_age=pwd_age;//更新文件中的年龄
//pw_entry->pw_failed=pwd_failed;//更新文件中的失败计数器
pwdb_update_user(pw_条目);//更新实际文件
/*显示本地PW文件中的用户信息*/
如果(打印信息(用户名)=NOUSER){
/*如果没有具有该usename的用户*/
printf(“\n未找到名称为:%s\n”的用户,用户名);
返回0;
}}}
我想让新的终端窗口运行一个我自己实现的函数。我不太清楚该怎么做,有人有什么想法或方向可以帮忙吗

编辑: 我现在编辑了这个问题,这样整个程序都可以看到。下面是程序应该能够做的。我不知道怎么走得更远

  • 成功验证用户后,程序应分叉并启动终端 带有用户首选外壳的窗口。父进程应该一直等到子进程 退出,然后再次显示“登录:”提示
  • 在启动终端窗口之前,子进程应该设置正确的r
    execl("/usr/bin/xterm", "xterm", "-e", "yourprogram", NULL);