home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume37 / ulayers / part02 < prev    next >
Encoding:
Text File  |  1993-05-29  |  57.8 KB  |  1,717 lines

  1. Newsgroups: comp.sources.misc
  2. From: david@bdt.com (David Beckemeyer)
  3. Subject: v37i090:  ulayers - Unix/X client to MacLayers, Part02/03
  4. Message-ID: <1993May29.181053.21794@sparky.imd.sterling.com>
  5. X-Md4-Signature: a455af7748fa31896611d4efc35a4de1
  6. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Sat, 29 May 1993 18:10:53 GMT
  9. Approved: kent@sparky.imd.sterling.com
  10.  
  11. Submitted-by: david@bdt.com (David Beckemeyer)
  12. Posting-number: Volume 37, Issue 90
  13. Archive-name: ulayers/part02
  14. Environment: UNIX, X11, PTY
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # Contents:  CHANGES ul_modems ulayers.c
  21. # Wrapped by kent@sparky on Sat May 29 13:04:06 1993
  22. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 2 (of 3)."'
  25. if test -f 'CHANGES' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'CHANGES'\"
  27. else
  28.   echo shar: Extracting \"'CHANGES'\" \(1862 characters\)
  29.   sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
  30. XV0.1    Mar 9 1993    First Beta Release
  31. X
  32. XV0.2    Mar 10, 1993    Added UUCP lockfile support to connect.c
  33. X
  34. XV0.3    Mar 11, 1993    Added uploading to ulslave.c
  35. X            NOTE: This won't work on binary files
  36. X            with 0xfd characters due to a bug in
  37. X            the V1.20 "layers" software.
  38. X
  39. XV0.4    Mar 12, 1993    Fixed Tilde handling in dumb term mode (startup.c)
  40. X            Fixed ulslave to pass-thru Zmodem partial inits
  41. X            Fixed to remove UUCP lock file on exit.
  42. X
  43. XV0.5    Mar 15, 1993    Improved ulslave startup synchronization
  44. X
  45. XV0.6    Mar 17, 1993    Fixed Tilde handling so "~c" sends "c".
  46. X            Added conf.h configuration header file.
  47. X            Added dialers database ($HOME/.ul_numbers)
  48. X            Added modems/ports databases (ul_modems/ul_ports)
  49. X
  50. XV0.7    Mar 24, 1993    Fix KillWindow() free buffer bug.
  51. X            Some changes to attempt portable/reliable kill.
  52. X
  53. XV0.8    Apr 1, 1993    Fixed bug in declaration of a_newfail in ulayers.c
  54. X            Ignore startup if protocol not 2 instead of abort
  55. X            Added -f (flowctl) and -v (version) command options.
  56. X            Added "ulterm" hook for starting layers sessions.
  57. X
  58. XV0.8.2    Apr 2, 1993    Added h)elp, s)tatus, a)bort ulayers commands.
  59. X            Added -m option to override modem type.
  60. X            Changed so that 'a' closes all windows, aborts
  61. X            layers mode, but returns to "dumb terminal mode",
  62. X            while 'q' closes and quits (as before).
  63. X            Rearranged some code internally.
  64. X
  65. XV0.8.3    Apr 4, 1993    Added support for System V style termio.
  66. X            Ported to SVR3.  Might also work on SVR4.
  67. X
  68. XV0.90    Apr 6, 1993    Fixed MAX_PID handling in connect.c.
  69. X            Minor cleanups to remove compile warnings.
  70. X            Fixed timeval initialization bug in ulayers.c
  71. X
  72. XV0.91    Apr 14, 1993    Fixed B2400 bug in Setspeed().
  73. X
  74. XV0.92    Apr 20, 1993    Changed dumb-terminal to strip stdout to 7-bits
  75. X
  76. XV0.93    Apr 29, 1993    Added "try all matches" in .ul_numbers file.
  77. X
  78. XV0.94    May 7, 1993    Don't remove lockfile when locked by another process
  79. X
  80. XV1.0    May 24, 1993    First offical release
  81. END_OF_FILE
  82.   if test 1862 -ne `wc -c <'CHANGES'`; then
  83.     echo shar: \"'CHANGES'\" unpacked with wrong size!
  84.   fi
  85.   # end of 'CHANGES'
  86. fi
  87. if test -f 'ul_modems' -a "${1}" != "-c" ; then 
  88.   echo shar: Will not clobber existing file \"'ul_modems'\"
  89. else
  90.   echo shar: Extracting \"'ul_modems'\" \(787 characters\)
  91.   sed "s/^X//" >'ul_modems' <<'END_OF_FILE'
  92. X#
  93. X# Ulayers modem database
  94. X#
  95. X# Fields are:
  96. X#     name:init:prefix:suffix:connect:
  97. X#
  98. X# Where:
  99. X#    name - the modem entry name
  100. X#    init - the modem init string
  101. X#    prefix - the dial prefix
  102. X#    suffix - the disl suffix
  103. X#    connect - the connect sring
  104. X#
  105. X# The following meta sequences are valid in the modem strings:
  106. X#
  107. X#    ~ - pause one second
  108. X#    ! - sends Carriage-return
  109. X#    ^ - sends a control char 
  110. X#    | - sends ESC
  111. X#    % - causes a BREAK
  112. X#
  113. X# The special meanings can be avoided by prepending \
  114. X#
  115. X# When no match is found, ulayers defaults to its compile-time dialer
  116. X# (usually a simple hayes dialer).
  117. X#
  118. X# Hayes Smart-modem
  119. Xhayes:ATE1V1X1Q0S2=255S12=255!:ATDT:!:CONNECT:
  120. X
  121. X# Telebit T3000/Worldblazer
  122. Xt3000:ATS111=0S50=254!:ATDT:!:CONNECT:
  123. X
  124. X# Telebit T2500
  125. Xt2500:ATE1V1X12Q0S50=0S94=1S0=0!:ATDT:!:CONNECT:
  126. END_OF_FILE
  127.   if test 787 -ne `wc -c <'ul_modems'`; then
  128.     echo shar: \"'ul_modems'\" unpacked with wrong size!
  129.   fi
  130.   # end of 'ul_modems'
  131. fi
  132. if test -f 'ulayers.c' -a "${1}" != "-c" ; then 
  133.   echo shar: Will not clobber existing file \"'ulayers.c'\"
  134. else
  135.   echo shar: Extracting \"'ulayers.c'\" \(52393 characters\)
  136.   sed "s/^X//" >'ulayers.c' <<'END_OF_FILE'
  137. X/********                    Ulayers.c
  138. X*********
  139. X*********     This is a quick & dirty implementation of the
  140. X*********     MacLayers protocol client-side for Unix.  It
  141. X*********     Basically is an emulation of the MacLayers
  142. X*********     Macintosh application for Unix, except that
  143. X*********     Ulayers is a bare-bones program, a far cry
  144. X*********     from the polished and professional MacLayers.
  145. X*********
  146. X*********     The hacks to produce Ulayers were made by me,
  147. X*********     David Beckemeyer david@bdt.com.  Essentially
  148. X*********     the entire credit for this goes to the original
  149. X*********     authors however, and all the contributors
  150. X*********     copyright messages appear below.  On the
  151. X*********     the other hand, the "real" Maclayers authors
  152. X*********     are not to blame for the shoddy hacks I made
  153. X*********     to their code either, and so I'm putting my
  154. X*********     name here because I'm sure they don't want their
  155. X*********     name associatyed with this mess!
  156. X*********
  157. X*********     Most of the code for Ulayers came straight from
  158. X*********     the Unix-side of the MacLayers implementation,
  159. X*********     the copyright messages to which follow:
  160. X*********
  161. X*********    Layers - MacLayers Multiwindow BSD Socket Driver
  162. X*********
  163. X*********          Dave Trissel oakhill!davet
  164. X*********
  165. X********* The sockets handling portion of this control module is based 
  166. X********* upon 'screen' by Oliver Laumann whose copyright remains below. 
  167. X********* The rest is
  168. X *
  169. X *             Copyright (C) 1989 by David W. Trissel
  170. X *
  171. X *              Not derived from licensed software.
  172. X *
  173. X * Permission is granted to freely use, copy, modify, and redistribute
  174. X * this software, provided that no attempt is made to gain profit from it,
  175. X * the author is not construed to be liable for any results of using the
  176. X * software, alterations are clearly marked as such, and this notice is
  177. X * not modified.
  178. X *
  179. X */
  180. Xstatic char UlayersVersion[] = "ulayers V1.0 24-May-1993";
  181. X
  182. X/* Copyright (c) 1987,1988 Oliver Laumann, Technical University of Berlin.
  183. X * Not derived from licensed software.
  184. X *
  185. X * Permission is granted to freely use, copy, modify, and redistribute
  186. X * this software, provided that no attempt is made to gain profit from it,
  187. X * the author is not construed to be liable for any results of using the
  188. X * software, alterations are clearly marked as such, and this notice is
  189. X * not modified.
  190. X *
  191. X *    Modified by Patrick Wolfe (pat@kai.com, kailand!pat)
  192. X *    Do whatever you want with (my modifications of) this program, but
  193. X *    don't claim you wrote them, don't try to make money from them, and
  194. X *    don't remove this notice.
  195. X */
  196. X#include <stdio.h>
  197. X#include <nlist.h>
  198. X#include <fcntl.h>   
  199. X#include <sys/types.h>
  200. X#include <sys/signal.h>
  201. X#include <sys/time.h>   
  202. X#ifdef USG
  203. X#include <stropts.h>
  204. X#include <poll.h>
  205. X#endif
  206. X#include <sys/file.h> 
  207. X#include <sys/wait.h> 
  208. X#include <sys/errno.h> 
  209. X#include <sys/socket.h>
  210. X#ifndef USG
  211. X#include <sys/un.h>  
  212. X#endif
  213. X#include <sys/stat.h>
  214. X#include <sys/dir.h>   
  215. X#include "conf.h"
  216. X#ifdef V7TTY
  217. X#include <sgtty.h>   
  218. X#include <sys/ioctl.h>
  219. X#else
  220. X#include <termio.h>
  221. X#endif
  222. X
  223. X#include "ulayers.h" 
  224. X
  225. X/* C Library items */
  226. Xextern int errno;
  227. X
  228. X/* Global items */
  229. Xint Dflag = 0;
  230. Xchar *ServerPort, *TtySpeed, *ServerNumber, *ModemName, *ServerName;
  231. X
  232. Xstatic char a_newfail[] = "\0333A01";
  233. X#define A_NEWFSZ    5
  234. X
  235. Xstatic char     inbuff[IOSIZE];     /* input buffer from MacLayers */
  236. Xstatic char     *inpos;             /* current input position in buffer */
  237. Xstatic int      insize = 0;         /* characters left to process */
  238. Xstatic int      settimeout = 0;     /* alarm system call timeout value */
  239. Xstatic int      Outstream = -1;     /* output channel (to xterm) */
  240. Xstatic int      Instream = -1;      /* input channel (to server) */
  241. Xstatic int      Sevenbits = 0;      /* communication channel is 7 bits */
  242. X
  243. X/* poll .20 secs for new startups */ 
  244. X#define WUSSTARTUP      200000  
  245. X#define WMSSTARTUP      200
  246. X
  247. Xstatic void     fill4();
  248. Xstatic void     fill2();
  249. Xstatic void     fill1();
  250. Xstatic int      parseshape();
  251. Xstatic unsigned get4();
  252. Xstatic unsigned get2();
  253. Xstatic unsigned get1();
  254. Xstatic int      myalarm();
  255. Xstatic void     dumptime();
  256. Xvoid            SendData();
  257. Xvoid            ReceiveData();
  258. Xvoid        hup();
  259. X
  260. X#define FLUSH tty_flush()
  261. X
  262. Xstatic usage()
  263. X{
  264. X
  265. X    fprintf(stderr, "usage: ulayers [ -df ] [ -m modem ]  tty speed [ number ]\n");
  266. X    fprintf(stderr, "       ulayers [ -df ] [ -m modem ] system\n");
  267. X    fprintf(stderr, "       ulayers -v\n");
  268. X    exit(1);
  269. X}
  270. X
  271. Xmain(argc, argv)
  272. Xint argc;
  273. Xchar *argv[];
  274. X{
  275. X    int fderr;
  276. X    int r, w, n;
  277. X    int len;
  278. X    char buf[IOSIZE];
  279. X    struct Layer *layer;
  280. X    struct Kbuff *kbptr;                /* input keyboard buffer pointer */
  281. X#ifdef USG
  282. X    struct pollfd fds[MAXPCHAN+2];
  283. X    int msec, numfds, i;
  284. X#else
  285. X    struct timeval tv;
  286. X#endif
  287. X    char *ap;
  288. X
  289. X    while (argc > 1)
  290. X      { ap = argv[1];
  291. X        if (*ap++ != '-')
  292. X            break;
  293. X        argv++;
  294. X        argc--;
  295. X    while (*ap)
  296. X          { switch (*ap++)
  297. X              { case 'd':
  298. X                  Dflag++;
  299. X                  break;
  300. X                case 'f':
  301. X                  flowctl++;
  302. X                  break;
  303. X                case 'm':
  304. X                  ModemName = argv[1];
  305. X                  argv++;
  306. X                  argc--;
  307. X                  break;
  308. X                case 'v':
  309. X                  printf("%s\n", UlayersVersion);
  310. X                  exit(0);
  311. X                default:
  312. X                  usage(); 
  313. X              }
  314. X          }
  315. X      }
  316. X    if (argc == 3 || argc == 4) {
  317. X        ServerPort = argv[1];
  318. X    TtySpeed = argv[2];
  319. X    ServerNumber = argv[3];
  320. X    }
  321. X    else if (argc == 2) {
  322. X    ReadStartup();
  323. X    ServerName = argv[1];
  324. X    if (GetNumber(ServerName, 1)) {
  325. X        fprintf(stderr, "%s: unknown system\n", ServerName);
  326. X        exit(1);
  327. X    }
  328. X    }
  329. X    else {
  330. X        usage();
  331. X    }
  332. X
  333. X    if (Dflag) {
  334. X        (void) freopen("ulayers.dump", "a", stderr); /* append mode */
  335. X#ifdef SEQUENT
  336. X        setlinebuf(stderr);
  337. X#else
  338. X        setvbuf(stderr, NULL, _IOLBF, 0);
  339. X#endif
  340. X    }
  341. X
  342. X    /* Set the mode on our input (keyboard) channel */
  343. X    GetTTY (0, OldMode);
  344. X    SetMode (OldMode, NewMode);
  345. X    SetTTY (0, NewMode);
  346. X
  347. X    /* Open the connection to the serial line */
  348. X    
  349. X        while (InitConnect() < 0)
  350. X          { if (!ServerName || GetNumber(ServerName, 0))
  351. X                FQuit(EXITABNORMAL);
  352. X      }
  353. X
  354. X    signal(SIGHUP, hup);
  355. X    
  356. Xrestart:
  357. X    StartUp();
  358. X
  359. X    DO DEBUG("Startup() done.  Serverlevel = %d\n", Serverlevel);
  360. X
  361. X    DO DEBUG("Writing startup string ESC [ ? 8 ; 10 ; 2 c\n");
  362. X    tty_puts("\033[?8;10;2c", 1);
  363. X    FLUSH;
  364. X
  365. X    /* From now on we are in MacLayers-speak */
  366. X    InitWorld();
  367. X
  368. X    fderr = 0;          /* startout no Nerror fd's */
  369. X
  370. X    while (1)
  371. X      {
  372. X
  373. X#ifdef USG
  374. X        /* check for I/O on all available I/O descriptors */
  375. X        fds[0].fd = 0;
  376. X        fds[0].events = POLLIN|POLLPRI;
  377. X        fds[1].fd = TtyFd;
  378. X        fds[1].events = POLLIN|POLLPRI;
  379. X        msec = 0;
  380. X
  381. X        /* for all active layers set read and write bits as appropriate */
  382. X        numfds = 2;
  383. X        for (n=0; n<MAXPCHAN; n++)
  384. X         { layer = &World[n];
  385. X         if (layer->allocated) /* if layer exists ... */
  386. X          { /* if not yet started or has just terminated ... */
  387. X            if (layer->ptymask & fderr)
  388. X                msec = WMSSTARTUP;    /* don't spinloop but wait-a-bit */
  389. X            else
  390. X              { fds[numfds].fd = layer->ptyfd;
  391. X                fds[numfds].events = POLLIN|POLLPRI;
  392. X                if (layer->kbuff && layer->kbuff->size)
  393. X                    /* keyboard input for layer */
  394. X                    fds[numfds].events |= POLLOUT;    /* try write to it */
  395. X                numfds++;
  396. X               }
  397. X            }
  398. X          }
  399. X        switch ( poll(fds, numfds, msec)) 
  400. X        { case -1:
  401. X            /* errno has report */
  402. X            if (errno == EINTR) /* signal delivered or timout */
  403. X              { errno = 0;
  404. X                msec = 0; /* clear timer wait value */
  405. X                fderr = 0;  /* turn off error stall */
  406. X                DO DEBUG("poll errno EINTR\n");
  407. X                continue;   /* re-loop */
  408. X              }
  409. X            Abortonmsg = 1;
  410. X            DO DEBUG("poll errno %d\n", errno);
  411. X            Msg (errno, "poll");
  412. X            /*NOTREACHED*/
  413. X
  414. X          case 0:
  415. X            /* timeout reached */
  416. X            msec = 0;                       /* clear timer wait value */
  417. X            fderr = 0;                      /* turn off error stall */
  418. X            continue;                       /* re-loop */
  419. X
  420. X          default:
  421. X            /* a channel has read/write status pending */
  422. X            break;
  423. X        }
  424. X
  425. X        for (n=0; n<MAXPCHAN; n++)
  426. X          if ((layer = &World[n])->allocated)
  427. X
  428. X        /* process keyboard input first
  429. X        */
  430. X        for (n=0; n<MAXPCHAN; n++)
  431. X          if ((layer = &World[n])->allocated)
  432. X            for (i = 0; i < numfds; i++)
  433. X             if (fds[i].fd == layer->ptyfd && fds[i].revents != 0)
  434. X              { /* input from xterm window, send to server */
  435. X                DO DEBUG("poll chan=%d, revents = %x\n", layer->chan, fds[i].revents);
  436. X                if ((fds[i].revents & (POLLIN|POLLPRI)) != 0)
  437. X                  { len = read(layer->ptyfd, buf, IOSIZE);
  438. X                    if (len >= 0)               /* if no error ... */
  439. X                     { DO DEBUG("input chan %d len %d\n", layer->chan, len);
  440. X                     }
  441. X                    else
  442. X                     {  DO DEBUG("read input err chan %d errno %d len %d\n",
  443. X                           layer->chan, errno, len);
  444. X                        if (errno == EIO || errno == EAGAIN)
  445. X                           { DO DEBUG(" ...anticipated\n");
  446. X                           }
  447. X                        /* layer not ready or just terminated so wait-a-bit */
  448. X                        fderr |= layer->ptymask;
  449. X                        errno = 0;              /* clear errno */
  450. X                      }
  451. X                    if (len > 0)
  452. X                        SendData(layer->chan, buf, len);
  453. X                  }
  454. X                if ((fds[i].revents & POLLOUT) != 0)
  455. X                  { while ((kbptr=layer->kbuff)->size)
  456. X                      { /* pass as much keyboard as possible */
  457. X                        len = write(layer->ptyfd, &kbptr->text[kbptr->offset],
  458. X                                kbptr->size);
  459. X                        DO DEBUG("keyin len %d to chan %d\n", len, layer->chan);
  460. X                        if (len <= 0)           /* if no data accepted ... */
  461. X                          { if (errno == EIO)   /* if I/O error indicated ... */
  462. X                                fderr |= layer->ptymask; /* wait-a-bit on this */
  463. X                            errno = 0;          /* clear errno */
  464. X                            break;              /* try again later */
  465. X                          }
  466. X                        /* some of buffer accepted */
  467. X                        kbptr->size -= len;     /* length processed */
  468. X                        kbptr->offset += len;   /* bump up offset */
  469. X                        if (kbptr->size > 0)    /* not all buffer accepted ... */
  470. X                            break;              /* try feed again later */
  471. X                        /* see if another buffer chained */
  472. X                        if (kbptr->next)
  473. X                          { /* yes, free up current buffer and queue next */
  474. X                            layer->kbuff = kbptr->next; /* to next buffer */
  475. X                            free(kbptr);    /* free this buffer up */
  476. X                          }
  477. X                        else
  478. X                          { /* otherwise leave this for next input */
  479. X                            kbptr->size = 0;    /* empty buffer */
  480. X                            kbptr->offset = 0;  /* refill from the start */
  481. X                          }
  482. X                      }
  483. X                  }
  484. X                break;
  485. X              }
  486. X        /* next process input stream from layers server */
  487. X        if (fds[1].revents)
  488. X          { ProcessStreamin();  /* output and control packets */
  489. X            continue;   /* status may have changed */
  490. X          }
  491. X
  492. X        /* finally process commands from the Ulayers startup */
  493. X        if (fds[0].revents)
  494. X          {
  495. X            len = read(0, buf, 1);
  496. X            if (len > 0 && buf[0] > ' ')
  497. X              {
  498. X                if (DoCmd(buf[0])) {
  499. X                    ServerNumber = 0;
  500. X                    goto restart;
  501. X        }
  502. X              }
  503. X           }                
  504. X                
  505. X        if (fderr)
  506. X            DoWait();
  507. X
  508. X
  509. X#else
  510. X        /* check for I/O on all available I/O descriptors */
  511. X        r = (1 | TtyMask);  /* always read server stream */
  512. X        w = 0;          /* initalize to no write tests */
  513. X    tv.tv_sec = 0;
  514. X        tv.tv_usec = 0;     /* default no startup poll */
  515. X
  516. X        /* for all active layers set read and write bits as appropriate */
  517. X        for (n=0; n<MAXPCHAN; n++)
  518. X         { layer = &World[n];
  519. X         if (layer->allocated) /* if layer exists ... */
  520. X          { /* if not yet started or has just terminated ... */
  521. X            if (layer->ptymask & fderr)
  522. X                tv.tv_usec = WUSSTARTUP;    /* don't spinloop but wait-a-bit */
  523. X            else
  524. X              { if (layer->kbuff && layer->kbuff->size)
  525. X                    /* keyboard input for layer */
  526. X                    w |= layer->ptymask;    /* try write to it */
  527. X                /* read keys from xterm */
  528. X                r |= layer->ptymask;
  529. X               }
  530. X            }
  531. X          }
  532. X        DO DEBUG("Select(r %x, w %x, fderr %x, us %d)\n",
  533. X                    r, w, fderr, tv.tv_usec);
  534. X
  535. X        switch ( select(32, &r, &w, NULL, tv.tv_usec ? &tv : NULL) )
  536. X        { case -1:
  537. X            /* errno has report */
  538. X            if (errno == EINTR) /* signal delivered or timout */
  539. X              { errno = 0;
  540. X                tv.tv_usec = 0; /* clear timer wait value */
  541. X                fderr = 0;  /* turn off error stall */
  542. X                DO DEBUG("select errno EINTR\n");
  543. X                continue;   /* re-loop */
  544. X              }
  545. X            Abortonmsg = 1;
  546. X            DO DEBUG("select errno %d\n", errno);
  547. X            Msg (errno, "select");
  548. X            /*NOTREACHED*/
  549. X
  550. X          case 0:
  551. X            /* timeout reached */
  552. X            tv.tv_usec = 0;                 /* clear timer wait value */
  553. X            fderr = 0;                      /* turn off error stall */
  554. X            continue;                       /* re-loop */
  555. X
  556. X          default:
  557. X            /* a channel has read/write status pending */
  558. X            break;
  559. X        }
  560. X
  561. X        DO DEBUG("after select r %x w %x\n", r, w);
  562. X
  563. X        for (n=0; n<MAXPCHAN; n++)
  564. X          if ((layer = &World[n])->allocated)
  565. X            if (w & layer->ptymask)
  566. X                while ((kbptr=layer->kbuff)->size)
  567. X                  { /* pass as much keyboard as possible */
  568. X                    len = write(layer->ptyfd, &kbptr->text[kbptr->offset],
  569. X                                kbptr->size);
  570. X                    DO DEBUG("keyin len %d to chan %d\n", len, layer->chan);
  571. X                    if (len <= 0)           /* if no data accepted ... */
  572. X                      { if (errno == EIO)   /* if I/O error indicated ... */
  573. X                            fderr |= layer->ptymask; /* wait-a-bit on this */
  574. X                        errno = 0;          /* clear errno */
  575. X                        break;              /* try again later */
  576. X                      }
  577. X                    /* some of buffer accepted */
  578. X                    kbptr->size -= len;     /* length processed */
  579. X                    kbptr->offset += len;   /* bump up offset */
  580. X                    if (kbptr->size > 0)    /* not all buffer accepted ... */
  581. X                        break;              /* try feed again later */
  582. X                    /* see if another buffer chained */
  583. X                    if (kbptr->next)
  584. X                      { /* yes, free up current buffer and queue next */
  585. X                        layer->kbuff = kbptr->next; /* to next buffer */
  586. X                        free(kbptr);    /* free this buffer up */
  587. X                      }
  588. X                    else
  589. X                      { /* otherwise leave this for next input */
  590. X                        kbptr->size = 0;    /* empty buffer */
  591. X                        kbptr->offset = 0;  /* refill from the start */
  592. X                      }
  593. X                  }
  594. X
  595. X        /* process keyboard input first
  596. X        */
  597. X        for (n=0; n<MAXPCHAN; n++)
  598. X          if ((layer = &World[n])->allocated)
  599. X            if (r & layer->ptymask)
  600. X              { /* input from xterm window, send to server */
  601. X                len = read(layer->ptyfd, buf, IOSIZE);
  602. X                if (len >= 0)               /* if no error ... */
  603. X                  { DO DEBUG("input chan %d len %d\n", layer->chan, len);
  604. X                  }
  605. X                else
  606. X                  { 
  607. X                    /* We expect EIO error if socket not yet open on other end
  608. X                    ** or if process using socket has terminated. We expect
  609. X                    ** EWOULDBLOCK also after process terminates.
  610. X                    **/
  611. X                    DO DEBUG("read input err chan %d errno %d len %d\n",
  612. X                                layer->chan, errno, len);
  613. X                    if (errno == EIO || errno == EWOULDBLOCK)
  614. X                      { DO DEBUG(" ...anticipated\n");
  615. X                      }
  616. X                    /* layer not ready or just terminated so wait-a-bit */
  617. X                    fderr |= layer->ptymask;
  618. X                    errno = 0;              /* clear errno */
  619. X                  }
  620. X                if (len > 0)
  621. X                    SendData(layer->chan, buf, len);
  622. X              }
  623. X
  624. X        /* next process input stream from layers server */
  625. X        if ((r & TtyMask) != 0)
  626. X          { ProcessStreamin();  /* output and control packets */
  627. X            continue;   /* status may have changed */
  628. X          }
  629. X
  630. X        /* finally process commands from the Ulayers startup */
  631. X        if (r & 1)
  632. X          {
  633. X            len = read(0, buf, 1);
  634. X            if (len > 0 && buf[0] > ' ')
  635. X              {
  636. X                if (DoCmd(buf[0])) {
  637. X                    ServerNumber = 0;
  638. X                    goto restart;
  639. X        }
  640. X              }
  641. X           }                
  642. X                
  643. X        if (fderr)
  644. X            DoWait();
  645. X
  646. X
  647. X#endif
  648. X      } /* end while (1) */
  649. X
  650. X    /* NOT REACHED */
  651. X    
  652. X    
  653. X        
  654. X}
  655. X
  656. XDoCmd(c)
  657. Xint c;
  658. X{
  659. X    int chan, i;
  660. X    char obuf[64];
  661. X    static struct Shape shape;          /* Shape structure */
  662. X
  663. X    printf("\r\n[ CMD %c ]\r\n", c);
  664. X    DO DEBUG("Local CMD %c\n", c);
  665. X    switch (c) {
  666. X    case 'n':
  667. X        chan = MakeWindow(0, &shape);
  668. X        DO DEBUG("new channel = %d\n", chan);
  669. X        if (chan == 0) {
  670. X            break;
  671. X        }
  672. X        tty_putc(ESCAPE);
  673. X        tty_putc(ATTRSIZE + '2');
  674. X        tty_putc('N');
  675. X        tty_putc(chan+'0');
  676. X        asciishape(&shape, obuf);
  677. X        obuf[ATTRSIZE] = 0;
  678. X        tty_puts(obuf, 1);
  679. X        break;
  680. X        
  681. X    case 's':
  682. X        printf("\r\nLAYER    PID\r\n");
  683. X        for (i=0; i<MAXPCHAN; i++)
  684. X            if (World[i].allocated)
  685. X                printf(" %2d   %6d\r\n", World[i].chan, World[i].lpid);
  686. X        break;
  687. X    case 'q':
  688. X    case 'a':
  689. X        tty_putc(ESCAPE);
  690. X        tty_putc('1');
  691. X        tty_putc('E');
  692. X        FLUSH;
  693. X        for (i=0; i<MAXPCHAN; i++)
  694. X            KillWindow(&World[i]);  /* kill all windows */
  695. X        if (c == 'q')
  696. X            FQuit(0);
  697. X        return(-1);
  698. X        
  699. X    default:
  700. X        printf("*** UNKNOWN ULAYERS COMMAND KEY\r\n");
  701. X        /* FALL THROUGH */
  702. X    case 'h':
  703. X        printf("\r\nPress one of the following keys:\r\n");
  704. X        printf("\r\n    n - open a new layer session\r\n");
  705. X        printf("\r\n    s - show status of layers\r\n");
  706. X        printf("\r\n    a - abort host layers, return to dumb terminal\r\n");
  707. X        printf("\r\n    q - abort host layers, quit\r\n\r\n");
  708. X        break;
  709. X
  710. X    }
  711. X    return(0);
  712. X}
  713. X
  714. X            /* InitWorld() - initialize layer structures */
  715. X
  716. Xstatic
  717. XInitWorld()
  718. X{
  719. X    struct Layer *layer;                /* layer pointer */
  720. X    int     i;                          /* work variable */
  721. X
  722. X    for (i=0; i<MAXPCHAN; i++)
  723. X      { layer = &World[i];              /* point to layer */
  724. X        layer->chan = i+1;              /* channel ID */
  725. X        layer->allocated = 0;           /* does not exist yet */
  726. X        layer->lpid = 0;                /* head process */
  727. X        layer->ptyfd = 0;               /* no pseduo pty yet */
  728. X        layer->ptymask = 0;             /* no pty mask yet */
  729. X        ClearShape(&layer->shape);      /* clear shape structure */
  730. X
  731. X        /* allocate the primary input keybuffer for this layer */
  732. X        layer->kbuff = (struct Kbuff *) malloc(sizeof(struct Kbuff));
  733. X        layer->kbuff->next = NULL;      /* no next buffer */
  734. X        layer->kbuff->size = 0;         /* no data in buffer */
  735. X        layer->kbuff->offset = 0;       /* start filling at front */
  736. X
  737. X      } /* end for layer scan */
  738. X
  739. X} /* InitWorld() */
  740. X
  741. X
  742. X
  743. X                    /* clearshape() - initialize shape structure */
  744. X
  745. Xstatic
  746. XClearShape(shape)
  747. Xstruct Shape    *shape;                 /* shape structure pointer */
  748. X{
  749. X    shape->worigv = 0;                  /* default window position */
  750. X    shape->worigh = 0;
  751. X    shape->wlines = 0;                  /* default size */
  752. X    shape->wchars = 0;
  753. X    shape->wfont = 0;                   /* default font size */
  754. X    shape->wattr = 0;                   /* no attributes */
  755. X
  756. X} /* clearshape() */
  757. X
  758. X
  759. X
  760. X            /* ProcessStreamin() - MacLayers has input to process */
  761. X
  762. XProcessStreamin()
  763. X{
  764. X    DO dumptime();
  765. X    DO DEBUG("ProcessStreamin() insize %d\n", insize);
  766. X
  767. X    GetData();                      /* read some */
  768. X
  769. X    while (insize > 0)              /* while more data to process ... */
  770. X        Parse();                    /* process next chuck of data */
  771. X
  772. X} /* ProcessStreamin() */
  773. X
  774. X            /* Parse() - process next chunk of input stream */
  775. X
  776. Xstatic
  777. XParse()
  778. X{
  779. X#define ST_NULL     0               /* not primed for next state yet */
  780. X#define ST_STREAM   1               /* processing default stream input */
  781. X#define ST_PKT      2               /* processing packet data */
  782. X
  783. X    int     c;                      /* input character being processed */
  784. X
  785. X    static  int state = ST_NULL;    /* current input state */
  786. X    static  int psize = 0;          /* packet size */
  787. X    static  int rempsize = 0;       /* remembered packet size */
  788. X    static  char pdata[MAXSTR];     /* area for packet data */
  789. X    static  char *ppos;             /* packet read insert position */
  790. X    static  int escapemode = 0;     /* processing escape character */
  791. X    static  int escapechar;         /* escape character being processed */
  792. X    static  pchan = -1;             /* packet input stream channel */
  793. X
  794. X    DO dumptime();
  795. X    DO DEBUG("Parse() insize %d\n", insize);
  796. X
  797. X    while (insize-- > 0)            /* while more data */
  798. X      { c = (*inpos++ & 0x0ff);     /* get next character */
  799. X        switch (state)              /* process according to state */
  800. X        { case ST_NULL:             /* prepare for new packet */
  801. X            DO DEBUG("ST_NULL\n");
  802. X            psize = 0;              /* clear packet size */
  803. X            ppos = pdata;           /* start fill at data position */
  804. X            pchan = Outstream;      /* packet channel is current input stream */
  805. X            state = ST_STREAM;      /* default is stream processing */
  806. X
  807. X          case ST_STREAM:
  808. X            /* stream output for layer */
  809. X            /* check for escape char with possible high bit on */
  810. X#ifdef DUMPALL
  811. X            DO DEBUG("ST_STREAM %x/%x '%c' esc %d insz %d\n",
  812. X                        c, c & 0x7f, c & 0x7f, escapemode, insize);
  813. X#endif
  814. X            if (c == ESCAPE || c == (ESCAPE | 0x80))
  815. X             {  if (escapemode && c == escapechar) /* previous was ESCAPE */
  816. X                /* this is really a single ESCAPE character */
  817. X                    escapemode = 0;     /* back out of ESCAPE mode */
  818. X                else
  819. X                    /* what do we do with back to back esc esc+0x80 ? */
  820. X                  { /* flag in escape mode */
  821. X                    escapemode++;
  822. X                    escapechar = c;     /* remember character used for escape */
  823. X                    continue;           /* and continue scan */
  824. X                  }
  825. X              }
  826. X            else
  827. X            if (escapemode)
  828. X              { /* this is the start of a control packet */
  829. X                if (psize)              /* if we have previous data packet */
  830. X                    Packet(pchan, psize, pdata); /* finish up previous pkt */
  831. X                /* process packet size */
  832. X                psize = (c & 0x7f) - '0'; /* save size byte */
  833. X                if (psize <= 0 || psize > MAXSTR)
  834. X                  { /* bad size */
  835. X                    DO DEBUG("Bad pkt size %d\n", psize);
  836. X                    break;              /* trash this packet */
  837. X                  }
  838. X                rempsize = psize;       /* remember this size for later */
  839. X#if 0
  840. X                ptimo = rtimo;          /* start receive timeout */             
  841. X#endif
  842. X                escapemode = 0;         /* escape mode now off */
  843. X                ppos = pdata;           /* initialize data store pointer */
  844. X                state = ST_PKT;         /* expect packet data next */
  845. X                continue;               /* continue scan */
  846. X              }
  847. X                  
  848. X            /* process standard data output character for current stream */
  849. X            
  850. X            *ppos++ = c;                /* save next data character */
  851. X                
  852. X            if (++psize >= MAXSTR)      /* if packet full ... */
  853. X              { Packet(pchan, psize, pdata); /* process this packet */
  854. X                break;                  /* end packet processing */
  855. X              }               
  856. X            continue;                   /* continue scan */
  857. X                                                
  858. X          case ST_PKT:
  859. X            /* process next paket data byte */
  860. X            *ppos++ = c & 0x7f;     /* store next data byte */
  861. X#ifdef DUMPALL
  862. X            DO DEBUG("ST_PKT: %x '%c' sz %d\n", c & 0x7f, c & 0x7f, psize);
  863. X#endif
  864. X            if (--psize != 0)
  865. X                continue;
  866. X#if 0
  867. X            if (crc((unsigned char *) &rpkt, rpkt.pkt.HEADER_DSIZE+2))
  868. X                STATS(Scrcerr);         /* communications error */
  869. X            else
  870. X#endif
  871. X            Packet(0, rempsize, pdata); /* process it */
  872. X                
  873. X            } /* end build packet switch */
  874. X            
  875. X#if 0
  876. X        ptimo = 0;                      /* no more receive timeout */
  877. X#endif
  878. X        state = ST_NULL;                /* no more receive packet in progress */
  879. X            
  880. X      } /* end while (insize) */
  881. X          
  882. X    if (state == ST_STREAM && psize )   /* if we have some data ... */
  883. X      { Packet(Outstream, psize, pdata); /* process this data */
  884. X#if 0
  885. X        ptimo = 0;                      /* no more receive timeout */
  886. X#endif
  887. X        state = ST_NULL;                /* no more receive packet in progress */
  888. X      }
  889. X
  890. X} /* Parse() */
  891. X
  892. X
  893. X        /* Packet() - prcess next input data string or control packet */
  894. Xstatic
  895. XPacket(chan, size, buff)
  896. Xint         chan;                       /* channel (0 if control packet) */
  897. Xint         size;                       /* amount of data */
  898. Xchar        *buff;                      /* pointer to packet data */
  899. X{
  900. X    static struct Shape shape;          /* Shape structure */
  901. X    char obuf[64];
  902. X
  903. X    DO dumptime();
  904. X    DO DEBUG("Packet(chan %d, size %d, '%.*s')\n", chan, size, size, buff);
  905. X
  906. X    /* verify channel */
  907. X    if (chan < 0 || chan > MAXPCHAN)
  908. X      { DO DEBUG("BAD CHANNEL!!\n");
  909. X        return;                         /* ignore bad channel */
  910. X      }
  911. X
  912. X    /* if data packet (chan>0) feed data to xterm window */
  913. X    if (chan > 0)
  914. X      { ReceiveData(chan, buff, size);
  915. X        return;                         /* we are through */
  916. X      }
  917. X
  918. X    /* control packet (channel 0) */
  919. X    chan = buff[1] - '0';           /* assume channel specified */
  920. X    if (chan < 0 || chan > MAXPCHAN)    /* if invalid ... */
  921. X        chan = 0;           /* set to zero */
  922. X
  923. X    switch (buff[0])
  924. X    { case 'O':     /* redirect stream */
  925. X        DO DEBUG("CMD 'O' redirect stream to %c\n", buff[1]);
  926. X        if (size != 2)                  /* verify size */
  927. X            break;                      /* break if bad */
  928. X        if (chan == 0)                  /* verify channel */
  929. X            break;                      /* break if bad */
  930. X        Outstream = chan;               /* new Outstream channel */
  931. X        return;                         /* we are through */
  932. X
  933. X      case 'T':     /* title packet */
  934. X        buff[size] = 0;
  935. X        DO DEBUG("CMD 'T' title chan %c '%s'\n", buff[1], &buff[2]);
  936. X#ifdef XTERM_TITLE
  937. X        /* UGLY HACK - depends on xterm ESC sequence */
  938. X        sprintf(obuf, "\033]2;Layer %d - %s\007", chan, &buff[2]);
  939. X        ReceiveData(chan, obuf, strlen(obuf));
  940. X#endif
  941. X        return;
  942. X
  943. X      case 'A':     /* A_NEWLAYER packet */
  944. X        DO DEBUG("CMD 'A' A_NEWLAYER\n");
  945. X        if (size != 1 + ATTRSIZE)
  946. X            break;          /* break if bad */
  947. X
  948. X        /* build shape structure for SendNew() */
  949. X        if (parseshape(&shape, &buff[1]) == -1) {
  950. X            tty_puts(a_newfail, 1);
  951. X            break;
  952. X        }
  953. X        chan = MakeWindow(0, &shape);
  954. X        DO DEBUG("new channel = %d\n", chan);
  955. X        if (chan == 0) {
  956. X            tty_puts(a_newfail, 1);
  957. X            break;
  958. X        }
  959. X        tty_putc(ESCAPE);
  960. X        tty_putc(ATTRSIZE + '3');
  961. X        tty_putc('A');
  962. X        tty_putc(chan+'0');
  963. X        tty_putc('0');
  964. X        asciishape(&shape, obuf);
  965. X        obuf[ATTRSIZE] = 0;
  966. X        tty_puts(obuf, 1);
  967. X
  968. X        return;                         /* we are through */
  969. X        
  970. X      case 'N':     /* new layer creation */
  971. X        DO DEBUG("CMD 'N' new layer creation newchan %c\n", buff[1]);
  972. X        if (size != 2 + ATTRSIZE)       /* verify size */
  973. X            break;                      /* break if bad */
  974. X        if (chan == 0)                  /* verify channel */
  975. X            break;                      /* break if bad */
  976. X        /* build shape structure */
  977. X        if (parseshape(&shape, &buff[2]) == -1)
  978. X            break;                      /* if invalid data then bad packet */
  979. X        ReceiveNew(chan, &shape);       /* pass to server */
  980. X        return;                         /* packet is done */
  981. X
  982. X      case 'D':     /* delete layer */
  983. X        DO DEBUG("CMD 'D' delete layer %c\n", buff[1]);
  984. X        if (size != 2)                  /* verify size */
  985. X            break;                      /* break if bad */
  986. X        if (chan == 0)                  /* verify channel */
  987. X            break;                      /* break if bad */
  988. X        ReceiveDelete(chan);            /* pass on to server */
  989. X        return;                         /* packet is done */
  990. X
  991. X      case 'E':     /* exit - awaiting shutdown */
  992. X        DO DEBUG("CMD 'E' exit MacLayers awaiting shutdown msg\n");
  993. X        if (size != 1)                  /* verify size */
  994. X            break;                      /* break if bad */
  995. X        ReceiveQuit();                  /* pass to server */
  996. X        /* NOT REACHED*/
  997. X        return;                         /* ?? should never reach here */
  998. X
  999. X      case 'R':     /* reshape */
  1000. X        DO DEBUG("CMD 'R' reshape chan %c\n", buff[1]);
  1001. X
  1002. X        if (size != 2 + ATTRSIZE)       /* verify size */
  1003. X            break;              /* break if bad */
  1004. X
  1005. X        if (chan == 0)              /* verify channel */
  1006. X            break;              /* break if bad */
  1007. X
  1008. X        /* build shape structure */
  1009. X        if (parseshape(&shape, &buff[2]) == -1)
  1010. X            break;                      /* if invalid data then bad packet */
  1011. X
  1012. X        ReceiveReshape(chan, &shape);   /* tell server about shape */
  1013. X        return;                         /* packet processed */
  1014. X
  1015. X      default:
  1016. X        DO DEBUG("ILLEGAL CONTROL PACKET!!!\n");
  1017. X        return;                         /* ignore bad packet */
  1018. X
  1019. X    } /* end command packet switch */
  1020. X
  1021. X    /* switch falls out if bad size or channel for given command */
  1022. X    DO DEBUG("Invalid size or channel!!!\n");   /* dump error */
  1023. X    return;                             /* ignore packet */
  1024. X
  1025. X} /* Packet() */
  1026. X
  1027. X
  1028. X            /* GetData() - read next input from MacLayers stream */
  1029. X
  1030. X/*  The settimeout variable indicates if we return when nothing
  1031. X**  is read within a certain amount of seconds. The return code is:
  1032. X**
  1033. X**      0 - timeout occured and no data was read
  1034. X**
  1035. X**      1 - no timeout occured, data read
  1036. X*/
  1037. Xstatic int
  1038. XGetData()
  1039. X{
  1040. X    int     result;                 /* return from read() */
  1041. X    int     i;                      /* work counter */
  1042. X    char    *ptr;                   /* work pointer */
  1043. X
  1044. X    DO dumptime();
  1045. X    DO DEBUG("GetData()\n");
  1046. X
  1047. X    /* if buffer still has data simply return (SHOULD NOT OCCUR?) */
  1048. X    if (insize > 0)
  1049. X      { DO DEBUG("early return insize %d\n", insize);
  1050. X        return ( 1 );               /* act as through data read */
  1051. X      }
  1052. X    inpos = inbuff;                 /* next get will start at beginning */
  1053. X    insize = 0;                     /* default insize back to zero */
  1054. X
  1055. X    /* set timeout if we are to do so */
  1056. X    if (settimeout)
  1057. X      { DO DEBUG("alarm(%d)\n", settimeout);
  1058. X        (void) alarm(settimeout);   /* set timeout in seconds */
  1059. X      }
  1060. X
  1061. X    /* do the read from the serial channel */
  1062. X    result = read(TtyFd, inbuff, IOSIZE);
  1063. X
  1064. X    /* if alarm was set cancel it now */
  1065. X    if (settimeout)
  1066. X      { DO DEBUG("alarm(0)\n");
  1067. X        (void) myalarm(0);          /* cancel alarm */
  1068. X      }
  1069. X
  1070. X    /* check for timeout or error */
  1071. X    /* EWOULDBLOCK for no data avail -(but we should not see this) */
  1072. X    /* EINTR if signal stopped the read -(rare but could happen) */
  1073. X    if (result <= 0)
  1074. X      { DO DEBUG(" ?? no data result %d\n", result);
  1075. X        return ( 0 );               /* return nothing read */
  1076. X      }
  1077. X
  1078. X    /* return with fresh buffer data */
  1079. X    insize = result;
  1080. X
  1081. X    /* if 7-bit communication channel then strip all high bits */
  1082. X    if (Sevenbits)
  1083. X      for (i=result,ptr = inbuff; i>0; --i)
  1084. X        *ptr++ &= 0x7f;             /* strip high bit */
  1085. X
  1086. X    DO DEBUG("read %d bytes\n", insize);
  1087. X    return ( 1 );                   /* return OK code */
  1088. X
  1089. X} /* GetData() */
  1090. X
  1091. X                /* asciishape() - convert Shape structure to ASCII */
  1092. Xstatic
  1093. Xasciishape(shape, loc)
  1094. Xstruct Shape    *shape;                     /* Shape structure for channel */
  1095. Xchar            *loc;                       /* location to start filling result */
  1096. X{
  1097. X    char        *origloc;                   /* (for debuggin) */
  1098. X
  1099. X    origloc = loc;                          /* remember start of string */
  1100. X    fill4(&loc, shape->worigh);             /* origin h */
  1101. X    fill4(&loc, shape->worigv);             /* origin v */
  1102. X    fill2(&loc, shape->wlines);             /* lines high */
  1103. X    fill2(&loc, shape->wchars);             /* chars wide */
  1104. X    fill1(&loc, shape->wfont);              /* font size */
  1105. X    fill2(&loc, shape->wattr);              /* attributes */
  1106. X
  1107. X    DO DEBUG("asciishape(): %.*s\n", ATTRSIZE, origloc);
  1108. X
  1109. X} /* asciishape() */
  1110. X
  1111. X
  1112. X
  1113. X                    /* fill4() - convert parameter to ASCII */
  1114. X
  1115. Xstatic void
  1116. Xfill4(loc, valu)
  1117. Xchar        **loc;                          /* pointer to fill area pointer */
  1118. Xunsigned    valu;                           /* value to use */
  1119. X{
  1120. X    fill2(loc, valu>>8);                    /* fill high half word */
  1121. X    fill2(loc, valu & 0xff);                /* fill low half word */
  1122. X
  1123. X} /* fill4() */
  1124. X
  1125. X
  1126. X                    /* fill2() - convert parameter to ASCII */
  1127. X
  1128. Xstatic void
  1129. Xfill2(loc, valu)
  1130. Xchar        **loc;                          /* pointer to fill area pointer */
  1131. Xunsigned    valu;                           /* value to use */
  1132. X{
  1133. X    fill1(loc, valu>>4);                    /* fill high byte */
  1134. X    fill1(loc, valu & 0xf);                 /* fill low byte */
  1135. X    
  1136. X} /* fill2() */
  1137. X
  1138. X
  1139. X                    /* fill1() - convert parameter to ASCII */
  1140. X
  1141. Xstatic void
  1142. Xfill1(loc, valu)
  1143. Xchar        **loc;                          /* pointer to fill area pointer */
  1144. Xunsigned    valu;                           /* value to use */
  1145. X{
  1146. X    *(*loc)++ = "0123456789ABCDEF"[valu & 0xf]; /* return hex value */
  1147. X
  1148. X} /* fill1() */
  1149. X
  1150. X
  1151. X
  1152. X            /* parseshape() - convert ASCII image to Shape structure */
  1153. X                
  1154. Xstatic int  Badconvert;                     /* indicates bad conversion */
  1155. X
  1156. Xstatic int
  1157. Xparseshape(shape, loc)
  1158. Xstruct Shape    *shape;                     /* Shape structure for channel */
  1159. Xchar            *loc;                       /* location to start parsing */
  1160. X{
  1161. X    Badconvert = 0;                         /* clear bad characters indicator */
  1162. X    shape->worigh = get4(&loc);             /* origin h */
  1163. X    shape->worigv = get4(&loc);             /* origin v */
  1164. X    shape->wlines = get2(&loc);             /* lines high */
  1165. X    shape->wchars = get2(&loc);             /* chars wide */
  1166. X    shape->wfont = get1(&loc);              /* font size */
  1167. X    shape->wattr = get2(&loc);              /* attributes */
  1168. X
  1169. X    DO DEBUG("ParseShape(): origv %d, origh %d, lines %d, chars %d\n",
  1170. X                shape->worigv, shape->worigh, shape->wlines, shape->wchars);
  1171. X    DO DEBUG("   font %d, attr 0x%x, badconv %d\n",
  1172. X                    shape->wfont, shape->wattr, Badconvert);
  1173. X
  1174. X    return ( Badconvert ? -1 : 0 );         /* return conversion code */
  1175. X
  1176. X} /* parseshape() */
  1177. X
  1178. X
  1179. X                    /* get4() - convert ASCII to parameter */
  1180. X
  1181. Xstatic unsigned
  1182. Xget4(loc)
  1183. Xchar        **loc;                          /* pointer to fill area pointer */
  1184. X{
  1185. X    unsigned    hi;                         /* high portion */
  1186. X    unsigned    low;                        /* low portion */
  1187. X
  1188. X    hi = get2(loc);                         /* get high byte */
  1189. X    low = get2(loc);                        /* get low byte */
  1190. X
  1191. X    return ( (hi<<8) + low );               /* return word value */
  1192. X
  1193. X} /* get4() */
  1194. X
  1195. X
  1196. X                    /* get2() - convert ASCII to parameter */
  1197. X
  1198. Xstatic unsigned
  1199. Xget2(loc)
  1200. Xchar        **loc;                          /* pointer to fill area pointer */
  1201. X{
  1202. X    unsigned    hi;                         /* high portion */
  1203. X    unsigned    low;                        /* low portion */
  1204. X
  1205. X    hi = get1(loc);                         /* get high half */
  1206. X    low = get1(loc);                        /* get low half */
  1207. X
  1208. X    return ( (hi<<4) + low );               /* return byte value */
  1209. X    
  1210. X} /* get2() */
  1211. X
  1212. X
  1213. X                    /* get1() - convert ASCII to parameter */
  1214. X
  1215. X/*  This function sets 'Badconvert' if an invalid character is detected */
  1216. X
  1217. Xstatic unsigned
  1218. Xget1(loc)
  1219. Xchar        **loc;                          /* pointer to fill area pointer */
  1220. X{
  1221. X    int         c;                          /* character to convert */
  1222. X    
  1223. X    c = *(*loc)++;                          /* fetch character */
  1224. X    
  1225. X    if (c >= '0' && c <= '9')
  1226. X        /* zero through nine */
  1227. X        return ( c - '0' );                 /* return it's binary value */
  1228. X    
  1229. X    if (c >= 'a' && c <= 'f')
  1230. X        /* lower case hex */
  1231. X        return ( c - 'a' + 10);             /* return it's binary value */
  1232. X        
  1233. X    if (c >= 'A' && c <= 'F')
  1234. X        /* upper case hex */
  1235. X        return ( c - 'A' + 10);             /* return it's binary value */
  1236. X        
  1237. X    /* invalid digit! */
  1238. X    Badconvert++;                           /* set bad character flag */
  1239. X    return ( 0 );                           /* return a zero */
  1240. X
  1241. X} /* get1() */
  1242. X
  1243. X
  1244. X
  1245. X
  1246. X                /* myalarm() - setup alarm timeout for next read */
  1247. X
  1248. Xstatic int
  1249. Xmyalarm(time)
  1250. Xint         time;                       /* time in seconds (or zero) */
  1251. X{
  1252. X    DO dumptime();
  1253. X    DO DEBUG("myalarm(%d)\n", time);
  1254. X    settimeout = time;                  /* set for next read */
  1255. X
  1256. X} /* myalarm() */
  1257. X
  1258. X                /* dumptime() - print out time in seconds */
  1259. X
  1260. X/* THIS MAY BE SYSTEM DEPENDENT SO IS BASED UPON DEBUG IFDEF */
  1261. X#ifdef DUMPALL
  1262. X#include <sys/types.h>
  1263. X#include <sys/time.h>
  1264. X#endif
  1265. X
  1266. Xstatic void
  1267. Xdumptime()
  1268. X{
  1269. X#ifdef DUMPALL
  1270. X    time_t  seconds;
  1271. X    static time_t   base;
  1272. X
  1273. X    if (base == 0)
  1274. X      { seconds = 0;
  1275. X        base = time(NULL);
  1276. X      }
  1277. X    else
  1278. X        seconds = time(NULL) - base;
  1279. X
  1280. X    DO DEBUG("[%3d] ", seconds);
  1281. X    
  1282. X#endif
  1283. X} /* dumptime() */
  1284. X
  1285. X
  1286. X            /* SendData() - send keyboard data to server */
  1287. X
  1288. Xvoid
  1289. XSendData(chan, buff, cnt)
  1290. Xint         chan;                   /* layer window ID */
  1291. Xunsigned char *buff;                /* new title string */
  1292. Xint         cnt;                    /* count of title length */
  1293. X{
  1294. X    unsigned c;                     /* output character being sent */
  1295. X
  1296. X    DO
  1297. X      { int     dcnt;
  1298. X
  1299. X        dumptime();
  1300. X        DEBUG("SendData(chan %d, len %d, '", chan, cnt, cnt, buff);
  1301. X        for (dcnt=0; dcnt<cnt; dcnt++)
  1302. X            DEBUG("%c", buff[dcnt]); /* dump each char so null doesn't stop */
  1303. X        DEBUG("')\n");
  1304. X      }
  1305. X
  1306. X    if (chan <= 0 || chan > MAXPCHAN)
  1307. X      { DO DEBUG("BAD CHANNEL!!!\n");
  1308. X        return;                     /* ignore request */
  1309. X      }
  1310. X
  1311. X    /* if new input channel stream then prefix redirect command */
  1312. X    if (chan != Instream)
  1313. X      { DO DEBUG("Redirecting input from %d '~2O%d'\n", chan, chan);
  1314. X        tty_putc(ESCAPE);           /* start of command sequence */
  1315. X        tty_putc('2');              /* send command size */
  1316. X        tty_putc('I');              /* send command */
  1317. X        tty_putc(chan + '0');       /* put out channel in ASCII */
  1318. X        Instream = chan;            /* new input stream set */
  1319. X      }
  1320. X
  1321. X    /* transmit the buffer converting the ESCAPE sequence to double ESCAPE */
  1322. X    while (cnt--)
  1323. X      { c = *buff++;                /* get next input character */
  1324. X#ifdef DUMPALL
  1325. X        DO DEBUG("inchar %c 0x%x\n", c, c);
  1326. X#endif
  1327. X        if (c == ESCAPE || c == (ESCAPE + 0x80))
  1328. X          { tty_putc(c);                /* send it twice */
  1329. X#ifdef DUMPALL
  1330. X            DO DEBUG(" Doubled Escape!\n");
  1331. X#endif
  1332. X          }
  1333. X        tty_putc(c);                    /* write character out */
  1334. X      }
  1335. X
  1336. X    FLUSH;                          /* force out queued output characters */
  1337. X        
  1338. X} /* SendData() */
  1339. X
  1340. Xvoid
  1341. XSendDelete(chan)
  1342. Xint     chan;                       /* dead channel ID */
  1343. X{
  1344. X    DO DEBUG("SendDelete(%d) '~2D%d'\n", chan, chan);
  1345. X
  1346. X    if (chan <= 0 || chan > MAXPCHAN) /* check channel ID */
  1347. X      { DO DEBUG("BAD CHANNEL!!!\n");
  1348. X        return;                     /* ignore request */
  1349. X      }
  1350. X
  1351. X    tty_putc(ESCAPE);               /* send control packet start char */
  1352. X    tty_putc('2');                  /* send command size */
  1353. X    tty_putc('D');                  /* send command character */
  1354. X    tty_putc(chan + '0');           /* channel ID in ascii */
  1355. X    FLUSH;
  1356. X
  1357. X} /* SendDelete() */
  1358. X
  1359. X
  1360. X    /* DoWait() -  send SIGCONT to stopped windows, Free dead process windows */
  1361. Xstatic
  1362. XDoWait()
  1363. X{
  1364. X    register pid;
  1365. X    register struct Layer *layer;
  1366. X    int     i;
  1367. X#ifdef USG
  1368. X    /* dead or stopped child process found */
  1369. X    for (i=0; i<MAXPCHAN; i++)
  1370. X        if (kill((layer = &World[i])->lpid, 0) == -1 && (errno == ESRCH))
  1371. X          {     /* remove dead process's layer */
  1372. X            DO DEBUG("kill dead process window %d\n", layer->chan);
  1373. X            KillWindow (layer);
  1374. X            /* tell server layer is dead */
  1375. X            SendDelete(layer->chan);
  1376. X          }
  1377. X#else
  1378. X    union wait wstat;
  1379. X
  1380. X    DO DEBUG("DoWait()\n");
  1381. X    while ((pid = wait3 (&wstat, WNOHANG|WUNTRACED, NULL)) > 0)
  1382. X        /* dead or stopped child process found */
  1383. X        for (i=0; i<MAXPCHAN; i++)
  1384. X            if ((layer = &World[i])->lpid == pid)
  1385. X              {     /* remove dead process's layer */
  1386. X                DO DEBUG("kill dead process window %d\n", layer->chan);
  1387. X                KillWindow (layer);
  1388. X                /* tell server layer is dead */
  1389. X                SendDelete(layer->chan);
  1390. X              }
  1391. X#endif
  1392. X} /* DoWait() */
  1393. X                /* KillWindow() - remove a layer from the system */
  1394. X
  1395. X/* Note: This function does NOT tell MacLayers about the dead layer */
  1396. X
  1397. Xstatic
  1398. XKillWindow (layer)
  1399. Xstruct Layer *layer;
  1400. X{
  1401. X    struct Kbuff    *kb;                /* work buffer free pointer */
  1402. X    int i, j;
  1403. Xstatic int ksig[] = { SIGHUP, SIGTERM, SIGKILL, 0 };
  1404. X
  1405. X    if (layer->allocated)
  1406. X      {
  1407. X        for (i = 0; layer->lpid != 0 && ksig[i] != 0; i++)
  1408. X          { DO DEBUG("sending signal %d to pid %d\n", ksig[i], layer->lpid);
  1409. X            if (kill(layer->lpid, ksig[i]) == -1)
  1410. X              {
  1411. X                DO DEBUG("Kill failed. Error=%d\n", errno);
  1412. X                if (errno == ESRCH)
  1413. X                  layer->lpid = 0;        /* clear pid field */
  1414. X              }
  1415. X            else
  1416. X              { for (j = 0; layer->lpid != 0 && j < 5; j++)
  1417. X                  {  sleep(1);
  1418. X                     if ((kill(layer->lpid, 0) == -1) && (errno == ESRCH)) 
  1419. X                       layer->lpid = 0;        /* clear pid field */
  1420. X                  }
  1421. X                if (layer->lpid)
  1422. X                  DO DEBUG("kill accepted, but process didn't die\n");
  1423. X              }
  1424. X          }
  1425. X        (void) chmod(layer->tty, 0666);
  1426. X        (void) chown(layer->tty, 0, 0);
  1427. X        close(layer->ptyfd);
  1428. X        DO DEBUG("chmod/chown %s, SendDelete(%d)\n",layer->tty, layer->chan);
  1429. X
  1430. X        ClearShape(&layer->shape);      /* reset the shape structure */
  1431. X        /* free all keybuffers but one and reprime it */
  1432. X        for (kb=layer->kbuff; kb->next; kb=layer->kbuff)
  1433. X          { layer->kbuff = kb->next;    /* reset buffer chain */
  1434. X            free(kb);                   /* free input buffers */
  1435. X          }
  1436. X        kb->size = 0;                   /* empty buffer */
  1437. X        kb->offset = 0;                 /* start refill from front */
  1438. X        layer->allocated = 0;           /* window no longer allocated */
  1439. X      }
  1440. X
  1441. X} /* KillWindow() */
  1442. X
  1443. Xvoid
  1444. XReceiveData(chanid, buff, cnt)
  1445. Xint     chanid;                         /* channel receiving input */
  1446. Xchar    *buff;                          /* buffer containing data */
  1447. Xint     cnt;                            /* count of data bytes */
  1448. X{
  1449. X    struct Layer *layer;                /* layer pointer */
  1450. X    struct Kbuff *kb;                   /* keybuff pointer */
  1451. X
  1452. X    DO DEBUG("ReceiveData(%d, '%.*s')\n", chanid, cnt, buff);
  1453. X    /* verify channel */
  1454. X    if (chanid <= 0 || chanid > MAXPCHAN)
  1455. X        return;         /* ignore invalid channel */
  1456. X    layer = &World[chanid-1];   /* locate target layer */
  1457. X
  1458. X    if (layer->allocated == 0) {
  1459. X        DO DEBUG("Channel %d is not allocated!\n", chanid);
  1460. X    }
  1461. X    /* add character stream to xterm's input buffers for main loop processing */
  1462. X    for (kb=layer->kbuff; kb->next; kb=kb->next); /* find oldest buffer */
  1463. X    while (cnt--)
  1464. X      { 
  1465. X        /* if current buffer full then chain in a new one */
  1466. X        if (kb->offset+kb->size >= IOSIZE)
  1467. X          { kb->next = (struct Kbuff *) malloc(sizeof(struct Kbuff));
  1468. X            kb = kb->next;                  /* base new keybuff */
  1469. X            kb->next = NULL;                /* no next yet */
  1470. X            kb->size = 0;                   /* this character is first */
  1471. X            kb->offset = 0;                 /* at zero offset */
  1472. X          }
  1473. X
  1474. X        /* add new character to the end of this buffer */
  1475. X        kb->text[kb->offset+kb->size++] = *buff++; /* insert at end of data */
  1476. X      }
  1477. X
  1478. X} /* ReceiveData() */
  1479. X
  1480. X                    /* MakeWindow() - create new layer */
  1481. Xstatic
  1482. XMakeWindow (chan, shape)
  1483. Xint     chan;           /* zero or channel to use for window */
  1484. Xstruct Shape *shape;            /* shape to use for window */
  1485. X{
  1486. X    register struct Layer *layer;
  1487. X    register f;
  1488. X
  1489. X    DO DEBUG("MakeWindow(%d, ", chan);
  1490. X    DO DEBUG("    origv %d, origh %d, lines %d, chars %d, ",
  1491. X                shape->worigv, shape->worigh, shape->wlines, shape->wchars);
  1492. X    DO DEBUG("font %d, attr 0x%x\n", shape->wfont, shape->wattr);
  1493. X                    
  1494. X    if ((f = OpenPTY ()) == -1)
  1495. X      { Msg (0, "No more PTYs.");
  1496. X        return ( -1 );
  1497. X      }
  1498. X
  1499. X    /* if channel not given obtain one from MacLayers */
  1500. X    if (chan == 0)
  1501. X      { chan = GetNew(shape);               /* try to get free window */
  1502. X        if (chan == 0)
  1503. X          { Msg (0, "No more windows.");
  1504. X            return ( -1 );
  1505. X          }
  1506. X        DO DEBUG("GetNew() == %d\n", chan);
  1507. X      }
  1508. X
  1509. X    /* verify channel */
  1510. X    if (chan <= 0 || chan > MAXPCHAN)
  1511. X      { Msg(0, "Invalid channel %d.", chan);
  1512. X        return ( -1 );
  1513. X      }
  1514. X
  1515. X    layer = &World[chan-1];         /* find layer structure */
  1516. X    shape->wlines = 25;
  1517. X    shape->wchars = 80;
  1518. X    layer->shape = *shape;          /* install new window shape */
  1519. X    
  1520. X    /* ??? What do we do if layer is still active as far as we're concerned? */
  1521. X    if (layer->allocated)
  1522. X      { DO DEBUG("??? newlayer not free !!!\n");
  1523. X        KillWindow(layer);      /* kill off old layer */
  1524. X        SendDelete(layer->chan);    /* kill window back off */
  1525. X        Msg (0, "Makewindow error: Duplicate active layer %d.", chan);
  1526. X        return ( -1 );          /* return failed */
  1527. X      }
  1528. X
  1529. X    layer->allocated = 1;           /* show layer now in use */
  1530. X
  1531. X    (void) fcntl (f, F_SETFL, FNDELAY);
  1532. X    layer->ptyfd = f;                       /* pseudo pty for task's I/O */
  1533. X    layer->ptymask = 1<<f;                  /* set pty device mask */
  1534. X    strncpy (layer->tty, TtyName, MAXSTR-1);
  1535. X    DO DEBUG("tty %s, ptyfd %d, mask %x\n",
  1536. X                layer->tty, layer->ptyfd, layer->ptymask);
  1537. X    (void) chown (TtyName, getuid (), getgid ());
  1538. X    layer->lpid = StartTerm(f, chan);
  1539. X    DO DEBUG("Starterm() pid = %d\n", layer->lpid);
  1540. X
  1541. X    if (layer->lpid <= 0) {
  1542. X        Msg (0, "Makewindow error: cannot start terminal layer %d.", chan);
  1543. X        layer->allocated = 0;
  1544. X        return(0);
  1545. X    }
  1546. X    return ( chan );
  1547. X
  1548. X} /* MakeWindow() */
  1549. X
  1550. Xvoid
  1551. XReceiveReshape(chanid, shape)
  1552. Xint             chanid;                 /* channel having shape */
  1553. Xstruct Shape    *shape;                 /* shape structure */
  1554. X{
  1555. X
  1556. X    DO DEBUG("ReceiveReshape(%d)\n", chanid);
  1557. X
  1558. X} /* ReceiveReshape() */
  1559. X        
  1560. X                /* ReceiveDelete() - Server says to kill window*/
  1561. Xvoid
  1562. XReceiveDelete(chanid)
  1563. Xint     chanid;                             /* channel which was deleted */
  1564. X{
  1565. X    struct Layer *layer;                /* layer pointer */
  1566. X
  1567. X    /* validate channel */
  1568. X    DO DEBUG("ReceiveDelete(%d)\n", chanid);
  1569. X    if (chanid <= 0 || chanid > MAXPCHAN)
  1570. X        return;                             /* ignore invalid channel */
  1571. X
  1572. X    /* if this layer active then kill it off, else ignore request */
  1573. X    layer = &World[chanid-1];       /* locate target layer */
  1574. X    if (layer->allocated)
  1575. X        KillWindow(layer);
  1576. X
  1577. X} /* ReceiveDelete() */
  1578. X        
  1579. X        
  1580. X                /* ReceiveNew() - MacLayers requests a new shell layer */
  1581. X
  1582. Xvoid
  1583. XReceiveNew(chanid, shape)
  1584. Xint     chanid;                             /* channel for new shell layer */
  1585. Xstruct Shape *shape;                        /* shape for new channel */
  1586. X{
  1587. X    DO DEBUG("ReceiveNew(%d)\n", chanid);
  1588. X    (void) MakeWindow (chanid, shape);
  1589. X
  1590. X} /* ReceiveNew() */
  1591. X
  1592. X
  1593. X                    /* ReceiveQuit() - MacLayers sends Quit packet */
  1594. X
  1595. Xvoid
  1596. XReceiveQuit()
  1597. X{
  1598. X    /* We completely quit layers cancelling all active processes */
  1599. X    DO DEBUG("ReceiveQuit()\n");
  1600. X    FQuit(EXITNORMAL);                  /* normal termination */
  1601. X    /* NOT REACHED */
  1602. X
  1603. X} /* ReceiveQuit() */
  1604. X
  1605. XGetNew()
  1606. X{
  1607. X    int i;
  1608. X
  1609. X    DO DEBUG("GetNew()\n");
  1610. X    for (i=0; i<MAXPCHAN; i++)
  1611. X        if (World[i].allocated == 0)
  1612. X            return(i+1);
  1613. X    return(0);
  1614. X}
  1615. X
  1616. Xvoid                    /* FQuit() - terminate layers */
  1617. XFQuit(exitcode)
  1618. Xint     exitcode;
  1619. X{
  1620. X    int i;
  1621. X
  1622. X    DO DEBUG("FQuit(%d)\n",exitcode);
  1623. X    for (i=0; i<MAXPCHAN; i++)
  1624. X        KillWindow(&World[i]);          /* kill all windows */
  1625. X
  1626. X    SetTTY (0, OldMode);
  1627. X    printf("\n[ulayers exiting]\n");
  1628. X    EndConnect();
  1629. X    exit (exitcode);
  1630. X
  1631. X} /* FQuit() */
  1632. X
  1633. X
  1634. Xstatic char ttybuf[IOSIZE];
  1635. Xstatic char *ttyptr = ttybuf;
  1636. Xstatic int ttylen = 0;
  1637. X
  1638. Xtty_putc(c)
  1639. X{
  1640. X    if (ttylen >= IOSIZE)
  1641. X        tty_flush();
  1642. X    *ttyptr++ = c;
  1643. X    ttylen++;
  1644. X}
  1645. X
  1646. Xtty_puts(s, flg)
  1647. Xchar *s;
  1648. Xint flg;
  1649. X{
  1650. X    while (*s)
  1651. X        tty_putc(*s++);
  1652. X    if (flg)
  1653. X        tty_flush();
  1654. X}
  1655. X
  1656. Xtty_flush()
  1657. X{
  1658. X    if (ttylen) {
  1659. X        DO DEBUG("FLUSH writing %d bytes to TTyfd = %d\n", ttylen, TtyFd);
  1660. X        if (write(TtyFd, ttybuf, ttylen) != ttylen) {
  1661. X            DO DEBUG("TTY write error %d\n", errno);
  1662. X        }
  1663. X        ttylen = 0;
  1664. X        ttyptr = ttybuf;
  1665. X    }
  1666. X}
  1667. X
  1668. X
  1669. X/* 
  1670. X * Send a modem break
  1671. X */
  1672. Xtty_break() 
  1673. X{ 
  1674. X    tty_flush();
  1675. X#ifdef V7TTY
  1676. X    ioctl(TtyFd, TIOCSBRK, (struct sgttyb *) 0);
  1677. X    sleep(1);
  1678. X    return(ioctl(TtyFd, TIOCCBRK, (struct sgttyb *) 0));
  1679. X#else
  1680. X    return(ioctl(TtyFd, TCSBRK, 0));
  1681. X#endif
  1682. X}
  1683. X
  1684. Xvoid
  1685. Xhup(sig)
  1686. Xint sig;
  1687. X{
  1688. X    signal(sig, SIG_IGN);
  1689. X    DO DEBUG("CAUGHT SIGNAL %d\n", sig);
  1690. X    FQuit(1);
  1691. X}
  1692. X
  1693. END_OF_FILE
  1694.   if test 52393 -ne `wc -c <'ulayers.c'`; then
  1695.     echo shar: \"'ulayers.c'\" unpacked with wrong size!
  1696.   fi
  1697.   # end of 'ulayers.c'
  1698. fi
  1699. echo shar: End of archive 2 \(of 3\).
  1700. cp /dev/null ark2isdone
  1701. MISSING=""
  1702. for I in 1 2 3 ; do
  1703.     if test ! -f ark${I}isdone ; then
  1704.     MISSING="${MISSING} ${I}"
  1705.     fi
  1706. done
  1707. if test "${MISSING}" = "" ; then
  1708.     echo You have unpacked all 3 archives.
  1709.     rm -f ark[1-9]isdone
  1710. else
  1711.     echo You still must unpack the following archives:
  1712.     echo "        " ${MISSING}
  1713. fi
  1714. exit 0
  1715. exit 0 # Just in case...
  1716.