home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / m / mxterm.zip / mxterm / resize.c < prev    next >
C/C++ Source or Header  |  1992-10-17  |  12KB  |  537 lines

  1. /*
  2.  *    $XConsortium: resize.c,v 1.27 91/07/23 11:11:19 rws Exp $
  3.  */
  4.  
  5. /*
  6.  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  7.  *
  8.  *                         All Rights Reserved
  9.  *
  10.  * Permission to use, copy, modify, and distribute this software and its
  11.  * documentation for any purpose and without fee is hereby granted,
  12.  * provided that the above copyright notice appear in all copies and that
  13.  * both that copyright notice and this permission notice appear in
  14.  * supporting documentation, and that the name of Digital Equipment
  15.  * Corporation not be used in advertising or publicity pertaining to
  16.  * distribution of the software without specific, written prior permission.
  17.  *
  18.  *
  19.  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  20.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  21.  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  22.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  23.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  24.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  25.  * SOFTWARE.
  26.  */
  27.  
  28.  
  29. /* resize.c */
  30.  
  31. #include <X11/Xos.h>
  32. #include <stdio.h>
  33. #include <ctype.h>
  34.  
  35. #if defined(att) || (defined(SYSV) && defined(SYSV386))
  36. #define ATT
  37. #endif
  38.  
  39. #ifdef SVR4
  40. #define SYSV
  41. #define ATT
  42. #endif
  43.  
  44. #ifdef ATT
  45. #define USE_USG_PTYS
  46. #endif
  47.  
  48. #ifdef APOLLO_SR9
  49. #define CANT_OPEN_DEV_TTY
  50. #endif
  51.  
  52. #ifdef macII
  53. #define USE_SYSV_TERMIO
  54. #undef SYSV                /* pretend to be bsd */
  55. #endif /* macII */
  56.  
  57. #ifdef SYSV
  58. #define USE_SYSV_TERMIO
  59. #define USE_SYSV_UTMP
  60. #else /* else not SYSV */
  61. #define USE_TERMCAP
  62. #endif /* SYSV */
  63.  
  64. #include <sys/ioctl.h>
  65. #ifdef USE_SYSV_TERMIO
  66. #include <sys/termio.h>
  67. #else /* else not USE_SYSV_TERMIO */
  68. #include <sgtty.h>
  69. #endif    /* USE_SYSV_TERMIO */
  70.  
  71. #ifdef USE_USG_PTYS
  72. #include <sys/stream.h>
  73. #include <sys/ptem.h>
  74. #endif
  75.  
  76. #include <signal.h>
  77. #include <pwd.h>
  78.  
  79. #ifdef SIGNALRETURNSINT
  80. #define SIGNAL_T int
  81. #else
  82. #define SIGNAL_T void
  83. #endif
  84.  
  85. #ifndef X_NOT_STDC_ENV
  86. #include <stdlib.h>
  87. #else
  88. char *getenv();
  89. #endif
  90.  
  91. #ifdef USE_SYSV_TERMIO
  92. #ifdef X_NOT_POSIX
  93. #ifndef SYSV386
  94. extern struct passwd *getpwuid();     /* does ANYBODY need this? */
  95. #endif /* SYSV386 */
  96. #endif /* X_NOT_POSIX */
  97. #define    bzero(s, n)    memset(s, 0, n)
  98. #endif    /* USE_SYSV_TERMIO */
  99.  
  100. #define    EMULATIONS    2
  101. #define    SUN        1
  102. #define    TIMEOUT        10
  103. #define    VT100        0
  104.  
  105. #define    SHELL_UNKNOWN    0
  106. #define    SHELL_C        1
  107. #define    SHELL_BOURNE    2
  108. struct {
  109.     char *name;
  110.     int type;
  111. } shell_list[] = {
  112.     "csh",        SHELL_C,    /* vanilla cshell */
  113.     "tcsh",        SHELL_C,
  114.     "jcsh",        SHELL_C,
  115.     "sh",        SHELL_BOURNE,    /* vanilla Bourne shell */
  116.     "ksh",        SHELL_BOURNE,    /* Korn shell (from AT&T toolchest) */
  117.     "ksh-i",    SHELL_BOURNE,    /* other name for latest Korn shell */
  118.     "bash",        SHELL_BOURNE,    /* GNU Bourne again shell */
  119.     "jsh",        SHELL_BOURNE,
  120.     NULL,        SHELL_BOURNE    /* default (same as xterm's) */
  121. };
  122.  
  123. char *emuname[EMULATIONS] = {
  124.     "VT100",
  125.     "Sun",
  126. };
  127. char *myname;
  128. int shell_type = SHELL_UNKNOWN;
  129. char *getsize[EMULATIONS] = {
  130.     "\0337\033[r\033[999;999H\033[6n",
  131.     "\033[18t",
  132. };
  133. #ifndef sun
  134. #ifdef TIOCSWINSZ
  135. char *getwsize[EMULATIONS] = {    /* size in pixels */
  136.     0,
  137.     "\033[14t",
  138. };
  139. #endif    /* TIOCSWINSZ */
  140. #endif    /* sun */
  141. char *restore[EMULATIONS] = {
  142.     "\0338",
  143.     0,
  144. };
  145. char *setname = "";
  146. char *setsize[EMULATIONS] = {
  147.     0,
  148.     "\033[8;%s;%st",
  149. };
  150. #ifdef USE_SYSV_TERMIO
  151. struct termio tioorig;
  152. #else /* not USE_SYSV_TERMIO */
  153. struct sgttyb sgorig;
  154. #endif /* USE_SYSV_TERMIO */
  155. char *size[EMULATIONS] = {
  156.     "\033[%d;%dR",
  157.     "\033[8;%d;%dt",
  158. };
  159. char sunname[] = "sunsize";
  160. int tty;
  161. FILE *ttyfp;
  162. #ifndef sun
  163. #ifdef TIOCSWINSZ
  164. char *wsize[EMULATIONS] = {
  165.     0,
  166.     "\033[4;%hd;%hdt",
  167. };
  168. #endif    /* TIOCSWINSZ */
  169. #endif    /* sun */
  170.  
  171. char *strindex ();
  172.  
  173. SIGNAL_T onintr();
  174.  
  175. /*
  176.    resets termcap string to reflect current screen size
  177.  */
  178. main (argc, argv)
  179.     int argc;
  180.     char **argv;
  181. {
  182.     register char *ptr, *env;
  183.     register int emu = VT100;
  184.     char *shell;
  185.     struct passwd *pw;
  186.     int i;
  187.     int rows, cols;
  188. #ifdef USE_SYSV_TERMIO
  189.     struct termio tio;
  190. #else /* not USE_SYSV_TERMIO */
  191.     struct sgttyb sg;
  192. #endif /* USE_SYSV_TERMIO */
  193. #ifdef USE_TERMCAP
  194.     char termcap [1024];
  195.     char newtc [1024];
  196. #endif /* USE_TERMCAP */
  197.     char buf[BUFSIZ];
  198. #ifdef sun
  199. #ifdef TIOCSSIZE
  200.     struct ttysize ts;
  201. #endif    /* TIOCSSIZE */
  202. #else    /* sun */
  203. #ifdef TIOCSWINSZ
  204.     struct winsize ws;
  205. #endif    /* TIOCSWINSZ */
  206. #endif    /* sun */
  207.     char *name_of_tty;
  208. #ifdef CANT_OPEN_DEV_TTY
  209.     extern char *ttyname();
  210. #endif
  211.  
  212.     ptr = rindex(myname = argv[0], '/');
  213.     if(ptr)
  214.         myname = ptr + 1;
  215.     if(strcmp(myname, sunname) == 0)
  216.         emu = SUN;
  217.     for(argv++, argc-- ; argc > 0 && **argv == '-' ; argv++, argc--) {
  218.         switch((*argv)[1]) {
  219.          case 's':    /* Sun emulation */
  220.             if(emu == SUN)
  221.                 Usage();    /* Never returns */
  222.             emu = SUN;
  223.             break;
  224.          case 'u':    /* Bourne (Unix) shell */
  225.             shell_type = SHELL_BOURNE;
  226.             break;
  227.          case 'c':    /* C shell */
  228.             shell_type = SHELL_C;
  229.             break;
  230.          default:
  231.             Usage();    /* Never returns */
  232.         }
  233.     }
  234.  
  235.     if (SHELL_UNKNOWN == shell_type) {
  236.         /* Find out what kind of shell this user is running.
  237.          * This is the same algorithm that xterm uses.
  238.          */
  239.         if (((ptr = getenv("SHELL")) == NULL || *ptr == 0) &&
  240.          (((pw = getpwuid(getuid())) == NULL) ||
  241.          *(ptr = pw->pw_shell) == 0))
  242.             /* this is the same default that xterm uses */
  243.             ptr = "/bin/sh";
  244.  
  245.         shell = rindex(ptr, '/');
  246.         if(shell)
  247.             shell++;
  248.         else
  249.             shell = ptr;
  250.  
  251.         /* now that we know, what kind is it? */
  252.         for (i = 0; shell_list[i].name; i++)
  253.             if (!strcmp(shell_list[i].name, shell))
  254.                 break;
  255.         shell_type = shell_list[i].type;
  256.     }
  257.  
  258.     if(argc == 2) {
  259.         if(!setsize[emu]) {
  260.             fprintf(stderr,
  261.              "%s: Can't set window size under %s emulation\n",
  262.              myname, emuname[emu]);
  263.             exit(1);
  264.         }
  265.         if(!checkdigits(argv[0]) || !checkdigits(argv[1]))
  266.             Usage();    /* Never returns */
  267.     } else if(argc != 0)
  268.         Usage();    /* Never returns */
  269.  
  270. #ifdef CANT_OPEN_DEV_TTY
  271.     if ((name_of_tty = ttyname(fileno(stderr))) == NULL) 
  272. #endif
  273.       name_of_tty = "/dev/tty";
  274.  
  275.     if ((ttyfp = fopen (name_of_tty, "r+")) == NULL) {
  276.         fprintf (stderr, "%s:  can't open terminal %s\n",
  277.              myname, name_of_tty);
  278.         exit (1);
  279.     }
  280.     tty = fileno(ttyfp);
  281. #ifdef USE_TERMCAP
  282.     if(!(env = getenv("TERM")) || !*env) {
  283.         env = "xterm";
  284.         if(SHELL_BOURNE == shell_type)
  285.         setname = "TERM=xterm;\nexport TERM;\n";
  286.         else
  287.         setname = "setenv TERM xterm;\n";
  288.     }
  289.     if(tgetent (termcap, env) <= 0) {
  290.         fprintf(stderr, "%s: Can't get entry \"%s\"\n",
  291.             myname, env);
  292.         exit(1);
  293.     }
  294. #else /* else not USE_TERMCAP */
  295.     if(!(env = getenv("TERM")) || !*env) {
  296.         env = "xterm";
  297.         if(SHELL_BOURNE == shell_type)
  298.             setname = "TERM=xterm;\nexport TERM;\n";
  299.         else    setname = "setenv TERM xterm;\n";
  300.     }
  301. #endif    /* USE_TERMCAP */
  302.  
  303. #ifdef USE_SYSV_TERMIO
  304.     ioctl (tty, TCGETA, &tioorig);
  305.     tio = tioorig;
  306.     tio.c_iflag &= ~(ICRNL | IUCLC);
  307.     tio.c_lflag &= ~(ICANON | ECHO);
  308.     tio.c_cflag |= CS8;
  309.     tio.c_cc[VMIN] = 6;
  310.     tio.c_cc[VTIME] = 1;
  311. #else    /* else not USE_SYSV_TERMIO */
  312.      ioctl (tty, TIOCGETP, &sgorig);
  313.     sg = sgorig;
  314.     sg.sg_flags |= RAW;
  315.     sg.sg_flags &= ~ECHO;
  316. #endif    /* USE_SYSV_TERMIO */
  317.     signal(SIGINT, onintr);
  318.     signal(SIGQUIT, onintr);
  319.     signal(SIGTERM, onintr);
  320. #ifdef USE_SYSV_TERMIO
  321.     ioctl (tty, TCSETAW, &tio);
  322. #else    /* not USE_SYSV_TERMIO */
  323.     ioctl (tty, TIOCSETP, &sg);
  324. #endif    /* USE_SYSV_TERMIO */
  325.  
  326.     if (argc == 2) {
  327.         sprintf (buf, setsize[emu], argv[0], argv[1]);
  328.         write(tty, buf, strlen(buf));
  329.     }
  330.     write(tty, getsize[emu], strlen(getsize[emu]));
  331.     readstring(ttyfp, buf, size[emu]);
  332.     if(sscanf (buf, size[emu], &rows, &cols) != 2) {
  333.         fprintf(stderr, "%s: Can't get rows and columns\r\n", myname);
  334.         onintr(0);
  335.     }
  336.     if(restore[emu])
  337.         write(tty, restore[emu], strlen(restore[emu]));
  338. #ifdef sun
  339. #ifdef TIOCGSIZE
  340.     /* finally, set the tty's window size */
  341.     if (ioctl (tty, TIOCGSIZE, &ts) != -1) {
  342.         ts.ts_lines = rows;
  343.         ts.ts_cols = cols;
  344.         ioctl (tty, TIOCSSIZE, &ts);
  345.     }
  346. #endif    /* TIOCGSIZE */
  347. #else    /* sun */
  348. #ifdef TIOCGWINSZ
  349.     /* finally, set the tty's window size */
  350.     if(getwsize[emu]) {
  351.         /* get the window size in pixels */
  352.         write (tty, getwsize[emu], strlen (getwsize[emu]));
  353.         readstring(ttyfp, buf, wsize[emu]);
  354.         if(sscanf (buf, wsize[emu], &ws.ws_xpixel, &ws.ws_ypixel) != 2) {
  355.         fprintf(stderr, "%s: Can't get window size\r\n", myname);
  356.         onintr(0);
  357.         }
  358.         ws.ws_row = rows;
  359.         ws.ws_col = cols;
  360.         ioctl (tty, TIOCSWINSZ, &ws);
  361.     } else if (ioctl (tty, TIOCGWINSZ, &ws) != -1) {
  362.         /* we don't have any way of directly finding out
  363.            the current height & width of the window in pixels.  We try
  364.            our best by computing the font height and width from the "old"
  365.            struct winsize values, and multiplying by these ratios...*/
  366.         if (ws.ws_col != 0)
  367.             ws.ws_xpixel = cols * (ws.ws_xpixel / ws.ws_col);
  368.         if (ws.ws_row != 0)
  369.             ws.ws_ypixel = rows * (ws.ws_ypixel / ws.ws_row);
  370.         ws.ws_row = rows;
  371.         ws.ws_col = cols;
  372.         ioctl (tty, TIOCSWINSZ, &ws);
  373.     }
  374. #endif    /* TIOCGWINSZ */
  375. #endif    /* sun */
  376.  
  377. #ifdef USE_SYSV_TERMIO
  378.     ioctl (tty, TCSETAW, &tioorig);
  379. #else    /* not USE_SYSV_TERMIO */
  380.     ioctl (tty, TIOCSETP, &sgorig);
  381. #endif    /* USE_SYSV_TERMIO */
  382.     signal(SIGINT, SIG_DFL);
  383.     signal(SIGQUIT, SIG_DFL);
  384.     signal(SIGTERM, SIG_DFL);
  385.  
  386. #ifdef USE_TERMCAP
  387.     /* update termcap string */
  388.     /* first do columns */
  389.     if ((ptr = strindex (termcap, "co#")) == NULL) {
  390.         fprintf(stderr, "%s: No `co#'\n", myname);
  391.         exit (1);
  392.     }
  393.  
  394.     i = ptr - termcap + 3;
  395.     strncpy (newtc, termcap, i);
  396.     sprintf (newtc + i, "%d", cols);
  397.     ptr = index (ptr, ':');
  398.     strcat (newtc, ptr);
  399.  
  400.     /* now do lines */
  401.     if ((ptr = strindex (newtc, "li#")) == NULL) {
  402.         fprintf(stderr, "%s: No `li#'\n", myname);
  403.         exit (1);
  404.     }
  405.  
  406.     i = ptr - newtc + 3;
  407.     strncpy (termcap, newtc, i);
  408.     sprintf (termcap + i, "%d", rows);
  409.     ptr = index (ptr, ':');
  410.     strcat (termcap, ptr);
  411. #endif /* USE_TERMCAP */
  412.  
  413.     if(SHELL_BOURNE == shell_type) {
  414.  
  415. #ifdef USE_TERMCAP
  416.         printf ("%sTERMCAP='%s'\n",
  417.          setname, termcap);
  418. #else /* else not USE_TERMCAP */
  419. #ifndef SVR4
  420.         printf ("%sCOLUMNS=%d;\nLINES=%d;\nexport COLUMNS LINES;\n",
  421.             setname, cols, rows);
  422. #endif /* !SVR4 */
  423. #endif    /* USE_SYSV_TERMCAP */
  424.  
  425.     } else {        /* not Bourne shell */
  426.  
  427. #ifdef USE_TERMCAP
  428.         printf ("set noglob;\n%ssetenv TERMCAP '%s';\nunset noglob;\n",
  429.          setname, termcap);
  430. #else /* else not USE_TERMCAP */
  431. #ifndef SVR4
  432.         printf ("set noglob;\n%ssetenv COLUMNS '%d';\nsetenv LINES '%d';\nunset noglob;\n",
  433.             setname, cols, rows);
  434. #endif /* !SVR4 */
  435. #endif    /* USE_TERMCAP */
  436.     }
  437.     exit(0);
  438. }
  439.  
  440. char *strindex (s1, s2)
  441. /*
  442.    returns a pointer to the first occurrence of s2 in s1, or NULL if there are
  443.    none.
  444.  */
  445. register char *s1, *s2;
  446. {
  447.     register char *s3;
  448.     int s2len = strlen (s2);
  449.  
  450.     while ((s3 = index (s1, *s2)) != NULL)
  451.     {
  452.         if (strncmp (s3, s2, s2len) == 0) return (s3);
  453.         s1 = ++s3;
  454.     }
  455.     return (NULL);
  456. }
  457.  
  458. checkdigits(str)
  459. register char *str;
  460. {
  461.     while(*str) {
  462.         if(!isdigit(*str))
  463.             return(0);
  464.         str++;
  465.     }
  466.     return(1);
  467. }
  468.  
  469. readstring(fp, buf, str)
  470.     register FILE *fp;
  471.     register char *buf;
  472.     char *str;
  473. {
  474.     register int last, c;
  475.     SIGNAL_T timeout();
  476. #ifndef USG
  477.     struct itimerval it;
  478. #endif
  479.  
  480.     signal(SIGALRM, timeout);
  481. #ifdef USG
  482.     alarm (TIMEOUT);
  483. #else
  484.     bzero((char *)&it, sizeof(struct itimerval));
  485.     it.it_value.tv_sec = TIMEOUT;
  486.     setitimer(ITIMER_REAL, &it, (struct itimerval *)NULL);
  487. #endif
  488.     if ((c = getc(fp)) == 0233) {    /* meta-escape, CSI */
  489.         *buf++ = c = '\033';
  490.         *buf++ = '[';
  491.     } else
  492.         *buf++ = c;
  493.     if(c != *str) {
  494.         fprintf(stderr, "%s: unknown character, exiting.\r\n", myname);
  495.         onintr(0);
  496.     }
  497.     last = str[strlen(str) - 1];
  498.     while((*buf++ = getc(fp)) != last)
  499.         ;
  500. #ifdef USG
  501.     alarm (0);
  502. #else
  503.     bzero((char *)&it, sizeof(struct itimerval));
  504.     setitimer(ITIMER_REAL, &it, (struct itimerval *)NULL);
  505. #endif
  506.     *buf = 0;
  507. }
  508.  
  509. Usage()
  510. {
  511.     fprintf(stderr, strcmp(myname, sunname) == 0 ?
  512.      "Usage: %s [rows cols]\n" :
  513.      "Usage: %s [-u] [-c] [-s [rows cols]]\n", myname);
  514.     exit(1);
  515. }
  516.  
  517. SIGNAL_T
  518. timeout(sig)
  519.     int sig;
  520. {
  521.     fprintf(stderr, "%s: Time out occurred\r\n", myname);
  522.     onintr(sig);
  523. }
  524.  
  525. /* ARGSUSED */
  526. SIGNAL_T
  527. onintr(sig)
  528.     int sig;
  529. {
  530. #ifdef USE_SYSV_TERMIO
  531.     ioctl (tty, TCSETAW, &tioorig);
  532. #else    /* not USE_SYSV_TERMIO */
  533.     ioctl (tty, TIOCSETP, &sgorig);
  534. #endif    /* USE_SYSV_TERMIO */
  535.     exit(1);
  536. }
  537.