home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / alt / sources / 3064 < prev    next >
Encoding:
Internet Message Format  |  1993-01-23  |  49.9 KB

  1. Path: sparky!uunet!cs.utexas.edu!uwm.edu!rutgers!modus!lpds!wcp
  2. From: wcp@lpds.sublink.org (Walter C. Pelissero)
  3. Newsgroups: alt.sources
  4. Subject: mgetty - A modular getty v1.0, Part02/04
  5. Message-ID: <1993Jan22.162016.852@lpds.sublink.org>
  6. Date: 22 Jan 93 16:20:16 GMT
  7. Organization: Sweet home under white clouds
  8. Lines: 1867
  9. Phone: + 39 2 8464117 - 8435411 (work)    8267089 (home)
  10. Postal-Address: Via G. de Ruggiero 87, 20142 Milano - Italia
  11.  
  12. Submitted-by: wcp@lpds
  13. Archive-name: mgetty-1.0/part02
  14.  
  15. ---- Cut Here and feed the following to sh ----
  16. #!/bin/sh
  17. # this is mgetty10.02 (part 2 of mgetty-1.0)
  18. # do not concatenate these parts, unpack them in order with /bin/sh
  19. # file doc/mgetty.8 continued
  20. #
  21. if test ! -r _shar_seq_.tmp; then
  22.     echo 'Please unpack part 1 first!'
  23.     exit 1
  24. fi
  25. (read Scheck
  26.  if test "$Scheck" != 2; then
  27.     echo Please unpack part "$Scheck" next!
  28.     exit 1
  29.  else
  30.     exit 0
  31.  fi
  32. ) < _shar_seq_.tmp || exit 1
  33. if test ! -f _shar_wnt_.tmp; then
  34.     echo 'x - still skipping doc/mgetty.8'
  35. else
  36. echo 'x - continuing file doc/mgetty.8'
  37. sed 's/^X//' << 'SHAR_EOF' >> 'doc/mgetty.8' &&
  38. Xto DCE.
  39. X.TP
  40. Xrecord
  41. XThis is the \fIplay\fP counterpart. It is able to receive (and record
  42. Xto a file) voice from DCE.
  43. X.TP
  44. Xc2rec
  45. XThis is the Class 2 receiver, currently designed around ZyXEL U-1496.
  46. X.PP
  47. XAdd of new programs to this list is very simple; invoked programs will
  48. Xhave their stdin, stdout, and stderr properly redirected.
  49. X.SH FILES
  50. X.TP 2.3i
  51. X/usr/local/lib/mgetty
  52. XMgetty library area
  53. X.TP
  54. XLIBDIR/sound
  55. XDirectory of vocal messages to be used in TCL scripts.
  56. X.TP
  57. XLIBDIR/ttys 
  58. XDirectory of tty interface scripts.
  59. X.SH BUGS
  60. XThe \fIstty\fP command is not yet implemented.
  61. X.PP
  62. X/usr/lib/uucp/* files are never used so some difference may be
  63. Xnoticed. Examples: lock files are always created also if tty is not a
  64. Xdialout line; uucp dialers are never used to reset modem, all the
  65. Xnecessary steps should be done inside mgetty script.
  66. X.PP
  67. XHDB cu and uucico don't like mgetty; an ungetty (a true ungetty) call
  68. Xis needed before and after dialout on lines monitored by mgetty.
  69. X.SH AUTHOR
  70. XWalter Pelissero <wally@lpds.sublink.org>
  71. X.SH "SEE ALSO"
  72. Xc2rec(8), play(8), record(8)
  73. SHAR_EOF
  74. echo 'File doc/mgetty.8 is complete' &&
  75. true || echo 'restore of doc/mgetty.8 failed'
  76. rm -f _shar_wnt_.tmp
  77. fi
  78. # ============= doc/play.8 ==============
  79. if test -f 'doc/play.8' -a X"$1" != X"-c"; then
  80.     echo 'x - skipping doc/play.8 (File already exists)'
  81.     rm -f _shar_wnt_.tmp
  82. else
  83. > _shar_wnt_.tmp
  84. echo 'x - extracting doc/play.8 (Text)'
  85. sed 's/^X//' << 'SHAR_EOF' > 'doc/play.8' &&
  86. X.\"    -*- Nroff -*-
  87. X.\"
  88. X.\" $Id: play.8,v 1.2 1993/01/21 19:45:21 wcp Exp $
  89. X.\"
  90. X.\" Copyright (C) 1992    Walter Pelissero
  91. X.\"
  92. X.\" This program is free software; you can redistribute it and/or modify
  93. X.\" it under the terms of the GNU General Public License as published by
  94. X.\" the Free Software Foundation; either version 2 of the License, or
  95. X.\" (at your option) any later version.
  96. X.\"
  97. X.\" This program is distributed in the hope that it will be useful,
  98. X.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
  99. X.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  100. X.\" GNU General Public License for more details.
  101. X.\"
  102. X.\" You should have received a copy of the GNU General Public License
  103. X.\" along with this program; if not, write to the Free Software
  104. X.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  105. X.\"
  106. X.\"
  107. X.\" $Log: play.8,v $
  108. X.\" Revision 1.2  1993/01/21  19:45:21  wcp
  109. X.\" Changed .I in \fI/\fP.
  110. X.\"
  111. X.\" Revision 1.1  1993/01/13  21:40:54  wcp
  112. X.\" Initial revision
  113. X.\"
  114. X.\"
  115. X.de XX
  116. X.ds XX \\$4\ (v\\$3)
  117. X..
  118. X.XX $Id: play.8,v 1.2 1993/01/21 19:45:21 wcp Exp $
  119. X.TH PLAY 8 \*(XX
  120. X.AT 3
  121. X.SH NAME
  122. Xplay \- voice player for ZyXEL U-1496
  123. X.SH SYNOPSIS
  124. X.B play
  125. X.RI [ -x\ debug_level ]
  126. X.RI [ -s\ speaker ]
  127. X.RI [ -c\ device ]
  128. X.RI [ -v\ volume ]
  129. X.RI [ -e\ encoding ]
  130. X.RI [ voice_file ]
  131. X.SH DESCRIPTION
  132. X\fIPlay\fP is a sound player front end for \fImgetty\fP.  \fIRecord\fP
  133. Xcan work in two ways, on a successfully established connection, or in
  134. Xa batched way, to listen to already saved messages. If no file name is
  135. Xspecified on command line, \fIplay\fP take sound data from stdin.
  136. X.SH OPTIONS
  137. X.IP "-x \fIlevel\fP"
  138. XTell the verbosity of debug informations displayed during processing.
  139. X.IP "-s \fIspeaker\fP"
  140. XSpecify which speaker to play with: 0 = telco line, 1 = microphone, 2
  141. X= internal speaker. Default is internal speaker if \fI-c\fP is
  142. Xspecified, telco line instead. This option must be specified after the
  143. X\fI-c\fP option, if present.
  144. X.IP "-c \fIdevice\fP"
  145. XWhich device to connect to. If this option is not specified \fIplay\fP
  146. Xexpects to be already connected to a device and to have stdin/stdout
  147. Xalready redirected.
  148. X.IP "-v \fIvolume\fP"
  149. XPlayback volume in range from 0 to 7.
  150. X.IP "-e \fIencoding\fP"
  151. XSpecify encoding algorithm for data to be played: 1 = CELP, 2 = ADPCM
  152. Xwith two bits, 3 = ADPCM with three bits.
  153. X.SH BUGS
  154. XThe volume option is useless.
  155. X.PP
  156. XCurrently supported modems are ZyXEL U-1496 only.
  157. X.SH AUTHOR
  158. XWalter Pelissero <wally@lpds.sublink.org>
  159. X.SH "SEE ALSO"
  160. Xmgetty(8), record(8)
  161. SHAR_EOF
  162. true || echo 'restore of doc/play.8 failed'
  163. rm -f _shar_wnt_.tmp
  164. fi
  165. # ============= doc/record.8 ==============
  166. if test -f 'doc/record.8' -a X"$1" != X"-c"; then
  167.     echo 'x - skipping doc/record.8 (File already exists)'
  168.     rm -f _shar_wnt_.tmp
  169. else
  170. > _shar_wnt_.tmp
  171. echo 'x - extracting doc/record.8 (Text)'
  172. sed 's/^X//' << 'SHAR_EOF' > 'doc/record.8' &&
  173. X.\"    -*- Nroff -*-
  174. X.\"
  175. X.\" $Id: record.8,v 1.2 1993/01/21 19:45:21 wcp Exp $
  176. X.\"
  177. X.\" Copyright (C) 1992    Walter Pelissero
  178. X.\"
  179. X.\" This program is free software; you can redistribute it and/or modify
  180. X.\" it under the terms of the GNU General Public License as published by
  181. X.\" the Free Software Foundation; either version 2 of the License, or
  182. X.\" (at your option) any later version.
  183. X.\"
  184. X.\" This program is distributed in the hope that it will be useful,
  185. X.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
  186. X.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  187. X.\" GNU General Public License for more details.
  188. X.\"
  189. X.\" You should have received a copy of the GNU General Public License
  190. X.\" along with this program; if not, write to the Free Software
  191. X.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  192. X.\"
  193. X.\"
  194. X.\" $Log: record.8,v $
  195. X.\" Revision 1.2  1993/01/21  19:45:21  wcp
  196. X.\" Changed .I in \fI/\fP.
  197. X.\"
  198. X.\" Revision 1.1  1993/01/13  21:40:54  wcp
  199. X.\" Initial revision
  200. X.\"
  201. X.\"
  202. X.de XX
  203. X.ds XX \\$4\ (v\\$3)
  204. X..
  205. X.XX $Id: record.8,v 1.2 1993/01/21 19:45:21 wcp Exp $
  206. X.TH RECORD 8 \*(XX
  207. X.AT 3
  208. X.SH NAME
  209. Xrecord \- voice recorder for ZyXEL U-1496
  210. X.SH SYNOPSIS
  211. X.B record
  212. X.RI [ -x\ debug_level ]
  213. X.RI [ -f ]
  214. X.RI [ -d ]
  215. X.RI [ -m\ microphone ]
  216. X.RI [ -c\ device ]
  217. X.RI [ -t\ min_time [ :max_time ]]
  218. X.RI [ -e\ encoding ]
  219. X.RI [ file_or_directory ]
  220. X.SH DESCRIPTION
  221. X\fIRecord\fP is a sound recorder front end for \fImgetty\fP.
  222. X\fIRecord\fP can work in two ways, on a successfully established
  223. Xconnection, or in a batched way, to record greeting messages, etc. If
  224. Xno file name is specified on command line, \fIrecord\fP write sound
  225. Xdata to stdout. If a directory is specified instead of a file,
  226. X\fIrecord\fP creates a file in it with this name template: inXXXXXXXX.
  227. XWhere XXXXXXXXX stands for a message sequence number. The program
  228. Xadjust message sequence number to avoid overwriting of existing
  229. Xmessages.
  230. X.SH OPTIONS
  231. X.IP "-x \fIlevel\fP"
  232. XTell the verbosity of debug informations displayed during processing.
  233. X.IP "-m \fImicrophone\fP"
  234. XSpecify which microphone to record from: 0 = telco line, 1 =
  235. Xmicrophone, 2 = internal speaker. Default is microphone if \fI-c\fP is
  236. Xspecified, telco line instead. This option must be specified after the
  237. X\fI-c\fP option, if present.
  238. X.IP -f
  239. XDisable T.30 fax tone detection.
  240. X.IP -d
  241. XEnable DTMF digits detection.
  242. X.IP "-c \fIdevice\fP"
  243. XWhich device to connect to. If this option is not specified \fIplay\fP
  244. Xexpect to already connected and to have stdin/stdout already properly
  245. Xredirected.
  246. X.IP "-t \fImin_time\fP[\fI:max_time\fP]"
  247. XMinimum and (optionally) maximum recording time. If a message is
  248. Xrecorded with a length less than minimum, line garbage is assumed and
  249. Xno message is saved (output file, if any, is discarded). If message
  250. Xexceeds the maximum, it is truncated. Default values are respectively
  251. X10 senconds and 5 minutes.
  252. X.IP "-e \fIencoding\fP"
  253. XSpecify encoding algorithm for data to be recorded: 1 = CELP, 2 = ADPCM
  254. Xwith two bits, 3 = ADPCM with three bits.
  255. X.SH DIAGNOSTICS
  256. XOn exit it returns a code specifing the reason of exiting:
  257. X.IP 0
  258. XMessage recorded succesfully.
  259. X.IP 1
  260. XGot silence or message too short. No message is recorded. This may
  261. Xmean that a DCE is waiting on the other end of line.
  262. X.IP 2
  263. XHeard a T.30 fax tone. No message is recorded. A fax machine is
  264. Xwaiting to send.
  265. X.IP "10 through 19"
  266. XReceived DTMF digit. Real value is incremented by 10.
  267. X.SH BUGS
  268. XDTMF support is still untested.
  269. X.PP
  270. XCurrently supported modems are ZyXEL U-1496 only.
  271. X.SH AUTHOR
  272. XWalter Pelissero <wally@lpds.sublink.org>
  273. X.SH "SEE ALSO"
  274. Xmgetty(8), play(8)
  275. SHAR_EOF
  276. true || echo 'restore of doc/record.8 failed'
  277. rm -f _shar_wnt_.tmp
  278. fi
  279. # ============= listen.sh ==============
  280. if test -f 'listen.sh' -a X"$1" != X"-c"; then
  281.     echo 'x - skipping listen.sh (File already exists)'
  282.     rm -f _shar_wnt_.tmp
  283. else
  284. > _shar_wnt_.tmp
  285. echo 'x - extracting listen.sh (Text)'
  286. sed 's/^X//' << 'SHAR_EOF' > 'listen.sh' &&
  287. X: use /bin/sh
  288. X#
  289. X# @(#)$Id: listen.sh,v 1.2 1993/01/22 15:14:24 wcp Exp $
  290. X#
  291. X# Copyright (C) 1993    Walter Pelissero
  292. X#
  293. X# This program is free software; you can redistribute it and/or modify
  294. X# it under the terms of the GNU General Public License as published by
  295. X# the Free Software Foundation; either version 2 of the License, or
  296. X# (at your option) any later version.
  297. X#
  298. X# This program is distributed in the hope that it will be useful,
  299. X# but WITHOUT ANY WARRANTY; without even the implied warranty of
  300. X# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  301. X# GNU General Public License for more details.
  302. X#
  303. X# You should have received a copy of the GNU General Public License
  304. X# along with this program; if not, write to the Free Software
  305. X# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  306. X#
  307. X
  308. X#
  309. X# $Log: listen.sh,v $
  310. X# Revision 1.2  1993/01/22  15:14:24  wcp
  311. X# Removed magic string.
  312. X#
  313. X# Revision 1.1  1993/01/07  23:16:09  wcp
  314. X# Initial revision
  315. X#
  316. X#
  317. X
  318. XLIBDIR=%LIB_DIR%
  319. XPLAY="$LIBDIR/play"
  320. X
  321. Xflags=
  322. Xfor a in $*
  323. Xdo
  324. X    case $a in
  325. X    -*)    flags="$flags $a"
  326. X        shift; #=`eval $# - 1`
  327. X        ;;
  328. X    *)    break
  329. X        ;;
  330. X    esac
  331. Xdone
  332. X
  333. Xplay () {
  334. X    encoding=`sed -n '1,/^DATA:/s/^ENCODING:[ \t]*\(.*\)/\1/p' $1`
  335. X    [ "$encoding" ] || encoding=2
  336. X    tail +`awk '/^DATA:$/ { print NR + 1; exit }' $1` $1 | $PLAY $flags -s $encoding
  337. X}
  338. X
  339. X[ $# -lt 1 ] && set -- /usr/spool/voice/*
  340. X
  341. Xfor f in $*
  342. Xdo
  343. X    if [ -d $f ]
  344. X    then
  345. X        for ff in $f/*
  346. X        do
  347. X            play $ff
  348. X        done
  349. X    else
  350. X        play $f
  351. X    fi
  352. Xdone
  353. SHAR_EOF
  354. true || echo 'restore of listen.sh failed'
  355. rm -f _shar_wnt_.tmp
  356. fi
  357. # ============= localize.c ==============
  358. if test -f 'localize.c' -a X"$1" != X"-c"; then
  359.     echo 'x - skipping localize.c (File already exists)'
  360.     rm -f _shar_wnt_.tmp
  361. else
  362. > _shar_wnt_.tmp
  363. echo 'x - extracting localize.c (Text)'
  364. sed 's/^X//' << 'SHAR_EOF' > 'localize.c' &&
  365. X/*
  366. X * $Id: localize.c,v 1.1 1993/01/06 18:02:00 wcp Exp $
  367. X *
  368. X * Copyright (C) 1992    Walter Pelissero
  369. X *
  370. X * This program is free software; you can redistribute it and/or modify
  371. X * it under the terms of the GNU General Public License as published by
  372. X * the Free Software Foundation; either version 1, or (at your option)
  373. X * any later version.
  374. X *
  375. X * This program is distributed in the hope that it will be useful,
  376. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  377. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  378. X * GNU General Public License for more details.
  379. X *
  380. X * You should have received a copy of the GNU General Public License
  381. X * along with this program; if not, write to the Free Software
  382. X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  383. X */
  384. X
  385. X/*
  386. X * $Log: localize.c,v $
  387. X * Revision 1.1  1993/01/06  18:02:00  wcp
  388. X * Initial revision
  389. X *
  390. X */
  391. X
  392. Xextern int printf(const char *, ...);
  393. Xextern volatile void exit(int);
  394. X
  395. Xint main()
  396. X{
  397. X  printf("s#%%LIB_DIR%%#%s#\n", LIB_DIR);
  398. X  printf("s#%%BIN_DIR%%#%s#\n", BIN_DIR);
  399. X  printf("s#%%PBMPLUS%%#%s#\n", PBMPLUS);
  400. X  return exit(0), 0;
  401. X}
  402. SHAR_EOF
  403. true || echo 'restore of localize.c failed'
  404. rm -f _shar_wnt_.tmp
  405. fi
  406. # ============= locks.c ==============
  407. if test -f 'locks.c' -a X"$1" != X"-c"; then
  408.     echo 'x - skipping locks.c (File already exists)'
  409.     rm -f _shar_wnt_.tmp
  410. else
  411. > _shar_wnt_.tmp
  412. echo 'x - extracting locks.c (Text)'
  413. sed 's/^X//' << 'SHAR_EOF' > 'locks.c' &&
  414. X/*
  415. X * $Id: locks.c,v 1.2 1993/01/06 18:06:04 wcp Exp $
  416. X *
  417. X * Copyright (C) 1992    Walter Pelissero
  418. X *
  419. X * This program is free software; you can redistribute it and/or modify
  420. X * it under the terms of the GNU General Public License as published by
  421. X * the Free Software Foundation; either version 1, or (at your option)
  422. X * any later version.
  423. X *
  424. X * This program is distributed in the hope that it will be useful,
  425. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  426. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  427. X * GNU General Public License for more details.
  428. X *
  429. X * You should have received a copy of the GNU General Public License
  430. X * along with this program; if not, write to the Free Software
  431. X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  432. X */
  433. X
  434. X/*
  435. X * $Log: locks.c,v $
  436. X * Revision 1.2  1993/01/06  18:06:04  wcp
  437. X * Modified unlockLine() to be able to remove someone else locks.
  438. X * Added ilLocked().
  439. X *
  440. X * Revision 1.1  1992/08/28  22:44:05  wally
  441. X * Initial revision
  442. X *
  443. X */
  444. X
  445. X#include <sys/types.h>
  446. X#ifdef DEBUG
  447. X#include <dbmalloc.h>
  448. X#endif
  449. X#include <stdio.h>
  450. X#include <string.h>
  451. X#include <fcntl.h>
  452. X#include <stdlib.h>
  453. X#include <errno.h>
  454. X#include "common.h"
  455. X
  456. Xstatic char RcsId[] = "$Id: locks.c,v 1.2 1993/01/06 18:06:04 wcp Exp $";
  457. X
  458. Xbool unlockLine(const char *line)
  459. X{
  460. X  char *tty;
  461. X  char *pathname = malloc(strlen(LOCK_DIR) + strlen(line) + 7);
  462. X  int fd;
  463. X  bool ret = FAILED;
  464. X
  465. X  tty = strdup(basename(line));
  466. X  strlower(tty);
  467. X  sprintf(pathname, "%s/LCK..%s", LOCK_DIR, tty);
  468. X  free(tty);
  469. X  fd = open(pathname, O_RDONLY);
  470. X  if (fd >= 0)
  471. X    {
  472. X      char buf[32];
  473. X      int nread;
  474. X      int pid;
  475. X
  476. X      if ((nread = read(fd, buf, sizeof(buf))) > 0)
  477. X    {
  478. X#if defined(M_XENIX)
  479. X      buf[nread - 1] = '\0';
  480. X      pid = atoi(buf);
  481. X#else
  482. X#endif
  483. X    }
  484. X      else
  485. X    pid = getpid();
  486. X      close(fd);
  487. X      if (pid == getpid() || kill(pid, 0) < 0)
  488. X    {
  489. X      unlink(pathname);
  490. X      ret = SUCCEEDED;
  491. X    }
  492. X      else
  493. X    ret = FAILED;
  494. X    }
  495. X  else
  496. X    ret = (errno == ENOENT);
  497. X  free(pathname);
  498. X  return ret;
  499. X}
  500. X
  501. Xbool lockLine(const char *line, int time)
  502. X{
  503. X  char *pathname1 = makeTemp(LOCK_DIR), *pathname2, *tty;
  504. X  int fd = open(pathname1, O_WRONLY | O_CREAT, 0644), ret = TRUE;
  505. X
  506. X  if (fd < 0)
  507. X    return FALSE;
  508. X  else
  509. X    {
  510. X      char buf[32];
  511. X
  512. X#if defined(M_XENIX)
  513. X      sprintf(buf, "%10u\n", getpid());
  514. X      write(fd, buf, strlen(buf));
  515. X#else
  516. X# error unsupported UUCP locking system
  517. X#endif
  518. X      close(fd);
  519. X    }
  520. X  tty = strdup(basename(line));
  521. X  strlower(tty);
  522. X  pathname2 = malloc(strlen(LOCK_DIR) + strlen(tty) + 7);
  523. X  sprintf(pathname2, "%s/LCK..%s", LOCK_DIR, tty);
  524. X  free(tty);
  525. X  while (link(pathname1, pathname2) < 0)
  526. X    {
  527. X      if (!unlockLine(line))
  528. X    {
  529. X      sleep(10);
  530. X      if ((time -= 10) <= 0)
  531. X        {
  532. X          ret = FALSE;
  533. X          break;
  534. X        }
  535. X    }
  536. X    }
  537. X  unlink(pathname1);
  538. X  free(pathname1);
  539. X  free(pathname2);
  540. X  return ret;
  541. X}
  542. X
  543. Xbool isLocked(const char *line)
  544. X{
  545. X  char pathname[strlen(LOCK_DIR) + strlen(line) + 7];
  546. X  int fd;
  547. X  bool ret = FALSE;
  548. X
  549. X  sprintf(pathname, "%s/LCK..%s", LOCK_DIR, line);
  550. X  if ((fd = open(pathname, O_RDONLY)) >= 0)
  551. X    {
  552. X      int nread;
  553. X      char buf[30];
  554. X
  555. X      if ((nread = read(fd, buf, sizeof(buf))) > 0)
  556. X    {
  557. X      int pid;
  558. X
  559. X#if defined(M_XENIX)
  560. X      buf[nread - 1] = '\0';
  561. X      pid = atoi(buf);
  562. X#else
  563. X#endif
  564. X      if (kill(pid, 0) == 0)
  565. X        ret = TRUE;
  566. X    }
  567. X    }
  568. X  return ret;
  569. X}
  570. SHAR_EOF
  571. true || echo 'restore of locks.c failed'
  572. rm -f _shar_wnt_.tmp
  573. fi
  574. # ============= mgetty.c ==============
  575. if test -f 'mgetty.c' -a X"$1" != X"-c"; then
  576.     echo 'x - skipping mgetty.c (File already exists)'
  577.     rm -f _shar_wnt_.tmp
  578. else
  579. > _shar_wnt_.tmp
  580. echo 'x - extracting mgetty.c (Text)'
  581. sed 's/^X//' << 'SHAR_EOF' > 'mgetty.c' &&
  582. X/*
  583. X * $Id: mgetty.c,v 1.4 1993/01/15 23:06:14 wcp Exp $
  584. X *
  585. X * Copyright (C) 1992    Walter Pelissero
  586. X *
  587. X * This program is free software; you can redistribute it and/or modify
  588. X * it under the terms of the GNU General Public License as published by
  589. X * the Free Software Foundation; either version 1, or (at your option)
  590. X * any later version.
  591. X *
  592. X * This program is distributed in the hope that it will be useful,
  593. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  594. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  595. X * GNU General Public License for more details.
  596. X *
  597. X * You should have received a copy of the GNU General Public License
  598. X * along with this program; if not, write to the Free Software
  599. X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  600. X */
  601. X
  602. X/*
  603. X * $Log: mgetty.c,v $
  604. X * Revision 1.4  1993/01/15  23:06:14  wcp
  605. X * Modified CMD_receive to accept multiple tokens instead of a list.
  606. X *
  607. X * Revision 1.3  1993/01/13  21:28:37  wcp
  608. X * spawn() is substituted by invoke().
  609. X * Added CMD_slow_write(), to leave this choice at run time.
  610. X * Reenabled the old exec.
  611. X *
  612. X * Revision 1.2  1993/01/07  23:17:13  wcp
  613. X * Modified open() flags to tty for compatibility with tset.
  614. X *
  615. X * Revision 1.1  1993/01/06  18:07:40  wcp
  616. X * Initial revision
  617. X *
  618. X */
  619. X
  620. X#include <sys/types.h>
  621. X#ifdef DEBUG
  622. X#include <dbmalloc.h>
  623. X#endif
  624. X#include <stdio.h>
  625. X#include <fcntl.h>
  626. X#include <termio.h>
  627. X#include <getopt.h>
  628. X#include <string.h>
  629. X#include <ctype.h>
  630. X#include <errno.h>
  631. X#include <signal.h>
  632. X#include <utmp.h>
  633. X#include <stdlib.h>
  634. X#include <tcl.h>
  635. X#include <sys/wait.h>
  636. X#include "common.h"
  637. X#include "modemio.h"
  638. X
  639. Xconst unsigned long DEFAULT_BAUDRATE = 9600;
  640. X
  641. Xtypedef enum {
  642. X  MD_RAW = 1,
  643. X  MD_COOKED = 2,
  644. X  MD_XONXOFF = 4,
  645. X  MD_CTSRTS = 8,
  646. X  MD_NOFLOW = 16,
  647. X  MD_LOCAL = 32,
  648. X  MD_REMOTE = 64
  649. X  } TtyMode;
  650. X
  651. Xtypedef enum { UTMP_GETTY, UTMP_LOGIN, UTMP_EXIT, UTMP_PROCESS } UtmpStatus;
  652. X
  653. X#ifdef DEBUG
  654. Xstatic int verbosity = 9;
  655. X#else
  656. Xstatic int verbosity = 0;
  657. X#endif
  658. X
  659. Xconst char *myname;
  660. X
  661. Xstatic char RcsId[] = "$Id: mgetty.c,v 1.4 1993/01/15 23:06:14 wcp Exp $";
  662. Xstatic bool suspended = FALSE;
  663. Xstatic unsigned long baudrate;
  664. Xstatic const char *line, *site;
  665. Xstatic bool timedout;
  666. Xstatic Tcl_Interp *interp;
  667. Xstatic bool set_utmp(UtmpStatus, const char *, int);
  668. X
  669. X
  670. Xinline bool setUtmp(UtmpStatus status, const char *line)
  671. X{
  672. X  return set_utmp(status, line, getpid());
  673. X}
  674. X
  675. Xstatic bool closeLine()
  676. X{
  677. X  close(0);
  678. X  close(1);
  679. X  close(2);
  680. X  return TRUE;
  681. X}
  682. X
  683. Xstatic SIGTYPE suspend(int sig)
  684. X{
  685. X  if (!suspended)
  686. X    {
  687. X      suspended = TRUE;
  688. X      signal(sig, suspend);
  689. X      setUtmp(UTMP_PROCESS, line);
  690. X      closeLine();
  691. X      while(suspended)
  692. X    sleep(1024);
  693. X    }
  694. X#if SIGTYPE == int
  695. X  return 0;
  696. X#endif
  697. X}
  698. X
  699. Xstatic SIGTYPE restart(int sig)
  700. X{
  701. X  suspended = FALSE;
  702. X  signal(sig, restart);
  703. X  setUtmp(UTMP_LOGIN, line);
  704. X#if SIGTYPE == int
  705. X  return 0;
  706. X#endif
  707. X}
  708. X
  709. Xstatic bool setMode(int mode)
  710. X{
  711. X  struct termio    tty_settings;
  712. X
  713. X  if (ioctl(1, TCGETA, &tty_settings) < 0)
  714. X    {
  715. X      fprintf(stderr, "%s: can't ioctl\n", myname);
  716. X      return FAILED;
  717. X    }
  718. X  if (mode & MD_RAW)
  719. X    {
  720. X      if (verbosity > 8)
  721. X    fprintf(stderr, "%s: setting MD_RAW\n", myname);
  722. X      tty_settings.c_iflag &= ~(BRKINT | ICRNL | ISTRIP);
  723. X      tty_settings.c_cflag &= ~PARENB;
  724. X      tty_settings.c_cflag |= (HUPCL | CSIZE | CS8 | CREAD);
  725. X      tty_settings.c_lflag &= ~(ISIG | ECHO | ICANON);
  726. X      tty_settings.c_cc[VMIN] = 1;
  727. X      tty_settings.c_cc[VTIME] = 0;
  728. X      tty_settings.c_oflag &= ~OPOST;
  729. X    }
  730. X  if (mode & MD_COOKED)
  731. X    {
  732. X      if (verbosity > 8)
  733. X    fprintf(stderr, "%s: setting MD_COOKED\n", myname);
  734. X      tty_settings.c_lflag |= ICANON | ECHO | ISIG | ECHOE | ECHOK;
  735. X      tty_settings.c_iflag |= ICRNL | BRKINT | IGNPAR;
  736. X      tty_settings.c_oflag |= ONLCR | OPOST | TAB3;
  737. X      tty_settings.c_cc[VMIN] = 4;
  738. X      tty_settings.c_cc[VTIME] = 0;
  739. X    }
  740. X  if (mode & MD_XONXOFF)
  741. X    {
  742. X      if (verbosity > 8)
  743. X    fprintf(stderr, "%s: setting MD_XONXOFF\n", myname);
  744. X      tty_settings.c_iflag |= IXON | IXANY;
  745. X    }
  746. X  if (mode & MD_CTSRTS)
  747. X    {
  748. X      if (verbosity > 8)
  749. X    fprintf(stderr, "%s: setting MD_CTSRTS\n", myname);
  750. X      tty_settings.c_cflag |= CTSFLOW | RTSFLOW;
  751. X    }
  752. X  if (mode & MD_NOFLOW)
  753. X    {
  754. X      if (verbosity > 8)
  755. X    fprintf(stderr, "%s: setting MD_NOFLOW\n", myname);
  756. X      tty_settings.c_cflag &= ~(CTSFLOW | RTSFLOW);
  757. X      tty_settings.c_iflag &= ~(IXON | IXANY);
  758. X    }
  759. X  if (mode & MD_LOCAL)
  760. X    {
  761. X      if (verbosity > 8)
  762. X    fprintf(stderr, "%s: setting MD_LOCAL\n", myname);
  763. X      tty_settings.c_cflag |= CLOCAL;
  764. X    }
  765. X  if (mode & MD_REMOTE)
  766. X    {
  767. X      if (verbosity > 8)
  768. X    fprintf(stderr, "%s: setting MD_REMOTE\n", myname);
  769. X      tty_settings.c_cflag &= ~CLOCAL;
  770. X    }
  771. X  if (ioctl(1, TCSETAF, &tty_settings) < 0)
  772. X    {
  773. X      fprintf(stderr, "%s: can't set baud\n", myname);
  774. X      return FAILED;
  775. X    }
  776. X  return SUCCEEDED;
  777. X}
  778. X
  779. Xstatic bool setBaudRate(unsigned speed)
  780. X{
  781. X  struct termio tty_settings;
  782. X  int baud = B38400;
  783. X
  784. X  baudrate = speed;
  785. X  if (verbosity > 5)
  786. X    fprintf(stderr, "%s: setting baud rate to about %u\n", myname, speed);
  787. X  if (ioctl(1, TCGETA, &tty_settings) < 0)
  788. X    return FAILED;
  789. X  if (speed <= 19200)    baud = B19200;
  790. X  if (speed <= 9600)    baud = B9600;
  791. X  if (speed <= 4800)    baud = B4800;
  792. X  if (speed <= 2400)    baud = B2400;
  793. X  if (speed <= 1800)    baud = B1800;
  794. X  if (speed <= 1200)    baud = B1200;
  795. X  if (speed <= 600)    baud = B600;
  796. X  if (speed <= 300)    baud = B300;
  797. X  if (speed <= 200)    baud = B200;
  798. X  if (speed <= 150)    baud = B150;
  799. X  if (speed <= 134)    baud = B134;
  800. X  if (speed <= 110)    baud = B110;
  801. X  if (speed <= 75)    baud = B75;
  802. X  if (speed <= 50)    baud = B50;
  803. X  tty_settings.c_cflag &= ~CBAUD;
  804. X  tty_settings.c_cflag |= baud;
  805. X  if (ioctl(1, TCSETA, &tty_settings) < 0)
  806. X    return FAILED;
  807. X  return SUCCEEDED;
  808. X}
  809. X
  810. Xstatic bool openLine(const char *portname)
  811. X{
  812. X  /* If spawned from init stdin/stdout/stderr may (should?) point
  813. X     to unopened file descriptors. */
  814. X  close(0); close(1);
  815. X#ifndef DEBUG
  816. X  close(2);
  817. X#endif
  818. X  setpgrp();
  819. X  errno = 0;
  820. X  chdir("/dev");
  821. X  /* The following two open()s should have O_RDONLY and O_WRONLY
  822. X     respectively but tset (and other programs?) cannot work properly
  823. X     if we do so. */
  824. X  if (open(portname, (O_RDWR | O_NDELAY)) < 0 ||
  825. X      open(portname, (O_RDWR | O_NDELAY)) < 0)
  826. X    {
  827. X      if (errno == EBUSY)
  828. X    fprintf(stderr, "%s: port %s BUSY\n", myname, portname);
  829. X      else
  830. X    fprintf(stderr, "%s: can't connect into %s (%s)\n", myname,
  831. X        portname, sys_errlist[errno]);
  832. X      return FAILED;
  833. X    }
  834. X  setMode(MD_RAW | MD_NOFLOW | MD_LOCAL);
  835. X  setBaudRate(DEFAULT_BAUDRATE);
  836. X  if (fcntl(0, F_SETFL, O_RDONLY) == ERROR ||
  837. X      fcntl(1, F_SETFL, O_WRONLY) == ERROR)
  838. X    {
  839. X      fprintf(stderr, "%s: can't unset O_NDELAY for %s\n", myname, portname);
  840. X      return FAILED;
  841. X    }
  842. X#ifndef DEBUG
  843. X  dup(1);
  844. X#endif
  845. X  if (verbosity > 5)
  846. X    fprintf(stderr, "%s: line parameters set for %s\n", myname, portname);
  847. X  return SUCCEEDED;
  848. X}
  849. X
  850. Xstatic bool set_utmp(UtmpStatus status, const char *line, int pid)
  851. X{
  852. X  int ufd;
  853. X  bool ret = FAILED;
  854. X  const char *id;
  855. X  struct utmp ut;
  856. X
  857. X  id = line + strlen(line) - 2;
  858. X  if((ufd = open(UTMP_FILE, O_RDWR | O_CREAT, 0644)) < 0)
  859. X    return FAILED;
  860. X  while(read(ufd, (char *)&ut, sizeof(ut)) == sizeof(ut))
  861. X    {
  862. X      char buf[sizeof(ut.ut_line) + 1];
  863. X
  864. X      strncpy(buf, ut.ut_line, sizeof(ut.ut_line));
  865. X      buf[sizeof(buf) - 1] = 0;
  866. X      if((!strcmp(buf, line) || ut.ut_type == INIT_PROCESS)
  867. X     && pid == ut.ut_pid)
  868. X    {
  869. X      strncpy(ut.ut_line, line, sizeof(ut.ut_line));
  870. X      strncpy(ut.ut_id, id, sizeof(ut.ut_id));
  871. X      ut.ut_time = time(0);
  872. X      switch (status)
  873. X        {
  874. X        case UTMP_GETTY:
  875. X          strcpy(ut.ut_name, "LOGIN");
  876. X          ut.ut_type = LOGIN_PROCESS;
  877. X          break;
  878. X        case UTMP_LOGIN:
  879. X          strcpy(ut.ut_name, "LOGIN2");
  880. X          ut.ut_type = LOGIN_PROCESS;
  881. X          break;
  882. X        case UTMP_PROCESS:
  883. X          strncpy(ut.ut_name, "DIALOUT", sizeof(ut.ut_name));
  884. X          ut.ut_type = USER_PROCESS;
  885. X          break;
  886. X        case UTMP_EXIT:
  887. X          strncpy(ut.ut_name, "LOGIN", sizeof(ut.ut_name));
  888. X          ut.ut_type = DEAD_PROCESS;
  889. X          break;
  890. X        }
  891. X      lseek(ufd, -sizeof(ut), 1);
  892. X      write(ufd, (char *)&ut, sizeof(ut));
  893. X      ret = SUCCEEDED;
  894. X      if (verbosity > 8)
  895. X        fprintf(stderr, "%s: utmp file set\n", myname);
  896. X      break;
  897. X    }
  898. X    }
  899. X  close(ufd);
  900. X  return ret;
  901. X}
  902. X
  903. Xstatic SIGTYPE terminate(int sig)
  904. X{
  905. X  mdhangup(1);
  906. X  closeLine();
  907. X  setUtmp(UTMP_EXIT, line);
  908. X  exit(0);
  909. X#if SIGTYPE == int
  910. X  return 0;
  911. X#endif
  912. X}
  913. X
  914. Xstatic char *getLoginName()
  915. X{
  916. X  static char buf[80];
  917. X  int len;
  918. X
  919. X  timedout = FALSE;
  920. X  alarm(180);
  921. X  if ((len = read(0, buf, sizeof(buf))) > 0)
  922. X    {
  923. X      buf[len - 1] = 0;
  924. X      mdwrite("\r", 1);
  925. X    }
  926. X  alarm(0);
  927. X  if (timedout || len < 1)
  928. X    {
  929. X      mdhangup(1);
  930. X      return 0;
  931. X    }
  932. X  return buf;
  933. X}
  934. X
  935. Xstatic void spawnGetty(char **getty_args)
  936. X{
  937. X  struct termio tty_settings;
  938. X  char getty[strlen(getty_args[0] + 1)];
  939. X  
  940. X  if (ioctl(1, TCGETA, &tty_settings) < 0)
  941. X    return;
  942. X  /* Here we have to reset HUPCL because getty tries to hang up
  943. X     before continuing on its job.
  944. X     Resetting CLOCAL is necessary because we want getty to be
  945. X     aware of line losing. */
  946. X  tty_settings.c_cflag &= ~(HUPCL | CLOCAL);
  947. X  if (ioctl(1, TCSETAF, &tty_settings) < 0)
  948. X    return;
  949. X  strcpy(getty, getty_args[0]);
  950. X  getty_args[0] = "-";
  951. X  execv(getty, getty_args);
  952. X  return;
  953. X}
  954. X
  955. Xstatic void resetSignals()
  956. X{
  957. X  alarm(0);
  958. X  signal(SIGALRM, SIG_DFL);
  959. X  signal(SIGUSR1, SIG_DFL);
  960. X  signal(SIGUSR2, SIG_DFL);
  961. X  signal(SIGQUIT, SIG_DFL);
  962. X  signal(SIGTERM, SIG_DFL);
  963. X  signal(SIGHUP, SIG_DFL);
  964. X  signal(SIGINT, SIG_DFL);
  965. X}
  966. X
  967. Xstatic void doLogin()
  968. X{
  969. X  char *name;
  970. X  
  971. X  mdread(2, 0, 0, 0);
  972. X  setMode(MD_REMOTE | MD_NOFLOW | MD_COOKED);
  973. X  do
  974. X    {
  975. X      char buf[256];
  976. X      
  977. X      sprintf(buf, "\r\n\n[%u on %s]\r\n%s!login: ", baudrate, line, site);
  978. X      if (write(1, buf, strlen(buf)) < 0)
  979. X    {
  980. X      name = 0;
  981. X      break;
  982. X    }
  983. X    }
  984. X  while (!(name = getLoginName()) || !strlen(name));
  985. X  if (name)
  986. X    {
  987. X      if (verbosity > 4)
  988. X    fprintf(stderr, "%s: executing login\n", myname);
  989. X      setUtmp(UTMP_LOGIN, line);
  990. X      if (!lockLine(line, 30))
  991. X    return;
  992. X#ifdef DEBUG
  993. X      close(2);
  994. X      dup(1);
  995. X#endif
  996. X      setMode(MD_XONXOFF);
  997. X      resetSignals();
  998. X      execlp("/etc/login", "login", name, (char *)0);
  999. X      execlp("/bin/login", "login", name, (char *)0);
  1000. X      {
  1001. X    char buf[128];
  1002. X    
  1003. X    sprintf(buf, "\r\n%s: login not executable.\r\n", myname);
  1004. X    mdwrite(buf, 1);
  1005. X      }
  1006. X    }
  1007. X  sleep(1);
  1008. X}
  1009. X
  1010. Xstatic SIGTYPE timeout(int sig)
  1011. X{
  1012. X  timedout = TRUE;
  1013. X  signal(sig, timeout);
  1014. X#if SIGTYPE == int
  1015. X  return 0;
  1016. X#endif
  1017. X}
  1018. X
  1019. X
  1020. Xstatic int catcher(int sig)
  1021. X{
  1022. X  fprintf(stderr, "GOT SIGNAL %u\n", sig);
  1023. X  signal(sig, catcher);
  1024. X  return 0;
  1025. X}
  1026. X
  1027. Xstatic void catchSignals()
  1028. X{
  1029. X  unsigned i;
  1030. X
  1031. X  for (i = 0; i < NSIG; ++i)    /*  -wp9/20/92. */
  1032. X    if (i != SIGCLD)
  1033. X      signal(i, catcher);
  1034. X  signal(SIGALRM, timeout);
  1035. X  signal(SIGUSR1, suspend);
  1036. X  signal(SIGUSR2, terminate);    /* when restarted we exit to redo all the
  1037. X                   settings we may have already done. */
  1038. X  signal(SIGQUIT, terminate);
  1039. X  signal(SIGTERM, terminate);
  1040. X  signal(SIGHUP, terminate);
  1041. X  signal(SIGINT, terminate);
  1042. X}
  1043. X
  1044. Xstatic int CMD_send(ClientData clientData, Tcl_Interp *interp, int argc,
  1045. X            char *argv[])
  1046. X{
  1047. X  int i;
  1048. X
  1049. X  if (argc < 2)
  1050. X    {
  1051. X      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1052. X               " string ?string ...?\"", 0);
  1053. X      return TCL_ERROR;
  1054. X    }
  1055. X  for (i = 1; i < argc; ++i)
  1056. X    {
  1057. X      if (mdwrite(argv[i], 1) < 0)
  1058. X    {
  1059. X      Tcl_AppendResult(interp, "cannot send \"", argv[i], "\" (",
  1060. X               sys_errlist[errno], ")", 0);
  1061. X      return TCL_ERROR;
  1062. X    }
  1063. X    }
  1064. X  return TCL_OK;
  1065. X}
  1066. X
  1067. Xstatic int CMD_listen(ClientData clientData, Tcl_Interp *interp, int argc,
  1068. X              char *argv[])
  1069. X{
  1070. X  char *response;
  1071. X
  1072. X  if (argc > 1)
  1073. X    {
  1074. X      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], "\"", 0);
  1075. X      return TCL_ERROR;
  1076. X    }
  1077. X  while (!(response = mdread(1000, 0, 0, 0)) || strlen(response) == 0);
  1078. X  Tcl_SetResult(interp, response, TCL_STATIC);
  1079. X  return TCL_OK;
  1080. X}
  1081. X
  1082. Xstatic int CMD_receive(ClientData clientData, Tcl_Interp *interp, int argc,
  1083. X               char *argv[])
  1084. X{
  1085. X  unsigned t = 30;
  1086. X
  1087. X  if (argc > 1)
  1088. X    t = atoi(argv[1]);
  1089. X  if (argc > 2)
  1090. X    {
  1091. X      const char *p;
  1092. X      
  1093. X      if (p = mdread(t, 0, (const char **)argv + 2, 0))
  1094. X    Tcl_SetResult(interp, (char *)p, TCL_VOLATILE);
  1095. X      else
  1096. X    Tcl_SetResult(interp, "", TCL_STATIC);
  1097. X    }
  1098. X  else
  1099. X    {
  1100. X      char *p = mdread(t, 0, 0, 0);
  1101. X      
  1102. X      if (p)
  1103. X    Tcl_SetResult(interp, p, TCL_STATIC);
  1104. X      else
  1105. X    Tcl_SetResult(interp, "", TCL_STATIC);
  1106. X    }
  1107. Xreturn TCL_OK;
  1108. X}
  1109. X
  1110. Xstatic int CMD_flush_input(ClientData clientData, Tcl_Interp *interp,
  1111. X               int argc, char *argv[])
  1112. X{
  1113. X  if (argc > 1)
  1114. X    {
  1115. X      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1116. X               "\"", 0);
  1117. X      return TCL_ERROR;
  1118. X    }
  1119. X  mdflushin(0);
  1120. X  return TCL_OK;
  1121. X}
  1122. X
  1123. Xstatic int CMD_hangup(ClientData clientData, Tcl_Interp *interp, int argc,
  1124. X              char *argv[])
  1125. X{
  1126. X  if (argc > 1)
  1127. X    {
  1128. X      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1129. X               "\"", 0);
  1130. X      return TCL_ERROR;
  1131. X    }
  1132. X  mdhangup(1);
  1133. X  return TCL_OK;
  1134. X}
  1135. X
  1136. X/* This is mainly an exec (Tcl command) reedition to better follow
  1137. X   some need related to DCE handling. Input, output streams are
  1138. X   redirected to tty so invoked programs can deal with it. Output
  1139. X   is not collected in any way. */
  1140. Xstatic int CMD_invoke(ClientData clientData, Tcl_Interp *interp, int argc,
  1141. X             char *argv[])
  1142. X{
  1143. X  int *pidPtr;
  1144. X
  1145. X  /* See if the command is to be run in background;  if so, create
  1146. X     the command, detach it, and return. */
  1147. X  if ((argv[argc-1][0] == '&') && (argv[argc-1][1] == 0))
  1148. X    {
  1149. X      int numPids;
  1150. X      
  1151. X      argc--;
  1152. X      argv[argc] = NULL;
  1153. X      numPids = Tcl_CreatePipeline(interp, argc-1, argv+1, &pidPtr,
  1154. X                   (int *) NULL, (int *) NULL, (int *) NULL);
  1155. X      if (numPids < 0)
  1156. X    return TCL_ERROR;
  1157. X      Tcl_DetachPids(numPids, pidPtr);
  1158. X    }
  1159. X  else
  1160. X    {
  1161. X      int numPids, i, rvalue;
  1162. X      char buf[32];
  1163. X
  1164. X      lockLine(line, 30);
  1165. X      setUtmp(UTMP_PROCESS, line);
  1166. X      numPids = Tcl_CreatePipeline(interp, argc-1, argv+1, &pidPtr,
  1167. X                   (int *) NULL, (int *) NULL, (int *) NULL);
  1168. X      if (numPids < 0)
  1169. X    return TCL_ERROR;
  1170. X      /* This ensure last process on pipe has value saved
  1171. X     in rvalue, bacuse we must return it. */
  1172. X      for (i = 0; i < numPids; i++)
  1173. X    {
  1174. X      int pid;
  1175. X
  1176. X      pid = Tcl_WaitPids(1, &pidPtr[i], (int *) &rvalue);
  1177. X      if (pid == -1)
  1178. X        {
  1179. X          Tcl_AppendResult(interp, "error waiting for process to exit: ",
  1180. X                   Tcl_UnixError(interp), (char *) NULL);
  1181. X          continue;
  1182. X        }
  1183. X    }
  1184. X      rvalue = (WIFEXITED(rvalue)) ? WEXITSTATUS(rvalue) : -1;
  1185. X      if (verbosity > 6)
  1186. X    fprintf(stderr, "%s: invoked program returned %d\n", myname, rvalue);
  1187. X      sprintf(buf, "%d", rvalue);
  1188. X      Tcl_SetResult(interp, buf, TCL_VOLATILE);
  1189. X      unlockLine(line);
  1190. X      setUtmp(UTMP_GETTY, line);
  1191. X    }
  1192. X  ckfree((char *) pidPtr);
  1193. X  return TCL_OK;
  1194. X}
  1195. X
  1196. Xstatic int CMD_mode(ClientData clientData, Tcl_Interp *interp, int argc,
  1197. X            char *argv[])
  1198. X{
  1199. X  int i;
  1200. X
  1201. X  if (argc < 2)
  1202. X    {
  1203. X      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1204. X               " mode ?mode ...?\"", 0);
  1205. X      return TCL_ERROR;
  1206. X    }
  1207. X  for (i = 1; i < argc; ++i)
  1208. X    {
  1209. X      if (!strcomp(argv[i], "raw"))
  1210. X    setMode(MD_RAW);
  1211. X      else if (!strcomp(argv[i], "cooked"))
  1212. X    setMode(MD_COOKED);
  1213. X      else if (!strcomp(argv[i], "xon_xoff"))
  1214. X    setMode(MD_XONXOFF);
  1215. X      else if (!strcomp(argv[i], "cts_rts"))
  1216. X    setMode(MD_CTSRTS);
  1217. X      else if (!strcomp(argv[i], "no_flow"))
  1218. X    setMode(MD_NOFLOW);
  1219. X      else if (!strcomp(argv[i], "local"))
  1220. X    setMode(MD_LOCAL);
  1221. X      else if (!strcomp(argv[i], "remote"))
  1222. X    setMode(MD_REMOTE);
  1223. X      else
  1224. X    {
  1225. X      Tcl_AppendResult(interp, "unrecognized flag \"", argv[i], "\"", 0);
  1226. X      return TCL_ERROR;
  1227. X    }
  1228. X    }
  1229. X  return TCL_OK;
  1230. X}
  1231. X
  1232. Xstatic int CMD_baudrate(ClientData clientData, Tcl_Interp *interp, int argc,
  1233. X            char *argv[])
  1234. X{
  1235. X  char buf[16];
  1236. X
  1237. X  if (argc > 2)
  1238. X    {
  1239. X      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1240. X               " baud_rate\"", 0);
  1241. X      return TCL_ERROR;
  1242. X    }
  1243. X  if (argc > 1)
  1244. X    setBaudRate(atoi(argv[1]));
  1245. X  sprintf(buf, "%u", baudrate);
  1246. X  Tcl_SetResult(interp, buf, TCL_VOLATILE);
  1247. X  return TCL_OK;
  1248. X}
  1249. X
  1250. Xstatic int CMD_login(ClientData clientData, Tcl_Interp *interp, int argc,
  1251. X             char *argv[])
  1252. X{
  1253. X  if (argc > 1)
  1254. X    {
  1255. X      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1256. X               "\"", 0);
  1257. X      return TCL_ERROR;
  1258. X    }
  1259. X  doLogin();
  1260. X  /* Should not return. */
  1261. X  Tcl_SetResult(interp, "error in login process", TCL_STATIC);
  1262. X  return TCL_ERROR;
  1263. X}
  1264. X
  1265. Xstatic int CMD_sleep(ClientData clientData, Tcl_Interp *interp, int argc,
  1266. X             char *argv[])
  1267. X{
  1268. X  if (argc != 2)
  1269. X    {
  1270. X      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1271. X               " seconds\"", 0);
  1272. X      return TCL_ERROR;
  1273. X    }
  1274. X  sleep(atoi(argv[1]));
  1275. X  return TCL_OK;
  1276. X}
  1277. X
  1278. X#if DEBUG > 7
  1279. Xvoid Tcl_DEBUG(ClientData clientData, Tcl_Interp *interp, int level,
  1280. X           char *command, Tcl_CmdProc *cmdProc, ClientData cmdClientData,
  1281. X           int argc, char *argv[])
  1282. X{
  1283. X  int i;
  1284. X
  1285. X  fprintf(stderr, "%s: TRACE: [%u] %s --", myname, level, command);
  1286. X  for (i = 0; i < argc; ++i)
  1287. X    fprintf(stderr, " [%s]", argv[i]);
  1288. X  putc('\n', stderr);
  1289. X}
  1290. X#endif    /* DEBUG */
  1291. X
  1292. Xint CMD_exit(ClientData dummy, Tcl_Interp *interp, int argc, char *argv[])
  1293. X{
  1294. X  if ((argc != 1) && (argc != 2))
  1295. X    {
  1296. X      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1297. X               " ?returnCode?\"", (char *) NULL);
  1298. X      return TCL_ERROR;
  1299. X    }
  1300. X  mdhangup(1);
  1301. X  closeLine();
  1302. X  setUtmp(UTMP_EXIT, line);
  1303. X  if (argc == 1)
  1304. X    exit(0);
  1305. X  exit(atoi(argv[1]));
  1306. X  return TCL_ERROR;
  1307. X}
  1308. X
  1309. X
  1310. Xstatic void setBits(int flag, bool on, unsigned short *field)
  1311. X{
  1312. X  if (on)
  1313. X    *field |= flag;
  1314. X  else
  1315. X    *field &= ~flag;
  1316. X}
  1317. X
  1318. Xstatic int CMD_slow_write(ClientData clientData, Tcl_Interp *interp, int argc,
  1319. X              char *argv[])
  1320. X{
  1321. X  if (argc > 2)
  1322. X    {
  1323. X      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1324. X               " ?ON|OFF|1|0|TRUE|FALSE|TOGGLE?\"", 0);
  1325. X      return TCL_ERROR;
  1326. X    }
  1327. X  if (argc > 1)
  1328. X    {
  1329. X      char *p = argv[1];
  1330. X
  1331. X      if (!strcomp(p, "ON") || !strcomp(p, "1") || !strcomp(p, "TRUE"))
  1332. X    mdslowrite = TRUE;
  1333. X      else if (!strcomp(p, "OFF") || !strcomp(p, "0") || !strcomp(p, "FALSE"))
  1334. X    mdslowrite = FALSE;
  1335. X      else if (!strcomp(p, "TOGGLE"))
  1336. X    mdslowrite = !mdslowrite;
  1337. X      else
  1338. X    {
  1339. X      Tcl_AppendResult(interp, "unrecognized flag \"", p, "\"", 0);
  1340. X      return TCL_ERROR;
  1341. X    }
  1342. X    }
  1343. X  Tcl_SetResult(interp, mdslowrite ? "ON" : "OFF", TCL_STATIC);
  1344. X  return TCL_OK;
  1345. X}
  1346. X
  1347. X/* THIS FUNCTION IS NOT COMPLETE AT ALL!! -wp9/20/92. */
  1348. X
  1349. Xstatic int CMD_stty(ClientData clientData, Tcl_Interp *interp, int argc,
  1350. X            char *argv[])
  1351. X{
  1352. X  int i;
  1353. X  struct termio tty;
  1354. X
  1355. X  if (argc < 2)
  1356. X    {
  1357. X      Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1358. X               " mode ?mode ...?\"", 0);
  1359. X      return TCL_ERROR;
  1360. X    }
  1361. X  if (ioctl(1, TCGETA, &tty) < 0)
  1362. X    {
  1363. X      Tcl_SetResult(interp, "cannot get current line setting", TCL_STATIC);
  1364. X      return TCL_ERROR;
  1365. X    }
  1366. X  for (i = 1; i < argc; ++i)
  1367. X    {
  1368. X      char *p = argv[i];
  1369. X
  1370. X      if (*p == '-')
  1371. X    ++p;
  1372. X      /* Input flags */
  1373. X      if (!strcomp(p, "IGNBRK"))
  1374. X    setBits(IGNBRK, p == argv[i], &tty.c_iflag);
  1375. X      else if (!strcomp(p, "BRKINT"))
  1376. X    setBits(BRKINT, p == argv[i], &tty.c_iflag);
  1377. X      else if (!strcomp(p, "IGNPAR"))
  1378. X    setBits(IGNPAR, p == argv[i], &tty.c_iflag);
  1379. X      else if (!strcomp(p, "PARMRK"))
  1380. X    setBits(PARMRK, p == argv[i], &tty.c_iflag);
  1381. X      else if (!strcomp(p, "INPCK"))
  1382. X    setBits(INPCK, p == argv[i], &tty.c_iflag);
  1383. X      else if (!strcomp(p, "ISTRIP"))
  1384. X    setBits(ISTRIP, p == argv[i], &tty.c_iflag);
  1385. X      else if (!strcomp(p, "INLCR"))
  1386. X    setBits(INLCR, p == argv[i], &tty.c_iflag);
  1387. X      else if (!strcomp(p, "IGNCR"))
  1388. X    setBits(IGNCR, p == argv[i], &tty.c_iflag);
  1389. X      else if (!strcomp(p, "ICRNL"))
  1390. X    setBits(ICRNL, p == argv[i], &tty.c_iflag);
  1391. X      else if (!strcomp(p, "IUCLC"))
  1392. X    setBits(IUCLC, p == argv[i], &tty.c_iflag);
  1393. X      else if (!strcomp(p, "IXON"))
  1394. X    setBits(IXON, p == argv[i], &tty.c_iflag);
  1395. X      else if (!strcomp(p, "IXANY"))
  1396. X    setBits(IXANY, p == argv[i], &tty.c_iflag);
  1397. X      else if (!strcomp(p, "IXOFF"))
  1398. X    setBits(IXOFF, p == argv[i], &tty.c_iflag);
  1399. X#ifdef DOSMODE
  1400. X      else if (!strcomp(p, "DOSMODE"))
  1401. X    setBits(DOSMODE, p == argv[i], &tty.c_iflag);
  1402. X#endif
  1403. X      /* Output flags */
  1404. X      else if (!strcomp(p, "OPOST"))
  1405. X    setBits(OPOST, p == argv[i], &tty.c_oflag);
  1406. X      else if (!strcomp(p, "OLCUC"))
  1407. X    setBits(OLCUC, p == argv[i], &tty.c_oflag);
  1408. X      else if (!strcomp(p, "ONLCR"))
  1409. X    setBits(ONLCR, p == argv[i], &tty.c_oflag);
  1410. X      else if (!strcomp(p, "OCRNL"))
  1411. X    setBits(OCRNL, p == argv[i], &tty.c_oflag);
  1412. X      else if (!strcomp(p, "ONOCR"))
  1413. X    setBits(ONOCR, p == argv[i], &tty.c_oflag);
  1414. X      else if (!strcomp(p, "ONLRET"))
  1415. X    setBits(ONLRET, p == argv[i], &tty.c_oflag);
  1416. X      else if (!strcomp(p, "OFILL"))
  1417. X    setBits(OFILL, p == argv[i], &tty.c_oflag);
  1418. X      else if (!strcomp(p, "OFDEL"))
  1419. X    setBits(OFDEL, p == argv[i], &tty.c_oflag);
  1420. X      else if (!strcomp(p, "NL0"))
  1421. X    if (p != argv[i])
  1422. X      break;
  1423. X    else
  1424. X      setBits(NL1, FALSE, &tty.c_oflag);
  1425. X      else if (!strcomp(p, "NL1"))
  1426. X    if (p != argv[i])
  1427. X      break;
  1428. X    else
  1429. X      setBits(NL1, TRUE, &tty.c_oflag);
  1430. X      else if (!strcomp(p, "CR0"))
  1431. X    if (p != argv[i])
  1432. X      break;
  1433. X    else
  1434. X      setBits(CRDLY, FALSE, &tty.c_oflag);
  1435. X      else if (!strcomp(p, "CR1"))
  1436. X    if (p != argv[i])
  1437. X      break;
  1438. X    else setBits(CR1, TRUE, &tty.c_oflag);
  1439. X      else if (!strcomp(p, "CR2"))
  1440. X    if (p != argv[i])
  1441. X      break;
  1442. X    else setBits(CR2, TRUE, &tty.c_oflag);
  1443. X      else if (!strcomp(p, "CR3"))
  1444. X    if (p != argv[i])
  1445. X      break;
  1446. X    else setBits(CR3, TRUE, &tty.c_oflag);
  1447. X      else if (!strcomp(p, "TAB0"))
  1448. X    if (p != argv[i])
  1449. X      break;
  1450. X    else setBits(TAB0, p == argv[i], &tty.c_oflag);
  1451. X      else if (!strcomp(p, "TAB1"))
  1452. X    if (p != argv[i])
  1453. X      break;
  1454. X    else setBits(TAB1, p == argv[i], &tty.c_oflag);
  1455. X      else if (!strcomp(p, "TAB2"))
  1456. X    if (p != argv[i])
  1457. X      break;
  1458. X    else setBits(TAB2, p == argv[i], &tty.c_oflag);
  1459. X      else if (!strcomp(p, "TAB3"))
  1460. X    if (p != argv[i])
  1461. X      break;
  1462. X    else setBits(TAB3, p == argv[i], &tty.c_oflag);
  1463. X      else if (!strcomp(p, "BS0"))
  1464. X    if (p != argv[i])
  1465. X      break;
  1466. X    else setBits(BS0, p == argv[i], &tty.c_oflag);
  1467. X      else if (!strcomp(p, "BS1"))
  1468. X    if (p != argv[i])
  1469. X      break;
  1470. X    else setBits(BS1, p == argv[i], &tty.c_oflag);
  1471. X      else if (!strcomp(p, "VT0"))
  1472. X    if (p != argv[i])
  1473. X      break;
  1474. X    else setBits(VT0, p == argv[i], &tty.c_oflag);
  1475. X      else if (!strcomp(p, "VT1"))
  1476. X    if (p != argv[i])
  1477. X      break;
  1478. X    else setBits(VT1, p == argv[i], &tty.c_oflag);
  1479. X      else if (!strcomp(p, "FF0"))
  1480. X    if (p != argv[i])
  1481. X      break;
  1482. X    else setBits(FF0, p == argv[i], &tty.c_oflag);
  1483. X      else if (!strcomp(p, "FF1"))
  1484. X    if (p != argv[i])
  1485. X      break;
  1486. X    else setBits(FF1, p == argv[i], &tty.c_oflag);
  1487. X      /* Control flags */
  1488. X      else if (!strcomp(p, "B0"))
  1489. X    if (p != argv[i])
  1490. X      break;
  1491. X    else setBits(B0, p == argv[i], &tty.c_cflag);
  1492. X      else if (!strcomp(p, "B50"))
  1493. X    if (p != argv[i])
  1494. X      break;
  1495. X    else setBits(B50, p == argv[i], &tty.c_cflag);
  1496. X      else if (!strcomp(p, "B75"))
  1497. X    if (p != argv[i])
  1498. X      break;
  1499. X    else setBits(B75, p == argv[i], &tty.c_cflag);
  1500. X      else if (!strcomp(p, "B110"))
  1501. X    if (p != argv[i])
  1502. X      break;
  1503. X    else setBits(B110, p == argv[i], &tty.c_cflag);
  1504. X      else if (!strcomp(p, "B134"))
  1505. X    if (p != argv[i])
  1506. X      break;
  1507. X    else setBits(B134, p == argv[i], &tty.c_cflag);
  1508. X      else if (!strcomp(p, "B150"))
  1509. X    if (p != argv[i])
  1510. X      break;
  1511. X    else setBits(B150, p == argv[i], &tty.c_cflag);
  1512. X      else if (!strcomp(p, "B200"))
  1513. X    if (p != argv[i])
  1514. X      break;
  1515. X    else setBits(B200, p == argv[i], &tty.c_cflag);
  1516. X      else if (!strcomp(p, "B300"))
  1517. X    if (p != argv[i])
  1518. X      break;
  1519. X    else setBits(B300, p == argv[i], &tty.c_cflag);
  1520. X      else if (!strcomp(p, "B600"))
  1521. X    if (p != argv[i])
  1522. X      break;
  1523. X    else setBits(B600, p == argv[i], &tty.c_cflag);
  1524. X      else if (!strcomp(p, "B1200"))
  1525. X    if (p != argv[i])
  1526. X      break;
  1527. X    else setBits(B1200, p == argv[i], &tty.c_cflag);
  1528. X      else if (!strcomp(p, "B1800"))
  1529. X    if (p != argv[i])
  1530. X      break;
  1531. X    else setBits(B1800, p == argv[i], &tty.c_cflag);
  1532. X      else if (!strcomp(p, "B2400"))
  1533. X    if (p != argv[i])
  1534. X      break;
  1535. X    else setBits(B2400, p == argv[i], &tty.c_cflag);
  1536. X      else if (!strcomp(p, "B4800"))
  1537. X    if (p != argv[i])
  1538. X      break;
  1539. X    else setBits(B4800, p == argv[i], &tty.c_cflag);
  1540. X      else if (!strcomp(p, "B9600"))
  1541. X    if (p != argv[i])
  1542. X      break;
  1543. X    else setBits(B9600, p == argv[i], &tty.c_cflag);
  1544. X      else if (!strcomp(p, "B19200") || !strcomp(p, "EXTA"))
  1545. X    if (p != argv[i])
  1546. X      break;
  1547. X    else setBits(B19200, p == argv[i], &tty.c_cflag);
  1548. X      else if (!strcomp(p, "B38400") || !strcomp(p, "EXTB"))
  1549. X    if (p != argv[i])
  1550. X      break;
  1551. X    else setBits(B38400, p == argv[i], &tty.c_cflag);
  1552. X      else if (!strcomp(p, "CS5"))
  1553. X    if (p != argv[i])
  1554. X      break;
  1555. X    else setBits(CS5, p == argv[i], &tty.c_cflag);
  1556. X      else if (!strcomp(p, "CS6"))
  1557. X    if (p != argv[i])
  1558. X      break;
  1559. X    else setBits(CS6, p == argv[i], &tty.c_cflag);
  1560. X      else if (!strcomp(p, "CS7"))
  1561. X    if (p != argv[i])
  1562. X      break;
  1563. X    else setBits(CS7, p == argv[i], &tty.c_cflag);
  1564. X      else if (!strcomp(p, "CS8"))
  1565. X    if (p != argv[i])
  1566. X      break;
  1567. X    else setBits(CS8, p == argv[i], &tty.c_cflag);
  1568. X      else if (!strcomp(p, "CSTOPB"))
  1569. X    setBits(CSTOPB, p == argv[i], &tty.c_cflag);
  1570. X      else if (!strcomp(p, "CREAD"))
  1571. X    setBits(CREAD, p == argv[i], &tty.c_cflag);
  1572. X      else if (!strcomp(p, "PARENB"))
  1573. X    setBits(PARENB, p == argv[i], &tty.c_cflag);
  1574. X      else if (!strcomp(p, "PARODD"))
  1575. X    setBits(PARODD, p == argv[i], &tty.c_cflag);
  1576. X      else if (!strcomp(p, "HUPCL"))
  1577. X    setBits(HUPCL, p == argv[i], &tty.c_cflag);
  1578. X      else if (!strcomp(p, "CLOCAL"))
  1579. X    setBits(CLOCAL, p == argv[i], &tty.c_cflag);
  1580. X      else if (!strcomp(p, "LOBLK"))
  1581. X    setBits(LOBLK, p == argv[i], &tty.c_cflag);
  1582. X#ifdef CTSFLOW
  1583. X      else if (!strcomp(p, "CTSFLOW"))
  1584. X    setBits(CTSFLOW, p == argv[i], &tty.c_cflag);
  1585. X#endif
  1586. X#ifdef RTSFLOW
  1587. X      else if (!strcomp(p, "RTSFLOW"))
  1588. X    setBits(RTSFLOW, p == argv[i], &tty.c_cflag);
  1589. X#endif
  1590. X      /* Line discipline flags */
  1591. X      else if (!strcomp(p, "ISIG"))
  1592. X    setBits(ISIG, p == argv[i], &tty.c_lflag);
  1593. X      else if (!strcomp(p, "ICANON"))
  1594. X    setBits(ICANON, p == argv[i], &tty.c_lflag);
  1595. X      else if (!strcomp(p, "XCASE"))
  1596. X    setBits(XCASE, p == argv[i], &tty.c_lflag);
  1597. X      else if (!strcomp(p, "ECHO"))
  1598. X    setBits(ECHO, p == argv[i], &tty.c_lflag);
  1599. X      else if (!strcomp(p, "ECHOE"))
  1600. X    setBits(ECHOE, p == argv[i], &tty.c_lflag);
  1601. X      else if (!strcomp(p, "ECHOK"))
  1602. X    setBits(ECHOK, p == argv[i], &tty.c_lflag);
  1603. X      else if (!strcomp(p, "ECHONL"))
  1604. X    setBits(ECHONL, p == argv[i], &tty.c_lflag);
  1605. X      else if (!strcomp(p, "NOFLSH"))
  1606. X    setBits(NOFLSH, p == argv[i], &tty.c_lflag);
  1607. X      else if (!strcomp(p, "XCLUDE"))
  1608. X    setBits(XCLUDE, p == argv[i], &tty.c_lflag);
  1609. X      else
  1610. X    break;
  1611. X    }
  1612. X  if (i < argc)
  1613. X    {
  1614. X      Tcl_AppendResult(interp, "unrecognized flag \"", argv[i], "\"", 0);
  1615. X      return TCL_ERROR;
  1616. X    }
  1617. X  if (ioctl(1, TCSETAF, &tty) < 0)
  1618. X    {
  1619. X      Tcl_SetResult(interp, "cannot set line parameters", TCL_STATIC);
  1620. X      return TCL_ERROR;
  1621. X    }
  1622. X  return TCL_OK;
  1623. X}
  1624. X
  1625. Xstatic void createTclEnvironment()
  1626. X{
  1627. X  interp = Tcl_CreateInterp ();
  1628. X  Tcl_CreateCommand(interp, "listen", CMD_listen, 0, 0);
  1629. X  Tcl_CreateCommand(interp, "send", CMD_send, 0, 0);
  1630. X  Tcl_CreateCommand(interp, "receive", CMD_receive, 0, 0);
  1631. X  Tcl_CreateCommand(interp, "flush_input", CMD_flush_input, 0, 0);
  1632. X  Tcl_CreateCommand(interp, "hangup", CMD_hangup, 0, 0);
  1633. X  Tcl_CreateCommand(interp, "login", CMD_login, 0, 0);
  1634. X  Tcl_CreateCommand(interp, "invoke", CMD_invoke, 0, 0);
  1635. X  Tcl_CreateCommand(interp, "mode", CMD_mode, 0, 0);
  1636. X  Tcl_CreateCommand(interp, "baudrate", CMD_baudrate, 0, 0);
  1637. X  Tcl_CreateCommand(interp, "stty", CMD_stty, 0, 0);
  1638. X  Tcl_CreateCommand(interp, "sleep", CMD_sleep, 0, 0);
  1639. X  Tcl_CreateCommand(interp, "slow_write", CMD_slow_write, 0, 0);
  1640. X  Tcl_DeleteCommand(interp, "exit");
  1641. X  Tcl_CreateCommand(interp, "exit", CMD_exit, 0, 0);
  1642. X#if DEBUG > 7
  1643. X  Tcl_CreateTrace(interp, 5, Tcl_DEBUG, 0);
  1644. X#endif
  1645. X}
  1646. X
  1647. Xstatic bool processInitFile()
  1648. X{
  1649. X  char pathname[256];
  1650. X
  1651. X  sprintf(pathname, "%s/ttys/%s", LIB_DIR, line);
  1652. X  if (access(pathname, R_OK) == 0)
  1653. X    {
  1654. X      if (Tcl_EvalFile(interp, pathname) == TCL_OK)
  1655. X    return SUCCEEDED;
  1656. X      else
  1657. X    fprintf(stderr, "%s: error in tcl script (\"%s\" at line %u)\n",
  1658. X        myname, interp->result, interp->errorLine);
  1659. X    }
  1660. X  return FALSE;
  1661. X}
  1662. X
  1663. Xint main(unsigned argc, char *argv[])
  1664. X{
  1665. X#ifdef notdef
  1666. X  mdslowrite = TRUE;
  1667. X#endif
  1668. X  myname = basename(argv[0]);
  1669. X  site = siteName();
  1670. X#ifdef DEBUG
  1671. X  if (!isatty(fileno(stderr)))
  1672. X    {
  1673. X      /* If spawned from init stdin/stdout/stderr may (should?) point
  1674. X     to unopened file descriptors. */
  1675. X      close(0); close(1); close(2);
  1676. X      open("/dev/null", O_RDONLY);
  1677. X      dup(open("/tmp/getty-stderr", O_WRONLY | O_CREAT | O_APPEND, 0644));
  1678. X    }
  1679. X#endif
  1680. X  optind = 1;    /* the first argument is the real getty -wp9/20/92. */
  1681. X  mdverbosity = verbosity;
  1682. X#if defined(M_XENIX) || defined(BSD)
  1683. X  line = argv[optind + 1];
  1684. X#else
  1685. X  line = argv[argc - 1];
  1686. X#endif
  1687. X  if (isLocked(line))
  1688. X    exit(1);
  1689. X  createTclEnvironment();
  1690. X  if (!openLine(line))
  1691. X    {
  1692. X      fprintf(stderr, "%s: cannot open assigned tty\n", myname);
  1693. X      exit(6);
  1694. X    }
  1695. X  catchSignals();
  1696. X  if (!setUtmp(UTMP_GETTY, line))
  1697. X    {
  1698. X      fprintf(stderr, "%s: no slot in utmp\n", myname);
  1699. X      exit(5);
  1700. X    }
  1701. X  if (!processInitFile())
  1702. X    spawnGetty(argv + optind);
  1703. X  mdhangup(1);
  1704. X  closeLine();
  1705. X  setUtmp(UTMP_EXIT, line);
  1706. X  return exit(0), 0;
  1707. X}
  1708. SHAR_EOF
  1709. true || echo 'restore of mgetty.c failed'
  1710. rm -f _shar_wnt_.tmp
  1711. fi
  1712. # ============= modemio.c ==============
  1713. if test -f 'modemio.c' -a X"$1" != X"-c"; then
  1714.     echo 'x - skipping modemio.c (File already exists)'
  1715.     rm -f _shar_wnt_.tmp
  1716. else
  1717. > _shar_wnt_.tmp
  1718. echo 'x - extracting modemio.c (Text)'
  1719. sed 's/^X//' << 'SHAR_EOF' > 'modemio.c' &&
  1720. X/*
  1721. X * $Id: modemio.c,v 1.1 1993/01/06 18:09:44 wcp Exp $
  1722. X *
  1723. X * Copyright (C) 1992    Walter Pelissero
  1724. X *
  1725. X * This program is free software; you can redistribute it and/or modify
  1726. X * it under the terms of the GNU General Public License as published by
  1727. X * the Free Software Foundation; either version 1, or (at your option)
  1728. X * any later version.
  1729. X *
  1730. X * This program is distributed in the hope that it will be useful,
  1731. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1732. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1733. X * GNU General Public License for more details.
  1734. X *
  1735. X * You should have received a copy of the GNU General Public License
  1736. X * along with this program; if not, write to the Free Software
  1737. X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1738. X */
  1739. X
  1740. X/*
  1741. X * $Log: modemio.c,v $
  1742. X * Revision 1.1  1993/01/06  18:09:44  wcp
  1743. X * Initial revision
  1744. X *
  1745. X */
  1746. X
  1747. X#include <sys/types.h>
  1748. X#ifdef DEBUG
  1749. X#include <dbmalloc.h>
  1750. X#endif
  1751. X#include <string.h>
  1752. X#include <signal.h>
  1753. X#include <stdio.h>
  1754. X#include <stdlib.h>
  1755. X#include <termio.h>
  1756. X#include "common.h"
  1757. X
  1758. Xstatic char RcsId[] = "$Id: modemio.c,v 1.1 1993/01/06 18:09:44 wcp Exp $";
  1759. Xbool mdtimedout;
  1760. Xunsigned mdverbosity = 0;
  1761. Xbool mdslowrite = FALSE;
  1762. Xextern const char *myname;
  1763. Xchar mdread_buffer[1024];
  1764. Xstatic SIGTYPE (*exsa)(int), (*exsh)(int);
  1765. X
  1766. Xstatic SIGTYPE timeout(int sig)
  1767. X{
  1768. X  mdtimedout = TRUE;
  1769. X#if SIGTYPE == int
  1770. X  return 0;
  1771. X#endif
  1772. X}
  1773. X
  1774. Xstatic void getSignals()
  1775. X{
  1776. X  exsa = signal(SIGALRM, timeout);
  1777. X  exsh = signal(SIGHUP, timeout);
  1778. X  mdtimedout = FALSE;
  1779. X}
  1780. X
  1781. Xstatic void relSignals()
  1782. X{
  1783. X  alarm(0);
  1784. X  signal(SIGALRM, exsa);
  1785. X  signal(SIGHUP, exsh);
  1786. X}
  1787. X
  1788. X/*
  1789. X *  substr(s, l)
  1790. X *
  1791. X *  Function:    Checks for the presence of the string pointed to by s
  1792. X *        somewhere within the string pointed to by l.
  1793. X *
  1794. X *  Returns:    0 if found.
  1795. X *        -1 if not found.
  1796. X */
  1797. Xstatic int substr(const char *s, const char *l)
  1798. X{
  1799. X  int len;
  1800. X  
  1801. X  len = strlen(s);
  1802. X  while ((l = strchr(l, *s)) != NULL)
  1803. X    {
  1804. X      if (!strncmp(s, l, len))
  1805. X    return(0);
  1806. X      l++;
  1807. X    }
  1808. X  return(-1);
  1809. X}
  1810. X
  1811. X/*
  1812. X *  mdwrite(c)
  1813. X *
  1814. X *  Function:    Outputs the string pointed to by c to the ACU device.
  1815. X *
  1816. X *  Returns:    0 on completion.
  1817. X *        -1 on write errors.
  1818. X *
  1819. X */
  1820. Xint mdwrite(const char *c, int fd)
  1821. X{
  1822. X  getSignals();
  1823. X  if (mdverbosity > 6)
  1824. X    fprintf(stderr, "%s: sent modem <<", myname);
  1825. X  while (*c)
  1826. X    {
  1827. X      alarm(1);
  1828. X      if (mdtimedout || write(fd, c, 1) != 1)
  1829. X    {
  1830. X      relSignals();
  1831. X      if (mdverbosity > 6)
  1832. X        fprintf(stderr, ">>-FAIL\n");
  1833. X      fprintf(stderr, "%s: acu write error (%s)\n", myname,
  1834. X          sys_errlist[errno]);
  1835. X      return(-1);
  1836. X    }
  1837. X      if (mdverbosity > 6)
  1838. X    fprintf(stderr, "%s", vgets(*c));
  1839. X      if (mdslowrite)
  1840. X    nap(100);
  1841. X      c++;
  1842. X    }
  1843. X  relSignals();
  1844. X  if (mdverbosity > 6)
  1845. X    fprintf(stderr, ">>-OK\n");
  1846. X  return(0);
  1847. X}
  1848. X
  1849. X/*
  1850. X *
  1851. X *  Function:    Reads from the ACU until it finds a valid response (found
  1852. X *        in ModemAnswers) or times out after rtime seconds.
  1853. X *
  1854. X *  Returns:    The index in ModemAnswers of the modem response found.
  1855. X *        -1 on timeout.
  1856. X *
  1857. X */
  1858. Xchar *mdread(unsigned rtime, int fd, const char **tokens, unsigned *ret)
  1859. X{
  1860. X  char *bp = mdread_buffer, *rp = bp;
  1861. X  unsigned char c;
  1862. X  
  1863. X  getSignals();
  1864. X  if (mdverbosity > 6)
  1865. X    fprintf(stderr, "%s: modem returned <<", myname);
  1866. X  errno = 0;
  1867. X  alarm(rtime);
  1868. X  while (!mdtimedout && read(fd, &c, 1) == 1)
  1869. SHAR_EOF
  1870. true || echo 'restore of modemio.c failed'
  1871. fi
  1872. echo 'End of mgetty-1.0 part 2'
  1873. echo 'File modemio.c is continued in part 3'
  1874. echo 3 > _shar_seq_.tmp
  1875. exit 0
  1876.  
  1877. -- 
  1878. P4 32 8 @A ^@@A ^@@Ax^@@A ^@DA"^@D]%xJe&H1\236\331\306
  1879.