From 0e8fd3398771da2f016d72830179507f3edda51b Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Sat, 4 May 1996 07:50:46 +0000 Subject: Initial version imported to CVS (This used to be commit 291551d80711daab7b7581720bcd9a08d6096517) --- source3/smbd/vt_mode.c | 496 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 496 insertions(+) create mode 100644 source3/smbd/vt_mode.c (limited to 'source3/smbd/vt_mode.c') diff --git a/source3/smbd/vt_mode.c b/source3/smbd/vt_mode.c new file mode 100644 index 0000000000..83b62a38ac --- /dev/null +++ b/source3/smbd/vt_mode.c @@ -0,0 +1,496 @@ +/* vt_mode.c */ +/* +support vtp-sessions + +written by Christian A. Lademann +*/ + +/* +02.05.95:cal:ported to samba-1.9.13 +*/ + +#define __vt_mode_c__ + + +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ + +#include "includes.h" +#include "vt_mode.h" +#include + +#ifdef SCO + extern char *strdup(); +#endif + +extern int Client; + +#ifdef LINUX +# define HAS_VTY +#endif + +#ifdef SCO +# define HAS_PTY +# define HAS_VTY + +# include +#endif + +extern int DEBUGLEVEL; +extern char *InBuffer, *OutBuffer; +extern int done_become_user; + +char master_name [64], slave_name [64]; +int master, slave, i, o, e; + +int ms_type = MS_NONE, + ms_poll = 0; + + +/* +VT_Check: test incoming packet for "vtp" or "iVT1\0" +*/ +int VT_Check(buffer) +char *buffer; +{ + DEBUG(3,("Checking packet: <%10s...>\n", buffer+4)); + if((strncmp(buffer+4, "vtp", 3) == 0 && smb_len(buffer) == 3) || (strncmp(buffer+4, "iVT1\0", 5) == 0 && smb_len(buffer) == 5)) + return(1); + else + return(0); +} + + +/* +VT_Start_utmp: prepare /etc/utmp for /bin/login +*/ +VT_Start_utmp() +{ + struct utmp u, *v; + char *tt; + + + setutent(); + + strcpy(u.ut_line, VT_Line); + + if((v = getutline(&u)) == NULL) { + if(strncmp(VT_Line, "tty", 3) == 0) + tt = VT_Line + 3; + else if(strlen(VT_Line) > 4) + tt = VT_Line + strlen(VT_Line) - 4; + else + tt = VT_Line; + + strcpy(u.ut_id, tt); + u.ut_time = time((time_t*)0); + } + + strcpy(u.ut_user, "LOGIN"); + strcpy(u.ut_line, VT_Line); + u.ut_pid = getpid(); + u.ut_type = LOGIN_PROCESS; + pututline(&u); + + endutent(); + + return(0); +} + + +/* +VT_Stop_utmp: prepare /etc/utmp for other processes +*/ +VT_Stop_utmp() +{ + struct utmp u, *v; + + + if(VT_Line != NULL) { + setutent(); + + strcpy(u.ut_line, VT_Line); + + if((v = getutline(&u)) != NULL) { + strcpy(v->ut_user, ""); + v->ut_type = DEAD_PROCESS; + v->ut_time = time((time_t*)0); + pututline(v); + } + + endutent(); + } + + return(0); +} + + +/* +VT_AtExit: Things to do when the program exits +*/ +void VT_AtExit() +{ + if(VT_ChildPID > 0) { + kill(VT_ChildPID, SIGHUP); + (void)wait(NULL); + } + + VT_Stop_utmp(); +} + + +/* +VT_SigCLD: signalhandler for SIGCLD: set flag if child-process died +*/ +void VT_SigCLD(sig) +int sig; +{ + if(wait(NULL) == VT_ChildPID) + VT_ChildDied = True; + else + signal(SIGCLD, VT_SigCLD); +} + + +/* +VT_SigEXIT: signalhandler for signals that cause the process to exit +*/ +void VT_SigEXIT(sig) +int sig; +{ + VT_AtExit(); + + exit(1); +} + + +/* +VT_Start: initialize vt-specific data, alloc pty, spawn shell and send ACK +*/ +int VT_Start() +{ + char OutBuf [64], *X, *Y; + + + ms_type = MS_NONE; + master = slave = -1; + +#ifdef HAS_VTY +#ifdef LINUX +# define MASTER_TMPL "/dev/pty " +# define SLAVE_TMPL "/dev/tty " +# define LETTER1 "pqrs" +# define POS1 8 +# define LETTER2 "0123456789abcdef" +# define POS2 9 +#endif + +#ifdef SCO +# define MASTER_TMPL "/dev/ptyp_ " +# define SLAVE_TMPL "/dev/ttyp_ " +# define LETTER1 "0123456" +# define POS1 10 +# define LETTER2 "0123456789abcdef" +# define POS2 11 +#endif + + if(ms_poll == MS_VTY || ms_poll == 0) { + strcpy(master_name, MASTER_TMPL); + strcpy(slave_name, SLAVE_TMPL); + + for(X = LETTER1; *X && master < 0; X++) + for(Y = LETTER2; *Y && master < 0; Y++) { + master_name [POS1] = *X; + master_name [POS2] = *Y; + if((master = open(master_name, O_RDWR)) >= 0) { + slave_name [POS1] = *X; + slave_name [POS2] = *Y; + if((slave = open(slave_name, O_RDWR)) < 0) + close(master); + } + } + + if(master >= 0 && slave >= 0) + ms_type = MS_VTY; + } + +# undef MASTER_TMPL +# undef SLAVE_TMPL +# undef LETTER1 +# undef LETTER2 +# undef POS1 +# undef POS2 +#endif + + +#ifdef HAS_PTY +#ifdef SCO +# define MASTER_TMPL "/dev/ptyp%d" +# define SLAVE_TMPL "/dev/ttyp%d" +# define MIN_I 0 +# define MAX_I 63 +#endif + + if(ms_poll == MS_PTY || ms_poll == 0) { + int i; + + for(i = MIN_I; i <= MAX_I && master < 0; i++) { + sprintf(master_name, MASTER_TMPL, i); + if((master = open(master_name, O_RDWR)) >= 0) { + sprintf(slave_name, SLAVE_TMPL, i); + if((slave = open(slave_name, O_RDWR)) < 0) + close(master); + } + } + + if(master >= 0 && slave >= 0) + ms_type = MS_PTY; + } + +# undef MASTER_TMPL +# undef SLAVE_TMPL +# undef MIN_I +# undef MAX_I +#endif + + + if(! ms_type) + return(-1); + + VT_Line = strdup(strrchr(slave_name, '/') + 1); + + switch((VT_ChildPID = fork())) { + case -1: + return(-1); + break; + + case 0: +#ifdef SCO + setsid(); +#endif + close(0); + close(1); + close(2); + + i = open(slave_name, O_RDWR); + o = open(slave_name, O_RDWR); + e = open(slave_name, O_RDWR); + +#ifdef LINUX + setsid(); + if (ioctl(slave, TIOCSCTTY, (char *)NULL) == -1) + exit(1); +#endif +#ifdef SCO + tcsetpgrp(0, getpid()); +#endif + + VT_Start_utmp(); + + system("stty sane"); + execlp("/bin/login", "login", "-c", (char*)0); + exit(1); + break; + + default: + VT_Mode = True; + VT_Status = VT_OPEN; + VT_ChildDied = False; + VT_Fd = master; + + signal(SIGCLD, VT_SigCLD); + + signal(SIGHUP, VT_SigEXIT); + signal(SIGTERM, VT_SigEXIT); + signal(SIGINT, VT_SigEXIT); + signal(SIGQUIT, VT_SigEXIT); + + memset(OutBuf, 0, sizeof(OutBuf)); + OutBuf [4] = 0x06; + _smb_setlen(OutBuf, 1); + + send_smb(Client,OutBuf); + + return(0); + break; + } +} + + +/* +VT_Output: transport data from socket to pty +*/ +int VT_Output(Buffer) +char *Buffer; +{ + int i, len, nb; + + + if(VT_Status != VT_OPEN) + return(-1); + + len = smb_len(Buffer); + + nb = write(VT_Fd, Buffer + 4, len); + + return((nb == len) ? 0 : -1); +} + + +/* +VT_Input: transport data from pty to socket +*/ +int VT_Input(Buffer, Size) +char *Buffer; +int Size; +{ + int len; + + + if(VT_Status != VT_OPEN) + return(-1); + + memset(Buffer, 0, Size); + len = read(VT_Fd, Buffer + 4, MIN(VT_MAXREAD, Size)); + + _smb_setlen(Buffer, len); + + return(len + 4); +} + + +/* +VT_Process: main loop while in vt-mode +*/ +void VT_Process() +{ + static int trans_num = 0; + extern int Client; + int nread; + + + VT_Start(); + + atexit(VT_AtExit); + + while (True) { + int32 len; + int msg_type; + int msg_flags; + int counter; + int last_keepalive=0; + struct fd_set si; + struct timeval to, *top; + int n, ret, t; + + + errno = 0; + t = SMBD_SELECT_LOOP*1000; + + + FD_ZERO(&si); + FD_SET(Client, &si); + + FD_SET(VT_Fd, &si); + + if(t >= 0) { + to.tv_sec = t / 1000; + to.tv_usec = t - (to.tv_sec * 1000); + + top = &to; + } else + top = NULL; + + if(VT_ChildDied) + goto leave_VT_Process; + + n = select(MAX(VT_Fd, Client) + 1, &si, NULL, NULL, top); + + if(VT_ChildDied) + goto leave_VT_Process; + + if(n == 0) { + int i; + time_t t; + BOOL allidle = True; + extern int keepalive; + + counter += SMBD_SELECT_LOOP; + + t = time(NULL); + + if (keepalive && (counter-last_keepalive)>keepalive) { + if (!send_keepalive(Client)) + goto leave_VT_Process; + last_keepalive = counter; + } + } else if(n > 0) { + counter = 0; + + if(FD_ISSET(VT_Fd, &si)) { + /* got input from vt */ + nread = VT_Input(OutBuffer, MIN(BUFFER_SIZE,lp_maxxmit())); + + if(nread > 0) + send_smb(Client,OutBuffer); + } + + if(FD_ISSET(Client, &si)) { + /* got input from socket */ + + if(receive_smb(Client,InBuffer, 0)) { + msg_type = CVAL(InBuffer,0); + msg_flags = CVAL(InBuffer,1); + + len = smb_len(InBuffer); + + DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); + + nread = len + 4; + + DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); + + if(msg_type == 0) + VT_Output(InBuffer); + else { + nread = construct_reply(InBuffer,OutBuffer,nread,MIN(BUFFER_SIZE,lp_maxxmit())); + + if(nread > 0) { + if (nread != smb_len(OutBuffer) + 4) { + DEBUG(0,("ERROR: Invalid message response size! %d %d\n", + nread, + smb_len(OutBuffer))); + } else + send_smb(Client,OutBuffer); + } + } + } else + if(errno == EBADF) + goto leave_VT_Process; + } + } + + trans_num++; + } + + leave_VT_Process: +/* + if(VT_ChildPID > 0) + kill(VT_ChildPID, SIGHUP); + + VT_Stop_utmp(VT_Line); + return; +*/ + close_sockets(); + exit(0); +} -- cgit