C 如何使用fork()打开新的终端窗口?
在我的程序中,我调用函数fork(),然后我希望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>
/*
* 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);