home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / COMM / MISC / UWPC201.ZIP / UWSERVER.TAR / server / uw_win.c < prev   
Encoding:
C/C++ Source or Header  |  1991-01-25  |  10.5 KB  |  435 lines

  1. /*
  2.  *    uw_win - window handling for UW
  3.  *
  4.  * Copyright 1986 by John D. Bruner.  All rights reserved.  Permission to
  5.  * copy this program is given provided that the copy is not sold and that
  6.  * this copyright notice is included.
  7.  */
  8.  
  9. #include <sys/types.h>
  10. #include <sys/file.h>
  11. #include <sys/ioctl.h>
  12. #include <signal.h>
  13. #include <strings.h>
  14. #include <stdio.h>
  15.  
  16. #include "openpty.h"
  17. #include "uw_param.h"
  18. #include "uw_opt.h"
  19. #include "uw_win.h"
  20. #include "uw_fd.h"
  21.  
  22. /*
  23.  * "defwtype" specifies the default window type.  This type is used when
  24.  * more specific information is not available.
  25.  */
  26. wtype_t defwtype = WT_ADM31;
  27.  
  28. /*
  29.  * "window" is declared in "uw_win.h"  Here we define it.
  30.  */
  31. struct window window[NWINDOW];        /* window data structures */
  32.  
  33. /*
  34.  * "emulation" describes window emulation-specific data.  "generic_emul"
  35.  * describes emulations which do not require special server attention
  36.  * (e.g. file transfer, all of whose real work is done by a separate process).
  37.  */
  38. extern struct emulation adm31_emul, vt52_emul, ansi_emul, tek_emul;
  39. static struct emulation generic_emul;
  40. static struct emulation *emulation[WT_MAXTYPE+1] = {
  41.     &adm31_emul,
  42.     &vt52_emul,
  43.     &ansi_emul,
  44.     &tek_emul,
  45.     &generic_emul,
  46.     &generic_emul,
  47.     &generic_emul,
  48. };
  49.  
  50. extern char *win_getopt();
  51. extern void win_setopt();
  52.  
  53. static woptarg_t woa_vis[] = { WOA_UDATA(1), WOA_END };
  54. static woptarg_t woa_type[] = { WOA_UDATA(6), WOA_END };
  55. static woptarg_t woa_pos[] = { WOA_UDATA(12), WOA_UDATA(12), WOA_END };
  56. static woptarg_t woa_title[] = { WOA_STRING(255), WOA_END };
  57. static woptarg_t woa_size[] = { WOA_UDATA(12), WOA_UDATA(12), WOA_END };
  58.  
  59. static struct woptdefn genwinopt = {
  60.     (1<<WOG_VIS), 0, 0, 0,
  61.     (1<<WOG_VIS)|(1<<WOG_TYPE)|(1<<WOG_POS)|(1<<WOG_TITLE)|(1<<WOG_SIZE),
  62.     {
  63. /* WOG_END */    { NULL, NULL, NULL },
  64. /* WOG_VIS */    { woa_vis, win_getopt, win_setopt },
  65. /* WOG_TYPE */    { woa_type, win_getopt, win_setopt },
  66. /* WOG_POS */    { woa_pos, win_getopt, win_setopt },
  67. /* WOG_TITLE */    { woa_title, win_getopt, win_setopt },
  68. /* WOG_SIZE */    { woa_size, win_getopt, win_setopt },
  69. /* WOG_6 */    { NULL, NULL, NULL },
  70. /* WOG_7 */    { NULL, NULL, NULL }
  71.     }
  72. };
  73.  
  74. /*
  75.  * This is a violation of the level structure, but it is expedient.
  76.  */
  77. extern void ipc_optmsg();
  78.  
  79. win_init()
  80. {
  81.     register struct window *w;
  82.  
  83.     /*
  84.      * Initialize.  Mark all windows unallocated.
  85.      */
  86.     for (w=window; w < window+NWINDOW; w++)
  87.         w->w_alloc = 0;
  88. }
  89.  
  90. long
  91. win_mkid()
  92. {
  93.     static unsigned short i = 0;
  94.     static long pid = -1;
  95.  
  96.     if (pid == -1)
  97.         pid = getpid();
  98.     return((pid << (NBBY*(sizeof(long)/sizeof(short)))) | i++);
  99. }
  100.  
  101. struct window *
  102. win_search(wid, maxwin)
  103. long wid;
  104. nwin_t maxwin;
  105. {
  106.     register struct window *w;
  107.  
  108.     for (w=window; w < window+maxwin; w++)
  109.         if (w->w_alloc && w->w_id == wid)
  110.             return(w);
  111.     return((struct window *)0);
  112. }
  113.  
  114. struct window *
  115. win_neww(wclass, wtype, wnum, maxwin, wid, datafd, ctlfd, options)
  116. wclass_t wclass;
  117. wtype_t wtype;
  118. nwin_t wnum;
  119. nwin_t maxwin;
  120. long wid;
  121. fildes_t datafd;
  122. fildes_t ctlfd;
  123. struct woptdefn *options;
  124. {
  125.     fildes_t fd;
  126.     int pid;
  127.     struct window *w;
  128.     char *tty, *shell;
  129.     auto struct ptydesc pt;
  130.     extern char *getenv();
  131.  
  132.     /*
  133.      * Create a new window.  "wclass" specifies the window wclass.
  134.      * If "wnum" is negative, choose a window number; otherwise,
  135.      * "wnum" is the window number.  "datafd" and "ctlfd" are the
  136.      * data and control file descriptors to be associated with
  137.      * this window.  If "datafd" is negative and "wclass" is
  138.      * WC_INTERNAL, allocate a pseudo-terminal.
  139.      *
  140.      * If "options" is non-NULL it specifies the address of an
  141.      * option definition structure; otherwise, a new one is constructed
  142.      * from the generic and emulation-specific prototype structures.
  143.      *
  144.      * If "wid" is nonzero it is a proposed window ID.  It must be
  145.      * unique (not in use).  If "wid" is zero, a new ID is assigned.
  146.      *
  147.      * The window type "wtype" will always be a terminal emulation
  148.      * if the wclass is WC_INTERNAL.
  149.      *
  150.      * Internal-class windows are visible by default, while external
  151.      * ones are initially invisible.
  152.      *
  153.      * Return the address of the window structure or NULL if
  154.      * none could be created.
  155.      */
  156.     tty = (char *)0;
  157.     if (wtype > WT_MAXTYPE)
  158.         return((struct window *)0);
  159.     if (wid == 0) {
  160.         while (win_search(wid=win_mkid(), maxwin) != NULL)
  161.             ;
  162.     } else if (win_search(wid, maxwin) != NULL)
  163.         return((struct window *)0);
  164.     if (datafd < 0 && wclass == WC_INTERNAL) {
  165.         if (!openpty(&pt)) {
  166.             datafd = pt.pt_pfd;
  167.             tty = pt.pt_tname;
  168.             while ((pid = fork()) < 0)
  169.                 sleep(5);
  170.             if (!pid) {
  171.                 win_envinit(wtype, wid);
  172.                 (void)signal(SIGHUP, SIG_DFL);
  173.                 (void)signal(SIGINT, SIG_DFL);
  174.                 (void)signal(SIGQUIT, SIG_DFL);
  175.                 (void)signal(SIGTERM, SIG_DFL);
  176.                 (void)signal(SIGTSTP, SIG_IGN);
  177.                 (void)signal(SIGCHLD, SIG_DFL);
  178.                 (void)ioctl(open("/dev/tty",O_RDWR),
  179.                     (int)TIOCNOTTY, (char *)0);
  180.                 (void)close(open(pt.pt_tname, O_RDONLY));
  181.                 (void)setuid(getuid());
  182.                 if (!(shell = getenv("SHELL")))
  183.                     shell = "/bin/sh";
  184.                 if (pt.pt_tfd != 0)
  185.                     (void)dup2(pt.pt_tfd, 0);
  186.                 if (pt.pt_tfd != 1);
  187.                     (void)dup2(pt.pt_tfd, 1);
  188.                 if (pt.pt_tfd != 2)
  189.                     (void)dup2(pt.pt_tfd, 2);
  190.                 for (fd=3; fd < nfds; fd++)
  191.                     (void)close(fd);
  192.                 tty_mode(0);    /* HACK! */
  193.                 execl(shell, shell, (char *)0);
  194.                 _exit(1);
  195.             } else {
  196.                 utmp_add(tty);
  197.                 (void)close(pt.pt_tfd);
  198.             }
  199.         }
  200.     }
  201.  
  202.     if (datafd >= 0) {
  203.         if (wnum > 0) {
  204.             w = WIN_PTR(wnum);
  205.             if (w->w_alloc)
  206.                 w = (struct window *)0;
  207.         } else {
  208.             for (w=window; w < window+maxwin && w->w_alloc; w++)
  209.                 ;
  210.             if (w >= window+maxwin)
  211.                 w = (struct window *)0;
  212.         }
  213.     } else
  214.         w = (struct window *)0;
  215.  
  216.     if (w) {
  217.         w->w_alloc = 1;
  218.         w->w_id = wid;
  219.         w->w_class = wclass;
  220.         w->w_type = wtype;
  221.         w->w_visible = (w->w_class == WC_INTERNAL);
  222.         w->w_position.h = w->w_position.v = 0;
  223.         w->w_size.h = w->w_size.v = 0;
  224.         w->w_title[0] = '\0';
  225.         if (emulation[wtype]->we_start &&
  226.             !(*emulation[wtype]->we_start)(w)) {
  227.             if (options)
  228.                 w->w_optdefn = *options;
  229.             else
  230.                 opt_new(&w->w_optdefn, &genwinopt,
  231.                     (struct woptdefn *)0);
  232.         } else {
  233.             if (options)
  234.                 w->w_optdefn = *options;
  235.             else
  236.                 opt_new(&w->w_optdefn, &genwinopt,
  237.                     &emulation[wtype]->we_optdefn);
  238.         }
  239.         w->w_datafd = datafd;
  240.         (void)fcntl(datafd, F_SETFL, FNDELAY);
  241.         FD_SET(datafd, &selmask[0].sm_rd);
  242.         fdmap[datafd].f_type = FDT_DATA;
  243.         fdmap[datafd].f_win = w;
  244.         if (w->w_class == WC_INTERNAL) {
  245.             if (tty)
  246.                 (void)strncpy(w->w_tty, tty, sizeof w->w_tty);
  247.         } else {
  248.             w->w_ctlfd = ctlfd;
  249.             if (ctlfd >= 0) {
  250.                 (void)fcntl(ctlfd, F_SETFL, FNDELAY);
  251.                 FD_SET(ctlfd, &selmask[0].sm_rd);
  252.                 fdmap[ctlfd].f_type = FDT_CTL;
  253.                 fdmap[ctlfd].f_win = w;
  254.                 if (emulation[wtype]->we_setext)
  255.                     (*emulation[wtype]->we_setext)(&w->w_optdefn);
  256.                 opt_setext(&w->w_optdefn, ipc_optmsg);
  257.             }
  258.         }
  259.     }
  260.             
  261.     return(w);
  262. }
  263.  
  264. win_killw(w)
  265. register struct window *w;
  266. {
  267.     /*
  268.      * Kill the window "w".  This is pretty simple; we just close
  269.      * the data and control file descriptors and mark the structure
  270.      * inactive.
  271.      */
  272.     if (w && w->w_alloc) {
  273.         if (w->w_datafd >= 0) {
  274.             if (w->w_class == WC_INTERNAL)
  275.                 utmp_rm(w->w_tty);
  276.             FD_CLR(w->w_datafd, &selmask[0].sm_rd);
  277.             FD_CLR(w->w_datafd, &selmask[0].sm_wt);
  278.             FD_CLR(w->w_datafd, &selmask[0].sm_ex);
  279.             fdmap[w->w_datafd].f_type = FDT_NONE;
  280.             (void)close(w->w_datafd);
  281.         }
  282.         if (w->w_class == WC_EXTERNAL && w->w_ctlfd >= 0) {
  283.             FD_CLR(w->w_ctlfd, &selmask[0].sm_rd);
  284.             FD_CLR(w->w_ctlfd, &selmask[0].sm_wt);
  285.             FD_CLR(w->w_ctlfd, &selmask[0].sm_ex);
  286.             fdmap[w->w_ctlfd].f_type = FDT_NONE;
  287.             (void)close(w->w_ctlfd);
  288.         }
  289.         w->w_alloc = 0;
  290.     }
  291. }
  292.  
  293. win_renew(w, report)
  294. struct window *w;
  295. int report;
  296. {
  297.     /*
  298.      * Reinitialize (re-NEW) the window "w".  Report the state of the
  299.      * window to the Mac if "report" is nonzero.
  300.      */
  301.     opt_renew(&w->w_optdefn, report);
  302. }
  303.  
  304. win_newtype(w, wtype)
  305. register struct window *w;
  306. register wtype_t wtype;
  307. {
  308.     /*
  309.      * Change the window emulation type to "wtype".
  310.      */
  311.     if (wtype <= WT_MAXTYPE && wtype != w->w_type) {
  312.         if (emulation[w->w_type]->we_stop)
  313.             (*emulation[w->w_type]->we_stop)(w);
  314.         w->w_type = wtype;
  315.         if (emulation[wtype]->we_start &&
  316.             !(*emulation[wtype]->we_start)(w)) {
  317.             opt_newtype(&w->w_optdefn, &genwinopt,
  318.                 (struct woptdefn *)0);
  319.         } else {
  320.             opt_newtype(&w->w_optdefn, &genwinopt,
  321.                 &emulation[wtype]->we_optdefn);
  322.         }
  323.         if (w->w_class == WC_EXTERNAL && w->w_ctlfd >= 0) {
  324.             if (emulation[wtype]->we_setext)
  325.                 (*emulation[wtype]->we_setext)(&w->w_optdefn);
  326.             opt_setext(&w->w_optdefn, ipc_optmsg);
  327.         }
  328.     }
  329. }
  330.  
  331. win_envinit(wtype, wid)
  332. register wtype_t wtype;
  333. long wid;
  334. {
  335.     register char *widstr;
  336.     auto char *env[2];
  337.  
  338.     /*
  339.      * Set up the environment according to the new window type and
  340.      * window ID.
  341.      *
  342.      * A 64-bit integer will fit in 20 digits.  If a "long" is wider
  343.      * than this, then this code will have to be adjusted.
  344.      */
  345.     if (wtype <= WT_TEK4010)
  346.         tty_envinit(wtype);
  347.     if ((widstr = malloc(sizeof "UW_ID=" + 20)) != NULL) {
  348.         sprintf(widstr, "UW_ID=%ld", wid);
  349.         env[0] = widstr;
  350.         env[1] = (char *)0;
  351.         env_set(env);
  352.     }
  353. }
  354.  
  355. static
  356. char *
  357. win_getopt(win, num)
  358. caddr_t win;
  359. woption_t num;
  360. {
  361.     register struct window *w;
  362.     static union optvalue ov;
  363.  
  364.     /*
  365.      * Get the value of window option "num".  It is arguably wrong to
  366.      * always return the address of "ov" (even if the window isn't
  367.      * allocated or an unknown option type was requested); however,
  368.      * we're already in trouble and there is no good way to recover
  369.      * at this point.
  370.      */
  371.     if ((w = (struct window *)win) != NULL && w->w_alloc) {
  372.         switch (num) {
  373.         case WOG_VIS:
  374.             ov.ov_udata1 = w->w_visible;
  375.             break;
  376.         case WOG_TYPE:
  377.             ov.ov_udata6 = w->w_type;
  378.             break;
  379.         case WOG_POS:
  380.             ov.ov_point.h = w->w_position.h;
  381.             ov.ov_point.v = w->w_position.v;
  382.             break;
  383.         case WOG_TITLE:
  384.             (void)strncpy(ov.ov_string, w->w_title,
  385.                 sizeof ov.ov_string);
  386.             ov.ov_string[sizeof ov.ov_string-1] = '\0';
  387.             break;
  388.         case WOG_SIZE:
  389.             ov.ov_point.h = w->w_size.h;
  390.             ov.ov_point.v = w->w_size.v;
  391.             break;
  392.         }
  393.     }
  394.     return((char *)&ov);
  395. }
  396.  
  397. static
  398. void
  399. win_setopt(win, num, value)
  400. caddr_t win;
  401. woption_t num;
  402. char *value;
  403. {
  404.     register struct window *w;
  405.     register union optvalue *ov;
  406.  
  407.     /*
  408.      * Set window option "num" to "value"
  409.      */
  410.     if ((w = (struct window *)win) != NULL && w->w_alloc &&
  411.         (ov = (union optvalue *)value) != NULL) {
  412.         switch (num) {
  413.         case WOG_VIS:
  414.             w->w_visible = ov->ov_udata1;
  415.             break;
  416.         case WOG_TYPE:
  417.             win_newtype(w, (wtype_t)ov->ov_udata6);
  418.             break;
  419.         case WOG_POS:
  420.             w->w_position.h = ov->ov_point.h;
  421.             w->w_position.v = ov->ov_point.v;
  422.             break;
  423.         case WOG_TITLE:
  424.             (void)strncpy(w->w_title, ov->ov_string,
  425.                 sizeof w->w_title);
  426.             w->w_title[sizeof w->w_title-1] = '\0';
  427.             break;
  428.         case WOG_SIZE:
  429.             w->w_size.h = ov->ov_point.h;
  430.             w->w_size.v = ov->ov_point.v;
  431.             break;
  432.         }
  433.     }
  434. }
  435.