void ClientThread::SubProcess(const char *ttyName) { struct termios termbuf; //子进程开始执行 setenv("TERM", this->type.c_str(), 1); setsid(); close(0); int ttyfd = open(ttyName, O_RDWR, 0666); dup2(0, 1); dup2(0, 2); int pid = getpid(); tcsetpgrp(0, pid); /* switch this tty's process group to us */ tcgetattr(0, &termbuf); termbuf.c_lflag |= ECHO; termbuf.c_oflag |= ONLCR | XTABS; termbuf.c_iflag |= ICRNL; termbuf.c_iflag &= ~IXOFF; /*termbuf.c_lflag &= ~ICANON;*/ tcsetattr(STDIN_FILENO, TCSANOW, &termbuf); print_login_issue("/etc/issue.net", ttyName); //启动登陆程序 char login[] = "/bin/login"; char *login_argv[2] = { login, NULL }; execvp("/bin/login", (char**) (login_argv)); }
/* We rely on that there is space in the buffer for now. */ char *b = ts->buf2 + ts->rdidx2; *b++ = IAC; *b++ = command; *b++ = option; ts->rdidx2 += 3; ts->size2 += 3; } static struct tsession * #ifdef CONFIG_FEATURE_TELNETD_INETD make_new_session(void) #else /* CONFIG_FEATURE_TELNETD_INETD */ make_new_session(int sockfd) #endif /* CONFIG_FEATURE_TELNETD_INETD */ { struct termios termbuf; int pty, pid; char tty_name[32]; struct tsession *ts = malloc(sizeof(struct tsession) + BUFSIZE * 2); ts->buf1 = (char *)(&ts[1]); ts->buf2 = ts->buf1 + BUFSIZE; #ifdef CONFIG_FEATURE_TELNETD_INETD ts->sockfd_read = 0; ts->sockfd_write = 1; #else /* CONFIG_FEATURE_TELNETD_INETD */ ts->sockfd = sockfd; #endif /* CONFIG_FEATURE_TELNETD_INETD */ ts->rdidx1 = ts->wridx1 = ts->size1 = 0; ts->rdidx2 = ts->wridx2 = ts->size2 = 0; #ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT /* initialize it with the timeout value*/ ts->timeout_time = time(NULL) + TIMEOUT; #endif /* CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT */ /* Got a new connection, set up a tty and spawn a shell. */ pty = getpty(tty_name); if (pty < 0) { syslog(LOG_ERR, "All network ports in use!"); return 0; } if (pty > maxfd) maxfd = pty; ts->ptyfd = pty; /* Make the telnet client understand we will echo characters so it * should not do it locally. We don't tell the client to run linemode, * because we want to handle line editing and tab completion and other * stuff that requires char-by-char support. */ send_iac(ts, DO, TELOPT_ECHO); send_iac(ts, DO, TELOPT_NAWS); send_iac(ts, DO, TELOPT_LFLOW); send_iac(ts, WILL, TELOPT_ECHO); send_iac(ts, WILL, TELOPT_SGA); if ((pid = fork()) < 0) { syslog(LOG_ERR, "Can`t forking"); } if (pid == 0) { /* In child, open the child's side of the tty. */ int i; for(i = 0; i <= maxfd; i++) close(i); /* make new process group */ setsid(); if (open(tty_name, O_RDWR /*| O_NOCTTY*/) < 0) { syslog(LOG_ERR, "Could not open tty"); exit(1); } dup(0); dup(0); tcsetpgrp(0, getpid()); /* The pseudo-terminal allocated to the client is configured to operate in * cooked mode, and with XTABS CRMOD enabled (see tty(4)). */ tcgetattr(0, &termbuf); termbuf.c_lflag |= ECHO; /* if we use readline we dont want this */ termbuf.c_oflag |= ONLCR|XTABS; termbuf.c_iflag |= ICRNL; termbuf.c_iflag &= ~IXOFF; /*termbuf.c_lflag &= ~ICANON;*/ tcsetattr(0, TCSANOW, &termbuf); print_login_issue(issuefile, NULL); /* exec shell, with correct argv and env */ execv(loginpath, (char *const *)argv_init); /* NOT REACHED */ syslog(LOG_ERR, "execv error"); exit(1); } ts->shell_pid = pid; return ts; }