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

  1. Newsgroups: comp.sources.misc
  2. From: david@bdt.com (David Beckemeyer)
  3. Subject: v37i089:  ulayers - Unix/X client to MacLayers, Part01/03
  4. Message-ID: <csm-v37i089=ulayers.130855@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 47005ed1fc3efbf6fc9c2b5a1ea819e4
  6. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Sat, 29 May 1993 18:09:11 GMT
  9. Approved: kent@sparky.imd.sterling.com
  10.  
  11. Submitted-by: david@bdt.com (David Beckemeyer)
  12. Posting-number: Volume 37, Issue 89
  13. Archive-name: ulayers/part01
  14. Environment: UNIX, X11, PTY
  15.  
  16. Ulayers provides multi-window capability for a Unix system by
  17. emulating the Macintosh MacLayers application. To use Ulayers,
  18. you must have a terminal emulator windowing system on your local
  19. system (such as xterm, cmdtool, or a virtual terminal system)
  20. and the layers protocol program (from the Maclayers distribution)
  21. installed on your remote Unix system.  Refer to the FAQ from
  22. comp.sys.mac.comm for an overview of MacLayers.  Here is an
  23. excerpt from the FAQ:
  24.  
  25.      MacLayers allows you to logon to a Unix host and open more than
  26.      one window over a single (serial) connection. Each window
  27.      can correspond to a (login) shell or program running on your
  28.      choice of host(s). Up to seven full-screen resizable VT-100
  29.      windows are allowed.
  30.  
  31.      MacLayers comes in two parts: a program you run on your
  32.      Macintosh and a set of C source files that you compile
  33.      on your Unix host (a Makefile is provided). When you login
  34.      to your host while running MacLayers on your Macintosh, you
  35.      simply run one of the Unix-side programs to start up the
  36.      windowing system (similar to running a windowing-environment
  37.      like X-Windows at the console, except that everything is
  38.      character based -- no graphics).
  39.  
  40. The latest version of MacLayers is available via anonymous FTP
  41. from rascal.ics.utexas.edu in mac/communications/MacLayers.
  42. You only need the Unix-side of the MacLayers software. Check
  43. with the administartors of the systems you want to connect to
  44. because many systems already have the Unix-side layers programs
  45. installed.
  46.  
  47. Please DO NOT send mail to the official Layers support group
  48. about any problems you have with the Ulayers application!
  49. They don't want to hear it and they won't be able to help you
  50. anyway.  Send any comments, complaints, suggestions, etc. to
  51. david@bdt.com.
  52.  
  53.  
  54.                              ***  OVERVIEW  ***
  55.  
  56. Ulayers is a bare-bones emulation of the Mac-side of the MacLayers
  57. program.  The real MacLayers application is a Macintosh program
  58. with a nice Macintosh-style interface. Ulayers, on the other hand,
  59. is a quick and dirty non-graphics program. Ulayers is designed to
  60. be used in an X environment; it starts xterms to handle the
  61. MacLayers login sessions, almost as though you had ordinary
  62. xterm logins to a local host. Ulayers features:
  63.  
  64.         o Basic Modem Auto-dialer 
  65.  
  66.         o Configurable modem and ports databases
  67.  
  68.         o Dialing directory
  69.  
  70.         o Automatic ZMODEM uploading and downloading
  71.  
  72. It is possible to use Ulayers with some windowing system other
  73. than X by configuring a custom "terminal startup script".
  74.  
  75.  
  76.                          ***  SUPPORTED SYSTEMS  ***
  77.  
  78. Ulayers has been successfully installed on the following systems:
  79.  
  80.    SunOS 4.1.x on Sun3 and SPARC machines
  81.    Interatcive 386/ix Version 3.0 (System V, Release 3)
  82.    BSD386
  83.    PS/2 running AIX 1.3
  84.    SunOS 3.5 on Sun3
  85.    HP-UX A.08.02 on HP 9000
  86.    VAX/Ultrix 4.2
  87.    NeXT/Mach
  88.  
  89. If you port this code to any system not listed above, or can 
  90. provide additional information on the listed systems, please send
  91. e-mail to david@bdt.com.
  92.  
  93. NOTE: I left in some of the "#ifdef SEQUENT" code from the original
  94. MacLayers source.  I have not tested the code on a Sequent however.
  95.  
  96. ------------------------
  97. #! /bin/sh
  98. # This is a shell archive.  Remove anything before this line, then feed it
  99. # into a shell via "sh file" or similar.  To overwrite existing files,
  100. # type "sh file -c".
  101. # Contents:  README connect.c startup.c ul_ports ulayers.1 ulslave.c
  102. # Wrapped by kent@sparky on Sat May 29 13:04:06 1993
  103. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  104. echo If this archive is complete, you will see the following message:
  105. echo '          "shar: End of archive 1 (of 3)."'
  106. if test -f 'README' -a "${1}" != "-c" ; then 
  107.   echo shar: Will not clobber existing file \"'README'\"
  108. else
  109.   echo shar: Extracting \"'README'\" \(6468 characters\)
  110.   sed "s/^X//" >'README' <<'END_OF_FILE'
  111. X                              Ulayers v1.0
  112. X                   Unix/X Emulation of the Mac-side
  113. X                             MacLayers v1.20
  114. X                        Release 1.0 May 24, 1993
  115. X                      
  116. XThe following files are provided with the Ulayers package:
  117. X
  118. X    README        - this file
  119. X
  120. X    makefile    - ulayers Makefile
  121. X    ulayers.1    - ulayers man page
  122. X
  123. X    ulayers.c    - ulayers source files
  124. X    ulayers.h
  125. X    conf.h
  126. X    startup.c
  127. X    connect.c
  128. X    term.c
  129. X    dial.c
  130. X    numbers.c
  131. X    ulslave.c
  132. X
  133. X    ulterm.xterm    - sample terminal startup using xterm
  134. X    ulterm.cmdtool    - sample terminal startup using cmdtool
  135. X
  136. XUlayers provides multi-window capability for a Unix system by
  137. Xemulating the Macintosh MacLayers application. To use Ulayers,
  138. Xyou must have a terminal emulator windowing system on your local
  139. Xsystem (such as xterm, cmdtool, or a virtual terminal system)
  140. Xand the layers protocol program (from the Maclayers distribution)
  141. Xinstalled on your remote Unix system.  Refer to the FAQ from
  142. Xcomp.sys.mac.comm for an overview of MacLayers.  Here is an
  143. Xexcerpt from the FAQ:
  144. X
  145. X     MacLayers allows you to logon to a Unix host and open more than
  146. X     one window over a single (serial) connection. Each window
  147. X     can correspond to a (login) shell or program running on your
  148. X     choice of host(s). Up to seven full-screen resizable VT-100
  149. X     windows are allowed.
  150. X
  151. X     MacLayers comes in two parts: a program you run on your
  152. X     Macintosh and a set of C source files that you compile
  153. X     on your Unix host (a Makefile is provided). When you login
  154. X     to your host while running MacLayers on your Macintosh, you
  155. X     simply run one of the Unix-side programs to start up the
  156. X     windowing system (similar to running a windowing-environment
  157. X     like X-Windows at the console, except that everything is
  158. X     character based -- no graphics).
  159. X
  160. XThe latest version of MacLayers is available via anonymous FTP
  161. Xfrom rascal.ics.utexas.edu in mac/communications/MacLayers.
  162. XYou only need the Unix-side of the MacLayers software. Check
  163. Xwith the administartors of the systems you want to connect to
  164. Xbecause many systems already have the Unix-side layers programs
  165. Xinstalled.
  166. X
  167. XPlease DO NOT send mail to the official Layers support group
  168. Xabout any problems you have with the Ulayers application!
  169. XThey don't want to hear it and they won't be able to help you
  170. Xanyway.  Send any comments, complaints, suggestions, etc. to
  171. Xdavid@bdt.com.
  172. X
  173. X
  174. X                             ***  OVERVIEW  ***
  175. X
  176. XUlayers is a bare-bones emulation of the Mac-side of the MacLayers
  177. Xprogram.  The real MacLayers application is a Macintosh program
  178. Xwith a nice Macintosh-style interface. Ulayers, on the other hand,
  179. Xis a quick and dirty non-graphics program. Ulayers is designed to
  180. Xbe used in an X environment; it starts xterms to handle the
  181. XMacLayers login sessions, almost as though you had ordinary
  182. Xxterm logins to a local host. Ulayers features:
  183. X
  184. X        o Basic Modem Auto-dialer 
  185. X
  186. X        o Configurable modem and ports databases
  187. X
  188. X        o Dialing directory
  189. X
  190. X        o Automatic ZMODEM uploading and downloading
  191. X
  192. XIt is possible to use Ulayers with some windowing system other
  193. Xthan X by configuring a custom "terminal startup script".
  194. X
  195. X
  196. X                         ***  SUPPORTED SYSTEMS  ***
  197. X
  198. XUlayers has been successfully installed on the following systems:
  199. X
  200. X   SunOS 4.1.x on Sun3 and SPARC machines
  201. X   Interatcive 386/ix Version 3.0 (System V, Release 3)
  202. X   BSD386
  203. X   PS/2 running AIX 1.3
  204. X   SunOS 3.5 on Sun3
  205. X   HP-UX A.08.02 on HP 9000
  206. X   VAX/Ultrix 4.2
  207. X   NeXT/Mach
  208. X
  209. XIf you port this code to any system not listed above, or can 
  210. Xprovide additional information on the listed systems, please send
  211. Xe-mail to david@bdt.com.
  212. X
  213. XNOTE: I left in some of the "#ifdef SEQUENT" code from the original
  214. XMacLayers source.  I have not tested the code on a Sequent however.
  215. X
  216. X                           ***   INSTALLATION   ***
  217. X
  218. XYou need a Unix machine that supports pseudo terminals (ptys).
  219. XYou also need the "xterm" program from the X11 distribution
  220. Xor some other suitible terminal emulator. To do downloading
  221. Xand uploading you need the "rz" and "sz" programs (optional
  222. Xif you don't care about file transfers).
  223. X
  224. XTo build the ulayers programs, edit the "conf.h" file to
  225. Xmatch your system. If you're on a System V system, then
  226. Xyou'll also have to add the -DUSG to the CFLAGS definition
  227. Xin the makefile. Then type 'make' to compile the sources.
  228. X
  229. XThen create your "ulterm" script.  To run basic "xterm" windows,
  230. Xsimply copy the included "ulterm.xterm" to "ulterm".  Users
  231. Xcan override the default "ulterm" by setting the environment
  232. Xvariable ULTERM.  Refer to the ulterm.xterm and ulterm.cmdtool
  233. Xsample scripts for information on writing your own custom
  234. Xulterm module.
  235. X
  236. XThere are two ways to install the programs:
  237. X
  238. X    make installsetuid
  239. Xor
  240. X    make installnosetuid
  241. X
  242. XInstalling ulayers setuid may be necessary in order for the
  243. Xapplication to have access to your serial ports.  Even if this
  244. Xis not the case on your system, there is another reason for
  245. Xrunning the program setuid.  It allows the ulayers utility to
  246. Xperform chown/chmod on its allocated pseudo-ttys. This is
  247. Xnecessary to plug security holes in some systems which
  248. Xotherwise would allow outside users free access to the pseudo 
  249. Xcontrol terminal ttys of layers users.  When run setuid,
  250. Xulayers always runs the xterms as your user ID; only the
  251. Xulayers program itself runs setuid.
  252. X
  253. XNOTE: A minor bug exists in versions of the Unix-side MacLayers
  254. X"layers" prior to v1.30 which prevents the upload feature of
  255. XUlayers from working on binary files.  You should try and get
  256. Xthe server upgraded to the v1.30 release of MacLayers.
  257. X
  258. XNOTE ABOUT ZMODEM: Some implementations of Chuck Forsberg's szrz
  259. Xare incompatible with the automatic upload/download feature of ulayers
  260. Xbecause of the way they setup the I/O channel (they open the device 
  261. X"/dev/tty" and they generate diagnostic output on stdout).  You must
  262. Xobtain a more "external program friendly" version of sz/rz or
  263. Xmodify the one you have to use stdin (handle 0) for communication
  264. Xand generate diagnostics on stderr (handle 2).
  265. X
  266. X
  267. X                       ***   ACKNOWLEDGEMENT   ***
  268. X
  269. XThanks go to a lot of people for Ulayers.  First and foremost, of
  270. Xcourse, is the original MacLayers author, Dave Trissel.  Others
  271. Xin the MacLayers team have been helpful too, Peter Newton, Eric
  272. XRosen, et al.  Many thanks go to all the Ulayers beta testers,
  273. Xwho spent the time help me track down bugs and gave me ideas for
  274. Ximprovements, especially Bjorn Engsig and Johan Vromans.
  275. END_OF_FILE
  276.   if test 6468 -ne `wc -c <'README'`; then
  277.     echo shar: \"'README'\" unpacked with wrong size!
  278.   fi
  279.   # end of 'README'
  280. fi
  281. if test -f 'connect.c' -a "${1}" != "-c" ; then 
  282.   echo shar: Will not clobber existing file \"'connect.c'\"
  283. else
  284.   echo shar: Extracting \"'connect.c'\" \(9673 characters\)
  285.   sed "s/^X//" >'connect.c' <<'END_OF_FILE'
  286. X/********                    connect.c
  287. X*********
  288. X*********     This is a quick & dirty implementation of the
  289. X*********     MacLayers protocol client-side for Unix.  It
  290. X*********     Basically is an emulation of the MacLayers
  291. X*********     Macintosh application for Unix, except that
  292. X*********     Ulayers is a bare-bones program, a far cry
  293. X*********     from the polished and professional MacLayers.
  294. X*********
  295. X*********     The hacks to produce Ulayers were made by me,
  296. X*********     David Beckemeyer david@bdt.com.  Essentially
  297. X*********     the entire credit for this goes to the original
  298. X*********     authors however, and all the contributors
  299. X*********     copyright messages appear below.  On the
  300. X*********     the other hand, the "real" Maclayers authors
  301. X*********     are not to blame for the shoddy hacks I made
  302. X*********     to their code either, and so I'm putting my
  303. X*********     here because I'm sure they don't want their
  304. X*********     name associatyed with this mess!
  305. X*********
  306. X*********     The UUCP locking code came from PCOMM by
  307. X*********     Emmet P. Gray ...!uunet!uiucuxc!fthood!egray.
  308. X*********
  309. X*********     Most of the code for Ulayers came straight from
  310. X*********     the Unix-side of the MacLayers implementation,
  311. X*********     the copyright messages to which follow:
  312. X*********
  313. X*********    Layers - MacLayers Multiwindow BSD Socket Driver
  314. X*********
  315. X*********          Dave Trissel oakhill!davet
  316. X*********
  317. X********* The sockets handling portion of this control module is based 
  318. X********* upon 'screen' by Oliver Laumann whose copyright remains below. 
  319. X********* The rest is
  320. X *
  321. X *             Copyright (C) 1989 by David W. Trissel
  322. X *
  323. X *              Not derived from licensed software.
  324. X *
  325. X * Permission is granted to freely use, copy, modify, and redistribute
  326. X * this software, provided that no attempt is made to gain profit from it,
  327. X * the author is not construed to be liable for any results of using the
  328. X * software, alterations are clearly marked as such, and this notice is
  329. X * not modified.
  330. X *
  331. X */
  332. X
  333. X
  334. X/* Copyright (c) 1987,1988 Oliver Laumann, Technical University of Berlin.
  335. X * Not derived from licensed software.
  336. X *
  337. X * Permission is granted to freely use, copy, modify, and redistribute
  338. X * this software, provided that no attempt is made to gain profit from it,
  339. X * the author is not construed to be liable for any results of using the
  340. X * software, alterations are clearly marked as such, and this notice is
  341. X * not modified.
  342. X *
  343. X *    Modified by Patrick Wolfe (pat@kai.com, kailand!pat)
  344. X *    Do whatever you want with (my modifications of) this program, but
  345. X *    don't claim you wrote them, don't try to make money from them, and
  346. X *    don't remove this notice.
  347. X */
  348. X#include <stdio.h>
  349. X#include <signal.h>
  350. X#include <errno.h>
  351. X#include <ctype.h>
  352. X#include <pwd.h>
  353. X#include <nlist.h>
  354. X#include <fcntl.h>
  355. X#include <sys/types.h>
  356. X#include <sys/time.h>
  357. X#include <sys/file.h>
  358. X#include <sys/wait.h>
  359. X#include <sys/socket.h>
  360. X#include <utmp.h>
  361. X#ifndef USG
  362. X#include <sys/un.h>
  363. X#endif
  364. X#include <sys/stat.h>
  365. X#include <sys/dir.h>
  366. X#include <sys/ioctl.h>
  367. X#include <sys/param.h>
  368. X#include "ulayers.h"
  369. X
  370. X/* C library items */
  371. Xextern char *index(), *rindex(), *malloc(), *getenv();
  372. Xextern sys_nerr;
  373. Xextern char *sys_errlist[];
  374. X
  375. X
  376. X#ifdef MAXPID
  377. X#define MAX_PID  MAXPID
  378. X#else
  379. X#ifndef MAX_PID
  380. X#define MAX_PID  30000
  381. X#endif
  382. X#endif
  383. X
  384. X/* The name of the UUCP lock file */
  385. Xstatic char LockFile[512];
  386. Xstatic int IsLocked;
  387. X
  388. X/* #define LOCALDEBUG */
  389. X
  390. X#ifdef LOCALDEBUG
  391. X/* Local items */
  392. Xstatic char *ShellProg;
  393. Xstatic char *ShellArgs[2];
  394. Xstatic char DefaultShell[] = "/bin/sh";
  395. Xstatic char DefaultPath[] = ":/usr/ucb:/bin:/usr/bin";
  396. Xstatic char cmd[1024];
  397. Xstatic char tty[64];
  398. X
  399. XInitConnect ()
  400. X{
  401. X    register char **cp;
  402. X    register f, j;
  403. X    int tf;
  404. X    int DevTty;
  405. X    int mypid;
  406. X    int Oumask, lpid;
  407. X    char ebuf[10];
  408. X
  409. X    DO DEBUG("ForkShell()\n");
  410. X    if ((ShellProg = getenv ("SHELL")) == 0)
  411. X        ShellProg = DefaultShell;
  412. X    DO DEBUG("ShellProg %s\n", ShellProg);
  413. X
  414. X    ShellArgs[0] = ShellProg;
  415. X
  416. X
  417. X    if ((Oumask=umask(0)) == -1)
  418. X        Msg (errno, "Cannot change umask to zero");
  419. X    DO DEBUG("Original umask o%o\n", Oumask);
  420. X
  421. X    if ((DevTty = open ("/dev/tty", O_RDWR|O_NDELAY)) == -1)
  422. X        Msg (errno, "/dev/tty");
  423. X    DO DEBUG("opened /dev/tty fd %d\n", DevTty);
  424. X
  425. X    if ((f = OpenPTY ()) == -1)
  426. X      { Msg (0, "No more PTYs.");
  427. X        return ( -1 );
  428. X      }
  429. X
  430. X/*     (void) fcntl (f, F_SETFL, FNDELAY); */
  431. X
  432. X    TtyFd = f;                /* pseudo pty for task's I/O */
  433. X    TtyMask = 1<<f;            /* set pty device mask */
  434. X    strncpy (cmd, Filename (ShellArgs[0]), MAXSTR-1);
  435. X    cmd[MAXSTR-1] = '\0';
  436. X    strncpy (tty, TtyName, MAXSTR-1);
  437. X    DO DEBUG("forking %s, tty %s, TtyFd %d, mask %x\n",
  438. X                cmd, tty, TtyFd, TtyMask);
  439. X    (void) chown (TtyName, getuid (), getgid ());
  440. X    /* do not allow any other user access to this device */
  441. X    (void) chmod (TtyName, 0600);
  442. X    switch (lpid = fork ())
  443. X    { case -1:
  444. X        Msg (errno, "fork");
  445. X        lpid = 0;                    /* clear pid field */
  446. X        return ( -1 );                        /* return failed */
  447. X
  448. X      case 0:
  449. X        signal (SIGHUP, SIG_DFL);
  450. X        signal (SIGINT, SIG_DFL);
  451. X         signal (SIGQUIT, SIG_DFL);
  452. X        signal (SIGTERM, SIG_DFL);
  453. X        signal (SIGTTIN, SIG_DFL);
  454. X        signal (SIGTTOU, SIG_DFL);
  455. X        signal (SIGALRM, SIG_DFL);
  456. X        setuid (getuid ());
  457. X        setgid (getgid ());
  458. X        mypid = getpid ();
  459. X        ioctl (DevTty, TIOCNOTTY, (char *)0);
  460. X        if ((tf = open (TtyName, O_RDWR)) == -1)
  461. X          { Msg ("Cannot open %s: %s", TtyName, sys_errlist[errno]);
  462. X            exit(1);
  463. X          }
  464. X        DO DEBUG("Now in new process\n");
  465. X        (void) dup2 (tf, 0);
  466. X        (void) dup2 (tf, 1);
  467. X        (void) dup2 (tf, 2);
  468. X        for (f = getdtablesize () - 1; f > 2; f--)
  469. X            close (f);
  470. X        ioctl (0, TIOCSPGRP, &mypid);
  471. X        (void) setpgrp (0, mypid);
  472. X        SetTTY (0, OldMode);
  473. X          {    struct    winsize    wsize;        /* window size structure */
  474. X            int            retcode;        /* ioctl return code */
  475. X
  476. X            wsize.ws_col = 80; /* character width */
  477. X            wsize.ws_row = 25; /* window height */
  478. X            wsize.ws_xpixel = 0;        /* necessary? */
  479. X            wsize.ws_ypixel = 0;
  480. X            /* update O/S window state */
  481. X            retcode = ioctl(0, TIOCSWINSZ, &wsize);
  482. X          }
  483. X
  484. X        (void) umask(Oumask);            /* restore user's original umask */
  485. X        execvp (ShellProg, ShellArgs);
  486. X        printf("cannot exec %s: %s", ShellProg, sys_errlist[errno]);
  487. X        exit (1);
  488. X    }
  489. X
  490. X    sleep(2);
  491. X    return ( lpid );
  492. X
  493. X} /* ForkShell () */
  494. X
  495. X
  496. XEndConnect()
  497. X{
  498. X}
  499. X
  500. X#else
  501. X
  502. XInitConnect()
  503. X{
  504. X    int fd, lfd;
  505. X    char buf[40];
  506. X    int cmask;
  507. X#ifndef ASCII_PID
  508. X    int progpid;
  509. X#endif
  510. X    /* open the TTY port */
  511. X                    /* create a lock file name */
  512. X#ifdef SVR4_LOCKS
  513. X    struct stat sbuf;
  514. X    stat(ServerPort, &sbuf);
  515. X    sprintf(LockFile, "%s/LK.%03d.%03d.%03d", LOCK_DIR, major(sbuf.st_dev), major(sbuf.st_rdev), minor(sbuf.st_rdev));
  516. X#else /* SVR4_LOCKS */
  517. X    sprintf(LockFile, "%s/LCK..%s", LOCK_DIR, Filename(ServerPort));
  518. X#endif /* SVR4_LOCKS */
  519. X
  520. X    /* remove old lock if we created one */
  521. X    if (IsLocked) {
  522. X        unlink(LockFile);
  523. X        IsLocked = 0;
  524. X    }
  525. X
  526. X                /* no lock exists or it is dead */
  527. X    if (checklock(LockFile)) {
  528. X        cmask = umask(0);
  529. X        if ((lfd = open(LockFile, O_CREAT|O_EXCL|O_WRONLY, 0666)) < 0) {
  530. X            printf("Can't create the lockfile %s\r\n", LockFile);
  531. X            DO DEBUG("Can't create %s (errno %d)\n", LockFile, errno); 
  532. X            return(-1);
  533. X        }
  534. X        umask(cmask);
  535. X#ifdef ASCII_PID
  536. X        sprintf(buf, "%10d\n", getpid());
  537. X        write(lfd, buf, 11);
  538. X#else /* ASCII_PID */
  539. X        progpid = getpid();
  540. X        write(lfd, (char *) &progpid, sizeof(int));
  541. X#endif /* ASCII_PID */
  542. X        close(lfd);
  543. X        IsLocked = 1;
  544. X
  545. X                    /* open the device (ignore DCD) */
  546. X        if ((fd = open(ServerPort, O_RDWR|O_NDELAY)) < 0) {
  547. X            printf("Can't open \"%s\" for read and write\r\n", ServerPort);
  548. X            DO DEBUG("Can't open %s (errno %d)\n", ServerPort, errno);
  549. X            return(-1);
  550. X        }
  551. X                /* ...just to be sure */
  552. X        close(open(ServerPort, O_RDWR));
  553. X                    /* turn off the O_NDELAY setting */
  554. X#ifdef FASYNC
  555. X        (void) fcntl (fd, F_SETFL, FASYNC);
  556. X#endif
  557. X               TtyFd = fd;
  558. X            TtyMask = 1<<fd;
  559. X
  560. X        SetLine();
  561. X        while (ServerNumber) {
  562. X            printf("Dialing %s on %s...\r\n",
  563. X              ServerNumber, ServerPort);
  564. X            dial_it(ServerPort, ModemName, ServerNumber);
  565. X            if (read_codes() == 0) {
  566. X                printf("\r\nCONNECTED\007\007\r\n");
  567. X                break;
  568. X            }
  569. X            if (GetNumber(ServerName, 0)) {
  570. X                printf("\r\nFAILED\r\n");
  571. X                FQuit(1);
  572. X            }
  573. X        }
  574. X        return(fd);
  575. X    }
  576. X    printf("Device \"%s\" is in use by another process\r\n", ServerPort);
  577. X    return(-1);
  578. X}
  579. X
  580. XEndConnect()
  581. X{
  582. X    close(TtyFd);
  583. X    if (IsLocked) {
  584. X        unlink(LockFile);
  585. X        IsLocked = 0;
  586. X    }
  587. X}
  588. X
  589. X    
  590. X/*
  591. X * Check the lock file for a valid pid value.  Error conditions such
  592. X * as not being able to open the lock file or not being able to interpret
  593. X * the contents of the lock file cause the code to assume that the lock
  594. X * file is valid.  Let the user worry about weird special cases.  A 
  595. X * non-zero return code means the lock is dead or doesn't exist.
  596. X */
  597. X
  598. Xstatic int
  599. Xchecklock(lockfile)
  600. Xchar *lockfile;
  601. X{
  602. X    extern int errno;
  603. X    int lfd, lckpid, n;
  604. X    unsigned int sleep();
  605. X    char buf[40];
  606. X                    /* doesn't exist */
  607. X    if (access(lockfile, 0))
  608. X        return(1);
  609. X                    /* can't open the lock file */
  610. X    if ((lfd = open(lockfile, 0)) < 0)
  611. X        return(0);
  612. X
  613. X#ifdef ASCII_PID
  614. X    if ((n = read(lfd, buf, 40)) <= 0) {
  615. X        close(lfd);
  616. X        return(0);
  617. X    }
  618. X    close(lfd);
  619. X    buf[n--] = '\0';
  620. X    lckpid = atoi(buf);
  621. X#else /* ASCII_PID */
  622. X    if (read(lfd, (char *) &lckpid, sizeof(int)) != sizeof(int)) {
  623. X        close(lfd);
  624. X        return(0);
  625. X    }
  626. X    close(lfd);
  627. X#endif /* ASCII_PID */
  628. X                    /* invalid pid? */
  629. X    if (lckpid <= 0 || lckpid > MAX_PID)
  630. X        return(0);
  631. X
  632. X    if ((kill(lckpid, 0) == -1) && (errno == ESRCH)) {
  633. X        /*
  634. X         * If the kill was unsuccessful due to an ESRCH error,
  635. X         * that means the process is no longer active and the
  636. X         * lock file can be safely removed.
  637. X         */
  638. X        unlink(lockfile);
  639. X        sleep(1);
  640. X        return(1);
  641. X    }
  642. X    /*
  643. X     * If the kill() was successful, that means the process must
  644. X     * still be active.
  645. X     */
  646. X    return(0);
  647. X}
  648. X#endif
  649. X
  650. END_OF_FILE
  651.   if test 9673 -ne `wc -c <'connect.c'`; then
  652.     echo shar: \"'connect.c'\" unpacked with wrong size!
  653.   fi
  654.   # end of 'connect.c'
  655. fi
  656. if test -f 'startup.c' -a "${1}" != "-c" ; then 
  657.   echo shar: Will not clobber existing file \"'startup.c'\"
  658. else
  659.   echo shar: Extracting \"'startup.c'\" \(21155 characters\)
  660.   sed "s/^X//" >'startup.c' <<'END_OF_FILE'
  661. X/********                    startup.c
  662. X*********
  663. X*********     This is a quick & dirty implementation of the
  664. X*********     MacLayers protocol client-side for Unix.  It
  665. X*********     Basically is an emulation of the MacLayers
  666. X*********     Macintosh application for Unix, except that
  667. X*********     Ulayers is a bare-bones program, a far cry
  668. X*********     from the polished and professional MacLayers.
  669. X*********
  670. X*********     The hacks to produce Ulayers were made by me,
  671. X*********     David Beckemeyer david@bdt.com.  Essentially
  672. X*********     the entire credit for this goes to the original
  673. X*********     authors however, and all the contributors
  674. X*********     copyright messages appear below.  On the
  675. X*********     the other hand, the "real" Maclayers authors
  676. X*********     are not to blame for the shoddy hacks I made
  677. X*********     to their code either, and so I'm putting my
  678. X*********     here because I'm sure they don't want their
  679. X*********     name associatyed with this mess!
  680. X*********
  681. X*********     Most of the code for Ulayers came straight from
  682. X*********     the Unix-side of the MacLayers implementation,
  683. X*********     the copyright messages to which follow:
  684. X*********
  685. X*********    Layers - MacLayers Multiwindow BSD Socket Driver
  686. X*********
  687. X*********          Dave Trissel oakhill!davet
  688. X*********
  689. X********* The sockets handling portion of this control module is based 
  690. X********* upon 'screen' by Oliver Laumann whose copyright remains below. 
  691. X********* The rest is
  692. X *
  693. X *             Copyright (C) 1989 by David W. Trissel
  694. X *
  695. X *              Not derived from licensed software.
  696. X *
  697. X * Permission is granted to freely use, copy, modify, and redistribute
  698. X * this software, provided that no attempt is made to gain profit from it,
  699. X * the author is not construed to be liable for any results of using the
  700. X * software, alterations are clearly marked as such, and this notice is
  701. X * not modified.
  702. X *
  703. X */
  704. X
  705. X
  706. X/* Copyright (c) 1987,1988 Oliver Laumann, Technical University of Berlin.
  707. X * Not derived from licensed software.
  708. X *
  709. X * Permission is granted to freely use, copy, modify, and redistribute
  710. X * this software, provided that no attempt is made to gain profit from it,
  711. X * the author is not construed to be liable for any results of using the
  712. X * software, alterations are clearly marked as such, and this notice is
  713. X * not modified.
  714. X *
  715. X *    Modified by Patrick Wolfe (pat@kai.com, kailand!pat)
  716. X *    Do whatever you want with (my modifications of) this program, but
  717. X *    don't claim you wrote them, don't try to make money from them, and
  718. X *    don't remove this notice.
  719. X */
  720. X#include <stdio.h>
  721. X#include <signal.h>   
  722. X#include <errno.h>
  723. X#include <ctype.h>    
  724. X#ifdef USG
  725. X#include <stropts.h>
  726. X#include <poll.h>
  727. X#endif
  728. X#include <pwd.h>
  729. X#include <nlist.h> 
  730. X#include <fcntl.h>
  731. X#include <sys/types.h>
  732. X#include <sys/time.h>
  733. X#include <sys/file.h>
  734. X#include <sys/wait.h>
  735. X#include <sys/socket.h>
  736. X#include <utmp.h>
  737. X#ifndef USG
  738. X#include <sys/un.h>
  739. X#endif
  740. X#include <sys/stat.h>
  741. X#include <sys/dir.h> 
  742. X#include <setjmp.h>
  743. X#include "conf.h"
  744. X#ifdef V7TTY
  745. X#include <sgtty.h>
  746. X#include <sys/ioctl.h>
  747. X#else
  748. X#include <termio.h>
  749. X#endif
  750. X#include "ulayers.h"
  751. X
  752. Xstruct mode {
  753. X#ifdef V7TTY
  754. X    struct sgttyb m_ttyb;
  755. X    struct tchars m_tchars;
  756. X    struct ltchars m_ltchars;
  757. X    int m_ldisc;
  758. X    int m_lmode;
  759. X#else
  760. X    struct termio m_tty;
  761. X#endif
  762. X};
  763. X
  764. Xjmp_buf gl_buf;
  765. X
  766. X#define EXITNORMAL      0   /* normal exit - connection succeeded */
  767. X#define EXITNOMACLAYERS     1   /* MacLayers server error */
  768. X#define EXITABNORMAL        2   /* something wrong generic error */
  769. X#define EXITSIGQUIT     3   /* TERM or QUIT signal got us */
  770. X#define EXITSIGHUP      4   /* HUP signal got us */
  771. X
  772. X#define OUT_ERR_OK
  773. X
  774. Xstatic exitcode = EXITABNORMAL;
  775. X
  776. X/* C Library items */
  777. Xextern sys_nerr;
  778. Xextern char *sys_errlist[];
  779. X
  780. X/* Local items */
  781. Xstatic char PtyProto[] = "/dev/ptyXY";
  782. Xstatic char TtyProto[] = "/dev/ttyXY";
  783. Xstatic char *initseq = "\033[c";
  784. Xstatic int scanloc = 0;
  785. X
  786. X/* Global items */
  787. Xint TtyMask = 0;
  788. Xint TtyFd = 0;
  789. Xchar PtyName[32], TtyName[32];
  790. Xint flowctl = 0;
  791. Xstatic struct mode OldModeBuf, NewModeBuf;
  792. X
  793. Xchar *OldMode = (char *)&OldModeBuf;
  794. Xchar *NewMode = (char *)&NewModeBuf;
  795. X
  796. Xint Serverlevel = 1;            /* have to assume a level one server */
  797. Xint Protocollevel = 1;
  798. Xint Abortonmsg = 0;
  799. Xstruct Layer World[MAXPCHAN];
  800. X
  801. XSetTTY (fd, mp)
  802. Xstruct mode *mp;
  803. X{
  804. X#ifdef V7TTY
  805. X    ioctl (fd, TIOCSETP, &mp->m_ttyb);
  806. X    ioctl (fd, TIOCSETC, &mp->m_tchars);
  807. X    ioctl (fd, TIOCSLTC, &mp->m_ltchars);
  808. X    ioctl (fd, TIOCLSET, &mp->m_lmode);
  809. X    ioctl (fd, TIOCSETD, &mp->m_ldisc);
  810. X#else
  811. X    ioctl (fd, TCSETAF, &mp->m_tty);
  812. X#endif
  813. X} /* SetTTY() */
  814. X
  815. XGetTTY (fd, mp)
  816. Xstruct mode *mp;
  817. X{
  818. X#ifdef V7TTY
  819. X    ioctl (fd, TIOCGETP, &mp->m_ttyb);
  820. X    ioctl (fd, TIOCGETC, &mp->m_tchars);
  821. X    ioctl (fd, TIOCGLTC, &mp->m_ltchars);
  822. X    ioctl (fd, TIOCLGET, &mp->m_lmode);
  823. X    ioctl (fd, TIOCGETD, &mp->m_ldisc);
  824. X#else
  825. X    ioctl (fd, TCGETA, &mp->m_tty);
  826. X#endif
  827. X} /* GetTTY() */
  828. X
  829. XSetMode (op, np)
  830. Xstruct mode *op, *np;
  831. X{
  832. X    *np = *op;
  833. X#ifdef V7TTY
  834. X    if (flowctl)
  835. X      { np->m_ttyb.sg_flags &= ~(CRMOD|ECHO);
  836. X        np->m_ttyb.sg_flags |= CBREAK | ANYP | TANDEM;
  837. X      }
  838. X    else
  839. X        np->m_ttyb.sg_flags = RAW | ANYP;
  840. X    np->m_tchars.t_intrc = -1;
  841. X    np->m_tchars.t_quitc = -1;
  842. X    if (!flowctl)
  843. X      { np->m_tchars.t_startc = -1;
  844. X        np->m_tchars.t_stopc = -1;
  845. X      }
  846. X    np->m_ltchars.t_suspc = -1;
  847. X    np->m_ltchars.t_dsuspc = -1;
  848. X    np->m_ltchars.t_flushc = -1;
  849. X    np->m_ltchars.t_lnextc = -1;
  850. X#else
  851. X    np->m_tty.c_cc[4] = 1;               /* VMIN */
  852. X    np->m_tty.c_cc[5] = 0;               /* VTIME */
  853. X    np->m_tty.c_oflag = 0;
  854. X    np->m_tty.c_iflag = 0;
  855. X    np->m_tty.c_cflag |= (CREAD|HUPCL|CLOCAL);
  856. X    np->m_tty.c_lflag = 0;
  857. X
  858. X    if (flowctl)
  859. X        np->m_tty.c_iflag |= (IXON|IXOFF);
  860. X#endif
  861. X} /* SetMode() */
  862. X
  863. XSetSpeed (np, set)
  864. Xstruct mode *np;
  865. Xchar *set;
  866. X{
  867. X    int spd;
  868. X
  869. X    switch (atoi(set)) {
  870. X    case 300:
  871. X        spd = B300;
  872. X        break;
  873. X    case 1200:
  874. X        spd = B1200;
  875. X        break;
  876. X    case 2400:
  877. X        spd = B2400;
  878. X        break;
  879. X    case 4800:
  880. X        spd = B4800;
  881. X        break;
  882. X    case 9600:
  883. X        spd = B9600;
  884. X        break;
  885. X    case 19200:
  886. X#ifdef B19200
  887. X        spd = B19200;
  888. X#else
  889. X        spd = EXTA;
  890. X#endif
  891. X        break;
  892. X    case 38400:
  893. X#ifdef B38400
  894. X        spd = B38400;
  895. X#else
  896. X        spd = EXTB;
  897. X#endif
  898. X        break;
  899. X    default:
  900. X        DO DEBUG("SetSpeed(%s) unsupported speed\n", set);
  901. X        return;
  902. X    }
  903. X    while (*set >= '0' && *set <= '9')
  904. X    set++;
  905. X    if (*set == '-')
  906. X    set++;
  907. X    /* Any parity by default */
  908. X#ifdef V7TTY
  909. X    np->m_ttyb.sg_flags |= ANYP; 
  910. X#else
  911. X    np->m_tty.c_iflag &= ~INPCK;
  912. X    np->m_tty.c_cflag &= ~(CSIZE|PARODD|PARENB|CBAUD);
  913. X#ifdef CIBAUD
  914. X    np->m_tty.c_cflag &= ~CIBAUD;
  915. X#endif
  916. X    np->m_tty.c_iflag |= IGNPAR;
  917. X#endif
  918. X    switch (*set) {
  919. X    case 'O': 
  920. X    case 'o': 
  921. X#ifdef V7TTY
  922. X        np->m_ttyb.sg_flags &= ~ANYP; 
  923. X        np->m_ttyb.sg_flags |= ODDP; 
  924. X#else
  925. X        np->m_tty.c_iflag &= ~IGNPAR;
  926. X        np->m_tty.c_iflag |= INPCK;
  927. X        np->m_tty.c_cflag |= (CS7|PARODD|PARENB);
  928. X#endif
  929. X        break;
  930. X    case 'E':
  931. X    case 'e':
  932. X#ifdef V7TTY
  933. X        np->m_ttyb.sg_flags &= ~ANYP; 
  934. X        np->m_ttyb.sg_flags |= EVENP;
  935. X#else
  936. X        np->m_tty.c_iflag &= ~IGNPAR;
  937. X        np->m_tty.c_iflag |= INPCK;
  938. X        np->m_tty.c_cflag |= (CS7|PARENB);
  939. X#endif
  940. X        break;
  941. X#ifndef V7TTY
  942. X    default:
  943. X        np->m_tty.c_cflag |= CS8;
  944. X        break;
  945. X#endif
  946. X    }               
  947. X#ifdef V7TTY
  948. X    np->m_ttyb.sg_ispeed = spd;
  949. X    np->m_ttyb.sg_ospeed = spd;
  950. X#else
  951. X    np->m_tty.c_cflag |= spd;
  952. X#endif
  953. X} /* SetSpeed() */
  954. X
  955. X#ifdef sequent
  956. XOpenPTY ()
  957. X{
  958. X    char *m, *s;
  959. X    register f;
  960. X
  961. X    f = getpseudotty (&s, &m);
  962. X    strncpy (PtyName, m, sizeof (PtyName));
  963. X    strncpy (TtyName, s, sizeof (TtyName));
  964. X#ifdef V7TTY
  965. X    ioctl (f, TIOCFLUSH, (char *)0);
  966. X#else
  967. X    ioctl (f, TCFLSH, TCIOFLUSH);
  968. X#endif
  969. X    return (f);
  970. X}
  971. X
  972. X#else
  973. X
  974. XOpenPTY ()
  975. X{
  976. X    register char *p, *l, *d;
  977. X    register i, f, tf;
  978. X
  979. X    strcpy (PtyName, PtyProto);
  980. X    strcpy (TtyName, TtyProto);
  981. X    for (p = PtyName, i = 0; *p != 'X'; ++p, ++i);
  982. X#ifndef SEQUENT
  983. X    for (l = "pqrstuvwxyzPQRST"; *p = *l; ++l)
  984. X      { for (d = "0123456789abcdef"; p[1] = *d; ++d)
  985. X#else
  986. X    for (l = "pqrstuvwPQRSTUVW"; *p = *l; ++l)
  987. X      { for (d = "0123456789abcdef"; p[1] = *d; ++d)
  988. X#endif
  989. X          { if ((f = open (PtyName, O_RDWR)) != -1)
  990. X              { TtyName[i] = p[0];
  991. X                TtyName[i+1] = p[1];
  992. X                if ((tf = open (TtyName, O_RDWR)) != -1)
  993. X                  { close (tf);
  994. X                    return f;
  995. X                  }
  996. X                close (f);
  997. X              }
  998. X          }
  999. X      }
  1000. X
  1001. X    return -1;
  1002. X
  1003. X} /* OpenPTY() */
  1004. X#endif
  1005. X
  1006. XScanInput(buf, len)
  1007. Xchar *buf;
  1008. Xint len;
  1009. X{
  1010. X    char obuf[IOSIZE+2];
  1011. X    char *ip, *op;
  1012. X    int olen;
  1013. X
  1014. X    DO DEBUG("ScanInput(), len = %d buf '%s', scanloc = %d\n", 
  1015. X            len, buf, scanloc);
  1016. X    op = obuf;
  1017. X    olen = 0;
  1018. X    while (len-- > 0) {
  1019. X        if (*buf == initseq[scanloc]) {
  1020. X            scanloc++;
  1021. X            if (initseq[scanloc] == 0) {
  1022. X                DO DEBUG("INIT received from layers server\n");
  1023. X                printf("\r\n[MacLayers Startup Requested]\r\n");
  1024. X            /* Confirm the Maclayers protocol level */
  1025. X            if (Serverlevel != 2) {
  1026. X                DO DEBUG("Cannot accept connection to a level %d server\n", 
  1027. X                       Serverlevel);
  1028. X                    Abortonmsg = 0;
  1029. X                    Msg(0, "Sorry I can't talk to a level %d layers server\n", 
  1030. X                       Serverlevel);
  1031. X                    goto init_abort;
  1032. X                }
  1033. X                scanloc = 0;
  1034. X                if (len) {
  1035. X                    DO DEBUG("%d chars after INIT dumped '%s'\n",
  1036. X                            len, buf+1);
  1037. X                }
  1038. X                return(1);
  1039. X            }
  1040. X        }
  1041. X        else {
  1042. X            if (scanloc) {
  1043. X                /* protocol setting is a special case */
  1044. X                if (scanloc == 1 && *buf > '1' && *buf < '7') {
  1045. X                    DO DEBUG("Protocol set to %c\n", *buf);
  1046. X                    Serverlevel = (*buf - '0');
  1047. X                    printf("\r\n[Maclayers Protocol set to %d]\r\n", Serverlevel);
  1048. X                    scanloc = 0;
  1049. X                    buf++;
  1050. X                    continue;
  1051. X                }
  1052. X                else {
  1053. Xinit_abort:
  1054. X                    for (ip = initseq; scanloc > 0; scanloc--) {
  1055. X                        *op++ = *ip++ & 0x7f;
  1056. X                        olen++;
  1057. X                    }
  1058. X                }
  1059. X            }
  1060. X            *op++ = *buf & 0x7f;
  1061. X            olen++;
  1062. X        }
  1063. X        buf++;
  1064. X    }
  1065. X    obuf[olen] = 0;
  1066. X    DO DEBUG("olen = %d obuf '%s'\n", olen, obuf);
  1067. X    if (olen)
  1068. X        write(1, obuf, olen);
  1069. X    return(0);
  1070. X}
  1071. X
  1072. XSetLine()
  1073. X{
  1074. X    struct mode TtyMode;
  1075. X    
  1076. X    /* Set the mode on the layers I/O channel */
  1077. X    GetTTY (TtyFd, &TtyMode);
  1078. X    SetMode (&TtyMode, &TtyMode);
  1079. X    SetSpeed(&TtyMode, TtySpeed);
  1080. X    SetTTY (TtyFd, &TtyMode);
  1081. X}
  1082. X
  1083. XCookedMode()
  1084. X{
  1085. X    struct mode Mode;
  1086. X
  1087. X    GetTTY(0, &Mode);
  1088. X#ifdef V7TTY
  1089. X    Mode.m_ttyb.sg_flags &= ~RAW;
  1090. X    Mode.m_tchars.t_intrc = 3;
  1091. X#else
  1092. X    Mode.m_tty.c_lflag |= ISIG;
  1093. X#endif
  1094. X    SetTTY(0, &Mode);
  1095. X}
  1096. X
  1097. XRawMode()
  1098. X{
  1099. X    struct mode Mode;
  1100. X
  1101. X    GetTTY(0, &Mode);
  1102. X#ifdef V7TTY
  1103. X    Mode.m_ttyb.sg_flags |= RAW;
  1104. X    Mode.m_tchars.t_intrc = -1;
  1105. X#else
  1106. X    Mode.m_tty.c_lflag &= ~ISIG;
  1107. X#endif
  1108. X    SetTTY(0, &Mode);
  1109. X}
  1110. X
  1111. X
  1112. XStartUp()
  1113. X{
  1114. X    register len;
  1115. X    int     r;              /* read fd test bits */
  1116. X    int     w;              /* write fd test bits */
  1117. X    int     fderr;              /* error fd test bits */
  1118. X    int i;
  1119. X#ifdef USG
  1120. X    struct pollfd fds[2];
  1121. X#endif
  1122. X    char    buf[IOSIZE];
  1123. X        static  int escapemode = 0;
  1124. X
  1125. X    signal (SIGALRM, SIG_IGN);  /* alarm clock used by protocol.c */
  1126. X
  1127. X    printf("\r\n[ Layers - dumb terminal mode ]\r\n");
  1128. X
  1129. X    Abortonmsg = 0;         /* don't abort on msg from now on */
  1130. X
  1131. X    /* startup processing loop */
  1132. X
  1133. X    fderr = 0;                              /* startout no error fd's */
  1134. X
  1135. X    while (1)
  1136. X      {
  1137. X       
  1138. X#ifdef USG
  1139. X        fds[0].fd = 0;
  1140. X        fds[0].events = POLLIN|POLLPRI;
  1141. X        fds[1].fd = TtyFd;
  1142. X        fds[1].events = POLLIN|POLLPRI;
  1143. X
  1144. X        switch (poll(fds, 2, -1)) {
  1145. X        case -1:
  1146. X            Abortonmsg = 1;
  1147. X            DO DEBUG("poll errno %d\n", errno);
  1148. X            Msg (errno, "poll");
  1149. X            /*NOTREACHED*/
  1150. X
  1151. X          case 0:
  1152. X            /* timeout reached - SHOULD NOT OCCUR */
  1153. X            DO DEBUG("Unexpected poll timeout in StartUp\n");
  1154. X            continue;           /* re-loop */
  1155. X
  1156. X          default:
  1157. X            /* a channel has read/write status pending */
  1158. X            break;
  1159. X        }
  1160. X
  1161. X        DO DEBUG("after poll stdin = %x, TtyFd = %x\n", 
  1162. X         fds[0].revents, fds[1].revents);
  1163. X
  1164. X        /* process input stream from remote */
  1165. X        if (fds[0].revents)
  1166. X          { 
  1167. X            len = read(0, buf, IOSIZE);
  1168. X            if (len >= 0)               /* if no error ... */
  1169. X              { DO DEBUG("keyboard len %d\n", len);
  1170. X              }
  1171. X            else
  1172. X              {
  1173. X                DO DEBUG("read keyboard %d len %d\n",
  1174. X                        errno, len);
  1175. X#ifdef KEY_ERR_OK
  1176. X                /* We expect EIO error if socket not yet open on other end
  1177. X                ** or if process using socket has terminated. We expect
  1178. X                ** EWOULDBLOCK also after process terminates.
  1179. X                **/
  1180. X                if (errno == EIO || errno == EAGAIN)
  1181. X                  { DO DEBUG(" ...anticipated\n");
  1182. X                  }
  1183. X#else
  1184. X            FQuit(EXITNORMAL);
  1185. X#endif
  1186. X              }
  1187. X            if (len > 0)
  1188. X              {
  1189. X                /* Process input stream */
  1190. X                for (i = 0; i < len; i++)
  1191. X                 {
  1192. X                  if ((buf[i] & 0x7f) == '~') {
  1193. X                    if (!escapemode) {
  1194. X                        escapemode++;
  1195. X                        continue;
  1196. X                    }
  1197. X                  }
  1198. X                  else if (escapemode) {
  1199. X                    Tilde(buf[i]);
  1200. X            escapemode = 0;
  1201. X                    continue;
  1202. X                  }
  1203. X                  write(TtyFd, &buf[i], 1);
  1204. X                 }
  1205. X              }
  1206. X             }
  1207. X
  1208. X        /* now pass all available output to remote */
  1209. X        if (fds[1].revents)
  1210. X         {  /* output to send to stdout */
  1211. X            len = read(TtyFd, buf, IOSIZE);
  1212. X            if (len >= 0)               /* if no error ... */
  1213. X              { DO DEBUG("output len %d\n", len);
  1214. X              }
  1215. X            else
  1216. X              {
  1217. X                DO DEBUG("read output errno %d len %d fd %d\n",
  1218. X                        errno, len, TtyFd);
  1219. X#ifdef OUT_ERR_OK
  1220. X                /* We expect EIO error if socket not yet open on other end
  1221. X                ** or if process using socket has terminated. We expect
  1222. X                ** EWOULDBLOCK also after process terminates.
  1223. X                **/
  1224. X                if (errno == EIO || errno == EAGAIN)
  1225. X                  { DO DEBUG(" ...anticipated\n");
  1226. X                  }
  1227. X                /* layer not ready or just terminated so wait-a-bit */
  1228. X                fderr |= TtyMask;
  1229. X                errno = 0;              /* clear errno */
  1230. X#else
  1231. X                FQuit(EXITNORMAL);
  1232. X#endif
  1233. X              }
  1234. X
  1235. X            if (len > 0)
  1236. X                /* Process input stream */
  1237. X                if (ScanInput(buf, len))
  1238. X                    return;
  1239. X             }
  1240. X#else /* USG */
  1241. X
  1242. X        r = (1 | TtyMask);  /* read stdio and shell output */
  1243. X        w = 0;          /* no write tests */
  1244. X
  1245. X
  1246. X        DO DEBUG("Select(r %x, w %x, fderr %x)\n",
  1247. X                    r, w, fderr);
  1248. X
  1249. X        switch ( select(32, &r, &w, NULL, NULL) )
  1250. X        { case -1:
  1251. X            /* errno has report */
  1252. X            if (errno == EINTR)             /* signal delivered or timout */
  1253. X              { errno = 0;
  1254. X                fderr = 0;                  /* turn off error stall */
  1255. X                DO DEBUG("select errno EINTR\n");
  1256. X                continue;                   /* re-loop */
  1257. X              }
  1258. X            Abortonmsg = 1;
  1259. X            DO DEBUG("select errno %d\n", errno);
  1260. X            Msg (errno, "select");
  1261. X            /*NOTREACHED*/
  1262. X
  1263. X          case 0:
  1264. X            /* timeout reached - SHOULD NOT OCCUR */
  1265. X            DO DEBUG("Unexpected select timeout in StartUp\n");
  1266. X            fderr = 0;          /* turn off error stall */
  1267. X            continue;           /* re-loop */
  1268. X
  1269. X          default:
  1270. X            /* a channel has read/write status pending */
  1271. X            break;
  1272. X        }
  1273. X
  1274. X        DO DEBUG("after select r %x w %x\n", r, w);
  1275. X
  1276. X        /* process input stream from remote */
  1277. X        if (r & 1 << 0)
  1278. X          { 
  1279. X            len = read(0, buf, IOSIZE);
  1280. X            if (len >= 0)               /* if no error ... */
  1281. X              { DO DEBUG("keyboard len %d\n", len);
  1282. X              }
  1283. X            else
  1284. X              {
  1285. X                DO DEBUG("read keyboard %d len %d\n",
  1286. X                        errno, len);
  1287. X#ifdef KEY_ERR_OK
  1288. X                /* We expect EIO error if socket not yet open on other end
  1289. X                ** or if process using socket has terminated. We expect
  1290. X                ** EWOULDBLOCK also after process terminates.
  1291. X                **/
  1292. X                if (errno == EIO || errno == EWOULDBLOCK)
  1293. X                  { DO DEBUG(" ...anticipated\n");
  1294. X                  }
  1295. X
  1296. X                /* layer not ready or just terminated so wait-a-bit */
  1297. X                fderr |= TtyMask;
  1298. X                errno = 0;              /* clear errno */
  1299. X#else
  1300. X            FQuit(EXITNORMAL);
  1301. X#endif
  1302. X              }
  1303. X            if (len > 0)
  1304. X              {
  1305. X                /* Process input stream */
  1306. X                for (i = 0; i < len; i++)
  1307. X                 {
  1308. X                  if ((buf[i] & 0x7f) == '~') {
  1309. X                    if (!escapemode) {
  1310. X                        escapemode++;
  1311. X                        continue;
  1312. X                    }
  1313. X                  }
  1314. X                  else if (escapemode) {
  1315. X                    Tilde(buf[i]);
  1316. X            escapemode = 0;
  1317. X                    continue;
  1318. X                  }
  1319. X                  write(TtyFd, &buf[i], 1);
  1320. X                 }
  1321. X              }
  1322. X             }
  1323. X
  1324. X        /* now pass all available output to remote */
  1325. X        if (r & TtyMask)
  1326. X         {  /* output to send to stdout */
  1327. X            len = read(TtyFd, buf, IOSIZE);
  1328. X            if (len >= 0)               /* if no error ... */
  1329. X              { DO DEBUG("output len %d\n", len);
  1330. X              }
  1331. X            else
  1332. X              {
  1333. X                DO DEBUG("read output errno %d len %d fd %d\n",
  1334. X                        errno, len, TtyFd);
  1335. X#ifdef OUT_ERR_OK
  1336. X                /* We expect EIO error if socket not yet open on other end
  1337. X                ** or if process using socket has terminated. We expect
  1338. X                ** EWOULDBLOCK also after process terminates.
  1339. X                **/
  1340. X                if (errno == EIO || errno == EWOULDBLOCK)
  1341. X                  { DO DEBUG(" ...anticipated\n");
  1342. X                  }
  1343. X                /* layer not ready or just terminated so wait-a-bit */
  1344. X                fderr |= TtyMask;
  1345. X                errno = 0;              /* clear errno */
  1346. X#else
  1347. X                FQuit(EXITNORMAL);
  1348. X#endif
  1349. X              }
  1350. X
  1351. X            if (len > 0)
  1352. X                /* Process input stream */
  1353. X                if (ScanInput(buf, len))
  1354. X                    return;
  1355. X             }
  1356. X#endif
  1357. X
  1358. X      } /* end while (1) */
  1359. X
  1360. X    /* NOT REACHED */
  1361. X
  1362. X}
  1363. X
  1364. XTilde(c)
  1365. Xint c;
  1366. X{
  1367. X    char buf[2];
  1368. X
  1369. X    DO DEBUG("Tilde CMD %c\n", c);
  1370. X    switch (c) {
  1371. X    case '.':
  1372. X        FQuit(0);
  1373. X    /* NOT REACHED */
  1374. X    case 'b':
  1375. X    tty_break();
  1376. X    break;
  1377. X    default:
  1378. X        buf[0] = c;
  1379. X    write(TtyFd, buf, 1);
  1380. X    break;
  1381. X    }
  1382. X}
  1383. X
  1384. X/*VARARGS2*/
  1385. XMsg (err, fmt, p1, p2, p3, p4, p5, p6)
  1386. Xchar *fmt;
  1387. X{
  1388. X    char buf[1024];
  1389. X    register char *p = buf;
  1390. X
  1391. X    sprintf (p, fmt, p1, p2, p3, p4, p5, p6);
  1392. X    if (err)
  1393. X      { p += strlen (p);
  1394. X        if (err > 0 && err < sys_nerr)
  1395. X            sprintf (p, ": %s", sys_errlist[err]);
  1396. X        else
  1397. X            sprintf (p, ": Error %d", err);
  1398. X      }
  1399. X    if (!Abortonmsg)
  1400. X      { /* MakeStatus (buf, curr);*/
  1401. X        printf("%s\r\n", buf);
  1402. X      } 
  1403. X    else
  1404. X      { printf ("%s\r\n", buf);
  1405. X        exit(exitcode);
  1406. X      }
  1407. X
  1408. X} /* Msg() */
  1409. X
  1410. X                /* DEBUG() - dump output routine */
  1411. X
  1412. Xvoid
  1413. XDEBUG(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
  1414. Xchar        *format;
  1415. Xint         arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8;
  1416. X{
  1417. X    fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
  1418. X}
  1419. X
  1420. Xchar *
  1421. XFilename (s)
  1422. Xchar *s;
  1423. X{
  1424. X    register char *p;
  1425. X
  1426. X    p = s + strlen (s) - 1;
  1427. X    while (p >= s && *p != '/')
  1428. X        --p;
  1429. X    return ++p;
  1430. X
  1431. X} /* Filename() */
  1432. X
  1433. X
  1434. Xstatic gl_timeout()
  1435. X{
  1436. X    DO DEBUG("getc_line: SIGALRM\n");
  1437. X        longjmp(gl_buf, 1);
  1438. X}
  1439. X
  1440. Xgetc_line(sec)
  1441. Xunsigned int sec;
  1442. X{       
  1443. X    int result;
  1444. X    char buf[2];
  1445. X    unsigned int alarm();
  1446. X
  1447. X    if (sec) {
  1448. X        alarm(sec);
  1449. X        signal(SIGALRM, gl_timeout);
  1450. X        if (setjmp(gl_buf))
  1451. X            return(-1);
  1452. X    }
  1453. X
  1454. X    do {
  1455. X        /* do the read from the serial channel */
  1456. X        CookedMode();   
  1457. X        result = read(TtyFd, buf, 1);
  1458. X    RawMode();
  1459. X    } while (result == 0);
  1460. X
  1461. X    if (sec) {
  1462. X       signal(SIGALRM, SIG_IGN);
  1463. X       alarm(0);
  1464. X    }
  1465. X
  1466. X    if (result <= 0)
  1467. X      { DO DEBUG("get_line: result = %d, errno = %d\n", result, errno);
  1468. X    return(-1);
  1469. X      }
  1470. X    return(buf[0] & 0x0ff);
  1471. X}
  1472. X
  1473. X            
  1474. END_OF_FILE
  1475.   if test 21155 -ne `wc -c <'startup.c'`; then
  1476.     echo shar: \"'startup.c'\" unpacked with wrong size!
  1477.   fi
  1478.   # end of 'startup.c'
  1479. fi
  1480. if test -f 'ul_ports' -a "${1}" != "-c" ; then 
  1481.   echo shar: Will not clobber existing file \"'ul_ports'\"
  1482. else
  1483.   echo shar: Extracting \"'ul_ports'\" \(392 characters\)
  1484.   sed "s/^X//" >'ul_ports' <<'END_OF_FILE'
  1485. X#
  1486. X# Ulayers ports database
  1487. X#
  1488. X# Each line identifies the default modem dialer to use for each port.
  1489. X# The modems are defined in the ul_modems database.
  1490. X# The -m option to ulayers overrides these defaults.
  1491. X# When no match is found, ulayers defaults to its compile-time dialer
  1492. X# (usually a simple hayes dialer).
  1493. X#
  1494. X# Examples: (remove the '#' to make them real)
  1495. X#/dev/cua0:t2500
  1496. X#/dev/cua1:t3000
  1497. END_OF_FILE
  1498.   if test 392 -ne `wc -c <'ul_ports'`; then
  1499.     echo shar: \"'ul_ports'\" unpacked with wrong size!
  1500.   fi
  1501.   # end of 'ul_ports'
  1502. fi
  1503. if test -f 'ulayers.1' -a "${1}" != "-c" ; then 
  1504.   echo shar: Will not clobber existing file \"'ulayers.1'\"
  1505. else
  1506.   echo shar: Extracting \"'ulayers.1'\" \(6137 characters\)
  1507.   sed "s/^X//" >'ulayers.1' <<'END_OF_FILE'
  1508. X.TH ULAYERS l  "1 April 1993"
  1509. X.SH NAME
  1510. X.PP
  1511. Xulayers \- Unix Emulation of MacLayers Multiwindow Terminal Emulator
  1512. X.SH SYNOPSIS
  1513. Xulayers [-df] [ -m modem ] device speed [ number ]
  1514. X.PP
  1515. Xulayers [-df] [ -m modem ] system
  1516. X.PP
  1517. Xulayers -v
  1518. X.SH DESCRIPTION
  1519. X.PP
  1520. XUlayers provides multi-window capability for a Unix system running X
  1521. Xby emulating the Macintosh application called MacLayers.
  1522. XTo use Ulayers, you must have the X Windows system installed on your
  1523. Xlocal Unix system and the layers protocol program installed on your
  1524. Xremote Unix system. Alternatives to X are possible by substituting
  1525. Xa custom
  1526. X.I ulterm
  1527. Xmodule (see below).
  1528. X.SH ULAYERS OPERATION
  1529. X.PP
  1530. XThe Ulayers application starts up as a "dumb"
  1531. Xterminal emulator. (As such you can use it with any
  1532. Xhost, not just a Unix machine.)  Ulayers does not emulate any
  1533. Xparticular terminal. Whatever terminal you're on is what the remote
  1534. Xsystem "sees".  You can quit the ulayers "dumb terminal" mode
  1535. Xby issuing the \~\. command.
  1536. X.PP
  1537. XIf only
  1538. X.I device
  1539. Xand
  1540. X.I speed
  1541. Xare specified, you
  1542. Xwill be connected directly to the serial port (modem) and you can
  1543. Xissue modem commands to dial the remote system.
  1544. XThe
  1545. X.I -f
  1546. Xoption enables flow control on the serial connection. The 
  1547. X.I -d
  1548. Xoption enables debugging mode, in which ulayers will print
  1549. Xdiagnostic information in a
  1550. X.I ulayers.dump
  1551. Xfile in the current directory. The
  1552. X.I -v
  1553. Xoption causes ulayers to print its version identification and exit.
  1554. XThe
  1555. X.I -m
  1556. Xoption allows one to override the default modem for the selected port.
  1557. X.PP
  1558. XWhen
  1559. X.IR device ,
  1560. X.IR speed ,
  1561. Xand
  1562. X.I number
  1563. Xare given, the specified number is dialed using the specified
  1564. Xport and speed parameters.  If 
  1565. X.I system
  1566. Xalone is given, the specified system is called, using the user's
  1567. Xpersonal dialing database (see below).
  1568. X.PP
  1569. XIn either case, once you're connected to the remote Unix system,
  1570. Xlogin and issue the 
  1571. X.I layers
  1572. Xcommand (from the standard MacLayers distribution) with no options
  1573. Xto start the MacLayers multi-window
  1574. Xprotocol. A new layers session will start. If you're using
  1575. Xthe default
  1576. X.I ulterm
  1577. Xthis will be an
  1578. X.I xterm
  1579. Xwindow. Once the MacLayers protocol
  1580. Xstarts, the original "dumb" terminal session enters a basic command
  1581. Xmode.  You can type 'n' (new) to the ulayers application to open a new
  1582. XMacLayers session.  Or you can start a new layer session by issuing 
  1583. Xthe
  1584. X.I layers
  1585. Xcommand to an existing layers session.  See layers(1) for other options.
  1586. X.PP
  1587. XYou can abort host 
  1588. X.I layers
  1589. Xby issuing the 'q' (quit) command to the ulayers program. The 's'
  1590. X(status) command shows the status of all active layers. The 'h' (help)
  1591. Xcommand lists all the possible
  1592. X.I ulayers 
  1593. Xcommands.
  1594. X.SH ZMODEM DOWNLOADING
  1595. X.PP
  1596. XUlayers has a download facility for downloading using the 
  1597. XZMODEM protocol.  When you start a ZMODEM download on the remote
  1598. Xsystem, the layers window automatically detects the ZMODEM
  1599. Xinitialization sequence and attempts to execute the
  1600. X.I rz
  1601. Xprogram on the local system. 
  1602. X.SH ZMODEM UPLOADING
  1603. X.PP
  1604. XUlayers supports an upload facility for transferring local
  1605. Xfiles to the remote system using the ZMODEM protocol.  When you
  1606. Xstart a ZMODEM upload on the remote
  1607. Xsystem, the layers window automatically detects the ZMODEM
  1608. Xinitialization sequence.  You will be prompted for the name
  1609. Xof the local file to send.
  1610. XUlayers attempts to execute the
  1611. X.I sz
  1612. Xprogram on the local system to send the requested file.
  1613. X.SH AUTOMATIC DIALING
  1614. XUlayers supports a modem and dialing database.  Each user may
  1615. Xhave a personal list of systems that they frequently call.
  1616. XThis file is stored in the file
  1617. X.B .ul_numbers
  1618. Xin the user's home directory.  This file must be created with
  1619. Xa text editor; there is no provision within Ulayers to create
  1620. Xthis file.  The .ul_numbers file consists of entries, one per line,
  1621. Xof the form:
  1622. X.IP
  1623. X.I
  1624. Xsystem\ \ \ speed\ \ \ line\ \ \ number
  1625. X.LP
  1626. X.TP 10
  1627. X.I system
  1628. Xis the name of the dialer enter. It corresponds to the argument
  1629. Xpassed on the ulayers command-line.
  1630. X.TP
  1631. X.I speed
  1632. Xdefines the communication parameters for the connection.  It specifies
  1633. Xthe baud rate and parity. For example, 19200-N-8-1, for 19.2K baud,
  1634. Xno parity, 8 data bits, and 1 stop bit.
  1635. X.TP
  1636. X.I line
  1637. Xspecifies the communications device, such as /dev/cua0.
  1638. X.TP
  1639. X.I number
  1640. Xis optional and is the telephone number of the remote system.
  1641. X.PP
  1642. XThe Ulayers modems database allows you to customize the way
  1643. XUlayers talks to your modem.
  1644. XUlayers assumes a Hayes-compatible modem. If your modem is Hayes
  1645. Xcompatible, then no special dialing instructions are required.
  1646. XThe compile-time parameter LIB_DIR defines the location of the
  1647. Xtwo modem database files. One file,
  1648. X.B ul_modems
  1649. Xdefines the modem commands used to initialize and dial.  Another
  1650. Xfile,
  1651. X.B ul_ports
  1652. Xdefines the default modem dialer to use with each tty port.
  1653. XRefer to the sample files provided for the format of these files.
  1654. X.SH FILES
  1655. X$HOME/.ul_numbers
  1656. X.br
  1657. Xul_modems
  1658. X.br
  1659. Xul_ports
  1660. X.br
  1661. Xulterm
  1662. X.br
  1663. Xrz
  1664. X.br
  1665. Xsz
  1666. X.br
  1667. Xulslave
  1668. X.br
  1669. X.SH ENVIRONMENT
  1670. X.TP 10
  1671. XULTERM
  1672. Xdefines the name of the terminal startup module. Ulayers executes this
  1673. Xcommand when a new layer session is started, passing the name of the
  1674. XPTY and the layer number as arguments. If the ULTERM environment is
  1675. Xnot defined, ulayers defaults to 
  1676. X.BR ulterm .
  1677. XThe supplied ulterm module is a Bourne shell script which runs
  1678. X.IB xterm .
  1679. X.SH AUTHOR
  1680. XMost of the source was derived from the original Maclayers
  1681. Xsource written by Dave Trissel.  The modifications to emulate
  1682. Xthe Mac-side of the protocol on Unix were made by David Beckemeyer.
  1683. X.SH BUGS AND CAVEATS
  1684. XUlayers doesn't support geometry and sizing options.  All windows
  1685. Xare assumed to be 80 columns by 25 rows.
  1686. X.PP
  1687. XDue to a bug in versions of "layers" prior to v1.30,
  1688. Xthe UPLOAD feature of Ulayers does not work for binary files
  1689. Xon all systems.  It should work on any file that does not contain
  1690. Xthe character 0xfd.  This bug is fixed in the v1.30 version of
  1691. Xlayers.
  1692. X.SH SEE ALSO
  1693. X.PP
  1694. XThe MacLayers program is
  1695. Xcompletely described in the manual that accompanies it.
  1696. X.PP
  1697. XManual page derived from layers(1) by Peter Newton.
  1698. X.PP
  1699. XUNIX(TM) is a registered trademark of American Telephone and Telegraph.
  1700. XMacintosh is a trademark of McIntosh Laboratories and is licensed to Apple 
  1701. XComputer.
  1702. END_OF_FILE
  1703.   if test 6137 -ne `wc -c <'ulayers.1'`; then
  1704.     echo shar: \"'ulayers.1'\" unpacked with wrong size!
  1705.   fi
  1706.   # end of 'ulayers.1'
  1707. fi
  1708. if test -f 'ulslave.c' -a "${1}" != "-c" ; then 
  1709.   echo shar: Will not clobber existing file \"'ulslave.c'\"
  1710. else
  1711.   echo shar: Extracting \"'ulslave.c'\" \(8428 characters\)
  1712.   sed "s/^X//" >'ulslave.c' <<'END_OF_FILE'
  1713. X/********                    ulslave.c
  1714. X*********
  1715. X*********     This is a quick & dirty implementation of the
  1716. X*********     MacLayers protocol client-side for Unix.  It
  1717. X*********     Basically is an emulation of the MacLayers
  1718. X*********     Macintosh application for Unix, except that
  1719. X*********     Ulayers is a bare-bones program, a far cry
  1720. X*********     from the polished and professional MacLayers.
  1721. X*********
  1722. X*********     The hacks to produce Ulayers were made by me,
  1723. X*********     David Beckemeyer david@bdt.com.  Essentially
  1724. X*********     the entire credit for this goes to the original
  1725. X*********     authors however, and all the contributors
  1726. X*********     copyright messages appear below.  On the
  1727. X*********     the other hand, the "real" Maclayers authors
  1728. X*********     are not to blame for the shoddy hacks I made
  1729. X*********     to their code either, and so I'm putting my
  1730. X*********     here because I'm sure they don't want their
  1731. X*********     name associatyed with this mess!
  1732. X*********
  1733. X*********     Most of the code for Ulayers came straight from
  1734. X*********     the Unix-side of the MacLayers implementation,
  1735. X*********     the copyright messages to which follow:
  1736. X*********
  1737. X*********    Layers - MacLayers Multiwindow BSD Socket Driver
  1738. X*********
  1739. X*********          Dave Trissel oakhill!davet
  1740. X*********
  1741. X********* The sockets handling portion of this control module is based 
  1742. X********* upon 'screen' by Oliver Laumann whose copyright remains below. 
  1743. X********* The rest is
  1744. X *
  1745. X *             Copyright (C) 1989 by David W. Trissel
  1746. X *
  1747. X *              Not derived from licensed software.
  1748. X *
  1749. X * Permission is granted to freely use, copy, modify, and redistribute
  1750. X * this software, provided that no attempt is made to gain profit from it,
  1751. X * the author is not construed to be liable for any results of using the
  1752. X * software, alterations are clearly marked as such, and this notice is
  1753. X * not modified.
  1754. X *
  1755. X */
  1756. X
  1757. X
  1758. X/* Copyright (c) 1987,1988 Oliver Laumann, Technical University of Berlin.
  1759. X * Not derived from licensed software.
  1760. X *
  1761. X * Permission is granted to freely use, copy, modify, and redistribute
  1762. X * this software, provided that no attempt is made to gain profit from it,
  1763. X * the author is not construed to be liable for any results of using the
  1764. X * software, alterations are clearly marked as such, and this notice is
  1765. X * not modified.
  1766. X *
  1767. X *    Modified by Patrick Wolfe (pat@kai.com, kailand!pat)
  1768. X *    Do whatever you want with (my modifications of) this program, but
  1769. X *    don't claim you wrote them, don't try to make money from them, and
  1770. X *    don't remove this notice.
  1771. X */
  1772. X#include <stdio.h>
  1773. X#include <signal.h>   
  1774. X#include <errno.h>
  1775. X#include <ctype.h>    
  1776. X#include <pwd.h>
  1777. X#ifdef USG
  1778. X#include <stropts.h>
  1779. X#include <poll.h>
  1780. X#endif
  1781. X#include <nlist.h> 
  1782. X#include <fcntl.h>
  1783. X#include <sys/types.h>
  1784. X#include <sys/time.h>
  1785. X#include <sys/file.h>
  1786. X#include <sys/wait.h>
  1787. X#include <sys/socket.h>
  1788. X#include <utmp.h>
  1789. X#ifndef USG
  1790. X#include <sys/un.h>
  1791. X#endif
  1792. X#include <sys/stat.h>
  1793. X#include <sys/dir.h> 
  1794. X#include "conf.h"
  1795. X#ifdef V7TTY
  1796. X#include <sgtty.h>
  1797. X#include <sys/ioctl.h>
  1798. X#else
  1799. X#include <termio.h>
  1800. X#endif
  1801. X
  1802. X#define IOSIZE 1024
  1803. X
  1804. X#define RZ "rz"
  1805. X#define SZ "sz"
  1806. X
  1807. Xstatic char *RzArgs[] = { RZ, NULL };
  1808. Xstatic char *SzArgs[3];
  1809. X
  1810. X#define DO if (Dflag)
  1811. X
  1812. X#ifdef DEBUG
  1813. Xint Dflag = 1;
  1814. X#else
  1815. Xint Dflag = 0;
  1816. X#endif
  1817. X
  1818. Xstruct mode {
  1819. X#ifdef V7TTY
  1820. X    struct sgttyb m_ttyb;
  1821. X    struct tchars m_tchars;
  1822. X    struct ltchars m_ltchars;
  1823. X    int m_ldisc;
  1824. X    int m_lmode;
  1825. X#else
  1826. X    struct termio m_tty;
  1827. X#endif
  1828. X};
  1829. X
  1830. Xstatic char *initseq = "**\030B0";
  1831. Xstatic int scanloc = 0;
  1832. Xstatic int ttyfd;
  1833. Xstatic struct mode TtyMode, OldMode;
  1834. X
  1835. XSetTTY (fd, mp)
  1836. Xstruct mode *mp;
  1837. X{
  1838. X#ifdef V7TTY
  1839. X    ioctl (fd, TIOCSETP, &mp->m_ttyb);
  1840. X    ioctl (fd, TIOCSETC, &mp->m_tchars);
  1841. X    ioctl (fd, TIOCSLTC, &mp->m_ltchars);
  1842. X    ioctl (fd, TIOCLSET, &mp->m_lmode);
  1843. X    ioctl (fd, TIOCSETD, &mp->m_ldisc);
  1844. X#else
  1845. X    ioctl (fd, TCSETAF, &mp->m_tty);
  1846. X#endif
  1847. X} /* SetTTY() */
  1848. X
  1849. XGetTTY (fd, mp)
  1850. Xstruct mode *mp;
  1851. X{
  1852. X#ifdef V7TTY
  1853. X    ioctl (fd, TIOCGETP, &mp->m_ttyb);
  1854. X    ioctl (fd, TIOCGETC, &mp->m_tchars);
  1855. X    ioctl (fd, TIOCGLTC, &mp->m_ltchars);
  1856. X    ioctl (fd, TIOCLGET, &mp->m_lmode);
  1857. X    ioctl (fd, TIOCGETD, &mp->m_ldisc);
  1858. X#else
  1859. X    ioctl (fd, TCGETA, &mp->m_tty);
  1860. X#endif
  1861. X} /* GetTTY() */
  1862. X
  1863. XSetMode (op, np)
  1864. Xstruct mode *op, *np;
  1865. X{
  1866. X    *np = *op;
  1867. X#ifdef V7TTY
  1868. X    np->m_ttyb.sg_flags = RAW | ANYP;
  1869. X    np->m_tchars.t_intrc = -1;
  1870. X    np->m_tchars.t_quitc = -1;
  1871. X    np->m_tchars.t_startc = -1;
  1872. X    np->m_tchars.t_stopc = -1;
  1873. X    np->m_ltchars.t_suspc = -1;
  1874. X    np->m_ltchars.t_dsuspc = -1;
  1875. X    np->m_ltchars.t_flushc = -1;
  1876. X    np->m_ltchars.t_lnextc = -1;
  1877. X#else
  1878. X    np->m_tty.c_cc[4] = 1;               /* VMIN */
  1879. X    np->m_tty.c_cc[5] = 0;               /* VTIME */
  1880. X    np->m_tty.c_oflag = 0;
  1881. X    np->m_tty.c_iflag = 0;
  1882. X    np->m_tty.c_cflag |= (CREAD|HUPCL|CLOCAL);
  1883. X    np->m_tty.c_lflag = 0;
  1884. X#endif
  1885. X} /* SetMode() */
  1886. X
  1887. Xusage()
  1888. X{
  1889. X    fprintf(stderr, "usage: ulslave tty\n");
  1890. X    exit(1);
  1891. X}
  1892. X
  1893. Xmain(argc, argv)
  1894. Xint argc;
  1895. Xchar *argv[];
  1896. X{
  1897. X    char *tty;
  1898. X    int ttymask;
  1899. X    int len, r;
  1900. X#ifdef USG
  1901. X    struct pollfd fds[2];
  1902. X#endif
  1903. X
  1904. Xstatic char buf[IOSIZE];
  1905. X
  1906. X    if (argc != 2)
  1907. X        usage();
  1908. X    tty = argv[1];
  1909. X
  1910. X    ttyfd = open(tty, O_RDWR);
  1911. X    ttymask = (1 << ttyfd);
  1912. X    printf("Ulayers session on local pty %s\n", tty);
  1913. X    if (ttyfd < 0) {
  1914. X        printf("ulslave: open failed (errno %d)\n", errno);
  1915. X        exit(1);
  1916. X    }
  1917. X    GetTTY(0, &OldMode);
  1918. X    SetMode(&OldMode, &TtyMode);
  1919. X    SetTTY(0, &TtyMode);
  1920. X    SetTTY(1, &TtyMode);
  1921. X    SetTTY(ttyfd, &TtyMode);
  1922. X
  1923. X    /* Enable signals */
  1924. X    signal(SIGHUP, SIG_DFL);
  1925. X    signal(SIGTERM, SIG_DFL);
  1926. X    signal(SIGINT, SIG_IGN);
  1927. X
  1928. X    /* Send Init message */
  1929. X    sprintf(buf, "%dT", getpid());
  1930. X    write(ttyfd, buf, strlen(buf));
  1931. X
  1932. X    while (1) {
  1933. X#ifdef USG
  1934. X        fds[0].fd = 0;
  1935. X        fds[0].events = POLLIN|POLLPRI;
  1936. X        fds[1].fd = ttyfd;
  1937. X        fds[1].events = POLLIN|POLLPRI;
  1938. X
  1939. X        poll(fds, 2, -1);
  1940. X        if (fds[0].revents) {
  1941. X            len = read(0, buf, IOSIZE);
  1942. X            DO printf("read %d bytes from stdin\n", len);
  1943. X            if (len > 0)
  1944. X                write(ttyfd, buf, len);
  1945. X        }
  1946. X        if (fds[1].revents) {
  1947. X            len = read(ttyfd, buf, IOSIZE);
  1948. X            DO printf("read %d bytes from tty", len);
  1949. X            if (len > 0)
  1950. X                ScanStream(buf, len);
  1951. X            else {
  1952. X                /* closed PTY, send a SIGHUP */
  1953. X                kill(getpid(), SIGHUP);
  1954. X            }
  1955. X        }
  1956. X#else
  1957. X        r = 1 | ttymask;
  1958. X        select(32, &r, 0, 0, 0);
  1959. X        DO printf("back from select r = %x\n", r);
  1960. X        if (r & 1) {
  1961. X            len = read(0, buf, IOSIZE);
  1962. X            DO printf("read %d bytes from stdin\n", len);
  1963. X            if (len > 0)
  1964. X                write(ttyfd, buf, len);
  1965. X        }
  1966. X        if (r & ttymask) {
  1967. X            len = read(ttyfd, buf, IOSIZE);
  1968. X            DO printf("read %d bytes from tty", len);
  1969. X            if (len > 0)
  1970. X                ScanStream(buf, len);
  1971. X            else {
  1972. X                /* closed PTY, send a SIGHUP */
  1973. X                kill(getpid(), SIGHUP);
  1974. X            }
  1975. X        }
  1976. X#endif        
  1977. X    }
  1978. X}
  1979. X
  1980. X
  1981. XScanStream(buf, len)
  1982. Xchar *buf;
  1983. Xint len;
  1984. X{
  1985. X    char *op;
  1986. X    int olen;
  1987. X    char fname[256];
  1988. X
  1989. X    /* save original pointer */
  1990. X    op = buf;
  1991. X    olen = len;
  1992. X    while (len-- > 0) {
  1993. X        /* buffer chars while we have a match on out startup sequence */
  1994. X        if (*buf == initseq[scanloc]) {
  1995. X            scanloc++;
  1996. X        }
  1997. X        else {
  1998. X            /* If we matched the Zmodem INIT sequence */
  1999. X            if (initseq[scanloc] == 0) {
  2000. X                /* see if it's a upload or download */
  2001. X                switch (*buf) {
  2002. X                case '0':
  2003. X                    scanloc = 0;
  2004. X                    write(1, "\r\n[ZMODEM D/L]\r\n", 16);
  2005. X                    do_udl(RZ, RzArgs);
  2006. X                    return(1);
  2007. X                case '1':
  2008. X                    scanloc = 0;
  2009. X                    write(1, "\r\n[ZMODEM U/L]\r\n", 16);
  2010. X                    write(1, "Enter Filename: ", 16);
  2011. X                    SetTTY(0, &OldMode);
  2012. X                    len = readline(0, fname, IOSIZE);
  2013. X                    SetTTY(0, &TtyMode);
  2014. X                    if (len <= 0)
  2015. X                        return(0);
  2016. X                    SzArgs[0] = SZ;
  2017. X                    SzArgs[1] = fname;
  2018. X                    SzArgs[2] = NULL;
  2019. X                    do_udl(SZ, SzArgs);
  2020. X                    return(1);
  2021. X                }
  2022. X                /* not a valid start, ignore */
  2023. X            }
  2024. X        }
  2025. X        buf++;
  2026. X    }
  2027. X    write(1, op, olen);
  2028. X    return(0);
  2029. X}
  2030. X    
  2031. X
  2032. X
  2033. X
  2034. X
  2035. X
  2036. X
  2037. Xdo_udl(cmd, args)
  2038. Xchar *cmd, **args;
  2039. X{
  2040. X    int pid;
  2041. X    FILE *fp;
  2042. X
  2043. X    switch (pid = fork()) {
  2044. X    case 0:
  2045. X        fp = fdopen(dup(1), "w");
  2046. X        close(0);
  2047. X        dup(ttyfd);
  2048. X        close(1);
  2049. X        dup(ttyfd);
  2050. X        execvp(cmd, args);
  2051. X        write(1, "\030\030\030\030\030", 5);
  2052. X        fprintf(fp, "\r\n[ The \"%s\" program must be installed in your path locally. ]\r\n", cmd);
  2053. X        fclose(fp);
  2054. X        exit(1);
  2055. X    case -1:
  2056. X        perror("ulslave: fork failed");
  2057. X        break;
  2058. X    default:
  2059. X        wait(NULL);
  2060. X        SetTTY(ttyfd, &TtyMode);
  2061. X        printf("[ZMODEM DONE]\r\n");
  2062. X        break;
  2063. X    }
  2064. X}
  2065. X
  2066. X        
  2067. Xreadline(fd, ptr, maxlen)
  2068. Xint fd;
  2069. Xchar *ptr;
  2070. Xint maxlen;
  2071. X{
  2072. X    int n, rc;
  2073. X
  2074. X    for (n = 0; n < maxlen; n++) {
  2075. X        if ((rc = read(fd, ptr, 1)) == 1) {
  2076. X            if (*ptr <= ' ')
  2077. X                break;
  2078. X            ptr++;
  2079. X        }
  2080. X        else if (rc == 0) {
  2081. X            break;        /* EOF, some data read */
  2082. X        }
  2083. X        else
  2084. X            return(-1);    /* error */
  2085. X    }
  2086. X    *ptr = 0;
  2087. X    return(n);
  2088. X}
  2089. END_OF_FILE
  2090.   if test 8428 -ne `wc -c <'ulslave.c'`; then
  2091.     echo shar: \"'ulslave.c'\" unpacked with wrong size!
  2092.   fi
  2093.   # end of 'ulslave.c'
  2094. fi
  2095. echo shar: End of archive 1 \(of 3\).
  2096. cp /dev/null ark1isdone
  2097. MISSING=""
  2098. for I in 1 2 3 ; do
  2099.     if test ! -f ark${I}isdone ; then
  2100.     MISSING="${MISSING} ${I}"
  2101.     fi
  2102. done
  2103. if test "${MISSING}" = "" ; then
  2104.     echo You have unpacked all 3 archives.
  2105.     rm -f ark[1-9]isdone
  2106. else
  2107.     echo You still must unpack the following archives:
  2108.     echo "        " ${MISSING}
  2109. fi
  2110. exit 0
  2111. exit 0 # Just in case...
  2112.