home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 July & August / Pcwk78a98.iso / Wtestowe / Clico / UNIX / SAMBA / SOURCE / SAMBA.TAR / samba-1.9.17 / source / vt_mode.c < prev    next >
C/C++ Source or Header  |  1996-06-04  |  8KB  |  491 lines

  1. /* vt_mode.c */
  2. /*
  3. support vtp-sessions
  4.  
  5. written by Christian A. Lademann <cal@zls.com>
  6. */
  7.  
  8. /*
  9. 02.05.95:cal:ported to samba-1.9.13
  10. */
  11.  
  12. #define    __vt_mode_c__
  13.  
  14.  
  15. /* #include    <stdio.h> */
  16. /* #include    <fcntl.h> */
  17. /* #include    <sys/types.h> */
  18. /* #include    <unistd.h> */
  19. /* #include    <signal.h> */
  20. /* #include    <errno.h> */
  21. /* #include    <ctype.h> */
  22. /* #include    <utmp.h> */
  23. /* #include    <sys/param.h> */
  24. /* #include    <sys/ioctl.h> */
  25. /* #include    <stdlib.h> */
  26. /* #include    <string.h> */
  27.  
  28. #include    "includes.h"
  29. #include    "vt_mode.h"
  30. #include    <utmp.h>
  31.  
  32. #ifdef SCO
  33.     extern char    *strdup();
  34. #endif
  35.  
  36. extern int Client;
  37.  
  38. #ifdef LINUX
  39. #    define    HAS_VTY
  40. #endif
  41.  
  42. #ifdef SCO
  43. #    define    HAS_PTY
  44. #    define    HAS_VTY
  45.  
  46. #    include    <sys/tty.h>
  47. #endif
  48.  
  49. extern int    DEBUGLEVEL;
  50. extern char    *InBuffer, *OutBuffer;
  51. extern int    done_become_user;
  52.  
  53. char    master_name [64], slave_name [64];
  54. int        master, slave, i, o, e;
  55.  
  56. int        ms_type = MS_NONE,
  57.         ms_poll = 0;
  58.  
  59.  
  60. /*
  61. VT_Check: test incoming packet for "vtp" or "iVT1\0"
  62. */
  63. int    VT_Check(char    *buffer)
  64. {
  65.     DEBUG(3,("Checking packet: <%10s...>\n", buffer+4));
  66.     if((strncmp(buffer+4, "vtp", 3) == 0 && smb_len(buffer) == 3) || (strncmp(buffer+4, "iVT1\0", 5) == 0 && smb_len(buffer) == 5))
  67.         return(1);
  68.     else
  69.         return(0);
  70. }
  71.  
  72.  
  73. /*
  74. VT_Start_utmp: prepare /etc/utmp for /bin/login
  75. */
  76. int VT_Start_utmp(void)
  77. {
  78.     struct utmp    u, *v;
  79.     char        *tt;
  80.  
  81.  
  82.     setutent();
  83.  
  84.     strcpy(u.ut_line, VT_Line);
  85.  
  86.     if((v = getutline(&u)) == NULL) {
  87.         if(strncmp(VT_Line, "tty", 3) == 0)
  88.             tt = VT_Line + 3;
  89.         else if(strlen(VT_Line) > 4)
  90.             tt = VT_Line + strlen(VT_Line) - 4;
  91.         else
  92.             tt = VT_Line;
  93.  
  94.         strcpy(u.ut_id, tt);
  95.         u.ut_time = time((time_t*)0);
  96.     }
  97.  
  98.     strcpy(u.ut_user, "LOGIN");
  99.     strcpy(u.ut_line, VT_Line);
  100.     u.ut_pid = getpid();
  101.     u.ut_type = LOGIN_PROCESS;
  102.     pututline(&u);
  103.  
  104.     endutent();
  105.  
  106.     return(0);
  107. }
  108.  
  109.  
  110. /*
  111. VT_Stop_utmp: prepare /etc/utmp for other processes
  112. */
  113. int VT_Stop_utmp(void)
  114. {
  115.     struct utmp    u, *v;
  116.  
  117.  
  118.     if(VT_Line != NULL) {
  119.         setutent();
  120.  
  121.         strcpy(u.ut_line, VT_Line);
  122.  
  123.         if((v = getutline(&u)) != NULL) {
  124.             strcpy(v->ut_user, "");
  125.             v->ut_type = DEAD_PROCESS;
  126.             v->ut_time = time((time_t*)0);
  127.             pututline(v);
  128.         }
  129.  
  130.         endutent();
  131.     }
  132.  
  133.     return(0);
  134. }
  135.  
  136.  
  137. /*
  138. VT_AtExit: Things to do when the program exits
  139. */
  140. void    VT_AtExit(void)
  141. {
  142.     if(VT_ChildPID > 0) {
  143.         kill(VT_ChildPID, SIGHUP);
  144.         (void)wait(NULL);
  145.     }
  146.  
  147.     VT_Stop_utmp();
  148. }
  149.  
  150.  
  151. /*
  152. VT_SigCLD: signalhandler for SIGCLD: set flag if child-process died
  153. */
  154. void    VT_SigCLD(int    sig)
  155. {
  156.     if(wait(NULL) == VT_ChildPID)
  157.         VT_ChildDied = True;
  158.     else
  159.         signal(SIGCLD, VT_SigCLD);
  160. }
  161.  
  162.  
  163. /*
  164. VT_SigEXIT: signalhandler for signals that cause the process to exit
  165. */
  166. void    VT_SigEXIT(int    sig)
  167. {
  168.     VT_AtExit();
  169.  
  170.     exit(1);
  171. }
  172.  
  173.  
  174. /*
  175. VT_Start: initialize vt-specific data, alloc pty, spawn shell and send ACK
  176. */
  177. int    VT_Start(void)
  178. {
  179.     char    OutBuf [64], *X, *Y;
  180.  
  181.  
  182.     ms_type = MS_NONE;
  183.     master = slave = -1;
  184.  
  185. #ifdef HAS_VTY
  186. #ifdef LINUX
  187. #    define    MASTER_TMPL    "/dev/pty  "
  188. #    define    SLAVE_TMPL    "/dev/tty  "
  189. #    define    LETTER1        "pqrs"
  190. #    define    POS1        8
  191. #    define    LETTER2        "0123456789abcdef"
  192. #    define    POS2        9
  193. #endif
  194.  
  195. #ifdef SCO
  196. #    define    MASTER_TMPL    "/dev/ptyp_  "
  197. #    define    SLAVE_TMPL    "/dev/ttyp_  "
  198. #    define    LETTER1        "0123456"
  199. #    define    POS1        10
  200. #    define    LETTER2        "0123456789abcdef"
  201. #    define    POS2        11
  202. #endif
  203.  
  204.     if(ms_poll == MS_VTY || ms_poll == 0) {
  205.         strcpy(master_name, MASTER_TMPL);
  206.         strcpy(slave_name, SLAVE_TMPL);
  207.  
  208.         for(X = LETTER1; *X && master < 0; X++)
  209.             for(Y = LETTER2; *Y && master < 0; Y++) {
  210.                 master_name [POS1] = *X;
  211.                 master_name [POS2] = *Y;
  212.                 if((master = open(master_name, O_RDWR)) >= 0) {
  213.                     slave_name [POS1] = *X;
  214.                     slave_name [POS2] = *Y;
  215.                     if((slave = open(slave_name, O_RDWR)) < 0)
  216.                         close(master);
  217.                 }
  218.             }
  219.  
  220.         if(master >= 0 && slave >= 0)
  221.             ms_type = MS_VTY;
  222.     }
  223.  
  224. #    undef    MASTER_TMPL
  225. #    undef    SLAVE_TMPL
  226. #    undef    LETTER1
  227. #    undef    LETTER2
  228. #    undef    POS1
  229. #    undef    POS2
  230. #endif
  231.  
  232.  
  233. #ifdef HAS_PTY
  234. #ifdef SCO
  235. #    define    MASTER_TMPL    "/dev/ptyp%d"
  236. #    define    SLAVE_TMPL    "/dev/ttyp%d"
  237. #    define    MIN_I        0
  238. #    define    MAX_I        63
  239. #endif
  240.  
  241.     if(ms_poll == MS_PTY || ms_poll == 0) {
  242.         int    i;
  243.  
  244.         for(i = MIN_I; i <= MAX_I && master < 0; i++) {
  245.             sprintf(master_name, MASTER_TMPL, i);
  246.             if((master = open(master_name, O_RDWR)) >= 0) {
  247.                 sprintf(slave_name, SLAVE_TMPL, i);
  248.                 if((slave = open(slave_name, O_RDWR)) < 0)
  249.                     close(master);
  250.             }
  251.         }
  252.  
  253.         if(master >= 0 && slave >= 0)
  254.             ms_type = MS_PTY;
  255.     }
  256.  
  257. #    undef    MASTER_TMPL
  258. #    undef    SLAVE_TMPL
  259. #    undef    MIN_I
  260. #    undef    MAX_I
  261. #endif
  262.  
  263.  
  264.     if(! ms_type)
  265.         return(-1);
  266.  
  267.     VT_Line = strdup(strrchr(slave_name, '/') + 1);
  268.  
  269.     switch((VT_ChildPID = fork())) {
  270.     case -1:
  271.         return(-1);
  272.         break;
  273.  
  274.     case 0:
  275. #ifdef SCO
  276.         setsid();
  277. #endif
  278.         close(0);
  279.         close(1);
  280.         close(2);
  281.  
  282.         i = open(slave_name, O_RDWR);
  283.         o = open(slave_name, O_RDWR);
  284.         e = open(slave_name, O_RDWR);
  285.  
  286. #ifdef LINUX
  287.         setsid();
  288.         if (ioctl(slave, TIOCSCTTY, (char *)NULL) == -1)
  289.             exit(1);
  290. #endif
  291. #ifdef SCO
  292.         tcsetpgrp(0, getpid());
  293. #endif
  294.  
  295.         VT_Start_utmp();
  296.  
  297.         system("stty sane");
  298.         execlp("/bin/login", "login", "-c", (char*)0);
  299.         exit(1);
  300.         break;
  301.  
  302.     default:
  303.         VT_Mode = True;
  304.         VT_Status = VT_OPEN;
  305.         VT_ChildDied = False;
  306.         VT_Fd = master;
  307.  
  308.         signal(SIGCLD, VT_SigCLD);
  309.  
  310.         signal(SIGHUP, VT_SigEXIT);
  311.         signal(SIGTERM, VT_SigEXIT);
  312.         signal(SIGINT, VT_SigEXIT);
  313.         signal(SIGQUIT, VT_SigEXIT);
  314.  
  315.         memset(OutBuf, 0, sizeof(OutBuf));
  316.         OutBuf [4] = 0x06;
  317.         _smb_setlen(OutBuf, 1);
  318.  
  319.         send_smb(Client,OutBuf);
  320.  
  321.         return(0);
  322.         break;
  323.     }
  324. }
  325.  
  326.  
  327. /*
  328. VT_Output: transport data from socket to pty
  329. */
  330. int    VT_Output(char    *Buffer)
  331. {
  332.     int        i, len, nb;
  333.  
  334.  
  335.     if(VT_Status != VT_OPEN)
  336.         return(-1);
  337.  
  338.     len = smb_len(Buffer);
  339.  
  340.     nb = write(VT_Fd, Buffer + 4, len);
  341.  
  342.     return((nb == len) ? 0 : -1);
  343. }
  344.  
  345.  
  346. /*
  347. VT_Input: transport data from pty to socket
  348. */
  349. int    VT_Input(char    *Buffer,int        Size)
  350. {
  351.     int        len;
  352.  
  353.  
  354.     if(VT_Status != VT_OPEN)
  355.         return(-1);
  356.  
  357.     memset(Buffer, 0, Size);
  358.     len = read(VT_Fd, Buffer + 4, MIN(VT_MAXREAD, Size));
  359.  
  360.     _smb_setlen(Buffer, len);
  361.  
  362.     return(len + 4);
  363. }
  364.  
  365.  
  366. /*
  367. VT_Process: main loop while in vt-mode
  368. */
  369. void VT_Process(void)
  370. {
  371.     static int    trans_num = 0;
  372.     extern int    Client;
  373.     int            nread;
  374.  
  375.  
  376.     VT_Start();
  377.  
  378.     atexit(VT_AtExit);
  379.  
  380.     while (True) {
  381.         int32            len;      
  382.         int                msg_type;
  383.         int                msg_flags;
  384.         int                counter;
  385.         int                last_keepalive=0;
  386.         struct fd_set    si;
  387.         struct timeval    to, *top;
  388.         int                n, ret, t;
  389.  
  390.  
  391.         errno = 0;
  392.         t = SMBD_SELECT_LOOP*1000;
  393.  
  394.  
  395.         FD_ZERO(&si);
  396.         FD_SET(Client, &si);
  397.  
  398.         FD_SET(VT_Fd, &si);
  399.  
  400.         if(t >= 0) {
  401.             to.tv_sec = t / 1000;
  402.             to.tv_usec = t - (to.tv_sec * 1000);
  403.  
  404.             top = &to;
  405.         } else
  406.             top = NULL;
  407.  
  408.         if(VT_ChildDied)
  409.             goto leave_VT_Process;
  410.  
  411.         n = select(MAX(VT_Fd, Client) + 1, &si, NULL, NULL, top);
  412.  
  413.         if(VT_ChildDied)
  414.             goto leave_VT_Process;
  415.     
  416.         if(n == 0) {
  417.             int i;
  418.             time_t t;
  419.             BOOL allidle = True;
  420.             extern int keepalive;
  421.     
  422.             counter += SMBD_SELECT_LOOP;
  423.  
  424.             t = time(NULL);
  425.     
  426.             if (keepalive && (counter-last_keepalive)>keepalive) {
  427.                 if (!send_keepalive(Client))
  428.                     goto leave_VT_Process;
  429.                 last_keepalive = counter;
  430.             }
  431.         } else if(n > 0) {
  432.             counter = 0;
  433.  
  434.             if(FD_ISSET(VT_Fd, &si)) {
  435.                 /* got input from vt */
  436.                 nread = VT_Input(OutBuffer, MIN(BUFFER_SIZE,lp_maxxmit()));
  437.  
  438.                 if(nread > 0)
  439.                     send_smb(Client,OutBuffer);
  440.             }
  441.  
  442.             if(FD_ISSET(Client, &si)) {
  443.                 /* got input from socket */
  444.  
  445.                 if(receive_smb(Client,InBuffer, 0)) {
  446.                     msg_type = CVAL(InBuffer,0);
  447.                     msg_flags = CVAL(InBuffer,1);
  448.     
  449.                     len = smb_len(InBuffer);
  450.     
  451.                     DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
  452.     
  453.                     nread = len + 4;
  454.           
  455.                     DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
  456.     
  457.                     if(msg_type == 0)
  458.                         VT_Output(InBuffer);
  459.                     else {
  460.                         nread = construct_reply(InBuffer,OutBuffer,nread,MIN(BUFFER_SIZE,lp_maxxmit()));
  461.          
  462.                         if(nread > 0) {
  463.                             if (nread != smb_len(OutBuffer) + 4) {
  464.                                 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
  465.                                     nread,
  466.                                     smb_len(OutBuffer)));
  467.                             } else
  468.                                 send_smb(Client,OutBuffer);
  469.                         }
  470.                     }
  471.                 } else
  472.                     if(errno == EBADF)
  473.                         goto leave_VT_Process;
  474.             }
  475.         }
  476.  
  477.         trans_num++;
  478.     }
  479.  
  480.     leave_VT_Process:
  481. /*
  482.         if(VT_ChildPID > 0)
  483.             kill(VT_ChildPID, SIGHUP);
  484.  
  485.         VT_Stop_utmp(VT_Line);
  486.         return;
  487. */
  488.         close_sockets();
  489.         exit(0);
  490. }
  491.