home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / unix / uw_shar.sit / uw-42-part4.shar < prev    next >
Text File  |  1989-09-14  |  61KB  |  2,429 lines

  1. #Date: Wed, 2 Mar 88 10:01:04 PST
  2. #From: rothberg@polya.stanford.edu (Edward Rothberg)
  3. #Subject: UW 4.2 part 4 of 8
  4. : This is a shar archive.  Extract with sh, not csh.
  5. if test ! -d server; then
  6.     echo mkdir server
  7.     mkdir server
  8. fi
  9. echo x - server/uw_ipc.c
  10. sed -e 's/^X//' > server/uw_ipc.c << '!EOF!server/uw_ipc.c!'
  11. X/*
  12. X *    uw IPC
  13. X *
  14. X * Copyright 1986 by John D. Bruner.  All rights reserved.  Permission to
  15. X * copy this program is given provided that the copy is not sold and that
  16. X * this copyright notice is included.
  17. X */
  18. X
  19. X#include <sys/types.h>
  20. X#include <sys/file.h>
  21. X#include <sys/stat.h>
  22. X#include <sys/socket.h>
  23. X#include <sys/un.h>
  24. X#include <sys/ioctl.h>
  25. X#include <sys/uio.h>
  26. X#include <netinet/in.h>
  27. X#include <strings.h>
  28. X#include <netdb.h>
  29. X#include <errno.h>
  30. X#include <stdio.h>
  31. X
  32. X#include "uw_param.h"
  33. X#include "uw_err.h"
  34. X#include "uw_opt.h"
  35. X#include "uw_win.h"
  36. X#include "uw_fd.h"
  37. X#include "uw_pcl.h"
  38. X#include "uw_ipc.h"
  39. X
  40. X#ifndef ntohs
  41. X/* declaring these as one-element arrays or as NULL pointers is a HACK */
  42. Xextern unsigned long ntohl(), htonl();
  43. Xextern unsigned short ntohs(), htons();
  44. Xstatic struct netadj na_ntoh[1] = {
  45. X    (short (*)())ntohs, (long (*)())ntohl, ntohs, ntohl
  46. X};
  47. Xstatic struct netadj na_hton[1] = {
  48. X    (short (*)())htons, (long (*)())htonl, htons, htonl
  49. X};
  50. X#else
  51. Xstatic struct netadj *na_ntoh = NULL;
  52. Xstatic struct netadj *na_hton = NULL;
  53. X#endif
  54. X
  55. Xstatic int have_udport;
  56. Xstatic char uipc_port[] = "/tmp/uwXXXXXX";
  57. X
  58. Xstatic int inet_sd;
  59. Xstatic struct ipcmsg {
  60. X    int        im_len;
  61. X    struct uwipc    im_msg;
  62. X} *inet_buf;
  63. X
  64. Xextern int errno;
  65. X
  66. Xipc_init(use_uipc)
  67. X{
  68. X    ipc_isinit();
  69. X    if (use_uipc)
  70. X        ipc_udinit();
  71. X}
  72. X
  73. X
  74. X/*
  75. X * UNIX-domain
  76. X */
  77. X
  78. Xstatic
  79. Xipc_udinit()
  80. X{
  81. X    register int len;
  82. X    register char *cp;
  83. X    register fildes_t sd;
  84. X    auto struct sockaddr_un sa;
  85. X    auto char *env[2];
  86. X    extern char *mktemp();
  87. X
  88. X    len = strlen(UIPC_ENV) + sizeof uipc_port + 1;
  89. X    if ((cp = malloc(len)) != NULL) {
  90. X        (void)sprintf(cp, "%s=%s", UIPC_ENV, mktemp(uipc_port));
  91. X        env[0] = cp;
  92. X        env[1] = (char *)0;
  93. X        env_set(env);
  94. X
  95. X        sa.sun_family = AF_UNIX;
  96. X        (void)strncpy(sa.sun_path, uipc_port, sizeof sa.sun_path-1);
  97. X        sa.sun_path[sizeof sa.sun_path-1] = '\0';
  98. X        if ((sd = socket(AF_UNIX, SOCK_DGRAM, 0)) >= 0 &&
  99. X            bind(sd,&sa,sizeof sa.sun_family+strlen(sa.sun_path)) >= 0){
  100. X            have_udport = 1;
  101. X            (void)chmod(uipc_port, S_IREAD|S_IWRITE);
  102. X            (void)fcntl(sd, F_SETFL, FNDELAY);
  103. X            fdmap[sd].f_type = FDT_UDSOCK;
  104. X            FD_SET(sd, &selmask[0].sm_rd);
  105. X        }
  106. X    }
  107. X}
  108. X
  109. Xipc_exit()
  110. X{
  111. X    if (have_udport)
  112. X        (void)unlink(uipc_port);
  113. X}
  114. X
  115. Xipc_udrecv(sd)
  116. Xregister fildes_t sd;
  117. X{
  118. X    register struct window *w;
  119. X    register int cnt;
  120. X    struct msghdr msg;
  121. X    auto int fd;
  122. X    struct iovec iov;
  123. X    struct stat st1, st2;
  124. X    union {
  125. X        struct uwipc uwip;
  126. X        char data[1024];
  127. X    } buf;
  128. X
  129. X
  130. X    /*
  131. X     * main() calls this routine when there is a message waiting on
  132. X     * the UNIX-domain socket.  The message's access rights are
  133. X     * expected to contain the file descriptor for the "master" side
  134. X     * of a pseudo-tty.  The message contains the name of the pty.
  135. X     * The sender is expected to start up a process on the slave side
  136. X     * of the pty.  This allows the host end to create windows which
  137. X     * run something other than the shell.
  138. X     */
  139. X    fd = -1;
  140. X
  141. X    iov.iov_base = (caddr_t)buf.data;
  142. X    iov.iov_len = sizeof buf - 1;
  143. X
  144. X    msg.msg_name = (caddr_t)0;
  145. X    msg.msg_namelen = 0;
  146. X    msg.msg_iov = &iov;
  147. X    msg.msg_iovlen = 1;
  148. X    msg.msg_accrights = (caddr_t)&fd;
  149. X    msg.msg_accrightslen = sizeof fd;
  150. X
  151. X    if ((cnt=recvmsg(sd, &msg, 0)) < 0 || cnt != buf.uwip.uwip_len)
  152. X        return;
  153. X    switch (buf.uwip.uwip_cmd) {
  154. X    case UWC_NEWT:
  155. X        if (msg.msg_accrightslen > 0 && fd >= 0) {
  156. X            /*
  157. X             * We can't trust the process which connected to us,
  158. X             * so we verify that it really passed us a pseudo-tty's
  159. X             * file descriptor by checking the device name and its
  160. X             * inode number.  [Of course, if someone else wants to
  161. X             * hand us a terminal session running under their
  162. X             * uid....]
  163. X             */
  164. X            if (cnt == sizeof buf)
  165. X                cnt--;
  166. X            buf.data[cnt] = '\0';
  167. X            if (strncmp(buf.uwip.uwip_newt.uwnt_pty,
  168. X                "/dev/pty", sizeof "/dev/pty"-1) ||
  169. X                fstat(fd, &st1) < 0 ||
  170. X                stat(buf.uwip.uwip_newt.uwnt_pty, &st2) < 0 ||
  171. X                st1.st_dev != st2.st_dev ||
  172. X                st1.st_ino != st2.st_ino) {
  173. X                (void)close(fd);
  174. X                return;
  175. X            }
  176. X            /*
  177. X             * OK, we believe the sender.  We allocate a window and
  178. X             * tell the Macintosh to create that window on its end.
  179. X             * If we have no free windows, then we close the file
  180. X             * descriptor (which will terminate the slave process).
  181. X             */
  182. X            w = PCL_NEWW(0, WC_INTERNAL,
  183. X                  buf.uwip.uwip_newt.uwnt_type,
  184. X                  (nwin_t)0, buf.uwip.uwip_newt.uwnt_id,
  185. X                  fd, (fildes_t)-1);
  186. X            if (w != NULL) {
  187. X                (void)strncpy(w->w_tty,
  188. X                    buf.uwip.uwip_newt.uwnt_pty,
  189. X                    sizeof w->w_tty-1);
  190. X                w->w_tty[5] = 't'; /* switch to "/dev/ttyp?" */
  191. X                utmp_add(w->w_tty);
  192. X            } else
  193. X                (void)close(fd);
  194. X        }
  195. X        break;
  196. X    case UWC_OPTION:
  197. X        w = win_search(buf.uwip.uwip_option.uwop_id,
  198. X            protocol->p_maxwin);
  199. X        if (w != NULL) {
  200. X            opt_extopt((caddr_t)w, &w->w_optdefn,
  201. X                (woptcmd_t)buf.uwip.uwip_option.uwop_cmd,
  202. X                (woption_t)buf.uwip.uwip_option.uwop_opt,
  203. X                (char *)&buf.uwip.uwip_option.uwop_val,
  204. X                (struct netadj *)0);
  205. X        }
  206. X        break;
  207. X    }
  208. X}
  209. X
  210. X
  211. X/*
  212. X * Internet domain
  213. X */
  214. X
  215. Xstatic
  216. Xipc_isinit()
  217. X{
  218. X    register fildes_t sd;
  219. X    register char *cp;
  220. X    struct hostent *h;
  221. X    struct sockaddr_in sin;
  222. X    auto int sinlen;
  223. X    char hostname[32];
  224. X    char *env[2];
  225. X
  226. X    /*
  227. X     * Allocate enough buffers for each file descriptor to have one.
  228. X     * This is overkill.
  229. X     */
  230. X    inet_buf = (struct ipcmsg *)malloc(nfds * sizeof(struct ipcmsg));
  231. X    if (inet_buf == NULL)
  232. X        return;
  233. X
  234. X    /*
  235. X     * Determine our host name and get an Internet stream socket.
  236. X     * We really should specify the protocol here (rather than 0)
  237. X     * but we "know" that it defaults to TCP.
  238. X     */
  239. X    if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  240. X        return;
  241. X    sin.sin_family = AF_INET;
  242. X    sin.sin_port = 0;
  243. X    bzero(sin.sin_zero, sizeof sin.sin_zero);
  244. X    if (gethostname(hostname, sizeof hostname) < 0 || hostname[0] == '\0')
  245. X        (void)strcpy(hostname, "localhost");
  246. X    if ((h = gethostbyname(hostname)) != NULL)
  247. X        bcopy(h->h_addr, (char *)&sin.sin_addr, h->h_length);
  248. X    else
  249. X        sin.sin_addr.s_addr = htonl(0x7f000001L); /* 128.0.0.1 (lo0) */
  250. X    if (bind(sd, &sin, sizeof sin) < 0) {
  251. X        /*
  252. X         * Unable to bind to unspecified port -- try once more with
  253. X         * loopback device.  If we already were using the loopback
  254. X         * device we just suffer the inefficiency of doing this twice.
  255. X         */
  256. X        sin.sin_addr.s_addr = htonl(0x7f000001L);
  257. X        if (bind(sd, &sin, sizeof sin) < 0) {
  258. X            (void)close(sd);
  259. X            return;
  260. X        }
  261. X    }
  262. X
  263. X    /*
  264. X     * Listen for incoming connections
  265. X     */
  266. X    if (listen(sd, NWINDOW) < 0) {
  267. X        (void)close(sd);
  268. X        return;
  269. X    }
  270. X
  271. X    /*
  272. X     * Determine our port number and put our address in the environment.
  273. X     */
  274. X    sinlen = sizeof sin;
  275. X    if (getsockname(sd, (char *)&sin, &sinlen) < 0) {
  276. X        /* huh?  Oh well, give up */
  277. X        (void)close(sd);
  278. X        return;
  279. X    }
  280. X    if ((cp = malloc(sizeof INET_ENV + 1 + 8 + 1 + 5)) == NULL) {
  281. X        /* no memory, give up */
  282. X        (void)close(sd);
  283. X        return;
  284. X    }
  285. X    sprintf(cp, "%s=%08lx.%05u", INET_ENV,
  286. X        ntohl(sin.sin_addr.s_addr), ntohs(sin.sin_port));
  287. X    env[0] = cp;
  288. X    env[1] = (char *)0;
  289. X    env_set(env);
  290. X
  291. X    inet_sd = sd;
  292. X    fdmap[sd].f_type = FDT_ISSOCK;
  293. X    FD_SET(sd, &selmask[0].sm_rd);
  294. X}
  295. X
  296. Xipc_isrecv(sd)
  297. Xregister fildes_t sd;
  298. X{
  299. X    register fildes_t fd;
  300. X    register struct uwipc *uwip;
  301. X    register struct window *w;
  302. X    register uwerr_t uwerr;
  303. X    register int len;
  304. X    struct sockaddr sin;
  305. X    struct uwipc reply;
  306. X    auto int sinlen;
  307. X
  308. X    /*
  309. X     * This routine is called when one of two conditions occur.  It is
  310. X     * called when an outside process tries to establish a steam
  311. X     * Internet connection.
  312. X     *
  313. X     * Later, as soon as data is available, this routine will be
  314. X     * called again to handle the external message (which must be
  315. X     * a "new window" command).
  316. X     */
  317. X    if (sd == inet_sd) {
  318. X        sinlen = sizeof sin;
  319. X        if ((fd = accept(sd, &sin, &sinlen)) >= 0) {
  320. X            (void)fcntl(fd, F_SETFL, FNDELAY);
  321. X            fdmap[fd].f_type = FDT_ISSOCK;
  322. X            fdmap[fd].f_win = (struct window *)0;
  323. X            FD_SET(fd, &selmask[0].sm_rd);
  324. X            inet_buf[fd].im_len = 0;
  325. X        }
  326. X    } else {
  327. X        switch (ipc_getmsg(sd, inet_buf + sd)) {
  328. X        case -1:
  329. X            (void)close(sd);
  330. X            fdmap[sd].f_type = FDT_NONE;
  331. X            FD_CLR(sd, &selmask[0].sm_rd);
  332. X            FD_CLR(sd, &selmask[0].sm_wt);
  333. X            FD_CLR(sd, &selmask[0].sm_ex);
  334. X            break;
  335. X        case 1:
  336. X            uwip = &inet_buf[sd].im_msg;
  337. X            uwerr = UWE_NONE;
  338. X            if ((uwip->uwip_len < sizeof(struct uwneww) + 
  339. X                ((char *)&uwip->uwip_neww - (char *)uwip)) ||
  340. X                uwip->uwip_cmd != UWC_NEWW) {
  341. X                uwerr = UWE_NXTYPE;
  342. X            } else {
  343. X                fd = ipc_ctlopen(sd,
  344. X                    (unsigned)uwip->uwip_neww.uwnw_ctlport);
  345. X                w = PCL_NEWW(0, WC_EXTERNAL,
  346. X                      ntohs(uwip->uwip_neww.uwnw_type),
  347. X                      (nwin_t)0, ntohl(uwip->uwip_neww.uwnw_id),
  348. X                      sd, fd);
  349. X                if (w == (struct window *)0)
  350. X                    uwerr = UWE_NXTYPE;    /* for now */
  351. X                else
  352. X                    uwerr = UWE_NONE;
  353. X            }
  354. X            len = sizeof(struct uwstatus) +
  355. X                ((char *)&reply.uwip_status - (char *)&reply);
  356. X            reply.uwip_len = htons(len);
  357. X            reply.uwip_cmd = htons(UWC_STATUS);
  358. X            reply.uwip_status.uwst_err = htons(uwerr);
  359. X            reply.uwip_status.uwst_errno = htons(errno);
  360. X            if (uwerr == UWE_NONE)
  361. X                reply.uwip_status.uwst_id = htonl(w->w_id);
  362. X            else
  363. X                reply.uwip_status.uwst_id = 0;
  364. X            (void)write(sd, (char *)&reply, len);
  365. X            if (uwerr != UWE_NONE) {
  366. X                (void)close(sd);
  367. X                fdmap[sd].f_type = FDT_NONE;
  368. X                FD_CLR(sd, &selmask[0].sm_rd);
  369. X                FD_CLR(sd, &selmask[0].sm_wt);
  370. X                FD_CLR(sd, &selmask[0].sm_ex);
  371. X            }
  372. X            inet_buf[sd].im_len = 0;
  373. X        }
  374. X    }
  375. X}
  376. X
  377. Xipc_ctlopen(sd, port)
  378. Xfildes_t sd;
  379. Xunsigned port;
  380. X{
  381. X    register int fd;
  382. X    auto struct sockaddr_in sin;
  383. X    auto int sinlen;
  384. X
  385. X    /*
  386. X     * Create a control socket and connect it to the same host as
  387. X     * "sd" on the specified port.
  388. X     */
  389. X    sinlen = sizeof sin;
  390. X    if (port == 0 ||
  391. X        getpeername(sd, (struct sockaddr *)&sin, &sinlen) < 0 ||
  392. X        (fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  393. X        return(-1);
  394. X    } else {
  395. X        sin.sin_port = port;
  396. X        (void)fcntl(fd, F_SETFL, FNDELAY);
  397. X        if (connect(fd, &sin, sinlen) < 0 && errno != EINPROGRESS) {
  398. X            (void)close(fd);
  399. X            return(-1);
  400. X        } else
  401. X            return(fd);
  402. X    }
  403. X}
  404. X
  405. Xvoid
  406. Xipc_optmsg(win, optcmd, optnum, data, datalen)
  407. Xcaddr_t win;
  408. Xwoptcmd_t optcmd;
  409. Xwoption_t optnum;
  410. Xchar *data;
  411. Xunsigned datalen;
  412. X{
  413. X    register struct window *w;
  414. X    register int len;
  415. X    struct uwipc uwip;
  416. X
  417. X    /*
  418. X     * Propagate a window option message (WILL, WONT, SET) from the Mac
  419. X     * to the remote process (external windows only).
  420. X     */
  421. X    if ((w = (struct window *)win) != NULL && w->w_alloc &&
  422. X        w->w_class == WC_EXTERNAL && w->w_ctlfd >= 0 &&
  423. X        optnum <= WONUM_MAX && (optcmd == WOC_WILL || optcmd == WOC_WONT ||
  424. X         (optcmd == WOC_SET && data != NULL))) {
  425. X        len = datalen +
  426. X            ((char *)&uwip.uwip_option.uwop_val - (char *)&uwip);
  427. X        uwip.uwip_len = htons(len);
  428. X        uwip.uwip_cmd = htons(UWC_OPTION);
  429. X        uwip.uwip_option.uwop_id = htonl(w->w_id);
  430. X        uwip.uwip_option.uwop_opt = htons(optnum);
  431. X        uwip.uwip_option.uwop_cmd = htons(optcmd);
  432. X        if (optcmd == WOC_SET) {
  433. X            bcopy(data, (char *)&uwip.uwip_option.uwop_val,
  434. X                (int)datalen);
  435. X            opt_netadj(w->w_optdefn.wod_optlst[optnum].wol_argdefn,
  436. X                (char *)&uwip.uwip_option.uwop_val, na_hton);
  437. X        }
  438. X        (void)write(w->w_ctlfd, (char *)&uwip, len);
  439. X    }
  440. X}
  441. X
  442. Xipc_ctlrecv(mfd, sd, win)
  443. Xfildes_t mfd;
  444. Xregister fildes_t sd;
  445. Xregister struct window *win;
  446. X{
  447. X    register struct window *w;
  448. X    register struct uwipc *uwip;
  449. X
  450. X    switch (ipc_getmsg(sd, inet_buf + sd)) {
  451. X    case -1:
  452. X        (void)close(sd);
  453. X        fdmap[sd].f_type = FDT_NONE;
  454. X        FD_CLR(sd, &selmask[0].sm_rd);
  455. X        FD_CLR(sd, &selmask[0].sm_wt);
  456. X        FD_CLR(sd, &selmask[0].sm_ex);
  457. X        break;
  458. X    case 1:
  459. X        uwip = &inet_buf[sd].im_msg;
  460. X        switch (uwip->uwip_cmd) {
  461. X        case UWC_KILLW:
  462. X            if ((uwip->uwip_len == sizeof(struct uwkillw) + 
  463. X                ((char *)&uwip->uwip_killw - (char *)uwip))) {
  464. X                w = win_search(ntohl(uwip->uwip_killw.uwkw_id),
  465. X                    protocol->p_maxwin);
  466. X                if (w == win)
  467. X                    PCL_KILLW(mfd, w);
  468. X            }
  469. X            break;
  470. X        case UWC_OPTION:
  471. X            /* hope the message is long enough... sigh */
  472. X            if (uwip->uwip_len > 
  473. X             ((char *)&uwip->uwip_option.uwop_val - (char *)uwip)) {
  474. X                w = win_search(ntohl(uwip->uwip_option.uwop_id),
  475. X                    protocol->p_maxwin);
  476. X                if (w == win) {
  477. X                    opt_extopt((caddr_t)w, &w->w_optdefn,
  478. X                        (woptcmd_t)ntohs(uwip->uwip_option.uwop_cmd),
  479. X                        (woption_t)ntohs(uwip->uwip_option.uwop_opt),
  480. X                        (char *)&uwip->uwip_option.uwop_val,
  481. X                        na_ntoh);
  482. X                }
  483. X            }
  484. X            break;
  485. X        }
  486. X        inet_buf[sd].im_len = 0;
  487. X    }
  488. X}
  489. X
  490. Xipc_getmsg(sd, im)
  491. Xregister fildes_t sd;
  492. Xregister struct ipcmsg *im;
  493. X{
  494. X    register int len;
  495. X    register char *cp;
  496. X
  497. X    /*
  498. X     * Read some more bytes from socket "sd" into the message buffer
  499. X     * contained in "im".  Return 1 if the message is now complete,
  500. X     * -1 if an EOF was reached, or 0 otherwise.  Before returning 1,
  501. X     * the byte order of the common parameters (command, length) is
  502. X     * changed from network to host order.
  503. X     *
  504. X     * This routine expects the socket to use non-blocking I/O (which
  505. X     * is enabled by ipc_isrecv() when the connection is accepted).
  506. X     */
  507. X    cp = (char *)&im->im_msg + im->im_len;
  508. X    if (im->im_len < sizeof(im->im_msg.uwip_len)) {
  509. X        len = read(sd, cp, sizeof im->im_msg.uwip_len - im->im_len);
  510. X        if (len == 0 || (len < 0 && errno != EWOULDBLOCK))
  511. X            return(-1);
  512. X        if ((im->im_len += len) < sizeof im->im_msg.uwip_len)
  513. X            return(0);
  514. X        im->im_msg.uwip_len = ntohs(im->im_msg.uwip_len);
  515. X        if (im->im_msg.uwip_len == sizeof im->im_msg.uwip_len)
  516. X            return(1);
  517. X        cp += len;
  518. X    }
  519. X    if (im->im_msg.uwip_len > sizeof(struct ipcmsg))
  520. X        im->im_msg.uwip_len = sizeof(struct ipcmsg);
  521. X    len = read(sd, cp, im->im_msg.uwip_len - im->im_len);
  522. X    if (len == 0)
  523. X        return(-1);
  524. X    if (len < 0)
  525. X        return((errno==EWOULDBLOCK) ? 0 : -1);
  526. X    if ((im->im_len += len) == im->im_msg.uwip_len) {
  527. X        im->im_msg.uwip_cmd = ntohs(im->im_msg.uwip_cmd);
  528. X        return(1);
  529. X    } else
  530. X        return(0);
  531. X}
  532. !EOF!server/uw_ipc.c!
  533. echo x - server/uw_opt.c
  534. sed -e 's/^X//' > server/uw_opt.c << '!EOF!server/uw_opt.c!'
  535. X/*
  536. X *    uw_opt - window option handling for UW
  537. X *
  538. X * Copyright 1986 by John D. Bruner.  All rights reserved.  Permission to
  539. X * copy this program is given provided that the copy is not sold and that
  540. X * this copyright notice is included.
  541. X */
  542. X
  543. X#include <sys/types.h>
  544. X
  545. X#include "uw_param.h"
  546. X#include "uw_opt.h"
  547. X
  548. X/*
  549. X * The following variable is a kludge for efficiency.  It is set to
  550. X * a nonzero value when a bitmask is changed, indicating that opt_scan()
  551. X * should be called.
  552. X */
  553. Xint calloptscan;            /* pending,do,dont awaits opt_scan */
  554. X
  555. X/* option input state variables */
  556. Xstatic caddr_t optwin;            /* window */
  557. Xstatic struct woptdefn *optwod;        /* window option definition */
  558. Xstatic woptcmd_t optcmd;        /* option command */
  559. Xstatic woption_t optnum;        /* current option number */
  560. Xstatic woptarg_t *optarg;        /* current encoding */
  561. Xstatic int optcnt;            /* count in current encoding */
  562. Xstatic char *optout;            /* decoded option */
  563. Xstatic char optbuf[512];        /* buffer for decoded option */
  564. X
  565. Xopt_new(wod, generic, unique)
  566. Xregister struct woptdefn *wod, *generic, *unique;
  567. X{
  568. X    register int n, mask;
  569. X
  570. X    /*
  571. X     * Set up the option definition structure pointed to by "wod" to
  572. X     * correspond with the option definitions in "generic" (common to
  573. X     * all window types) and "unique" (per-window).
  574. X     */
  575. X    mask = (1<<(WONUM_GENERIC+1))-1;
  576. X    if (unique) {
  577. X        wod->wod_askrpt = unique->wod_askrpt & ~mask;
  578. X        wod->wod_pending = unique->wod_pending & ~mask;
  579. X        for (n=WONUM_GENERIC+1; n <= WONUM_MAX; n++)
  580. X            wod->wod_optlst[n] = unique->wod_optlst[n];
  581. X    } else {
  582. X        wod->wod_askrpt = 0;
  583. X        wod->wod_pending = 0;
  584. X        for (n=WONUM_GENERIC+1; n <= WONUM_MAX; n++)
  585. X            wod->wod_optlst[n].wol_argdefn = (woptarg_t *)0;
  586. X    }
  587. X    if (generic) {
  588. X        wod->wod_askrpt |= generic->wod_askrpt & mask;
  589. X        wod->wod_pending |= generic->wod_pending & mask;
  590. X        for (n=1; n <= WONUM_GENERIC; n++)
  591. X            wod->wod_optlst[n] = generic->wod_optlst[n];
  592. X    } else {
  593. X        for (n=1; n <= WONUM_GENERIC; n++)
  594. X            wod->wod_optlst[n].wol_argdefn = (woptarg_t *)0;
  595. X    }
  596. X    wod->wod_do = wod->wod_askrpt;
  597. X    wod->wod_dont = 0;
  598. X    wod->wod_inquire = 0;
  599. X    calloptscan = 1;
  600. X}
  601. X
  602. Xopt_renew(wod, report)
  603. Xregister struct woptdefn *wod;
  604. Xint report;
  605. X{
  606. X    /*
  607. X     * Reset "wod_do" for all window options that we want the Macintosh
  608. X     * to report to us.  If "report" is nonzero, send the Mac the
  609. X     * current values of these options.
  610. X     */
  611. X    wod->wod_do = wod->wod_askrpt;
  612. X    wod->wod_dont = 0;
  613. X    if (report)
  614. X        wod->wod_pending = wod->wod_askrpt;
  615. X    calloptscan = 1;
  616. X}
  617. X
  618. Xopt_newtype(wod, generic, unique)
  619. Xregister struct woptdefn *wod, *generic, *unique;
  620. X{
  621. X    register int n, bit;
  622. X    register woptbmask_t oldask;
  623. X
  624. X    /*
  625. X     * Change the window options to reflect a new window emulation type.
  626. X     * The new emulation may not support all of the events that the old
  627. X     * one did, and in any event they may not mean the same thing.
  628. X     */
  629. X    oldask = wod->wod_askrpt;
  630. X    opt_new(wod, generic, unique);
  631. X    for (n=1, bit=2; n <= WONUM_GENERIC; n++,bit<<=1) {
  632. X        if ((oldask&bit) && !(wod->wod_askrpt&bit))
  633. X            wod->wod_dont |= bit;
  634. X        if (!(oldask&bit) && (wod->wod_askrpt&bit))
  635. X            wod->wod_do |= bit;
  636. X    }
  637. X    for ( ; n <= WONUM_MAX; n++, bit<<=1)
  638. X        if (wod->wod_askrpt&bit)
  639. X            wod->wod_do |= bit;
  640. X    calloptscan = 1;
  641. X}
  642. X
  643. Xopt_setext(wod, fn)
  644. Xregister struct woptdefn *wod;
  645. Xregister void (*fn)();
  646. X{
  647. X    register int n;
  648. X
  649. X    /*
  650. X     * Set "wol_ext" to "fn" for each option that has a defined "wol_set".
  651. X     */
  652. X    for (n=1; n <= WONUM_MAX; n++)
  653. X        if (wod->wod_optlst[n].wol_set)
  654. X            wod->wod_optlst[n].wol_ext = fn;
  655. X}
  656. X
  657. Xopt_scan(w, wod, fn, mfd, cmd)
  658. Xcaddr_t w;
  659. Xregister struct woptdefn *wod;
  660. Xvoid (*fn)();
  661. Xfildes_t mfd;
  662. Xint cmd;
  663. X{
  664. X    register struct woptlst *wol;
  665. X    register char *cp;
  666. X    register int n, bit, maxsize;
  667. X    char buf[512];
  668. X
  669. X    /*
  670. X     * Scan the entire list of options for pending ones.  For each
  671. X     * one, call "fn".  "cmd" is the command that we are to pass as the
  672. X     * first argument to "fn".
  673. X     *
  674. X     * Note that we must send data (wod_pending) before processing
  675. X     * DO commands (wod_do); otherwise, the host and Mac may not
  676. X     * agree upon the value of a window option.  (The Mac might
  677. X     * respond to the "do" command before it sees the new value.)
  678. X     */
  679. X    cp = buf;
  680. X#ifdef notdef
  681. X    for (n=1,bit=2,wol=wod->wod_optlst+1; n<=WONUM_MAX; n++,bit<<=1,wol++) {
  682. X#else
  683. X    for (n=WONUM_MAX, bit=(1<<WONUM_MAX), wol=wod->wod_optlst+WONUM_MAX;
  684. X         n > 0;
  685. X         n--, bit >>= 1, wol--) {
  686. X#endif
  687. X        if (wod->wod_pending&bit) {
  688. X            wod->wod_pending &= ~bit;
  689. X            if (wol->wol_argdefn) {
  690. X                maxsize = 2 +
  691. X                    opt_size(wol->wol_argdefn);
  692. X                if (cp > buf + sizeof buf - maxsize - 1) {
  693. X                    *cp++ = 0;
  694. X                    (*fn)(mfd, cmd, buf, cp-buf);
  695. X                    cp = buf;
  696. X                }
  697. X                if (WONUM_USELONG(n)) {
  698. X                    *cp++ = WOC_SET|WONUM_LPREFIX;
  699. X                    *cp++ = WONUM_LENCODE(n);
  700. X                } else
  701. X                    *cp++ = WOC_SET|WONUM_SENCODE(n);
  702. X                cp += opt_encode(cp, wol->wol_argdefn,
  703. X                    (*wol->wol_get)(w, n));
  704. X            }
  705. X        }
  706. X        if (wod->wod_inquire&bit) {
  707. X            wod->wod_inquire &= ~bit;
  708. X            if (cp > buf + sizeof buf - 3) {
  709. X                *cp++ = 0;
  710. X                (*fn)(mfd, cmd, buf, cp-buf);
  711. X                cp = buf;
  712. X            }
  713. X            if (wol->wol_argdefn) {
  714. X                if (WONUM_USELONG(n)) {
  715. X                    *cp++ = WOC_INQUIRE|WONUM_LPREFIX;
  716. X                    *cp++ = WONUM_LENCODE(n);
  717. X                } else
  718. X                    *cp++ = WOC_INQUIRE|WONUM_SENCODE(n);
  719. X            }
  720. X        }
  721. X        if ((wod->wod_do|wod->wod_dont)&bit) {
  722. X            if (cp > buf + sizeof buf - 3) {
  723. X                *cp++ = 0;
  724. X                (*fn)(mfd, cmd, buf, cp-buf);
  725. X                cp = buf;
  726. X            }
  727. X            if (wod->wod_do&bit) {
  728. X                wod->wod_do &= ~bit;
  729. X                wod->wod_dont &= ~bit;
  730. X                if (wol->wol_argdefn) {
  731. X                    if (WONUM_USELONG(n)) {
  732. X                        *cp++ = WOC_DO|WONUM_LPREFIX;
  733. X                        *cp++ = WONUM_LENCODE(n);
  734. X                    } else
  735. X                        *cp++ = WOC_DO|WONUM_SENCODE(n);
  736. X                }
  737. X            } else if (wod->wod_dont&bit) {
  738. X                wod->wod_do &= ~bit;
  739. X                wod->wod_dont &= ~bit;
  740. X                if (wol->wol_argdefn) {
  741. X                    if (WONUM_USELONG(n)) {
  742. X                        *cp++ = WOC_DONT|WONUM_LPREFIX;
  743. X                        *cp++ = WONUM_LENCODE(n);
  744. X                    } else
  745. X                        *cp++=WOC_DONT|WONUM_SENCODE(n);
  746. X                }
  747. X            }
  748. X        }
  749. X        if (cp > buf) {
  750. X            *cp++ = 0;
  751. X            (*fn)(mfd, cmd, buf, cp-buf);
  752. X            cp = buf;
  753. X        }
  754. X    }
  755. X}
  756. X
  757. Xopt_size(woa)
  758. Xregister woptarg_t *woa;
  759. X{
  760. X    register int size, cnt;
  761. X
  762. X    /*
  763. X     * Determine the maximum size of an option whose argument encoding
  764. X     * is specified by "woa".  This does NOT include additional encoding
  765. X     * (e.g. for meta characters) at the protocol level.
  766. X     */
  767. X    if (woa) {
  768. X        for (size=0; *woa != WOA_END; woa++) {
  769. X            cnt = *woa & ~WOA_CMDMASK;
  770. X            switch (*woa & WOA_CMDMASK) {
  771. X            case WOA_CHARS(0):
  772. X            case WOA_STRING(0):
  773. X                size += cnt;
  774. X                break;
  775. X            case WOA_UDATA(0):
  776. X                size += (cnt + 5) / 6;
  777. X                break;
  778. X            }
  779. X        }
  780. X    } else
  781. X        size = 0;
  782. X    return(size);
  783. X}
  784. X
  785. Xopt_encode(buf, woa, data)
  786. Xchar *buf;
  787. Xregister woptarg_t *woa;
  788. Xchar *data;
  789. X{
  790. X    register char *cp, *cq;
  791. X    register int n, cnt;
  792. X    register unsigned long ival;
  793. X    union {
  794. X        struct {
  795. X            char    c1;
  796. X            short    s;
  797. X        }    cs;
  798. X        struct {
  799. X            char    c2;
  800. X            long    l;
  801. X        }    cl;
  802. X    } u;
  803. X
  804. X    /*
  805. X     * Encode "data" according to the option argument specifier "woa"
  806. X     * into the buffer "buf".  Return the number of bytes of "buf"
  807. X     * actually used.  The caller has already verified that "buf" is
  808. X     * large enough.
  809. X     */
  810. X    if (!data)
  811. X        return(0);
  812. X    for (cp=buf,cq=data; *woa != WOA_END; woa++) {
  813. X        cnt = *woa & ~WOA_CMDMASK;
  814. X        switch (*woa & WOA_CMDMASK) {
  815. X        case WOA_CHARS(0):
  816. X            for (n=0; n < cnt; n++)
  817. X                *cp++ = *cq++;
  818. X            break;
  819. X        case WOA_STRING(0):
  820. X            for (n=0; n < cnt-1 && *cq; n++)
  821. X                *cp++ = *cq++;
  822. X            if (n < cnt)
  823. X                cq += cnt-n;
  824. X            *cp++ = '\0';
  825. X            break;
  826. X        case WOA_UDATA(0):
  827. X            if (cnt <= NBBY) {
  828. X                ival = (unsigned char)*cq++;
  829. X            } else if (cnt <= sizeof(short)*NBBY) {
  830. X                while ((int)cq & ((char *)&u.cs.s-&u.cs.c1-1))
  831. X                    cq++;
  832. X                ival = *(unsigned short *)cq;
  833. X                cq += sizeof(short);
  834. X            } else {
  835. X                while ((int)cq & ((char *)&u.cl.l-&u.cl.c2-1))
  836. X                    cq++;
  837. X                ival = *(unsigned long *)cq;
  838. X                cq += sizeof(long);
  839. X            }
  840. X            if (cnt != sizeof(long)*NBBY)
  841. X                ival &= (1<<cnt) - 1;
  842. X            for (n=0; n < cnt; n += 6, ival >>= 6)
  843. X                *cp++ = (ival & 077) | 0100;
  844. X            break;
  845. X        }
  846. X    }
  847. X    return(cp-buf);
  848. X}
  849. X            
  850. Xopt_istart(w, wod)
  851. Xcaddr_t w;
  852. Xstruct woptdefn *wod;
  853. X{
  854. X    /*
  855. X     * Start collecting input for a window option specification.
  856. X     */
  857. X    optwin = w;
  858. X    optwod = wod;
  859. X    optnum = 0;
  860. X}
  861. X
  862. Xopt_input(c)
  863. Xchar c;
  864. X{
  865. X    register int cnt, bit;
  866. X    register struct woptdefn *wod;
  867. X    register struct woptlst *wol;
  868. X    register unsigned long ival;
  869. X    union {
  870. X        struct {
  871. X            char    c1;
  872. X            short    s;
  873. X        }    cs;
  874. X        struct {
  875. X            char    c2;
  876. X            long    l;
  877. X        }    cl;
  878. X    } u;
  879. X
  880. X    /*
  881. X     * Add the received character "c" to the current option specification.
  882. X     * If it is complete, take the appropriate action.  If option 0
  883. X     * (the endmarker) is received, return 0 (to notify the caller that
  884. X     * we are done).  Otherwise, return 1 -- more option data remains
  885. X     * to be processed.
  886. X     *
  887. X     * This code isn't as readable as it should be; there are far too
  888. X     * many return statements floating around.  Sorry about that.
  889. X     */
  890. X    if (optwin) {
  891. X        wod = optwod;
  892. X        if (optnum == 0 || optnum == WONUM_MAX+1) {
  893. X            /* start (or continue) decoding a new option */
  894. X            if (optnum == 0) {
  895. X                /* start new option (or decode endmarker) */
  896. X                if (c & WONUM_MASK) {
  897. X                    /* new option */
  898. X                    optcmd = c & WOC_MASK;
  899. X                    if (WOC_BADCMD(optcmd)) {
  900. X                        opt_iflush();
  901. X                        return(0);
  902. X                    }
  903. X                    if (c == WONUM_LPREFIX) {
  904. X                        optnum = WONUM_MAX+1;
  905. X                        return(1);
  906. X                    } else
  907. X                        optnum = WONUM_SDECODE(c);
  908. X                } else {
  909. X                    /* end of options */
  910. X                    opt_iflush();
  911. X                    return(0);
  912. X                }
  913. X            } else {
  914. X                /* read second byte of long option number */
  915. X                optnum = WONUM_LDECODE(c);
  916. X                if (optnum > WONUM_MAX) {
  917. X                    opt_iflush();
  918. X                    return(0);
  919. X                }
  920. X            }
  921. X            /*
  922. X             * This point is reached when the option number has
  923. X             * been completely decoded.  If the command is not
  924. X             * WOC_SET, then it has no arguments and we can
  925. X             * process it immediately.
  926. X             */
  927. X            wol = &wod->wod_optlst[optnum];
  928. X            bit = 1<<optnum;
  929. X            if (optcmd == WOC_SET) {
  930. X                optout = optbuf;
  931. X                optcnt = 0;
  932. X                optarg = wol->wol_argdefn;
  933. X                if (!optarg) {
  934. X                    opt_iflush();
  935. X                    return(0);
  936. X                }
  937. X            } else {
  938. X                if (wol->wol_ext &&
  939. X                    (optcmd == WOC_WILL || optcmd == WOC_WONT))
  940. X                    (*wol->wol_ext)(optwin, optcmd,
  941. X                        optnum, (char *)0, 0);
  942. X                switch (optcmd) {
  943. X                case WOC_INQUIRE:
  944. X                    wod->wod_pending |= bit;
  945. X                    calloptscan = 1;
  946. X                    break;
  947. X                case WOC_DO:
  948. X                case WOC_DONT:
  949. X                    break;
  950. X                case WOC_WILL:
  951. X                    wod->wod_askrpt |= bit;
  952. X                    wod->wod_do &= ~bit;
  953. X                    break;
  954. X                case WOC_WONT:
  955. X                    wod->wod_askrpt &= ~bit;
  956. X                    wod->wod_dont &= ~bit;
  957. X                    break;
  958. X                }
  959. X                optnum = 0;
  960. X            }
  961. X            return(1);
  962. X        } else {
  963. X            /* continue processing argument to option */
  964. X            wol = &wod->wod_optlst[optnum];
  965. X            bit = 1<<optnum;
  966. X            cnt = *optarg & ~WOA_CMDMASK;
  967. X            switch (*optarg & WOA_CMDMASK) {
  968. X            case WOA_CHARS(0):
  969. X                *optout++ = c;
  970. X                optcnt++;
  971. X                break;
  972. X            case WOA_STRING(0):
  973. X                *optout++ = c;
  974. X                optcnt++;
  975. X                if (!c) {
  976. X                    optout += cnt - optcnt;
  977. X                    optcnt = cnt;
  978. X                } else if (optcnt == cnt-1) {
  979. X                    *optout++ = '\0';
  980. X                    optcnt = cnt;
  981. X                }
  982. X                break;
  983. X            case WOA_UDATA(0):
  984. X                if (optcnt == 0) {
  985. X                    if (cnt <= NBBY) {
  986. X                        *optout = 0;
  987. X                    } else if (cnt <= sizeof(short)*NBBY) {
  988. X                        while ((int)optout & ((char *)&u.cs.s-&u.cs.c1-1))
  989. X                            optout++;
  990. X                        *(short *)optout = 0;
  991. X                    } else {
  992. X                        while ((int)optout & ((char *)&u.cl.l-&u.cl.c2-1))
  993. X                            optout++;
  994. X                        *(long *)optout = 0;
  995. X                    }
  996. X                }
  997. X                ival = (c & 077) << optcnt;
  998. X                if (cnt != NBBY*sizeof(long))
  999. X                    ival &= (1<<cnt) - 1;
  1000. X                optcnt += 6;
  1001. X                if (cnt <= NBBY) {
  1002. X                    *(unsigned char *)optout |= (unsigned char)ival;
  1003. X                    if (optcnt >= cnt)
  1004. X                        optout++;
  1005. X                } else if (cnt <= sizeof(short)*NBBY) {
  1006. X                    *(unsigned short *)optout |= (unsigned short)ival;
  1007. X                    if (optcnt >= cnt)
  1008. X                        optout += sizeof(short);
  1009. X                } else {
  1010. X                    *(unsigned long *)optout |= ival;
  1011. X                    if (optcnt >= cnt)
  1012. X                        optout += sizeof(long);
  1013. X                }
  1014. X                break;
  1015. X            }
  1016. X            if (optcnt >= cnt) {
  1017. X                optcnt = 0;
  1018. X                if (*++optarg == WOA_END) {
  1019. X                    wod->wod_pending &= ~bit;
  1020. X                    (*wol->wol_set)(optwin, optnum, optbuf);
  1021. X                    if (wol->wol_ext) {
  1022. X                        (*wol->wol_ext)(optwin, WOC_SET,
  1023. X                            optnum, optbuf,
  1024. X                            optout-optbuf);
  1025. X                    }
  1026. X                    optnum = 0;
  1027. X                }
  1028. X            }
  1029. X            return(1);
  1030. X        }
  1031. X        /*NOTREACHED*/
  1032. X    }
  1033. X    return(0);
  1034. X}
  1035. X
  1036. Xopt_iflush()
  1037. X{
  1038. X    optwin = (caddr_t)0;
  1039. X}
  1040. X
  1041. Xopt_extopt(w, wod, cmd, num, data, na)
  1042. Xcaddr_t w;
  1043. Xregister struct woptdefn *wod;
  1044. Xwoptcmd_t cmd;
  1045. Xwoption_t num;
  1046. Xchar *data;
  1047. Xstruct netadj *na;
  1048. X{
  1049. X    register struct woptlst *wol;
  1050. X
  1051. X    if (w != NULL && wod != NULL && num <= WONUM_MAX) {
  1052. X        wol = wod->wod_optlst + num;
  1053. X        if (wol->wol_argdefn) {
  1054. X            switch (cmd) {
  1055. X            case WOC_SET:
  1056. X                if (data && wol->wol_set) {
  1057. X                    if (na) {
  1058. X                        opt_netadj(wol->wol_argdefn,
  1059. X                            data, na);
  1060. X                    }
  1061. X                    /*
  1062. X                     * Set the new value and notify the Mac.
  1063. X                     * Because of a race condition (the Mac
  1064. X                     * might concurrently be sending us its
  1065. X                     * value for this option), we ask the
  1066. X                     * Mac to send back the value after it
  1067. X                     * is set.
  1068. X                     */
  1069. X                    (*wol->wol_set)(w, num, data);
  1070. X                    WOPT_SET(wod->wod_pending, num);
  1071. X                    WOPT_SET(wod->wod_inquire, num);
  1072. X                    calloptscan = 1;
  1073. X                }
  1074. X                break;
  1075. X            case WOC_INQUIRE:
  1076. X                WOPT_SET(wod->wod_inquire, num);
  1077. X                calloptscan = 1;
  1078. X                break;
  1079. X            case WOC_DO:
  1080. X                WOPT_SET(wod->wod_do, num);
  1081. X                WOPT_SET(wod->wod_askrpt, num);
  1082. X                calloptscan = 1;
  1083. X                break;
  1084. X            case WOC_DONT:
  1085. X                WOPT_SET(wod->wod_dont, num);
  1086. X                WOPT_CLR(wod->wod_askrpt, num);
  1087. X                calloptscan = 1;
  1088. X                break;
  1089. X            }
  1090. X        }
  1091. X    }
  1092. X}
  1093. X
  1094. Xopt_netadj(woa, data, na)
  1095. Xregister woptarg_t *woa;
  1096. Xchar *data;
  1097. Xregister struct netadj *na;
  1098. X{
  1099. X    register char *cp;
  1100. X    register int cnt;
  1101. X    union {
  1102. X        struct {
  1103. X            char    c1;
  1104. X            short    s;
  1105. X        }    cs;
  1106. X        struct {
  1107. X            char    c2;
  1108. X            long    l;
  1109. X        }    cl;
  1110. X    } u;
  1111. X
  1112. X    /*
  1113. X     * Convert an option (in internal format) from host byte order
  1114. X     * to network byte order.  If the two are the same then this is
  1115. X     * a NOP.
  1116. X     */
  1117. X    if (data && na) {
  1118. X        for (cp=data; *woa != WOA_END; woa++) {
  1119. X            cnt = *woa & ~WOA_CMDMASK;
  1120. X            switch (*woa & WOA_CMDMASK) {
  1121. X            case WOA_CHARS(0):
  1122. X            case WOA_STRING(0):
  1123. X                cp += cnt;
  1124. X                break;
  1125. X            case WOA_UDATA(0):
  1126. X                if (cnt <= NBBY) {
  1127. X                    cp++;
  1128. X                } else if (cnt <= sizeof(short)*NBBY) {
  1129. X                    while ((int)cp & ((char *)&u.cs.s-&u.cs.c1-1))
  1130. X                        cp++;
  1131. X                    *(u_short *)cp =
  1132. X                        (*na->na_ushort)(*(u_short *)cp);
  1133. X                    cp += sizeof(short);
  1134. X                } else {
  1135. X                    while ((int)cp & ((char *)&u.cl.l-&u.cl.c2-1))
  1136. X                        cp++;
  1137. X                    *(u_short *)cp =
  1138. X                        (*na->na_ushort)(*(u_short *)cp);
  1139. X                    cp += sizeof(long);
  1140. X                }
  1141. X            }
  1142. X        }
  1143. X    }
  1144. X}
  1145. !EOF!server/uw_opt.c!
  1146. echo x - server/uw_pcl.c
  1147. sed -e 's/^X//' > server/uw_pcl.c << '!EOF!server/uw_pcl.c!'
  1148. X/*
  1149. X *    uw_pcl - protocol handling for UW
  1150. X *
  1151. X * Copyright 1985,1986 by John D. Bruner.  All rights reserved.  Permission to
  1152. X * copy this program is given provided that the copy is not sold and that
  1153. X * this copyright notice is included.
  1154. X */
  1155. X
  1156. X#include <sys/types.h>
  1157. X#include <sys/ioctl.h>
  1158. X#include <errno.h>
  1159. X
  1160. X#include "uw_param.h"
  1161. X#include "uw_clk.h"
  1162. X#include "uw_opt.h"
  1163. X#include "uw_win.h"
  1164. X#include "uw_pcl.h"
  1165. X#include "openpty.h"
  1166. X
  1167. X#define    XON    0021            /* ASCII XON */
  1168. X#define    XOFF    0023            /* ASCII XOFF */
  1169. X#define    RUB    0177            /* ASCII RUBout */
  1170. X#define    META    0200            /* "meta" bit for whatever it's worth */
  1171. X
  1172. X/*
  1173. X * Protocol negotiation is performed by a finite state machine (implemented
  1174. X * in pcl_haggle()).  The states are defined as the enumerated type
  1175. X * "pnstate_t".  The inputs have type "pnreq_t".
  1176. X */
  1177. Xtypedef enum {
  1178. X    PNST_NOP,            /* no protocol negotiation */
  1179. X    PNST_AWAIT,            /* timing out an ASKPCL */
  1180. X    PNST_CWAIT,            /* timing out a CANPCL */
  1181. X    PNST_OK,            /* negotiations completed */
  1182. X    PNST_FAIL            /* negotiation failed */
  1183. X} pnstate_t;
  1184. X
  1185. Xtypedef unsigned short pnreq_t;        /* finite state machine requests */
  1186. X#define    PNRQ_PCL    0000377        /* protocol mask */
  1187. X#define    PNRQ_CMD    0177400        /* command mask: */
  1188. X#define    PNRQ_NONE    (pnreq_t)(0<<8)    /*    no request */
  1189. X#define    PNRQ_START    (pnreq_t)(1<<8)    /*    start negotiation */
  1190. X#define    PNRQ_AWAIT    (pnreq_t)(2<<8)    /*    timeout waiting for ASKPCL */
  1191. X#define    PNRQ_ASK    (pnreq_t)(3<<8)    /*    process received ASKPCL */
  1192. X#define    PNRQ_CAN    (pnreq_t)(4<<8)    /*    process received CANPCL */
  1193. X#define    PNRQ_SET    (pnreq_t)(5<<8)    /*    process received SETPCL */
  1194. X#define    PNRQ_CWAIT    (pnreq_t)(6<<8)    /*    timeout waiting for CANPCL */
  1195. X#define    PNRQ_INIT    (pnreq_t)(7<<8)    /*    initialize everything */
  1196. X
  1197. Xstatic int p1_ctlch[] = { -1, P1_IAC, XON, XOFF, -1, -1, -1, -1 };
  1198. X
  1199. Xextern void p1_entry(), p1_renew(), p2_renew();
  1200. Xextern struct window *p1_neww(), *p2_neww();
  1201. Xextern void p1_killw(), p1_xmit(), p1_recv();
  1202. Xextern void p1_askpcl(), p1_canpcl(), p1_setpcl();
  1203. Xextern void p2_recv(), p2_chkopt(), p2_sendopt();
  1204. X
  1205. Xstatic struct protocol pcl_table[] = {
  1206. X    {
  1207. X      ' ',
  1208. X      P1_NWINDOW,
  1209. X      p1_ctlch, sizeof p1_ctlch / sizeof p1_ctlch[0],
  1210. X      p1_entry, NULL, p1_renew,
  1211. X      p1_neww, p1_killw,
  1212. X      p1_xmit, p1_recv, NULL, NULL,
  1213. X      p1_askpcl, p1_canpcl, p1_setpcl
  1214. X    },
  1215. X    {
  1216. X      '!',
  1217. X      P2_NWINDOW,
  1218. X      p1_ctlch, sizeof p1_ctlch / sizeof p1_ctlch[0],
  1219. X      p1_entry, NULL, p2_renew,
  1220. X      p2_neww, p1_killw,
  1221. X      p1_xmit, p2_recv, p2_chkopt, p2_sendopt,
  1222. X      p1_askpcl, p1_canpcl, p1_setpcl
  1223. X    },
  1224. X};
  1225. X
  1226. Xstruct protocol *protocol = pcl_table;
  1227. X
  1228. X/*
  1229. X * Two "current" windows are defined: the current input window (for
  1230. X * input from the Macintosh) and the current output window (for output
  1231. X * to the Macintosh).
  1232. X */
  1233. Xstatic struct {
  1234. X    struct window    *in;
  1235. X    struct window    *out;
  1236. X} curwin;
  1237. X
  1238. X
  1239. Xpcl_entry(mfd)
  1240. Xregister fildes_t mfd;
  1241. X{
  1242. X    /*
  1243. X     * This routine is called to start up protocol handling.  We always
  1244. X     * start with protocol 1 (the original UW protocol).
  1245. X     */
  1246. X    protocol = pcl_table;
  1247. X    pcl_haggle(mfd, PNRQ_INIT);
  1248. X    if (protocol->p_entry)
  1249. X        (*protocol->p_entry)(mfd);
  1250. X}
  1251. X
  1252. Xpcl_exit(mfd)
  1253. Xregister fildes_t mfd;
  1254. X{
  1255. X    /*
  1256. X     * This routine is called when we shut down (just before the server
  1257. X     * exits).
  1258. X     */
  1259. X    if (protocol->p_exit)
  1260. X        (*protocol->p_exit)(mfd);
  1261. X    protocol = pcl_table;
  1262. X}
  1263. X
  1264. Xstatic
  1265. Xpcl_newpcl(newproto)
  1266. Xstruct protocol *newproto;
  1267. X{
  1268. X    extern void rc_kludge();
  1269. X
  1270. X    /*
  1271. X     * Switch to new protocol "newproto".  Right now we can get away
  1272. X     * with just changing the value of "protocol".  Eventually we will
  1273. X     * probably want to call protocol-dependent functions to shut down
  1274. X     * the old protocol and start up the new one.
  1275. X     */
  1276. X    protocol = newproto;
  1277. X
  1278. X    /*
  1279. X     * This is a horrible kludge.  See rc_kludge() in "main.c" for
  1280. X     * further details.
  1281. X     */
  1282. X    rc_kludge();
  1283. X}
  1284. X
  1285. Xstatic
  1286. Xvoid
  1287. Xpcl_tohaggle(arg)
  1288. Xregister toarg_t arg;
  1289. X{
  1290. X    /*
  1291. X     * This is a kludge to get around the single-argument restriction
  1292. X     * on clk_timeout.  We split the argument "arg" into two 16-bit
  1293. X     * pieces and invoke pcl_haggle.
  1294. X     */
  1295. X    pcl_haggle((fildes_t)((arg>>16)&0177777), (pnreq_t)(arg&0177777));
  1296. X}
  1297. X
  1298. Xstatic
  1299. Xpcl_haggle(mfd, req)
  1300. Xfildes_t mfd;
  1301. Xregister pnreq_t req;
  1302. X{
  1303. X    register struct protocol *p, *q;
  1304. X    register char pname;
  1305. X    register int request;
  1306. X    static pnstate_t pnstate;
  1307. X    static int waitcnt;
  1308. X
  1309. X    /*
  1310. X     * This routine implements the finite-state machine that handles
  1311. X     * protocol negotiation.  This routine is called by routines which
  1312. X     * recognize incoming protocol commands and at 5 second intervals
  1313. X     * when negotiations are in progress.  The current protocol is
  1314. X     * described by the variable "protocol".
  1315. X     */
  1316. X    if (req == PNRQ_INIT) {
  1317. X        waitcnt = 0;
  1318. X        pnstate = PNST_NOP;
  1319. X        req = PNRQ_NONE;
  1320. X    }
  1321. X    if (!(p = protocol) || !p->p_askpcl || !p->p_canpcl || !p->p_setpcl) {
  1322. X        req = PNRQ_NONE;
  1323. X    } else {
  1324. X        pname = req & PNRQ_PCL;
  1325. X        request = req & PNRQ_CMD;
  1326. X        switch (request) {
  1327. X        case PNRQ_START:    /* start protocol negotiation */
  1328. X            /*
  1329. X             * The Macintosh is responsible for starting protocol
  1330. X             * negotiation (if it wants something other than the
  1331. X             * standard protocol).  This code is present for
  1332. X             * purposes of exposition only.
  1333. X             */
  1334. X            (*p->p_askpcl)(mfd);
  1335. X            req = PNRQ_AWAIT | pname;
  1336. X            waitcnt = 0;
  1337. X            pnstate = PNST_AWAIT;
  1338. X            break;
  1339. X        case PNRQ_AWAIT:    /* timeout an ASKPCL */
  1340. X            /*
  1341. X             * This state also is not reached on the host.
  1342. X             */
  1343. X            if (pnstate == PNST_AWAIT) {
  1344. X                if (++waitcnt > 3) {
  1345. X                    pnstate = PNST_FAIL;
  1346. X                    req = PNRQ_NONE;
  1347. X                } else
  1348. X                    (*p->p_askpcl)(mfd);
  1349. X            } else
  1350. X                req = PNRQ_NONE;
  1351. X            break;
  1352. X        case PNRQ_ASK:        /* handle received ASKPCL */
  1353. X            q = pcl_table+sizeof pcl_table/sizeof pcl_table[0] - 1;
  1354. X            (*p->p_canpcl)(mfd, q->p_name);
  1355. X            pnstate = PNST_CWAIT;
  1356. X            req = PNRQ_CWAIT | q->p_name;
  1357. X            waitcnt = 0;
  1358. X            break;
  1359. X        case PNRQ_CAN:        /* handle received CANPCL */
  1360. X            for (q=pcl_table+sizeof pcl_table/sizeof pcl_table[0]-1;
  1361. X                 q > pcl_table && q->p_name > pname;
  1362. X                 q--)
  1363. X                ;
  1364. X            if (q->p_name == pname || q == pcl_table) {
  1365. X                (*p->p_setpcl)(mfd, q->p_name);
  1366. X                pcl_newpcl(q);
  1367. X                pnstate = PNST_OK;
  1368. X                req = PNRQ_NONE;
  1369. X            } else {
  1370. X                (*p->p_canpcl)(mfd, q->p_name);
  1371. X                pnstate = PNST_CWAIT;
  1372. X                req = PNRQ_CWAIT | q->p_name;
  1373. X                waitcnt = 0;
  1374. X            }
  1375. X            break;
  1376. X        case PNRQ_CWAIT:    /* timeout a CANPCL */
  1377. X            if (pnstate == PNST_CWAIT) {
  1378. X                if (++waitcnt > 3) {
  1379. X                    pnstate = PNST_FAIL;
  1380. X                    req = PNRQ_NONE;
  1381. X                } else
  1382. X                    (*p->p_canpcl)(mfd, pname);
  1383. X            } else
  1384. X                req = PNRQ_NONE;
  1385. X            break;
  1386. X        case PNRQ_SET:        /* handle a received SETPCL */
  1387. X            for (q=pcl_table+sizeof pcl_table/sizeof pcl_table[0]-1;
  1388. X                 q > pcl_table && q->p_name != pname;
  1389. X                 q--)
  1390. X                ;
  1391. X            if (q->p_name == pname) {
  1392. X                pcl_newpcl(q);
  1393. X                pnstate = PNST_OK;
  1394. X                req = PNRQ_NONE;
  1395. X            } else {
  1396. X                /*
  1397. X                 * We are in trouble now -- the Mac has
  1398. X                 * instructed us to switch to a protocol
  1399. X                 * that we can't support.  We switch back
  1400. X                 * to protocol 1 and hope that our message
  1401. X                 * to the Mac (telling it to switch to
  1402. X                 * protocol 1) will be interpreted correctly.
  1403. X                 */
  1404. X                pnstate = PNST_FAIL;
  1405. X                req = PNRQ_NONE;
  1406. X                (*p->p_setpcl)(mfd, ' ');
  1407. X                if (p != pcl_table)
  1408. X                    pcl_newpcl(pcl_table);
  1409. X            }
  1410. X            break;
  1411. X        }
  1412. X        if (req != PNRQ_NONE)
  1413. X            (void)clk_timeout(5*CLK_HZ,
  1414. X                pcl_tohaggle, (toarg_t)(((long)mfd<<16)|req));
  1415. X    }
  1416. X}
  1417. X
  1418. Xstatic
  1419. Xvoid
  1420. Xp1_entry(mfd)
  1421. Xfildes_t mfd;
  1422. X{
  1423. X    static char cmdbuf[2] = { P1_IAC };
  1424. X
  1425. X    cmdbuf[1] = P1_DIR_HTOM|P1_FN_MAINT|P1_MF_ENTRY;
  1426. X    (void)write(mfd, cmdbuf, sizeof cmdbuf);
  1427. X}
  1428. X
  1429. Xstatic
  1430. Xstruct window *
  1431. Xp1_neww(mfd, wclass, wtype, wnum, wid, datafd, ctlfd)
  1432. Xfildes_t mfd;
  1433. Xwclass_t wclass;
  1434. Xwtype_t wtype;
  1435. Xnwin_t wnum;
  1436. Xlong wid;
  1437. Xfildes_t datafd;
  1438. Xfildes_t ctlfd;
  1439. X{
  1440. X    register struct window *w;
  1441. X    static char cmdbuf[2] = { P1_IAC, 0 };
  1442. X
  1443. X    /*
  1444. X     * Create a new window for the host.  This routine is not called when
  1445. X     * the Macintosh creates a window.
  1446. X     */
  1447. X    w = win_neww(wclass, wtype, wnum, protocol->p_maxwin, wid,
  1448. X        datafd, ctlfd, (struct woptdefn *)0);
  1449. X    if (w) {
  1450. X        cmdbuf[1] = P1_DIR_HTOM|P1_FN_NEWW|WIN_NUM(w);
  1451. X        (void)write(mfd, cmdbuf, sizeof cmdbuf);
  1452. X    }
  1453. X    return(w);
  1454. X}
  1455. X
  1456. Xstatic
  1457. Xvoid
  1458. Xp1_killw(mfd, w)
  1459. Xregister struct window *w;
  1460. X{
  1461. X    static char cmdbuf[] = { P1_IAC, P1_DIR_HTOM|P1_FN_KILLW };
  1462. X
  1463. X    /*
  1464. X     * Kill window "w" and tell the Macintosh to do the same.
  1465. X     */
  1466. X    if (w && w->w_alloc) {
  1467. X        if (curwin.in == w)
  1468. X            curwin.in = (struct window *)0;
  1469. X        if (curwin.out == w)
  1470. X            curwin.out = (struct window *)0;
  1471. X        cmdbuf[1] = P1_DIR_HTOM|P1_FN_KILLW|WIN_NUM(w);
  1472. X        (void)write(mfd, cmdbuf, sizeof cmdbuf);
  1473. X        win_killw(w);
  1474. X    }
  1475. X}
  1476. X
  1477. Xstatic
  1478. Xvoid
  1479. Xp1_xmit(mfd, w)
  1480. Xfildes_t mfd;
  1481. Xregister struct window *w;
  1482. X{
  1483. X    register char *cp, *cq;
  1484. X    register int i, len;
  1485. X    char ibuf[32], obuf[32];
  1486. X    static char refresh;
  1487. X    static char cmdbuf[] = { P1_IAC, 0 };
  1488. X    extern int errno;
  1489. X
  1490. X    /*
  1491. X     * Transmit data to the Macintosh (via file descriptor "mfd)
  1492. X     * on behalf of window "w".  Be sure to convert any embedded
  1493. X     * control characters and meta characters.
  1494. X     *
  1495. X     * Note that the input/output buffers should NOT be very large.
  1496. X     * It is undesirable to perform large reads and effectively
  1497. X     * "lock out" all other file descriptors.  The chosen size
  1498. X     * should preserve a reasonable amount of efficiency.
  1499. X     *
  1500. X     * The UW protocol only requires an OSELW command when the
  1501. X     * output window changes.  We issue this command more often
  1502. X     * to "refresh" the Mac's idea of what the output window is.
  1503. X     * This helps (slightly) to overcome spurious output redirects
  1504. X     * caused by a noisy line.
  1505. X     */
  1506. X    if (w && w->w_alloc) {
  1507. X        if (curwin.out != w || ++refresh == 0) {
  1508. X            refresh = 0;
  1509. X            curwin.out = w;
  1510. X            cmdbuf[1] = P1_DIR_HTOM|P1_FN_OSELW|WIN_NUM(w);
  1511. X            (void)write(mfd, cmdbuf, sizeof cmdbuf);
  1512. X        }
  1513. X        cq = obuf;
  1514. X        if ((len = read(w->w_datafd, ibuf, sizeof ibuf)) < 0 &&
  1515. X            errno != EWOULDBLOCK)
  1516. X            (*protocol->p_killw)(mfd, w);
  1517. X        for (cp=ibuf; cp < ibuf+len; cp++) {
  1518. X            if (*cp&META) {
  1519. X                if (cq > obuf) {
  1520. X                    (void)write(mfd, obuf, cq-obuf);
  1521. X                    cq = obuf;
  1522. X                }
  1523. X                cmdbuf[1] = P1_DIR_HTOM|P1_FN_META;
  1524. X                (void)write(mfd, cmdbuf, sizeof cmdbuf);
  1525. X                *cp &= ~META;
  1526. X            }
  1527. X            i = -1;
  1528. X            if (*cp == RUB || *cp < ' ') {
  1529. X                i = protocol->p_szctlch - 1;
  1530. X                while (i >= 0 && protocol->p_ctlch[i] != *cp)
  1531. X                    i--;
  1532. X            }
  1533. X            if (i >= 0) {
  1534. X                if (cq > obuf) {
  1535. X                    (void)write(mfd, obuf, cq-obuf);
  1536. X                    cq = obuf;
  1537. X                }
  1538. X                cmdbuf[1] = P1_DIR_HTOM|P1_FN_CTLCH|i;
  1539. X                (void)write(mfd, cmdbuf, sizeof cmdbuf);
  1540. X            } else {
  1541. X                *cq++ = *cp;
  1542. X                if (cq >= obuf+sizeof obuf) {
  1543. X                    (void)write(mfd, obuf, cq-obuf);
  1544. X                    cq = obuf;
  1545. X                }
  1546. X            }
  1547. X        }
  1548. X        if (cq > obuf)
  1549. X            (void)write(mfd, obuf, cq-obuf);
  1550. X    } else
  1551. X        (void)read(w->w_datafd, ibuf, sizeof ibuf);
  1552. X}
  1553. X
  1554. Xstatic
  1555. Xvoid
  1556. Xp1_recv(mfd, cbuf, clen)
  1557. Xfildes_t mfd;
  1558. Xchar *cbuf;
  1559. Xint clen;
  1560. X{
  1561. X    register int len;
  1562. X    register char *buf, *cp, *cq;
  1563. X    register struct window *w;
  1564. X    nwin_t wnum;
  1565. X    auto int nready;
  1566. X    char ibuf[512], obuf[512];
  1567. X    static int seen_iac, seen_meta;
  1568. X    static pnreq_t pnrq_cmd;
  1569. X    static char cmdbuf[2] = { P1_IAC };
  1570. X
  1571. X    /*
  1572. X     * The received bytestream is examined.  Non-command bytes are
  1573. X     * written to the file descriptor corresponding to the current
  1574. X     * "input" window (relative to the Macintosh -- the window the
  1575. X     * user types input to).
  1576. X     *
  1577. X     * If "clen" is nonzero, then the contents of the buffer "cbuf"
  1578. X     * are processed before any input is read.
  1579. X     */
  1580. X    if (ioctl(mfd, (int)FIONREAD, (char *)&nready) < 0) {
  1581. X        perror("FIONREAD");
  1582. X        return;
  1583. X    }
  1584. X    nready += clen;
  1585. X
  1586. X    for (cq = obuf; nready > 0; nready -= len) {
  1587. X        if (clen > 0) {
  1588. X            len = clen;
  1589. X            buf = cbuf;
  1590. X            clen = 0;
  1591. X        } else {
  1592. X            if (nready > sizeof ibuf)
  1593. X                len = read(mfd, ibuf, sizeof ibuf);
  1594. X            else
  1595. X                len = read(mfd, ibuf, nready);
  1596. X            if (len <= 0) {
  1597. X                perror("read");
  1598. X                return;
  1599. X            }
  1600. X            buf = ibuf;
  1601. X        }
  1602. X        for (cp=buf; cp < buf+len; cp++) {
  1603. X            if (pnrq_cmd) {
  1604. X                pcl_haggle(mfd, pnrq_cmd|*cp);
  1605. X                pnrq_cmd = 0;
  1606. X                /* pcl_haggle may have changed the protocol */
  1607. X                if (protocol != pcl_table) {
  1608. X                    if (protocol->p_recv)
  1609. X                        (*protocol->p_recv)(mfd,
  1610. X                            cp+1, buf+len-cp-1);
  1611. X                    return;
  1612. X                }
  1613. X            } else if (seen_iac) {
  1614. X                if ((*cp&P1_DIR) == P1_DIR_MTOH) {
  1615. X                    if (cq > obuf) {
  1616. X                        (void)write(curwin.in->w_datafd,
  1617. X                                obuf, cq-obuf);
  1618. X                        cq = obuf;
  1619. X                    }
  1620. X                    switch (*cp & P1_FN) {
  1621. X                    case P1_FN_NEWW:
  1622. X                        wnum = *cp & P1_WINDOW;
  1623. X                        if (!wnum)
  1624. X                            break;
  1625. X                        w = WIN_PTR(wnum);
  1626. X                        if (w->w_alloc)
  1627. X                            break;
  1628. X                        if (!win_neww(WC_INTERNAL,
  1629. X                            defwtype, wnum,
  1630. X                            protocol->p_maxwin, 0L,
  1631. X                            (fildes_t)-1, (fildes_t)-1,
  1632. X                            (struct woptdefn *)0)) {
  1633. X                            cmdbuf[1] = P1_DIR_HTOM|
  1634. X                                P1_FN_KILLW|wnum;
  1635. X                            (void)write(mfd, cmdbuf,
  1636. X                                sizeof cmdbuf);
  1637. X                        }
  1638. X                        break;
  1639. X                    case P1_FN_KILLW:
  1640. X                        wnum = *cp & P1_WINDOW;
  1641. X                        if (!wnum)
  1642. X                            break;
  1643. X                        win_killw(WIN_PTR(wnum));
  1644. X                        break;
  1645. X                    case P1_FN_ISELW:
  1646. X                        wnum = *cp & P1_WINDOW;
  1647. X                        if (!wnum)
  1648. X                            break;
  1649. X                        w = WIN_PTR(wnum);
  1650. X                        if (w->w_alloc)
  1651. X                            curwin.in = w;
  1652. X                        else
  1653. X                            curwin.in = NULL;
  1654. X                        break;
  1655. X                    case P1_FN_META:
  1656. X                        seen_meta = 1;
  1657. X                        break;
  1658. X                    case P1_FN_CTLCH:
  1659. X                        *cq = protocol->p_ctlch[*cp&P1_CC];
  1660. X                        if (seen_meta) {
  1661. X                            seen_meta = 0;
  1662. X                            *cq |= META;
  1663. X                        }
  1664. X                        if (curwin.in)
  1665. X                            cq++;
  1666. X                        break;
  1667. X                    case P1_FN_MAINT:
  1668. X                        switch (*cp & P1_MF) {
  1669. X                        case P1_MF_ENTRY:
  1670. X                            (*protocol->p_renew)(mfd);
  1671. X                            break;
  1672. X                        case P1_MF_ASKPCL:
  1673. X                            pcl_haggle(mfd,PNRQ_ASK);
  1674. X                            break;
  1675. X                        case P1_MF_CANPCL:
  1676. X                            pnrq_cmd = PNRQ_CAN;
  1677. X                            break;
  1678. X                        case P1_MF_SETPCL:
  1679. X                            pnrq_cmd = PNRQ_SET;
  1680. X                            break;
  1681. X                        case P1_MF_EXIT:
  1682. X                            done(0);
  1683. X                            break;
  1684. X                        }
  1685. X                        break;
  1686. X                    }
  1687. X                }
  1688. X                seen_iac = 0;
  1689. X            } else if (*cp == P1_IAC)
  1690. X                seen_iac++;
  1691. X            else {
  1692. X                if (seen_meta) {
  1693. X                    seen_meta = 0;
  1694. X                    *cq = *cp | META;
  1695. X                } else
  1696. X                    *cq = *cp;
  1697. X                if (curwin.in) {
  1698. X                    if (++cq >= obuf+sizeof obuf) {
  1699. X                        (void)write(curwin.in->w_datafd,
  1700. X                                obuf, cq-obuf);
  1701. X                        cq = obuf;
  1702. X                    }
  1703. X                }
  1704. X            }
  1705. X        }
  1706. X    }
  1707. X    if (cq > obuf)
  1708. X        (void)write(curwin.in->w_datafd, obuf, cq-obuf);
  1709. X}
  1710. X
  1711. Xstatic
  1712. Xvoid
  1713. Xp1_askpcl(mfd)
  1714. Xfildes_t mfd;
  1715. X{
  1716. X    static char cmdbuf[2] = { P1_IAC,P1_DIR_HTOM|P1_FN_MAINT|P1_MF_ASKPCL };
  1717. X
  1718. X    (void)write(mfd, cmdbuf, sizeof cmdbuf);
  1719. X}
  1720. X
  1721. Xstatic
  1722. Xvoid
  1723. Xp1_canpcl(mfd, pname)
  1724. Xfildes_t mfd;
  1725. Xchar pname;
  1726. X{
  1727. X    static char cmdbuf[3] = { P1_IAC,P1_DIR_HTOM|P1_FN_MAINT|P1_MF_CANPCL };
  1728. X
  1729. X    cmdbuf[2] = pname;
  1730. X    (void)write(mfd, cmdbuf, sizeof cmdbuf);
  1731. X}
  1732. X
  1733. Xstatic
  1734. Xvoid
  1735. Xp1_setpcl(mfd, pname)
  1736. Xfildes_t mfd;
  1737. Xchar pname;
  1738. X{
  1739. X    static char cmdbuf[3] = { P1_IAC,P1_DIR_HTOM|P1_FN_MAINT|P1_MF_SETPCL };
  1740. X
  1741. X    cmdbuf[2] = pname;
  1742. X    (void)write(mfd, cmdbuf, sizeof cmdbuf);
  1743. X}
  1744. X
  1745. Xstatic
  1746. Xvoid
  1747. Xp1_renew(mfd)
  1748. Xfildes_t mfd;
  1749. X{
  1750. X    register struct window *w;
  1751. X    static char cmdbuf[2] = { P1_IAC };
  1752. X
  1753. X    /*
  1754. X     * Re-init (re-NEW) an existing connection.  Send a NEWW command
  1755. X     * for each existing window.  This function is invoked when the
  1756. X     * Macintosh sends an ENTRY maintenance command.
  1757. X     */
  1758. X    for (w=window; w < window+protocol->p_maxwin; w++) {
  1759. X        if (w->w_alloc) {
  1760. X            win_renew(w, 0);
  1761. X            cmdbuf[1] = P1_DIR_HTOM|P1_FN_NEWW|WIN_NUM(w);
  1762. X            (void)write(mfd, cmdbuf, sizeof cmdbuf);
  1763. X        }
  1764. X    }
  1765. X}
  1766. X
  1767. Xstatic
  1768. Xvoid
  1769. Xp2_renew(mfd)
  1770. Xfildes_t mfd;
  1771. X{
  1772. X    register struct window *w;
  1773. X    static char cmdbuf[3] = { P2_IAC };
  1774. X
  1775. X    /*
  1776. X     * Re-init (re-NEW) an existing connection.  Send a NEWW command
  1777. X     * for each existing window.  This function is invoked when the
  1778. X     * Macintosh sends an ENTRY maintenance command.
  1779. X     */
  1780. X    for (w=window; w < window+protocol->p_maxwin; w++) {
  1781. X        if (w->w_alloc) {
  1782. X            win_renew(w, 1);
  1783. X            cmdbuf[1] = P2_DIR_HTOM|P2_FN_NEWW|WIN_NUM(w);
  1784. X            cmdbuf[2] = w->w_type + ' ';
  1785. X            (void)write(mfd, cmdbuf, sizeof cmdbuf);
  1786. X        }
  1787. X    }
  1788. X}
  1789. X
  1790. Xstatic
  1791. Xstruct window *
  1792. Xp2_neww(mfd, wclass, wtype, wnum, wid, datafd, ctlfd)
  1793. Xfildes_t mfd;
  1794. Xwclass_t wclass;
  1795. Xwtype_t wtype;
  1796. Xnwin_t wnum;
  1797. Xlong wid;
  1798. Xfildes_t datafd;
  1799. Xfildes_t ctlfd;
  1800. X{
  1801. X    register struct window *w;
  1802. X    static char cmdbuf[3] = { P2_IAC };
  1803. X
  1804. X    /*
  1805. X     * Create a new window as requested by the host.  This routine is not
  1806. X     * called when the Macintosh creates a window.
  1807. X     */
  1808. X    w = win_neww(wclass, wtype, wnum, protocol->p_maxwin, wid,
  1809. X        datafd, ctlfd, (struct woptdefn *)0);
  1810. X    if (w) {
  1811. X        cmdbuf[1] = P2_DIR_HTOM|P2_FN_NEWW|WIN_NUM(w);
  1812. X        cmdbuf[2] = ' ' + wtype;
  1813. X        (void)write(mfd, cmdbuf, sizeof cmdbuf);
  1814. X    }
  1815. X    return(w);
  1816. X}
  1817. X
  1818. Xstatic
  1819. Xvoid
  1820. Xp2_chkopt(mfd)
  1821. Xfildes_t mfd;
  1822. X{
  1823. X    register struct window *w;
  1824. X    nwin_t maxwin;
  1825. X
  1826. X    /*
  1827. X     * Ideally, this routine would call a routine in the window
  1828. X     * module (perhaps win_chkopt()), passing the maximum window
  1829. X     * number as one argument.  The "for" loop would be in that
  1830. X     * routine.  However, I'm not willing to accept the overhead
  1831. X     * for that conceptual nicety.
  1832. X     */
  1833. X    maxwin = protocol->p_maxwin;
  1834. X    for (w=window; w < window+maxwin; w++)
  1835. X        if (w->w_alloc)
  1836. X            opt_scan((caddr_t)w, &w->w_optdefn, p2_sendopt, mfd,
  1837. X                P2_FN_WOPT|WIN_NUM(w));
  1838. X}
  1839. X
  1840. Xstatic
  1841. Xvoid
  1842. Xp2_sendopt(mfd, fn, buf, len)
  1843. Xfildes_t mfd;
  1844. Xint fn;
  1845. Xregister char *buf;
  1846. Xregister int len;
  1847. X{
  1848. X    register char *cp;
  1849. X    register int i;
  1850. X    char outbuf[512];
  1851. X
  1852. X    /*
  1853. X     * Encode and transmit the option string contained in "buf".  The
  1854. X     * initial command (which will be P2_FN_WOPT|WIN_NUM(w)) is
  1855. X     * contained in "fn".
  1856. X     *
  1857. X     * The caller is responsible for handing us a correctly-formed
  1858. X     * option string.  This routine merely performs the protocol encoding
  1859. X     * which is required for control and meta characters.
  1860. X     */
  1861. X    curwin.out = NULL;
  1862. X    outbuf[0] = P2_IAC;
  1863. X    outbuf[1] = fn|P2_DIR_HTOM;
  1864. X    for (cp=outbuf+2; len > 0; buf++,len--) {
  1865. X        if (cp > outbuf+sizeof outbuf - 4) {
  1866. X            (void)write(mfd, outbuf, cp-outbuf);
  1867. X            cp = outbuf;
  1868. X        }
  1869. X        if (*buf & META) {
  1870. X            *cp++ = P2_IAC;
  1871. X            *cp++ = P2_DIR_HTOM|P2_FN_META;
  1872. X            *buf &= ~META;
  1873. X        }
  1874. X        i = -1;
  1875. X        if (*buf == RUB || *buf < ' ') {
  1876. X            i = protocol->p_szctlch - 1;
  1877. X            while (i >= 0 && protocol->p_ctlch[i] != *buf)
  1878. X                i--;
  1879. X        }
  1880. X        if (i >= 0) {
  1881. X            *cp++ = P2_IAC;
  1882. X            *cp++ = P2_DIR_HTOM|P2_FN_CTLCH|(i&7);
  1883. X        } else
  1884. X            *cp++ = *buf;
  1885. X    }
  1886. X    if (cp > outbuf)
  1887. X        (void)write(mfd, outbuf, cp-outbuf);
  1888. X}
  1889. X
  1890. Xstatic
  1891. Xvoid
  1892. Xp2_recv(mfd, cbuf, clen)
  1893. Xfildes_t mfd;
  1894. Xchar *cbuf;
  1895. Xint clen;
  1896. X{
  1897. X    register int len;
  1898. X    register char *buf, *cp, *cq;
  1899. X    register struct window *w;
  1900. X    register char c;
  1901. X    nwin_t wnum;
  1902. X    auto int nready;
  1903. X    char ibuf[512], obuf[512];
  1904. X    static int seen_iac, seen_meta, is_option;
  1905. X    static pnreq_t pnrq_cmd;
  1906. X    static nwin_t neww;
  1907. X    static char cmdbuf[2] = { P2_IAC };
  1908. X
  1909. X    /*
  1910. X     * The received bytestream is examined.  Non-command bytes are
  1911. X     * written to the file descriptor corresponding to the current
  1912. X     * "input" window (relative to the Macintosh -- the window the
  1913. X     * user types input to).
  1914. X     *
  1915. X     * If "clen" is nonzero, then the contents of the buffer "cbuf"
  1916. X     * are processed before any input is read.
  1917. X     */
  1918. X    if (ioctl(mfd, (int)FIONREAD, (char *)&nready) < 0) {
  1919. X        perror("FIONREAD");
  1920. X        return;
  1921. X    }
  1922. X    nready += clen;
  1923. X
  1924. X    for (cq = obuf; nready > 0; nready -= len) {
  1925. X        if (clen > 0) {
  1926. X            len = clen;
  1927. X            buf = cbuf;
  1928. X            clen = 0;
  1929. X        } else {
  1930. X            if (nready > sizeof ibuf)
  1931. X                len = read(mfd, ibuf, sizeof ibuf);
  1932. X            else
  1933. X                len = read(mfd, ibuf, nready);
  1934. X            if (len <= 0) {
  1935. X                perror("read");
  1936. X                return;
  1937. X            }
  1938. X            buf = ibuf;
  1939. X        }
  1940. X        for (cp=buf; cp < buf+len; cp++) {
  1941. X            if (pnrq_cmd) {
  1942. X                pcl_haggle(mfd, pnrq_cmd|*cp);
  1943. X                pnrq_cmd = 0;
  1944. X                /* pcl_haggle may have changed the protocol */
  1945. X                if (protocol != pcl_table) {
  1946. X                    if (protocol->p_recv)
  1947. X                        (*protocol->p_recv)(mfd,
  1948. X                            cp+1, buf+len-cp-1);
  1949. X                    return;
  1950. X                }
  1951. X            } else if (neww) {
  1952. X                w = WIN_PTR(neww);
  1953. X                if (!w->w_alloc &&
  1954. X                    !win_neww(WC_INTERNAL, (wtype_t)(*cp-' '),
  1955. X                    neww, protocol->p_maxwin, 0L,
  1956. X                    (fildes_t)-1, (fildes_t)-1,
  1957. X                    (struct woptdefn *)0)) {
  1958. X                    cmdbuf[1] = P2_DIR_HTOM|
  1959. X                        P2_FN_KILLW|neww;
  1960. X                    (void)write(mfd, cmdbuf,
  1961. X                        sizeof cmdbuf);
  1962. X                }
  1963. X                neww = 0;
  1964. X            } else if (seen_iac) {
  1965. X                if ((*cp&P2_DIR) == P2_DIR_MTOH) {
  1966. X                    c = *cp & P2_FN;
  1967. X                    if (is_option &&
  1968. X                        c!=P2_FN_META && c!=P2_FN_CTLCH) {
  1969. X                        opt_iflush();
  1970. X                        is_option = 0;
  1971. X                    }
  1972. X                    if (cq > obuf) {
  1973. X                        (void)write(curwin.in->w_datafd,
  1974. X                                obuf, cq-obuf);
  1975. X                        cq = obuf;
  1976. X                    }
  1977. X                    switch (*cp & P2_FN) {
  1978. X                    case P2_FN_NEWW:
  1979. X                        neww = *cp & P2_WINDOW;
  1980. X                        break;
  1981. X                    case P2_FN_WOPT:
  1982. X                        wnum = *cp & P2_WINDOW;
  1983. X                        if (!wnum)
  1984. X                            break;
  1985. X                        w = WIN_PTR(wnum);
  1986. X                        if (!w->w_alloc) {
  1987. X                            curwin.in = NULL;
  1988. X                            break;
  1989. X                        }
  1990. X                        is_option = 1;
  1991. X                        opt_istart((caddr_t)w, &w->w_optdefn);
  1992. X                        break;
  1993. X                    case P2_FN_KILLW:
  1994. X                        wnum = *cp & P2_WINDOW;
  1995. X                        if (!wnum)
  1996. X                            break;
  1997. X                        win_killw(WIN_PTR(wnum));
  1998. X                        break;
  1999. X                    case P2_FN_ISELW:
  2000. X                        wnum = *cp & P2_WINDOW;
  2001. X                        if (!wnum)
  2002. X                            break;
  2003. X                        w = WIN_PTR(wnum);
  2004. X                        if (w->w_alloc)
  2005. X                            curwin.in = w;
  2006. X                        else
  2007. X                            curwin.in = NULL;
  2008. X                        break;
  2009. X                    case P2_FN_META:
  2010. X                        seen_meta = 1;
  2011. X                        if ((*cp&P2_CC) == 0)
  2012. X                            break;
  2013. X                        /* no break */
  2014. X                    case P2_FN_CTLCH:
  2015. X                        c=protocol->p_ctlch[*cp&P2_CC];
  2016. X                        if (seen_meta) {
  2017. X                            seen_meta = 0;
  2018. X                            c |= META;
  2019. X                        }
  2020. X                        if (is_option)
  2021. X                            is_option=opt_input(c);
  2022. X                        else
  2023. X                            if (curwin.in)
  2024. X                                *cq++ = c;
  2025. X                        break;
  2026. X                    case P2_FN_MAINT:
  2027. X                        switch (*cp & P2_MF) {
  2028. X                        case P2_MF_ENTRY:
  2029. X                            (*protocol->p_setpcl)(mfd, protocol->p_name);
  2030. X                            (*protocol->p_renew)(mfd);
  2031. X                            break;
  2032. X                        case P2_MF_ASKPCL:
  2033. X                            pcl_haggle(mfd,PNRQ_ASK);
  2034. X                            break;
  2035. X                        case P2_MF_CANPCL:
  2036. X                            pnrq_cmd = PNRQ_CAN;
  2037. X                            break;
  2038. X                        case P2_MF_SETPCL:
  2039. X                            pnrq_cmd = PNRQ_SET;
  2040. X                            break;
  2041. X                        case P2_MF_EXIT:
  2042. X                            done(0);
  2043. X                            break;
  2044. X                        }
  2045. X                        break;
  2046. X                    }
  2047. X                }
  2048. X                seen_iac = 0;
  2049. X            } else if (*cp == P2_IAC)
  2050. X                seen_iac++;
  2051. X            else {
  2052. X                if (seen_meta) {
  2053. X                    c = *cp | META;
  2054. X                    seen_meta = 0;
  2055. X                } else
  2056. X                    c = *cp;
  2057. X                if (is_option)
  2058. X                    is_option = opt_input(c);
  2059. X                else
  2060. X                    if (curwin.in)
  2061. X                        *cq++ = c;
  2062. X                if (cq >= obuf+sizeof obuf) {
  2063. X                    (void)write(curwin.in->w_datafd,
  2064. X                            obuf, cq-obuf);
  2065. X                    cq = obuf;
  2066. X                }
  2067. X            }
  2068. X        }
  2069. X    }
  2070. X    if (cq > obuf)
  2071. X        (void)write(curwin.in->w_datafd, obuf, cq-obuf);
  2072. X}
  2073. !EOF!server/uw_pcl.c!
  2074. echo x - server/uw_tty.c
  2075. sed -e 's/^X//' > server/uw_tty.c << '!EOF!server/uw_tty.c!'
  2076. X/*
  2077. X *    uw_tty - terminal support for UW
  2078. X *
  2079. X * Copyright 1985,1986 by John D. Bruner.  All rights reserved.  Permission to
  2080. X * copy this program is given provided that the copy is not sold and that
  2081. X * this copyright notice is included.
  2082. X */
  2083. X
  2084. X#include <sys/types.h>
  2085. X#include <sys/file.h>
  2086. X#include <sys/ioctl.h>
  2087. X#include <sys/stat.h>
  2088. X
  2089. X#include "uw_param.h"
  2090. X#include "uw_win.h"
  2091. X#include "uw_opt.h"
  2092. X
  2093. X#define    XON    021    /* ASCII XON (ASR-33 paper-tape reader on) */
  2094. X#define    XOFF    023    /* ASCII XOFF (ASR-33 paper-tape reader off) */
  2095. X
  2096. Xstatic char *envinfo[][3] = {
  2097. X    {
  2098. X        "TERM=adm31",
  2099. X        "TERMCAP=adm31:cr=^M:do=^J:nl=^J:al=\\EE:am:le=^H:bs:ce=\\ET:cm=\\E=%+ %+ :cl=^Z:cd=\\EY:co#80:dc=\\EW:dl=\\ER:ei=\\Er:ho=^^:im=\\Eq:li#24:mi:nd=^L:up=^K:MT:km:so=\\EG1:se=\\EG0:",
  2100. X        (char *)0
  2101. X    },
  2102. X    {
  2103. X        "TERM=vt52",
  2104. X        (char *)0
  2105. X    },
  2106. X    {
  2107. X        "TERM=ansi",
  2108. X        (char *)0
  2109. X    },
  2110. X    {
  2111. X        "TERM=tek4010",
  2112. X        (char *)0
  2113. X    }
  2114. X};
  2115. X
  2116. X/* private (emulation-specific) data */
  2117. Xstruct tty {
  2118. X    struct {
  2119. X        unsigned short    h,v;
  2120. X    }        t_size;
  2121. X    unsigned    t_fontsz;
  2122. X    unsigned    t_clipb;
  2123. X    unsigned    t_bell;
  2124. X    unsigned    t_curs;
  2125. X    unsigned    t_chgsz;
  2126. X};
  2127. X
  2128. X#define    WOTTY_SIZE    8        /* terminal size in (row, col) */
  2129. X#define    WOTTY_FONTSZ    9        /* font size index (0=7pt, 1=9pt) */
  2130. X#define    WOTTY_CLIPB    10        /* 0=clipboard, 1=encode mouse clicks */
  2131. X#define    WOTTY_BELL    11        /* bell: bit 0=visible, bit 1=audible */
  2132. X#define    WOTTY_CURSOR    12        /* cursor type: 0=block, 1=underscore */
  2133. X#define    WOTTY_CHGSZ    13        /* change actual size (not view size) */
  2134. X
  2135. Xstatic woptarg_t size_xdr[] = { WOA_UDATA(12), WOA_UDATA(12), WOA_END };
  2136. Xstatic woptarg_t fontsz_xdr[] = { WOA_UDATA(6), WOA_END };
  2137. Xstatic woptarg_t clipb_xdr[] = { WOA_UDATA(1), WOA_END };
  2138. Xstatic woptarg_t bell_xdr[] = { WOA_UDATA(2), WOA_END };
  2139. Xstatic woptarg_t curs_xdr[] = { WOA_UDATA(1), WOA_END };
  2140. Xstatic woptarg_t chgsz_xdr[] = { WOA_UDATA(1), WOA_END };
  2141. X
  2142. X/* TIOCSWINSZ is in 4.3BSD, TIOCSSIZE is in Sun UNIX */
  2143. X#if defined(TIOCSWINSZ) || defined(TIOCSSIZE)
  2144. X#define    RPTWINSZ    (1<<WOTTY_SIZE)
  2145. X#else
  2146. X#define    RPTWINSZ    0
  2147. X#endif
  2148. X
  2149. X#define    TTY_WOPT    {                    \
  2150. X    0, 0, 0, 0,                        \
  2151. X    RPTWINSZ|(1<<WOTTY_FONTSZ)|(1<<WOTTY_CLIPB)|        \
  2152. X     (1<<WOTTY_BELL)|(1<<WOTTY_CURSOR)|(1<<WOTTY_CHGSZ),    \
  2153. X    {                            \
  2154. X        { NULL, NULL, NULL },                \
  2155. X        { NULL, NULL, NULL },                \
  2156. X        { NULL, NULL, NULL },                \
  2157. X        { NULL, NULL, NULL },                \
  2158. X        { NULL, NULL, NULL },                \
  2159. X        { NULL, NULL, NULL },                \
  2160. X        { NULL, NULL, NULL },                \
  2161. X        { NULL, NULL, NULL },                \
  2162. X        { size_xdr, tty_getopt, tty_setopt },        \
  2163. X        { fontsz_xdr, tty_getopt, tty_setopt },        \
  2164. X        { clipb_xdr, tty_getopt, tty_setopt },        \
  2165. X        { bell_xdr, tty_getopt, tty_setopt },        \
  2166. X        { curs_xdr, tty_getopt, tty_setopt },        \
  2167. X        { chgsz_xdr, tty_getopt, tty_setopt }        \
  2168. X    }                            \
  2169. X}
  2170. Xextern int tty_start();
  2171. Xextern void tty_stop(), tty_setopt(), tty_setext();
  2172. Xextern char *tty_getopt();
  2173. X
  2174. Xstruct emulation adm31_emul = { TTY_WOPT, tty_start, tty_stop, tty_setext };
  2175. Xstruct emulation vt52_emul = { TTY_WOPT, tty_start, tty_stop, tty_setext };
  2176. Xstruct emulation ansi_emul = { TTY_WOPT, tty_start, tty_stop, tty_setext };
  2177. Xstruct emulation tek_emul = { { 0, 0, 0, 0, 0 }, tty_start, tty_stop };
  2178. X
  2179. Xtty_mode(f)
  2180. Xint f;
  2181. X{
  2182. X    static struct sgttyb ostty, nstty;
  2183. X    static struct tchars otchars, ntchars;
  2184. X    static struct ltchars oltchars, nltchars;
  2185. X    static int olmode, nlmode;
  2186. X    static int operm;
  2187. X    static saved;
  2188. X    static int inout = FREAD|FWRITE;
  2189. X    struct stat st;
  2190. X
  2191. X    /*
  2192. X     * This routine either saves the current terminal modes and then
  2193. X     * sets up the terminal line or resets the terminal modes (depending
  2194. X     * upon the value of "f").  The terminal line is used in "cbreak"
  2195. X     * mode with all special characters except XON/XOFF disabled.  The
  2196. X     * hated (by me) LDECCTQ mode is required for the Macintosh to
  2197. X     * handle flow control properly.
  2198. X     */
  2199. X    if (f == 1) {
  2200. X        if (fstat(0, &st) == 0)
  2201. X            operm = st.st_mode & 06777;
  2202. X        else
  2203. X            operm = -1;
  2204. X        if (ioctl(0, (int)TIOCGETP, (char *)&ostty) < 0) {
  2205. X            perror("ioctl((int)TIOCGETP)");
  2206. X            done(1);
  2207. X        }
  2208. X        if (ioctl(0, (int)TIOCGETC, (char *)&otchars) < 0) {
  2209. X            perror("ioctl((int)TIOCGETC)");
  2210. X            done(1);
  2211. X        }
  2212. X        if (ioctl(0, (int)TIOCGLTC, (char *)&oltchars) < 0) {
  2213. X            perror("ioctl((int)TIOCGLTC)");
  2214. X            done(1);
  2215. X        }
  2216. X        if (ioctl(0, (int)TIOCLGET, (char *)&olmode) < 0) {
  2217. X            perror("ioctl((int)TIOCLGET)");
  2218. X            done(1);
  2219. X        }
  2220. X        nstty = ostty;
  2221. X        nstty.sg_erase = nstty.sg_kill = -1;
  2222. X        nstty.sg_flags |= CBREAK;
  2223. X        nstty.sg_flags &= ~(RAW|CRMOD|ECHO|LCASE|XTABS|ALLDELAY);
  2224. X        ntchars.t_intrc = ntchars.t_quitc = -1;
  2225. X        ntchars.t_eofc = ntchars.t_brkc = -1;
  2226. X        ntchars.t_startc = XON;
  2227. X        ntchars.t_stopc = XOFF;
  2228. X        nltchars.t_suspc = nltchars.t_dsuspc = -1;
  2229. X        nltchars.t_rprntc = nltchars.t_flushc = -1;
  2230. X        nltchars.t_werasc = nltchars.t_lnextc = -1;
  2231. X        nlmode = olmode | LDECCTQ;
  2232. X        if (operm != -1 && fchmod(0, S_IREAD|S_IWRITE) < 0)
  2233. X            operm = -1;
  2234. X        if (ioctl(0, (int)TIOCSETN, (char *)&nstty) < 0) {
  2235. X            perror("ioctl((int)TIOCSETN)");
  2236. X            done(1);
  2237. X        }
  2238. X        if (ioctl(0, (int)TIOCSETC, (char *)&ntchars) < 0) {
  2239. X            perror("ioctl((int)TIOCSETC");
  2240. X            done(1);
  2241. X        }
  2242. X        if (ioctl(0, (int)TIOCSLTC, (char *)&nltchars) < 0) {
  2243. X            perror("ioctl((int)TIOCSLTC");
  2244. X            done(1);
  2245. X        }
  2246. X        if (ioctl(0, (int)TIOCLSET, (char *)&nlmode) < 0) {
  2247. X            perror("ioctl((int)TIOCLSET)");
  2248. X            done(1);
  2249. X        }
  2250. X        saved = 1;
  2251. X    } else if (saved) {
  2252. X        (void)ioctl(0, (int)TIOCFLUSH, (char *)&inout);
  2253. X        (void)ioctl(0, (int)TIOCSETP, (char *)&ostty);
  2254. X        (void)ioctl(0, (int)TIOCSETC, (char *)&otchars);
  2255. X        (void)ioctl(0, (int)TIOCSLTC, (char *)&oltchars);
  2256. X        (void)ioctl(0, (int)TIOCLSET, (char *)&olmode);
  2257. X        if (operm != -1)
  2258. X            (void)fchmod(0, operm);
  2259. X    }
  2260. X}
  2261. X
  2262. Xstatic
  2263. Xtty_start(w)
  2264. Xregister struct window *w;
  2265. X{
  2266. X    register struct tty *t;
  2267. X    extern char *malloc();
  2268. X
  2269. X    /*
  2270. X     * Start up a terminal emulation.  Establish reasonable defaults
  2271. X     * for the terminal-specific window options.
  2272. X     */
  2273. X    if (w->w_type != WT_TEK4010) {
  2274. X        if ((w->w_private = malloc(sizeof(struct tty))) != NULL) {
  2275. X            t = (struct tty *)w->w_private;
  2276. X            t->t_size.h = 80;
  2277. X            t->t_size.v = 24;
  2278. X            t->t_fontsz = 0;
  2279. X            t->t_clipb = 0;
  2280. X            t->t_bell = 3;
  2281. X            t->t_curs = 0;
  2282. X            t->t_chgsz = 0;
  2283. X            return(1);
  2284. X        } else
  2285. X            return(0);
  2286. X    } else {
  2287. X        w->w_private = (char *)0;
  2288. X        return(1);
  2289. X    }
  2290. X}
  2291. X
  2292. Xstatic
  2293. Xvoid
  2294. Xtty_stop(w)
  2295. Xregister struct window *w;
  2296. X{
  2297. X    /*
  2298. X     * Shut down (stop) a terminal emulation.
  2299. X     */
  2300. X    free(w->w_private);
  2301. X    w->w_private = (char *)0;
  2302. X}
  2303. X
  2304. Xstatic
  2305. Xvoid
  2306. Xtty_setext(wod)
  2307. Xregister struct woptdefn *wod;
  2308. X{
  2309. X    /*
  2310. X     * This routine makes adjustments to the window option definitions
  2311. X     * for external windows.  Basically, we turn off reporting for
  2312. X     * WOTTY_SIZE.  (If the external process wants to handle this, it
  2313. X     * can turn it back on.)
  2314. X     */
  2315. X    WOPT_CLR(wod->wod_do, WOTTY_SIZE);
  2316. X    WOPT_CLR(wod->wod_askrpt, WOTTY_SIZE);
  2317. X}
  2318. X
  2319. Xtty_envinit(wtype)
  2320. Xregister wtype_t wtype;
  2321. X{
  2322. X    /*
  2323. X     * Set up environment variables corresponding to the window type
  2324. X     * "wtype".
  2325. X     */
  2326. X    env_set(envinfo[wtype]);
  2327. X}
  2328. X
  2329. Xstatic
  2330. Xchar *
  2331. Xtty_getopt(win, num)
  2332. Xcaddr_t win;
  2333. Xwoption_t num;
  2334. X{
  2335. X    register struct tty *t;
  2336. X    static union optvalue ov;
  2337. X    struct window *w;
  2338. X
  2339. X    if ((w=(struct window *)win) != NULL && w->w_alloc &&
  2340. X        (t=(struct tty *)w->w_private) != NULL) {
  2341. X        switch (num) {
  2342. X        case WOTTY_SIZE:
  2343. X            ov.ov_point.h = t->t_size.h;
  2344. X            ov.ov_point.v = t->t_size.v;
  2345. X            break;
  2346. X        case WOTTY_FONTSZ:
  2347. X            ov.ov_udata6 = t->t_fontsz;
  2348. X            break;
  2349. X        case WOTTY_CLIPB:
  2350. X            ov.ov_udata1 = t->t_clipb;
  2351. X            break;
  2352. X        case WOTTY_BELL:
  2353. X            ov.ov_udata2 = t->t_bell;
  2354. X            break;
  2355. X        case WOTTY_CURSOR:
  2356. X            ov.ov_udata1 = t->t_curs;
  2357. X            break;
  2358. X        case WOTTY_CHGSZ:
  2359. X            ov.ov_udata1 = t->t_chgsz;
  2360. X            break;
  2361. X        }
  2362. X    }
  2363. X    return((char *)&ov);
  2364. X}
  2365. X
  2366. Xstatic
  2367. Xvoid
  2368. Xtty_setopt(win, num, value)
  2369. Xcaddr_t win;
  2370. Xwoption_t num;
  2371. Xchar *value;
  2372. X{
  2373. X    register struct tty *t;
  2374. X    register union optvalue *ovp;
  2375. X    register struct window *w;
  2376. X
  2377. X    if ((w=(struct window *)win) != NULL && w->w_alloc &&
  2378. X        (t=(struct tty *)w->w_private) != NULL &&
  2379. X        (ovp = (union optvalue *)value) != NULL) {
  2380. X        switch (num) {
  2381. X        case WOTTY_SIZE:
  2382. X            t->t_size.h = ovp->ov_point.h;
  2383. X            t->t_size.v = ovp->ov_point.v;
  2384. X#ifdef TIOCSWINSZ
  2385. X            if (w->w_class == WC_INTERNAL) {
  2386. X                /* set window size on pty (4.3BSD) */
  2387. X                struct winsize ws;
  2388. X                ws.ws_row = t->t_size.v;
  2389. X                ws.ws_col = t->t_size.h;
  2390. X                ws.ws_xpixel = w->w_size.h;
  2391. X                ws.ws_ypixel = w->w_size.v;
  2392. X                (void)ioctl(w->w_datafd, (int)TIOCSWINSZ,
  2393. X                    (char *)&ws);
  2394. X            }
  2395. X#else
  2396. X#ifdef TIOCSSIZE
  2397. X            if (w->w_class == WC_INTERNAL) {
  2398. X                /* set window size on pty (Sun) */
  2399. X                struct ttysize ts;
  2400. X                ts.ts_lines = t->t_size.v;
  2401. X                ts.ts_cols = t->t_size.h;
  2402. X                (void)ioctl(w->w_datafd, (int)TIOCSSIZE,
  2403. X                    (char *)&ts);
  2404. X            }
  2405. X#endif
  2406. X#endif
  2407. X            break;
  2408. X        case WOTTY_FONTSZ:
  2409. X            t->t_fontsz = ovp->ov_udata6;
  2410. X            break;
  2411. X        case WOTTY_CLIPB:
  2412. X            t->t_clipb = ovp->ov_udata1;
  2413. X            break;
  2414. X        case WOTTY_BELL:
  2415. X            t->t_bell = ovp->ov_udata2;
  2416. X            break;
  2417. X        case WOTTY_CURSOR:
  2418. X            t->t_curs = ovp->ov_udata1;
  2419. X            break;
  2420. X        case WOTTY_CHGSZ:
  2421. X            t->t_chgsz = ovp->ov_udata1;
  2422. X            break;
  2423. X        }
  2424. X    }
  2425. X}
  2426. !EOF!server/uw_tty.c!
  2427. exit 0
  2428. : end of shell archive
  2429.