home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / modmpool / part01 < prev    next >
Encoding:
Text File  |  1993-04-05  |  87.6 KB  |  3,689 lines

  1. Newsgroups: comp.sources.unix
  2. From: lab@cgl.se (Lars Berntzon)
  3. Subject: v26i104: modempool - modem pool handler, with dialback, Part01/01
  4. Sender: unix-sources-moderator@vix.com
  5. Approved: paul@vix.com
  6.  
  7. Submitted-By: lab@cgl.se (Lars Berntzon)
  8. Posting-Number: Volume 26, Issue 104
  9. Archive-Name: modempool/part01
  10.  
  11. Modempool is a program that handles a pool of modems. When a user calls a
  12. modempool controlled modem he/she is requested a name, password and,
  13. sometimes, a phone number. If everything is ok, modempool will dialup the
  14. user and start a login prompt.  Modempool has the following features:
  15.  
  16.     - Your site only have to have one external phone line and still have many
  17.       modems on local lines.
  18.  
  19.     - Users do only have to known one number, this makes it easier for both
  20.       the system administrator and the user who does't have to try many numbers
  21.       to find a free line.
  22.  
  23.     - A user can have a list of valid phone numbers or asterisk for
  24.       any number.
  25.  
  26.     - If compiled with the RLOGIN-switch callback will login a user
  27.       on a specified machine.
  28.  
  29.     - Extensive logging of users loging in and of problems with the
  30.       modem and lines.
  31.  
  32. #! /bin/sh
  33. # This is a shell archive.  Remove anything before this line, then unpack
  34. # it by saving it into a file and typing "sh file".  To overwrite existing
  35. # files, type "sh file -c".  You can also feed this as standard input via
  36. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  37. # will see the following message at the end:
  38. #        "End of archive 1 (of 1)."
  39. # Contents:  Greetings.te MANIFEST Makefile README Users.templa db.c
  40. #   dialup.c getargs.c lock.c login.c modem.c modempool.1 modempool.c
  41. #   modempool.h modempool.te patchlevel.h poolstat.1 poolstat.c slot.c
  42. #   support.c termios.c termios.h tty.c utmplist.c
  43. # Wrapped by vixie@gw.home.vix.com on Tue Apr  6 03:46:51 1993
  44. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  45. if test -f 'Greetings.te' -a "${1}" != "-c" ; then 
  46.   echo shar: Will not clobber existing file \"'Greetings.te'\"
  47. else
  48. echo shar: Extracting \"'Greetings.te'\" \(25 characters\)
  49. sed "s/^X//" >'Greetings.te' <<'END_OF_FILE'
  50. Are you allowed to login
  51. END_OF_FILE
  52. if test 25 -ne `wc -c <'Greetings.te'`; then
  53.     echo shar: \"'Greetings.te'\" unpacked with wrong size!
  54. fi
  55. # end of 'Greetings.te'
  56. fi
  57. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  58.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  59. else
  60. echo shar: Extracting \"'MANIFEST'\" \(858 characters\)
  61. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  62. X   File Name        Archive #    Description
  63. X-----------------------------------------------------------
  64. X Greetings.te               1    
  65. X MANIFEST                   1    This shipping list
  66. X Makefile                   1    
  67. X README                     1    
  68. X Users.templa               1    
  69. X db.c                       1    
  70. X dialup.c                   1    
  71. X getargs.c                  1    
  72. X lock.c                     1    
  73. X login.c                    1    
  74. X modem.c                    1    
  75. X modempool.1                1    
  76. X modempool.c                1    
  77. X modempool.h                1    
  78. X modempool.te               1    
  79. X patchlevel.h               1    
  80. X poolstat.1                 1    
  81. X poolstat.c                 1    
  82. X slot.c                     1    
  83. X support.c                  1    
  84. X termios.c                  1    
  85. X termios.h                  1    
  86. X tty.c                      1    
  87. X utmplist.c                 1    
  88. END_OF_FILE
  89. if test 858 -ne `wc -c <'MANIFEST'`; then
  90.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  91. fi
  92. # end of 'MANIFEST'
  93. fi
  94. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  95.   echo shar: Will not clobber existing file \"'Makefile'\"
  96. else
  97. echo shar: Extracting \"'Makefile'\" \(1463 characters\)
  98. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  99. X#
  100. X# @(#)Makefile    4.5 92/04/22 - Makefile for modempool.
  101. X#
  102. DESTDIR   = /etc/local/modempool
  103. X#
  104. X# Unkomment for systems without stdlib.h
  105. X#
  106. X#NOSTDLIB = -DNOSTDLIB
  107. X#
  108. X# For systems without termios.
  109. X#
  110. X#TINCLUDE   = -I.
  111. X#TOFILES = termios.o
  112. X#THFILES = termios.h
  113. X#
  114. X# If you want the rlogin functionality.
  115. X#
  116. RLOGIN= -DRLOGIN
  117. X#
  118. X# If you want debug printouts to stdout ?
  119. X# DEBUG=-DDEBUG
  120. CFLAGS = -g $(RLOGIN) $(TINCLUDE) $(NOSTDLIB) $(DEBUG)
  121. X#
  122. OFILES = modempool.o support.o tty.o slot.o lock.o modem.o db.o \
  123. X     dialup.o login.o getargs.o $(TOFILES)
  124. HFILES = modempool.h $(THFILES)
  125. X#
  126. X# Unkomment for gcc
  127. X#
  128. X#CC=gcc -traditional
  129. CC=gcc
  130. COMPILE.c= $(CC) $(CFLAGS) $(CPPFLAGS) -c
  131. X
  132. all: modempool poolstat
  133. X
  134. modempool: $(OFILES)
  135. X    $(CC) -g -o modempool $(OFILES)
  136. X
  137. poolstat: poolstat.o
  138. X    $(CC) -o poolstat poolstat.o
  139. X
  140. X$(OFILES) : $(HFILES)
  141. X
  142. install: all
  143. X    test -d $(DESTDIR) || mkdir -p $(DESTDIR)
  144. X    cp poolstat modempool $(DESTDIR)
  145. X    touch $(DESTDIR)/Users $(DESTDIR)/log $(DESTDIR)/errlog \
  146. X          $(DESTDIR)/Greetings $(DESTDIR)/serverdb
  147. X    chown root $(DESTDIR)/Users $(DESTDIR)/log $(DESTDIR)/errlog \
  148. X               $(DESTDIR)/Greetings
  149. X    chmod 600 $(DESTDIR)/log $(DESTDIR)/errlog $(DESTDIR)/serverdb
  150. X    chmod 400 $(DESTDIR)/Users $(DESTDIR)/Greetings
  151. X    chmod 500 $(DESTDIR)/modempool
  152. X    chmod 4111 $(DESTDIR)/poolstat
  153. X    @echo "modempool installed"
  154. X
  155. clean:
  156. X    sccs clean
  157. X    -rm -f poolstat.o $(OFILES) modempool poolstat modempool.aux modempool.dvi \
  158. X               modempool.dlog  modempool.log
  159. END_OF_FILE
  160. if test 1463 -ne `wc -c <'Makefile'`; then
  161.     echo shar: \"'Makefile'\" unpacked with wrong size!
  162. fi
  163. # end of 'Makefile'
  164. fi
  165. if test -f 'README' -a "${1}" != "-c" ; then 
  166.   echo shar: Will not clobber existing file \"'README'\"
  167. else
  168. echo shar: Extracting \"'README'\" \(1626 characters\)
  169. sed "s/^X//" >'README' <<'END_OF_FILE'
  170. X
  171. X            M o d e m p o o l
  172. X
  173. X        Copyright (c) 1992, Lars Berntzon
  174. X                 All rights reserved.
  175. X
  176. X    This program is free software; you can redistribute it and/or modify
  177. X    it under the terms of the GNU General Public License as published by
  178. X    the Free Software Foundation
  179. X                                      
  180. Modempool is a program that handles a pool of modems. When a user calls a
  181. modempool controlled modem he/she is requested a name, password and,
  182. sometimes, a phone number. If everything is ok, modempool will dialup the
  183. user and start a login prompt.  Modempool has the following features:
  184. X
  185. X    - Your site only have to have one external phone line and still have many
  186. X      modems on local lines.
  187. X
  188. X    - Users do only have to known one number, this makes it easier for both
  189. X      the system administrator and the user who does't have to try many numbers
  190. X      to find a free line.
  191. X
  192. X    - A user can have a list of valid phone numbers or asterisk for
  193. X      any number.
  194. X
  195. X    - If compiled with the RLOGIN-switch callback will login a user
  196. X      on a specified machine.
  197. X
  198. X    - Extensive logging of users loging in and of problems with the
  199. X      modem and lines.
  200. X
  201. To compile modempool you should first decide whether to use -DRLOGIN switch.
  202. If you will not use it, edit the Makefile to turn it off.
  203. X
  204. Then do:
  205. X
  206. X   make
  207. X
  208. If everyting worked do as root:
  209. X
  210. X   make install
  211. X
  212. Also remember to read the manuals.
  213. X
  214. You should now start the modempool process in /etc/inittab (SYSV) or
  215. X/etc/ttytab (BSD), and add users to the /etc/local/modempool/Users-file.
  216. X
  217. X
  218. X
  219. Please mail bugreports or questions to me.
  220. X
  221. Lars Berntzon            E-Mail: lab@cgl.se
  222. Cap Gemini Logic AB
  223. END_OF_FILE
  224. if test 1626 -ne `wc -c <'README'`; then
  225.     echo shar: \"'README'\" unpacked with wrong size!
  226. fi
  227. # end of 'README'
  228. fi
  229. if test -f 'Users.templa' -a "${1}" != "-c" ; then 
  230.   echo shar: Will not clobber existing file \"'Users.templa'\"
  231. else
  232. echo shar: Extracting \"'Users.templa'\" \(87 characters\)
  233. sed "s/^X//" >'Users.templa' <<'END_OF_FILE'
  234. jerry:foo:123456:jerryws
  235. tom:mot:555626/555623:tomserver
  236. emergency:owjdojw:*:localhost
  237. END_OF_FILE
  238. if test 87 -ne `wc -c <'Users.templa'`; then
  239.     echo shar: \"'Users.templa'\" unpacked with wrong size!
  240. fi
  241. # end of 'Users.templa'
  242. fi
  243. if test -f 'db.c' -a "${1}" != "-c" ; then 
  244.   echo shar: Will not clobber existing file \"'db.c'\"
  245. else
  246. echo shar: Extracting \"'db.c'\" \(3525 characters\)
  247. sed "s/^X//" >'db.c' <<'END_OF_FILE'
  248. X/*******************************************************************
  249. X * 
  250. X * Module: @(#)db.c    4.2
  251. X *
  252. X * Description:
  253. X *    Handle user database functions.
  254. X *
  255. X * Revision:
  256. X *    Date    By            Reason    
  257. X *    ----    --            ------    
  258. X *    910414    Lars Berntzon        Created
  259. X *      910124  Lars H Carlsson     Changed pid format to %10d\n
  260. X *      910124  Lars H Carlsson        Changed mode of lockfile to 0444
  261. X *    910129    Lars Berntzon        Changed to termio for eightbit tty.
  262. X *      910224  Lars Berntzon        Newline right when loggin in.
  263. X *      910227  Lars Berntzon           The loggfile now reopens everytime.
  264. X *
  265. X *******************************************************************/
  266. static char SccsId[] = "@(#)db.c    4.2 92/04/16";
  267. X
  268. X#include <stdio.h>
  269. X#include <string.h>
  270. X#include <fcntl.h>
  271. X#include <stdarg.h>
  272. X
  273. X#include "modempool.h"
  274. X
  275. X/*
  276. X * Local stuff.
  277. X */
  278. static FILE *db_fp = NULL;
  279. X
  280. static db_open(char *filename);
  281. static db_read(char **ptrs, int n_ptrs);
  282. static db_close(void);
  283. X
  284. X/*******************************************************************
  285. X *        D B _ F I N D
  286. X *        -------------
  287. X *
  288. X * Description:
  289. X *    Lookup user in database.
  290. X *
  291. X * Arguments:
  292. X *    filename    - Name of users database.
  293. X *    ptrs        - Pointers to result vectors.
  294. X *    n_ptrs        - Number of vectors.
  295. X *    key_fiels    - Key-field index.
  296. X *     key        - Value to match.
  297. X *
  298. X * Return:
  299. X *    E_OK
  300. X *    E_FAIL        - Internal error.
  301. X *    E_NOTFOUND    - Key not found.
  302. X *
  303. X *******************************************************************/
  304. db_find(char *filename, char **ptrs, int n_ptrs, int key_field, char *key)
  305. X{
  306. X    if (key == NULL) {
  307. X    logerr("db_find: programming error: null-key");
  308. X    return E_FAIL;
  309. X    }
  310. X
  311. X    if (key_field >= n_ptrs) {
  312. X    logerr("db_find: programming error: key_field >= n_ptrs");
  313. X    }
  314. X
  315. X    if (db_open(filename) != E_OK) {
  316. X    return E_FAIL;
  317. X    }
  318. X    
  319. X    while(db_read(ptrs, n_ptrs) == E_OK)
  320. X    {
  321. X    if (ptrs[key_field] != NULL && strcmp(ptrs[key_field], key) == 0)
  322. X    {
  323. X        db_close();
  324. X        return E_OK;
  325. X    }
  326. X    }
  327. X    db_close();
  328. X    return E_NOTFOUND;
  329. X}
  330. X
  331. X/*******************************************************************
  332. X *        D B _ R E A D
  333. X *        -------------
  334. X *
  335. X * Description:
  336. X *    Read one row in users database.
  337. X *
  338. X * Arguments:
  339. X *    ptrs    - Pointers to result vectors.
  340. X *    n_ptrs    - Number of verctors.
  341. X *
  342. X * Return:
  343. X *     E_OK    
  344. X *    E_EOF    - No more users.
  345. X *
  346. X *******************************************************************/
  347. static db_read(char **ptrs, int n_ptrs) 
  348. X{
  349. X    static char in_line[NAME_SIZE];
  350. X    char *p;
  351. X    int i;
  352. X
  353. X    while (fgets(in_line, sizeof in_line, db_fp) != NULL)
  354. X    {
  355. X    p = strtok(in_line, ":\n");
  356. X
  357. X    for(i = 0; i < n_ptrs; i++) {
  358. X        ptrs[i] = p;
  359. X        if (p != NULL) p = strtok(NULL, ":\n");
  360. X    }
  361. X    if (ptrs[0] == NULL || ptrs[0][0] == '#') continue;
  362. X
  363. X    return E_OK;
  364. X    }
  365. X
  366. X    return E_EOF;
  367. X}
  368. X
  369. X/*******************************************************************
  370. X *        D B _ O P E N
  371. X *        -------------
  372. X *
  373. X * Description:
  374. X *    Open the users database.
  375. X *
  376. X * Arguments:
  377. X *    filename    - the users database filename.
  378. X *
  379. X *******************************************************************/
  380. static db_open(char *filename)
  381. X{
  382. X    if ((db_fp = fopen(filename, "r")) == NULL) {
  383. X         logerr("db_open: failed to open user database");
  384. X         return E_FAIL;
  385. X    }
  386. X
  387. X    return E_OK;
  388. X}
  389. X
  390. X/*******************************************************************
  391. X *        D B _ C L O S E
  392. X *        ---------------
  393. X *
  394. X * Description:
  395. X *    Close the users database.
  396. X *
  397. X *******************************************************************/
  398. static db_close(void)
  399. X{
  400. X    if (db_fp) fclose(db_fp);
  401. X    db_fp = NULL;
  402. X
  403. X    return E_OK;
  404. X}
  405. END_OF_FILE
  406. if test 3525 -ne `wc -c <'db.c'`; then
  407.     echo shar: \"'db.c'\" unpacked with wrong size!
  408. fi
  409. # end of 'db.c'
  410. fi
  411. if test -f 'dialup.c' -a "${1}" != "-c" ; then 
  412.   echo shar: Will not clobber existing file \"'dialup.c'\"
  413. else
  414. echo shar: Extracting \"'dialup.c'\" \(5769 characters\)
  415. sed "s/^X//" >'dialup.c' <<'END_OF_FILE'
  416. X/*******************************************************************
  417. X * 
  418. X * Module: @(#)dialup.c    4.2 92/04/16
  419. X *
  420. X * Description:
  421. X *    Dialup routines.
  422. X *
  423. X * Revision:
  424. X *    Date    By            Reason    
  425. X *    ----    --            ------    
  426. X *    920309    Lars Berntzon        Created
  427. X *
  428. X *******************************************************************/
  429. static char SccsId[] = "@(#)dialup.c    4.2 92/04/16";
  430. X
  431. X#include <stdio.h>
  432. X#ifndef NOSTDLIB
  433. X#include <stdlib.h>
  434. X#endif
  435. X#include <unistd.h>
  436. X#include <string.h>
  437. X#include <signal.h>
  438. X#include <fcntl.h>
  439. X#include <termios.h>
  440. X#include <ctype.h>
  441. X
  442. X#include "modempool.h"
  443. X
  444. X#ifdef RLOGIN
  445. X#include <pwd.h>
  446. X#endif
  447. X
  448. X/*******************************************************************
  449. X *
  450. X *         callback
  451. X *        --------
  452. X *
  453. X * Description:
  454. X *    Does the actual calling.
  455. X *
  456. X *******************************************************************/
  457. callback(slot_t *sp)
  458. X{
  459. X    struct slot free_slot;
  460. X    int main_port = 0;
  461. X    int fd;
  462. X    int id;
  463. X    int rc;
  464. X
  465. X    /*
  466. X     * Find free available line.
  467. X     */
  468. X    slot_lock();
  469. X    slot_open();
  470. X    while((rc = slot_traverse(&free_slot)) == E_OK) {
  471. X
  472. X    /* I will only use myself in last resort */
  473. X    if (free_slot.pid == getpid()) {
  474. X         continue;
  475. X    }
  476. X
  477. X    /* Of cause don't use a busy server */
  478. X    if (free_slot.status != SLOT_FREE) {
  479. X         continue;
  480. X    }
  481. X
  482. X    /* Maybe the port us taken by someone else, dont use it then */
  483. X    if (lock_line(free_slot.line, free_slot.pid) != E_OK) {
  484. X       continue;
  485. X    }
  486. X
  487. X    /* Now a free server is found */
  488. X    break;
  489. X    }
  490. X
  491. X    /*
  492. X     * Use myself if no other servers was found.
  493. X     */
  494. X    if (rc != E_OK) {
  495. X    debug("callback: using myself");
  496. X    memcpy(&free_slot, &slot, sizeof free_slot);
  497. X    }
  498. X
  499. X    mod_put(MSG_CALLING);
  500. X
  501. X    /*
  502. X     * Write command to slot e.i. tell server to dial.
  503. X     */
  504. X    free_slot.status = SLOT_BUSY;
  505. X    strncpy(free_slot.phone, sp->phone, sizeof free_slot.phone);
  506. X    strncpy(free_slot.name, sp->name, sizeof free_slot.name);
  507. X#ifdef RLOGIN
  508. X    strncpy(free_slot.host, sp->host, sizeof free_slot.host);
  509. X#endif
  510. X    free_slot.baud = sp->baud;
  511. X    debug("calling: slotid: %d, phone: %s, name: %s, baud: %d", 
  512. X    free_slot.id, free_slot.phone, free_slot.name, free_slot.baud);    
  513. X
  514. X    /*
  515. X     * Write the data and unlock server database.
  516. X     */
  517. X    slot_write(&free_slot);
  518. X    slot_unlock();
  519. X    
  520. X    /* Send signal to server to read its database (dont signal myself) */
  521. X    if (free_slot.pid != getpid()) {
  522. X    kill(free_slot.pid, SIG_SERVER);
  523. X    }
  524. X    else {
  525. X    if ( dialup() != E_OK) {
  526. X        log("dialup failed");
  527. X        return E_FAIL;
  528. X    }
  529. X    }
  530. X    
  531. X    return E_OK;
  532. X}    
  533. X
  534. X/*******************************************************************
  535. X *
  536. X *         DIALUP
  537. X *        ------
  538. X *
  539. X * Description:
  540. X *    Dials a number for this server.
  541. X *
  542. X *******************************************************************/
  543. dialup()
  544. X{
  545. X#ifdef RLOGIN   
  546. X    char name[NAME_SIZE];    /* Temporary name        */
  547. X    struct passwd *pw;        /* Pointer to passwd struct */
  548. X#endif
  549. X    int retry;            /* Retry counter        */
  550. X    int baud = 0;        /* Connected baudrate        */
  551. X    int rc;
  552. X
  553. X    /* Turn of signalled flag */
  554. X    signalled = 0;
  555. X
  556. X    /* Hangup line before dialing */
  557. X    tty_hangup();
  558. X    tty_close();
  559. X
  560. X    /* Wait some before dialing */
  561. X    sleep(DIALUP_DELAY);
  562. X
  563. X    /* Read baudrate and phone number to dial */
  564. X    if (slot_read(&slot) != E_OK) {
  565. X        logerr("dialup: failed to read slot");
  566. X        return E_FAIL;
  567. X    }
  568. X    
  569. X    /* log dialing */
  570. X    log("dialup: dialing #%s baud %d", slot.phone, slot.baud);
  571. X
  572. X    /* Open port again */
  573. X    if (tty_open(portname, slot.baud, O_NDELAY) != E_OK) {
  574. X    logerr("dialup: failed to open port");
  575. X    return E_FAIL;
  576. X    }
  577. X
  578. X    /* Try three times to dialup */
  579. X    for(retry = 0; retry < 3; retry++)
  580. X    {
  581. X        /* Send modem command */
  582. X    mod_put("ATDT");
  583. X    mod_put(prefix);
  584. X    mod_put(slot.phone);
  585. X    mod_put("\r");
  586. X    
  587. X    /* Expect connection in 20 sec */
  588. X    rc = mod_exp(MOD_ANY, DIALUP_TMOUT);
  589. X    debug("dial: got %d\n", rc);
  590. X
  591. X    switch(rc)
  592. X    {
  593. X    case MOD_CONNECT:
  594. X    case MOD_CONNECT_300:
  595. X        baud = 300;
  596. X    case MOD_CONNECT_1200:
  597. X        if (baud == 0) baud = 1200;
  598. X    case MOD_CONNECT_2400:
  599. X        if (baud == 0) baud = 2400;
  600. X    case MOD_CONNECT_4800:
  601. X        if (baud == 0) baud = 4800;
  602. X    case MOD_CONNECT_9600:
  603. X        if (baud == 0) baud = 9600;
  604. X
  605. X        sleep(2); /* Let modem settle */
  606. X        tty_flush();
  607. X        tty_local(0);
  608. X        tty_baud(baud);
  609. X        tty_sane();
  610. X        log("dialup: connected");
  611. X        mod_put("\r\n\r\n");
  612. X
  613. X        /*
  614. X         * Mark current baudrate in the server database.
  615. X         */
  616. X        slot.baud = baud;
  617. X        slot_write(&slot);
  618. X
  619. X#ifdef RLOGIN
  620. X        /*
  621. X         * Get login name.
  622. X         */
  623. X        retry = 0;
  624. X        do {
  625. X        rc = prompt(MSG_LOGIN, name, NAME_SIZE, LOGIN_TMOUT);
  626. X        } while(rc == E_OK && strlen(name) == 0);
  627. X
  628. X        if ((pw = getpwnam(name)) == NULL) {
  629. X        mod_put(MSG_LOGINFAIL);
  630. X        return E_FAIL;
  631. X        }
  632. X
  633. X        /*
  634. X         * Don't even try to login as same uid as this process.
  635. X         */
  636. X        if (pw->pw_uid < 10 || pw->pw_uid == getuid()) {
  637. X        log("pseudouser '%s' tried to log in as '%s'", slot.name, name);
  638. X        mod_put(MSG_LOGINFAIL);
  639. X        return E_FAIL;
  640. X        }
  641. X#endif
  642. X
  643. X        /*
  644. X         * Redirect port to stdin, stdout and stderr.
  645. X         */
  646. X        if (tty_redirect() != E_OK) {
  647. X           logerr("redirection failed");
  648. X           return E_FAIL;
  649. X        }
  650. X
  651. X#ifdef RLOGIN
  652. X        execl("/usr/ucb/rlogin", "rlogin", "-l", name, slot.host, NULL);
  653. X        logerr("dialup: failed to exec rlogin");
  654. X#else
  655. X        execl("/bin/login", "login", NULL);
  656. X        logerr("dialup: failed to exec login");
  657. X#endif
  658. X        return E_FAIL;
  659. X        
  660. X    case MOD_NO_CARRIER:
  661. X        logerr("dialup: got no carrier for number '%s'", slot.phone);
  662. X        break; /* Retry */
  663. X
  664. X    case MOD_BUSY:
  665. X        sleep(7);
  666. X        break; /* Retry */
  667. X        
  668. X    case MOD_OK:
  669. X    default:
  670. X        logerr("dialup: got %d from modem", rc);
  671. X        break; /* Retry */
  672. X    }
  673. X    sleep(5);
  674. X    }
  675. X
  676. X   /*
  677. X    * Failed to dialup.
  678. X    */
  679. X
  680. X    return E_FAIL;
  681. X}
  682. END_OF_FILE
  683. if test 5769 -ne `wc -c <'dialup.c'`; then
  684.     echo shar: \"'dialup.c'\" unpacked with wrong size!
  685. fi
  686. # end of 'dialup.c'
  687. fi
  688. if test -f 'getargs.c' -a "${1}" != "-c" ; then 
  689.   echo shar: Will not clobber existing file \"'getargs.c'\"
  690. else
  691. echo shar: Extracting \"'getargs.c'\" \(1381 characters\)
  692. sed "s/^X//" >'getargs.c' <<'END_OF_FILE'
  693. X/*******************************************************************
  694. X * 
  695. X * Module: @(#)getargs.c    4.2 92/04/16
  696. X *
  697. X * Description:
  698. X *    Get commandline arguments.
  699. X *
  700. X * Revision:
  701. X *    Date    By            Reason    
  702. X *    ----    --            ------    
  703. X *    920309    Lars Berntzon        Created
  704. X *
  705. X *******************************************************************/
  706. static char SccsId[] = "@(#)getargs.c    4.2 92/04/16";
  707. X
  708. X#include <stdio.h>
  709. X#ifndef NOSTDLIB
  710. X#include <stdlib.h>
  711. X#endif
  712. X#include <unistd.h>
  713. X#include <string.h>
  714. X#include <signal.h>
  715. X#include <fcntl.h>
  716. X#include <stdarg.h>
  717. X#include <termios.h>
  718. X#include <ctype.h>
  719. X
  720. X#include "modempool.h"
  721. X
  722. X/*******************************************************************
  723. X *        G E T A R G S
  724. X *        -------------
  725. X * Description:
  726. X *    Examine command line options.
  727. X *
  728. X *******************************************************************/
  729. int
  730. getargs(int *argc, char ***argv)
  731. X{
  732. X    /*
  733. X     * Get arguments
  734. X     */
  735. X    while((*argv)[1] != NULL && (*argv)[1][0] == '-')
  736. X    {
  737. X    switch((*argv)[1][1])
  738. X    {
  739. X    case 'd':
  740. X        debug_lvl++;
  741. X        break;
  742. X
  743. X    case 'p':
  744. X        (*argv)++, (*argc)--;
  745. X        if ((*argv)[1] == NULL) usage();    
  746. X        strcpy(prefix, (*argv)[1]);
  747. X        break;
  748. X
  749. X    case 'i':
  750. X        (*argv)++, (*argc)--;
  751. X        if((*argv)[1] == NULL) usage();
  752. X        initstr = (*argv)[1];
  753. X        break;
  754. X    }
  755. X    (*argv)++, (*argc)--;
  756. X    }
  757. X
  758. X    /* Check args */
  759. X    if ((*argc) != 3) usage();
  760. X    
  761. X    return E_OK;
  762. X}
  763. END_OF_FILE
  764. if test 1381 -ne `wc -c <'getargs.c'`; then
  765.     echo shar: \"'getargs.c'\" unpacked with wrong size!
  766. fi
  767. # end of 'getargs.c'
  768. fi
  769. if test -f 'lock.c' -a "${1}" != "-c" ; then 
  770.   echo shar: Will not clobber existing file \"'lock.c'\"
  771. else
  772. echo shar: Extracting \"'lock.c'\" \(4969 characters\)
  773. sed "s/^X//" >'lock.c' <<'END_OF_FILE'
  774. X/*******************************************************************
  775. X * 
  776. X * Module: @(#)lock.c    4.2 92/04/16
  777. X *
  778. X * Description:
  779. X *    Handle various lockfile functions.
  780. X *
  781. X * Revision:
  782. X *    Date    By            Reason    
  783. X *    ----    --            ------    
  784. X *    920306    Lars Berntzon        Created
  785. X *
  786. X *******************************************************************/
  787. static char SccsId[] = "@(#)lock.c    4.2 92/04/16";
  788. X
  789. X#include <stdio.h>
  790. X#include <string.h>
  791. X#include <unistd.h>
  792. X#include <fcntl.h>
  793. X#include <assert.h>
  794. X#include <stdarg.h>
  795. X
  796. X#include "modempool.h"
  797. X/*******************************************************************
  798. X *        L O C K _ L I N E
  799. X *        -----------------
  800. X *
  801. X * Description:
  802. X *    Lock a tty-port the old UNIX way.
  803. X *
  804. X * Arguments:
  805. X *    line    - Name of tty device.
  806. X *
  807. X *******************************************************************/
  808. int
  809. lock_line(char *line, int pid)
  810. X{
  811. X    char fname[NAME_SIZE];
  812. X    char id[NAME_SIZE];
  813. X    int fd;
  814. X
  815. X    sprintf(fname, "%s/LCK..%s", LOCKDIR, line);
  816. X
  817. X    /*
  818. X     * Check that lockdirectory is writeable.
  819. X     */
  820. X    if (access(LOCKDIR, O_WRONLY) != 0) {
  821. X    logerr("lock_line: lock directory not writeable");
  822. X    return E_FAIL;
  823. X    }
  824. X
  825. X    /*
  826. X     * First try to create own lockfile.
  827. X     */
  828. X    while(1)
  829. X    {
  830. X        if ((fd = open(fname, O_RDWR | O_CREAT | O_EXCL, 0666)) >= 0) 
  831. X    {
  832. X        /* Succeded, break out of retry loop */
  833. X        break;
  834. X    }
  835. X        else
  836. X        {
  837. X            /*
  838. X             * File allready existed, try to open it without creation.
  839. X         */
  840. X            if ((fd = open(fname, O_RDONLY)) < 0) {
  841. X        logerr("lock_line: can't read file '%s'", fname);
  842. X        return E_LOCK;
  843. X        }
  844. X
  845. X        id[0] = 0;
  846. X            if (read(fd, id, sizeof id) < 0)
  847. X            {
  848. X                close(fd);
  849. X        debug("lock_line: failed to read");
  850. X                return E_READ;
  851. X            }
  852. X            close(fd); 
  853. X
  854. X        /*
  855. X         * If I own the lock, it's all right.
  856. X         */
  857. X        if (atoi(id) == pid) {
  858. X        debug("lock_line: i allready owned the lock");
  859. X        break;
  860. X        }
  861. X
  862. X            /*
  863. X         * Process owning lock does exists so i can't use the line.
  864. X         */
  865. X            if (kill(atoi(id), 0) >= 0)
  866. X            {
  867. X        debug("lock_line: process exists");
  868. X                return E_PROC_EXIST;
  869. X            }
  870. X            if (unlink(fname) < 0)
  871. X            {
  872. X        debug("lock_line: failed to unlink");
  873. X            return E_UNLINK;
  874. X            }
  875. X        }
  876. X    }
  877. X
  878. X    /*
  879. X     * Here our own lock file has been created.
  880. X     */
  881. X    lseek(fd, 0, 0);
  882. X    sprintf(id, "%10d\n", pid);
  883. X    write(fd, id, strlen(id));
  884. X    close(fd);
  885. X
  886. X    debug("lock_line: ok");
  887. X
  888. X    return E_OK;
  889. X}
  890. X
  891. X/*******************************************************************
  892. X *        R E L O C K _ L I N E
  893. X *        ---------------------
  894. X *
  895. X * Description:
  896. X *    Relock the line
  897. X *
  898. X * Arguments:
  899. X *    line    - Name of tty device.
  900. X *
  901. X *******************************************************************/
  902. int
  903. relock_line(char *line)
  904. X{
  905. X    char fname[NAME_SIZE];
  906. X    char id[NAME_SIZE];
  907. X    int fd;
  908. X
  909. X    sprintf(fname, "%s/LCK..%s", LOCKDIR, line);
  910. X
  911. X    /* Open lockfile */
  912. X    if ((fd = open(fname, O_WRONLY | O_TRUNC)) < 0) return E_OPEN;
  913. X
  914. X    /* Write pid to lockfile */
  915. X    sprintf(id, "%10d\n", getpid());
  916. X    if (write(fd, id, strlen(id)) < 0) {
  917. X    return E_WRITE;
  918. X    }
  919. X
  920. X    close(fd);
  921. X    return E_OK;
  922. X}
  923. X
  924. X/*******************************************************************
  925. X *        U N L O C K _ L I N E
  926. X *        ---------------------
  927. X *
  928. X * Description:
  929. X *    Unlock line.
  930. X *
  931. X * Arguments:
  932. X *    line    - Name of tty device.
  933. X *
  934. X *******************************************************************/
  935. int
  936. unlock_line(char *line)
  937. X{
  938. X    char fname[NAME_SIZE];
  939. X    sprintf(fname, "%s/LCK..%s", LOCKDIR, line);
  940. X    unlink(fname);
  941. X    return E_OK;
  942. X}
  943. X
  944. X/*******************************************************************
  945. X *        L O C K _ W A I T
  946. X *        -----------------
  947. X *
  948. X * Description:
  949. X *    Wait until lock goes away.
  950. X *
  951. X *******************************************************************/
  952. int
  953. lock_wait(char *line)
  954. X{
  955. X    int fd = -1;
  956. X    char fname[NAME_SIZE], id[NAME_SIZE];
  957. X
  958. X    if (line == NULL) {
  959. X    logerr("lock_wait: programming error: line = NULL");
  960. X    return E_FAIL;
  961. X    }
  962. X
  963. X    sprintf(fname, "%s/LCK..%s", LOCKDIR, line);
  964. X
  965. X    /* 
  966. X     * This one never times out when line is locked.
  967. X     */
  968. X    while(1)
  969. X    {
  970. X    /*
  971. X     * Check if lockfile exists.
  972. X     */
  973. X    if (access(fname, F_OK) != 0) {
  974. X        return E_OK;
  975. X    }
  976. X
  977. X    /*
  978. X     * Open lockfile.
  979. X     */
  980. X    if ((fd = open(fname, O_RDONLY)) < 0) {
  981. X        fatal("lockfile not readable");
  982. X    }
  983. X
  984. X    id[0] = 0;
  985. X    if (read(fd, id, sizeof id) < 0) {
  986. X        logerr("lock_wait: failed to read lockfile");
  987. X        close(fd);
  988. X        return E_FAIL;
  989. X    }
  990. X
  991. X    /*
  992. X     * If I hold the lock, remove it and return.
  993. X     */
  994. X    if (atoi(id) == getpid()) {
  995. X        debug("lock_wait: i owned the lock");
  996. X        unlock_line(line);
  997. X        close(fd);
  998. X        return E_OK;
  999. X    }
  1000. X
  1001. X    /*
  1002. X     * If no owner of lock, remove it and return.
  1003. X     */
  1004. X    if (kill(atoi(id), 0) != 0) {
  1005. X        debug("lock_wait: no owner of lock");
  1006. X        unlock_line(line);
  1007. X        close(fd);
  1008. X        return E_OK;
  1009. X    }
  1010. X
  1011. X    close(fd);
  1012. X    sleep(5);
  1013. X    }
  1014. X}
  1015. END_OF_FILE
  1016. if test 4969 -ne `wc -c <'lock.c'`; then
  1017.     echo shar: \"'lock.c'\" unpacked with wrong size!
  1018. fi
  1019. # end of 'lock.c'
  1020. fi
  1021. if test -f 'login.c' -a "${1}" != "-c" ; then 
  1022.   echo shar: Will not clobber existing file \"'login.c'\"
  1023. else
  1024. echo shar: Extracting \"'login.c'\" \(6000 characters\)
  1025. sed "s/^X//" >'login.c' <<'END_OF_FILE'
  1026. X/*******************************************************************
  1027. X * 
  1028. X * Module: @(#)login.c    4.4 92/04/21
  1029. X *
  1030. X * Description:
  1031. X *    Handle login during user callup.
  1032. X *
  1033. X * Revision:
  1034. X *    Date    By            Reason    
  1035. X *    ----    --            ------    
  1036. X *    920309    Lars Berntzon        Created
  1037. X *
  1038. X *******************************************************************/
  1039. static char SccsId[] = "@(#)login.c    4.4 92/04/21";
  1040. X
  1041. X#include <stdio.h>
  1042. X#ifndef NOSTDLIB
  1043. X#include <stdlib.h>
  1044. X#endif
  1045. X#include <unistd.h>
  1046. X#include <string.h>
  1047. X#include <ctype.h>
  1048. X#include <errno.h>
  1049. X
  1050. X#include "modempool.h"
  1051. X
  1052. X#ifdef RLOGIN
  1053. X#include <pwd.h>
  1054. X#endif
  1055. X
  1056. X/*******************************************************************
  1057. X *        H D L _C O N N E C T
  1058. X *        --------------------
  1059. X *
  1060. X * Description:
  1061. X *    Handles initial connection to callback server.
  1062. X *
  1063. X * Arguments:
  1064. X *    mod_rc    - Return code from modem specifying connection.
  1065. X *
  1066. X *******************************************************************/
  1067. int
  1068. hdl_connect(int mod_rc)
  1069. X{
  1070. X    slot_t msg_slot;    /* A message carrier between do_login and callback */
  1071. X    int rc;
  1072. X
  1073. X    switch(mod_rc)
  1074. X    {
  1075. X    case MOD_CONNECT:
  1076. X    case MOD_CONNECT_300:
  1077. X    slot.baud = 300;
  1078. X    break;
  1079. X
  1080. X    case MOD_CONNECT_1200:
  1081. X    slot.baud = 1200;
  1082. X    break;
  1083. X        
  1084. X    case MOD_CONNECT_2400:
  1085. X    slot.baud = 2400;
  1086. X    break;
  1087. X        
  1088. X     case MOD_CONNECT_4800:
  1089. X    slot.baud = 4800;
  1090. X    break;
  1091. X        
  1092. X    case MOD_CONNECT_9600:
  1093. X    slot.baud = 9600;
  1094. X    break;
  1095. X
  1096. X    case MOD_RING:
  1097. X    case MOD_OK:
  1098. X    return E_RETRY;
  1099. X
  1100. X    default:
  1101. X    logerr("connect: unknown modem code: %d", mod_rc);
  1102. X    return E_FAIL;
  1103. X    }
  1104. X
  1105. X    /*
  1106. X     * Don't accept dialup orders during login.
  1107. X     */
  1108. X    slot.status = SLOT_LOGIN;
  1109. X    slot_write(&slot);
  1110. X
  1111. X    log("connected at baud %d", slot.baud);
  1112. X    /* Also set the message data to correct baud */
  1113. X    msg_slot.baud = slot.baud;
  1114. X
  1115. X    /*
  1116. X     * Setup port in sane mode.
  1117. X     */
  1118. X    tty_baud(slot.baud);
  1119. X    tty_local(0);
  1120. X    tty_sane();
  1121. X    tty_flush();
  1122. X
  1123. X    /*
  1124. X     * Request everything from calling user.
  1125. X     */
  1126. X    rc = do_login(&msg_slot);
  1127. X
  1128. X    tty_raw();
  1129. X
  1130. X    /* Turn back off DCD checking */
  1131. X    tty_local(1);
  1132. X
  1133. X    /* If login successful, do a callback.
  1134. X     * If I'm the only free server left, the
  1135. X     * call to callback will never return.
  1136. X     */
  1137. X    if (rc != E_OK)  {
  1138. X    return E_FAIL;
  1139. X    }
  1140. X
  1141. X    mod_put(MSG_HANGUP);
  1142. X    if (callback(&msg_slot) != E_OK) {
  1143. X    logerr("callback failed");
  1144. X    return E_FAIL;
  1145. X    }
  1146. X
  1147. X    return E_OK;
  1148. X}
  1149. X
  1150. X/*******************************************************************
  1151. X *
  1152. X *         DO_LOGIN
  1153. X *        --------
  1154. X *
  1155. X * Description:
  1156. X *    Reads username and password, does a check and return phone number
  1157. X *
  1158. X *******************************************************************/
  1159. int
  1160. do_login(slot_t *sp)
  1161. X{
  1162. X    char passwd[NAME_SIZE];        /* Temporary password        */
  1163. X    char str[200];            /* Temporary string             */
  1164. X    char *field[N_FIELDS];        /* Fields in the USERS file    */
  1165. X    int rc;                             /* Return code                  */
  1166. X    int retry;                /* Retry counter        */
  1167. X    FILE *fp;                /* Temporary file pointer    */
  1168. X    char *p;                /* Temporary char pointer    */
  1169. X
  1170. X    /*
  1171. X     * Give greetings message.
  1172. X     */
  1173. X    if ((fp = fopen(GREETINGSFILE, "r")) != NULL) {
  1174. X    while(fgets(str, sizeof str, fp) != NULL) {
  1175. X        mod_put(str);
  1176. X        mod_put("\r");
  1177. X    }
  1178. X    fclose(fp);
  1179. X    }
  1180. X    else {
  1181. X    logerr("failed to open greetings file");
  1182. X    }
  1183. X
  1184. X    for(retry = 0; retry < MAX_RETRY; retry++)
  1185. X    {
  1186. X    /* Get login name */
  1187. X    do {
  1188. X        rc = prompt(MSG_NAME, sp->name, sizeof sp->name, LOGIN_TMOUT);
  1189. X    }
  1190. X    while(rc == E_OK && strlen(sp->name) == 0);
  1191. X
  1192. X    if (rc != E_OK) {
  1193. X        if (rc == E_TMOUT) {
  1194. X        debug("do_login: timeout");
  1195. X            mod_put(MSG_LOGINFAIL);
  1196. X        return E_FAIL;
  1197. X        }
  1198. X        debug("do_login: login: rc = %d, errno = %d", rc, errno);
  1199. X        mod_put(MSG_LOGINFAIL);
  1200. X        continue;
  1201. X    }
  1202. X
  1203. X    /* Get passwd */
  1204. X    tty_noecho();
  1205. X    rc = prompt(MSG_PASSWD, passwd, sizeof passwd, LOGIN_TMOUT);
  1206. X    tty_echo();
  1207. X    mod_put("\r\n");
  1208. X
  1209. X    if (rc != E_OK) {
  1210. X        debug("do_login: passwd: rc = %d, errno = %d", rc, errno);
  1211. X        mod_put(MSG_LOGINFAIL);
  1212. X        continue;
  1213. X    }
  1214. X
  1215. X    /* Get user data */
  1216. X    if (db_find(USERS, field, sizeof field / sizeof field[0], 0, sp->name) != E_OK)
  1217. X    {
  1218. X        debug("do_login: db_find: rc = %d, errno = %d", rc, errno);
  1219. X            mod_put(MSG_LOGINFAIL);
  1220. X        continue;
  1221. X    }
  1222. X
  1223. X    /* Check validity */
  1224. X    if (field[0] == NULL || field[1] == NULL || field[2] == NULL
  1225. X#ifdef RLOGIN
  1226. X        || field[3] == NULL
  1227. X#endif
  1228. X       )
  1229. X    {
  1230. X        logerr("do_login: illegal data for user '%s'", sp->name);
  1231. X        mod_put(MSG_LOGINFAIL);
  1232. X        return E_FAIL;
  1233. X    }
  1234. X
  1235. X    /* Check if password is ok */
  1236. X    if (strcmp(field[1], passwd) != 0) {
  1237. X        debug("do_login: wrong password");
  1238. X        mod_put(MSG_LOGINFAIL);
  1239. X        continue;
  1240. X    }
  1241. X
  1242. X    /* Login succeded */
  1243. X    strncpy(sp->name, field[0], sizeof sp->name);
  1244. X#ifdef RLOGIN
  1245. X    strncpy(sp->host, field[3], sizeof sp->host);
  1246. X#endif
  1247. X
  1248. X    /*
  1249. X     * Check if wildcard phonenumber or phonenumber list.
  1250. X     */
  1251. X    if ((strchr(field[2], '*') != NULL) || (strchr(field[2], '/') != NULL)) {
  1252. X        /*
  1253. X         * Request phonenumber from user.
  1254. X         */
  1255. X        do {
  1256. X        rc = prompt(MSG_PHONE, sp->phone, sizeof sp->phone, LOGIN_TMOUT);
  1257. X        }
  1258. X        while(rc == E_OK && strlen(sp->phone) == 0);
  1259. X        if (rc != E_OK) {
  1260. X        log("failed to read phone number");
  1261. X        mod_put(MSG_LOGINFAIL);
  1262. X        continue;
  1263. X        }
  1264. X
  1265. X        /* 
  1266. X         * Check entered number against list.
  1267. X         */
  1268. X        for(p = strtok(field[2], "/"); p != NULL; p = strtok(NULL, "/"))
  1269. X        {
  1270. debug("trying '%s' vs. '%s'\n", p, sp->phone);
  1271. X        if ((strcmp(p, "*") == 0) || (strcmp(p, sp->phone) == 0)) {
  1272. X            break;
  1273. X        }
  1274. X        }
  1275. X        if (p == NULL) {
  1276. X        log("wrong phonenumber");
  1277. X        mod_put(MSG_LOGINFAIL);
  1278. X        continue;
  1279. X        }
  1280. X
  1281. X        if (strcmp(p, "*") == 0) {
  1282. X        log("privileged user '%s' succeded to login (phone: %s)", sp->name, sp->phone);
  1283. X        }
  1284. X        else {
  1285. X        log("user '%s' succeded to login (phone: %s)", sp->name, sp->phone);
  1286. X        }
  1287. X    }
  1288. X    else {
  1289. X        strncpy(sp->phone, field[2], sizeof sp->phone);
  1290. X        log("user '%s' succeded to login", sp->name);
  1291. X    }
  1292. X
  1293. X    return E_OK;
  1294. X    }
  1295. X    log("user '%s' tried to login but failed", sp->name);
  1296. X    return E_FAIL;
  1297. X}
  1298. END_OF_FILE
  1299. if test 6000 -ne `wc -c <'login.c'`; then
  1300.     echo shar: \"'login.c'\" unpacked with wrong size!
  1301. fi
  1302. # end of 'login.c'
  1303. fi
  1304. if test -f 'modem.c' -a "${1}" != "-c" ; then 
  1305.   echo shar: Will not clobber existing file \"'modem.c'\"
  1306. else
  1307. echo shar: Extracting \"'modem.c'\" \(6023 characters\)
  1308. sed "s/^X//" >'modem.c' <<'END_OF_FILE'
  1309. X/*******************************************************************
  1310. X * 
  1311. X * Module: @(#)modem.c    4.2 92/04/16
  1312. X *
  1313. X * Description:
  1314. X *    Handle various modem functions.
  1315. X *
  1316. X * Revision:
  1317. X *    Date    By            Reason    
  1318. X *    ----    --            ------    
  1319. X *    920306    Lars Berntzon        Created
  1320. X *
  1321. X *******************************************************************/
  1322. static char SccsId[] = "@(#)modem.c    4.2 92/04/16";
  1323. X
  1324. X#include <stdio.h>
  1325. X#include <string.h>
  1326. X#include <stdarg.h>
  1327. X#include <ctype.h>
  1328. X
  1329. X#include "modempool.h"
  1330. X
  1331. X#define N_MOD_CMDS (sizeof mod_cmds / sizeof mod_cmds[0])
  1332. static char *mod_cmds[] = { 
  1333. X  "*", "CONNECT\r", "CONNECT 300\r", "CONNECT 1200\r", "CONNECT 2400\r",
  1334. X  "RING\r", "BUSY\r", "ERROR\r", "NO CARRIER\r", "OK\r",
  1335. X  "CONNECT 4800\r", "CONNECT 9600\r"
  1336. X};
  1337. X
  1338. static char *cmd_str(int n);
  1339. X
  1340. X/*
  1341. X * Routines.
  1342. X */
  1343. X
  1344. X/*******************************************************************
  1345. X *
  1346. X *         M O D _ S E T U P
  1347. X *        -----------------
  1348. X *
  1349. X * Description:
  1350. X *    Sets the modem to a correct state.
  1351. X *
  1352. X *******************************************************************/
  1353. X
  1354. int
  1355. mod_setup(void)
  1356. X{
  1357. X    int retry;
  1358. X    int rc = 0;
  1359. X
  1360. X    for(retry = 0; retry < 2; retry++) {
  1361. X    if ((rc = mod_put(initstr)) == E_OK   &&
  1362. X        (rc = mod_put("\r")) == E_OK   &&
  1363. X        (rc = mod_exp(MOD_OK, 0)) == E_OK) return E_OK;
  1364. X    }
  1365. X
  1366. X    logerr("setup_modem: failed ( %d)", rc);
  1367. X    return rc;
  1368. X}
  1369. X
  1370. X/*******************************************************************
  1371. X *        M O D _ P U T
  1372. X *        -------------
  1373. X *
  1374. X * Description:
  1375. X *    Initialize the modem (hayes commands).
  1376. X *
  1377. X *******************************************************************/
  1378. mod_put(char *msg)
  1379. X{
  1380. X    int rc;
  1381. X
  1382. X    debug("mod_put(\"%s\")", msg);
  1383. X
  1384. X    trig(2);
  1385. X    rc = tty_write(msg, strlen(msg));
  1386. X    if (istimeout()) {
  1387. X    return E_TMOUT;
  1388. X    }
  1389. X    
  1390. X    if (rc < 0) {
  1391. X        logerr("mod_put: failed to write");
  1392. X        return E_WRITE;
  1393. X    }
  1394. X    
  1395. X    return E_OK;
  1396. X}
  1397. X
  1398. X/*******************************************************************
  1399. X *        M O D _ E X P
  1400. X *        -------------
  1401. X *
  1402. X * Description:
  1403. X *    Expect answer from modem.
  1404. X *
  1405. X * Arguments:
  1406. X *    expected    - Answer type (integern enumeration)
  1407. X *    tmout        - Timeout (0 means default)
  1408. X *
  1409. X *******************************************************************/
  1410. mod_exp(int expected, int tmout)
  1411. X{
  1412. X    va_list arg = NULL;
  1413. X    int exp_len = 0;
  1414. X    char buf[MATCH_SIZE];
  1415. X    int buf_len;
  1416. X    int pos = 0;
  1417. X    int i = 0;
  1418. X
  1419. X    /* Used default timeout if none specified */
  1420. X    if (tmout == 0) tmout = MODEM_TMOUT;
  1421. X
  1422. X    debug("expecting(\"%s\")", cmd_str(expected));
  1423. X    /* Read until text matches but not more than can fit into bufer */
  1424. X    while(pos < MATCH_SIZE)
  1425. X    {
  1426. X    buf[pos] = 0;
  1427. X
  1428. X        /* Read with timeout */
  1429. X        trig(tmout);
  1430. X        buf_len = tty_read(buf + pos++, 1);
  1431. X    if(istimeout()) {
  1432. X        return E_TMOUT;
  1433. X    }
  1434. X
  1435. X    /*
  1436. X     * Some one called us ?.
  1437. X     */
  1438. X    if (buf_len <= 0 && signalled) {
  1439. X        return E_TMOUT;
  1440. X    }
  1441. X
  1442. X        if (buf_len < 0) return E_READ;
  1443. X
  1444. X    if (!isprint(buf[pos - 1])) {
  1445. X        debugnonl("(0x%X)",  buf[pos - 1]);
  1446. X    }
  1447. X    else {
  1448. X        debugnonl("%c",  buf[pos - 1]);
  1449. X    }
  1450. X    
  1451. X        /* Check if any was right */
  1452. X        for(i = 0; i < N_MOD_CMDS; i++)
  1453. X        {
  1454. X        exp_len = strlen(mod_cmds[i]);
  1455. X        if (pos < exp_len) continue;
  1456. X            if (memcmp(mod_cmds[i], buf + pos - exp_len, exp_len) == 0) break;
  1457. X        }
  1458. X        if (i < N_MOD_CMDS)
  1459. X        {
  1460. X            buf[pos + 1] = 0;
  1461. X        debug("gotten(\"%s\")", cmd_str(i));
  1462. X        if (expected == MOD_ANY || expected == i)
  1463. X        {
  1464. X        /* Return what arrived if awaited for any */
  1465. X        if (expected == MOD_ANY) return i;
  1466. X
  1467. X        /*
  1468. X         * Otherwise just return that what had been awaited for
  1469. X         * has arrived OK.
  1470. X         */
  1471. X                return E_OK;
  1472. X        }
  1473. X        }
  1474. X    }
  1475. X
  1476. X    logerr("mod_exp: never got any sane answer from modem (%s)", buf);
  1477. X    return E_FAIL;
  1478. X}
  1479. X
  1480. X/************************************************************************
  1481. X *
  1482. X *            MOD_DIAL
  1483. X *            --------
  1484. X * Description:
  1485. X *     Dials a number
  1486. X *
  1487. X * Arguments:
  1488. X *    prefix    - Prefix telephone number, like '0w' to get external line.
  1489. X *    phone    - The phone number.
  1490. X *
  1491. X ************************************************************************/
  1492. mod_dial(char *prefix, char *phone)
  1493. X{
  1494. X    int rc;
  1495. X    int i;
  1496. X
  1497. X    /* Retry 3 times*/
  1498. X    for(i = 0; i < 5; i++)
  1499. X    {
  1500. X        /* Dialup */
  1501. X        mod_put("ATDT");
  1502. X        mod_put(prefix);
  1503. X        mod_put(phone);
  1504. X    mod_put("\r");
  1505. X
  1506. X    /* Wait for answer */
  1507. X        switch(mod_exp(MOD_ANY, 15))
  1508. X        {
  1509. X    case MOD_CONNECT:
  1510. X    case MOD_CONNECT_1200:
  1511. X    case MOD_CONNECT_2400:
  1512. X        log("dialup: succeded to dial '%s'", phone);
  1513. X        return E_OK;
  1514. X
  1515. X    case MOD_BUSY:
  1516. X        log("dialup: busy");
  1517. X        break;
  1518. X
  1519. X    case MOD_NO_CARRIER:
  1520. X        logerr("dialup: no carrier for phone '%s'", phone);
  1521. X    }
  1522. X    }    
  1523. X}
  1524. X
  1525. X/*******************************************************************
  1526. X *
  1527. X *         PROMPT
  1528. X *        ------
  1529. X *
  1530. X * Description:
  1531. X *    Writes prompt to port and reads line.
  1532. X *
  1533. X * Arguments:
  1534. X *    msg    - Prompt message.
  1535. X *    dest    - Where to store answer.
  1536. X *    size    - Dont read more than this.
  1537. X *    tmout    - Timeout, 0 means no timeout.
  1538. X *
  1539. X *******************************************************************/
  1540. int prompt(char *msg, char *dest, int size, int tmout)
  1541. X{
  1542. X    int i;
  1543. X    if (mod_put(msg) < 0)
  1544. X    {
  1545. X    logerr("prompt: failed to write to port");            
  1546. X    return E_FAIL;
  1547. X    }
  1548. X
  1549. X    trig(tmout);
  1550. X    size = tty_read(dest, size);
  1551. X    if (istimeout()) {
  1552. X    return E_TMOUT;
  1553. X    }
  1554. X
  1555. X    if (size < 0) {
  1556. X        logerr("prompt: failed to read");
  1557. X        return E_READ;
  1558. X    }
  1559. X
  1560. X    /* User pressed EOF */
  1561. X    if (size == 0)
  1562. X    {
  1563. X    mod_put(MSG_ABORTED);
  1564. X    return E_FAIL;
  1565. X    }
  1566. X
  1567. X    /* Remove leading blanks */
  1568. X    for(i = 0; i < size && isspace(dest[i]); i++)
  1569. X    ;
  1570. X
  1571. X    memcpy(dest, dest + i, size -= i);
  1572. X
  1573. X    /* Remove trailing blanks */    
  1574. X    for(i = size - 1; i >= 0 && isspace(dest[i]); i--,size --)
  1575. X    ;
  1576. X
  1577. X    dest[i + 1] = 0;
  1578. X
  1579. X    return E_OK;
  1580. X}
  1581. X
  1582. X/***************************************
  1583. X * Return ascii value for modem answers.
  1584. X ***************************************/
  1585. static char *cmd_str(int n)
  1586. X{
  1587. X    if (n < 0 || n > N_MOD_CMDS) {
  1588. X    return "[unknown]";
  1589. X    }
  1590. X
  1591. X    return mod_cmds[n];
  1592. X}
  1593. END_OF_FILE
  1594. if test 6023 -ne `wc -c <'modem.c'`; then
  1595.     echo shar: \"'modem.c'\" unpacked with wrong size!
  1596. fi
  1597. # end of 'modem.c'
  1598. fi
  1599. if test -f 'modempool.1' -a "${1}" != "-c" ; then 
  1600.   echo shar: Will not clobber existing file \"'modempool.1'\"
  1601. else
  1602. echo shar: Extracting \"'modempool.1'\" \(2338 characters\)
  1603. sed "s/^X//" >'modempool.1' <<'END_OF_FILE'
  1604. X.\" @(#)modempool.1    4.1 
  1605. X.TH MODEMPOOL 1V "920421"
  1606. X.SH NAME
  1607. modempool \- Program for handling modempools
  1608. X.SH SYNOPSIS
  1609. X.B modempool
  1610. X[
  1611. X.B \-d 
  1612. X]
  1613. X[
  1614. X.B \-p
  1615. prefix
  1616. X]
  1617. X[
  1618. X.B \-i 
  1619. initstring
  1620. X]
  1621. X.B speed line
  1622. X.SH DESCRIPTION
  1623. modempool is a program for handling a pool of modems. For each modem
  1624. connected to the system there should be a modempool process running.
  1625. All modempool processes communicate with each other and when a 
  1626. users calls one modem, the modempool server checks that the user is
  1627. allowed to log in and then tells another modempool process to do the
  1628. callback.
  1629. This has the effect that only one modem phone number has to be known by
  1630. the users, i.e. modempool works as a switchboard. Also users doesn't
  1631. have to try to call different numbers until he finds a free line, modempool
  1632. will do that for him.
  1633. XFinally only one external telephone line has to exist, the other modems
  1634. can sit on local lines but with the -p option set (usually to '0w').
  1635. X.ne 8
  1636. X.SH OPTIONS
  1637. X.TP
  1638. X.B \-d
  1639. Turn on debugging mode. All output goes to the log-file.
  1640. X.TP
  1641. X.B \-p
  1642. Specify what prefix to use before phonenumber. This usually is '0w' to 
  1643. get an external line on many switchboards.
  1644. X.TP
  1645. X.B \-i
  1646. Specify initialization string for the modem. The default string is: 'AT&FQ0E0S0=1&D2&C1'
  1647. but you may also try: 'AT&FQ0E0S0=1&D2&C1*G0&I0'.
  1648. X.TP
  1649. X.B speed
  1650. This is the initial baudrate modempool will use.
  1651. X.TP
  1652. X.B line
  1653. The is the name of the tty-device with the path '/dev/' removed,
  1654. ex. tty00h.
  1655. X.SH FILES
  1656. X.PD 0
  1657. X.TP 20
  1658. X.B /etc/local/modempool/Users
  1659. This is a list of users allowed to log in. Each row contains a couple
  1660. of fields separated by colons. The first field is the user name, the second is
  1661. his dialup password (don't use the real user password), the third field is a slash-separated
  1662. list of valid phonenumbers for user (or asterisk for any number). The fourth field is
  1663. the host to rlogin to when user loggs in (only if compiled with the -DRLOGIN flag).
  1664. X.TP 20
  1665. X.B /etc/local/modempool/Greetings
  1666. Text to print when modempool is called.
  1667. X.TP 20
  1668. X.B /etc/local/modempool/serverdb
  1669. Database file where all modempool servers register.
  1670. X.TP 20
  1671. X.B /etc/local/modempool/log
  1672. Log of all users loggin in.
  1673. X.TP 20
  1674. X.B /etc/local/modempool/errlog
  1675. Log of all errors detected by modempool.
  1676. X.SH "SEE ALSO"
  1677. X.PD
  1678. X.BR poolstat (1V)
  1679. X.br
  1680. X.ne 5
  1681. X.SH BUGS
  1682. X.LP
  1683. Currently only Hayes modems is supported.
  1684. END_OF_FILE
  1685. if test 2338 -ne `wc -c <'modempool.1'`; then
  1686.     echo shar: \"'modempool.1'\" unpacked with wrong size!
  1687. fi
  1688. # end of 'modempool.1'
  1689. fi
  1690. if test -f 'modempool.c' -a "${1}" != "-c" ; then 
  1691.   echo shar: Will not clobber existing file \"'modempool.c'\"
  1692. else
  1693. echo shar: Extracting \"'modempool.c'\" \(5892 characters\)
  1694. sed "s/^X//" >'modempool.c' <<'END_OF_FILE'
  1695. X/*******************************************************************
  1696. X * 
  1697. X * Module: @(#)modempool.c    4.2 92/04/16
  1698. X *
  1699. X * Description:
  1700. X *    Main file for the modempool daemon.
  1701. X *
  1702. X * Revision:
  1703. X *    Date    By            Reason    
  1704. X *    ----    --            ------    
  1705. X *    910114    Lars Berntzon        Created
  1706. X *      910124  Lars H Carlsson     Lock line before calling /bin/login
  1707. X *    910129    Lars Berntzon        Lockfile is removed at startup,
  1708. X *                    lockfile would otherwise stay after
  1709. X *                    user has logged out.
  1710. X *    910129    Lars Berntzon        Using termio to make port eightbit.
  1711. X *
  1712. X *******************************************************************/
  1713. static char SccsId[] = "@(#)modempool.c    4.2 92/04/16";
  1714. X
  1715. X#include <stdio.h>
  1716. X#ifndef NOSTDLIB
  1717. X#include <stdlib.h>
  1718. X#endif
  1719. X#include <unistd.h>
  1720. X#include <string.h>
  1721. X#include <signal.h>
  1722. X#include <fcntl.h>
  1723. X#include <stdarg.h>
  1724. X#include <termios.h>
  1725. X#include <ctype.h>
  1726. X
  1727. X#include "modempool.h"
  1728. X
  1729. X#ifdef RLOGIN
  1730. X#include <pwd.h>
  1731. X#endif
  1732. X
  1733. X/*
  1734. X * G l o b a l   d e f i n i t i o n .
  1735. X */
  1736. char line[NAME_SIZE];           /* Line this server uses        */
  1737. char portname[NAME_SIZE];       /* Full pathname for this line        */
  1738. char prefix[NAME_SIZE];         /* Prefix for dialing, ex. '0W'        */
  1739. int signalled;                  /* Indicates that serves should dialup    */
  1740. int debug_lvl = 0;              /* Of non zero debugging is one        */
  1741. char *initstr = INITSTRING;    /* Modem initializing string        */
  1742. slot_t slot;            /* Slot record for this server        */
  1743. X
  1744. X
  1745. X/*
  1746. X * L o c a l   s t u f f .
  1747. X */
  1748. static void hdl_signal(void);
  1749. X
  1750. X/*
  1751. X * M a i n   r o u t i n e .
  1752. X */
  1753. int
  1754. main(int argc, char **argv)
  1755. X{
  1756. X    char phone[NAME_SIZE];    /* User phone number            */
  1757. X    char name[NAME_SIZE];    /* User name                            */
  1758. X#ifdef RLOGIN
  1759. X    char host[NAME_SIZE];    /* Host name                            */
  1760. X#endif
  1761. X    int baud = 0;        /* Connected baudrate            */
  1762. X    int default_baud;        /* Default baudrate (command line arg)    */
  1763. X    int fd;            /* Port file descriptor            */
  1764. X    int rc;            /* Return code                */
  1765. X
  1766. X    /*
  1767. X     * Setup signals.
  1768. X     */
  1769. X    signal(SIGALRM, SIG_IGN);
  1770. X    signal(SIGCLD, SIG_IGN);
  1771. X    signal(SIGINT, SIG_IGN);
  1772. X    signal(SIGQUIT, SIG_IGN);
  1773. X#ifdef SV_INTERRUPT
  1774. X    /*
  1775. X     * Use sigvec if exists.
  1776. X     */
  1777. X    {
  1778. X    struct sigvec vec;
  1779. X    vec.sv_handler = hdl_signal;
  1780. X    vec.sv_mask = 0;
  1781. X    vec.sv_flags = SV_INTERRUPT;
  1782. X    sigvec(SIG_SERVER, &vec, NULL);
  1783. X    }
  1784. X#else
  1785. X    signal(SIG_SERVER, hdl_signal);
  1786. X#endif
  1787. X
  1788. X    /*
  1789. X     * Get commandline arguments.
  1790. X     */
  1791. X    getargs(&argc, &argv);
  1792. X
  1793. X    /*
  1794. X     * Save args into globals
  1795. X     */
  1796. X    if ((default_baud = atoi(argv[1])) == 0) usage();
  1797. X
  1798. X    strcpy(line, argv[2]);
  1799. X    sprintf(portname, "/dev/%s", line);
  1800. X
  1801. X    chmod(portname, 0777);
  1802. X
  1803. X    /*
  1804. X     * Make own processgroup, thereby make port as the controlling terminal.
  1805. X     */
  1806. X#ifdef _POSIX_JOB_CONTROL
  1807. X    if (setsid() < 0) fatal("failed to setsid");
  1808. X#else
  1809. X    if (setpgrp() < 0) fatal("failed to setpgrp");
  1810. X#endif
  1811. X
  1812. X    /*
  1813. X     * Allocate slot for this server in the server database (only once).
  1814. X     */
  1815. X    if (slot_alloc(&slot) != E_OK) {
  1816. X    fatal("failed to allocate slot");
  1817. X    }
  1818. X
  1819. X    /*
  1820. X     * Output start message.
  1821. X     */
  1822. X    if (log("modempool started with %d baud", default_baud) != E_OK) {
  1823. X        fatal("failed to open log file");
  1824. X    }
  1825. X
  1826. X    /*
  1827. X     * Loop through modem-setup and login-wait.
  1828. X     */
  1829. X    while(1)
  1830. X    {
  1831. X    /* 
  1832. X     * Wait for port to become free.
  1833. X     */
  1834. X    lock_wait(line);
  1835. X
  1836. X    /*
  1837. X     * Open port for seting up modem.
  1838. X     */
  1839. X    if (tty_open(portname, default_baud, O_NDELAY) != E_OK) {
  1840. X        logerr("failed to open main port");
  1841. X        slot.status = SLOT_FAULT;
  1842. X        slot_write(&slot);
  1843. X        sleep(5);
  1844. X        continue;
  1845. X    }
  1846. X    if (mod_setup() != E_OK) {
  1847. X        logerr("failed to setup modem");
  1848. X        slot.status = SLOT_FAULT;
  1849. X        slot_write(&slot);
  1850. X        tty_hangup();
  1851. X        tty_close();
  1852. X        continue;
  1853. X    }
  1854. X
  1855. X    debug("modem setup ok");
  1856. X
  1857. X    /*
  1858. X     * I will accept dialup command.
  1859. X     */
  1860. X    slot.status = SLOT_FREE;
  1861. X    slot_write(&slot);
  1862. X    
  1863. X    /*
  1864. X     * This open will hang until carrier detect ( = someone called),
  1865. X     * signalled or timeout.
  1866. X     */
  1867. X    tty_local(0);
  1868. X    trig(OPEN_TMOUT);
  1869. X    fd = open(portname, O_RDONLY);
  1870. X    if (fd < 0) {
  1871. X        if (!signalled) {
  1872. X        if (!istimeout()) {
  1873. X            logerr("failed to open port");
  1874. X        }
  1875. X        continue;
  1876. X        }
  1877. X    }
  1878. X    close(fd);
  1879. X    debug("port opened with no CLOCAL");
  1880. X
  1881. X    /*
  1882. X     * If signalled it means i've got a phone number to dial.
  1883. X     */
  1884. X    if (signalled)
  1885. X    {
  1886. X        debug("signalled in tty_open, doing dialup");
  1887. X        dialup();
  1888. X        /*
  1889. X         * Should never get here - mark as free again.
  1890. X         */
  1891. X        log("dialup failed");
  1892. X        unlock_line(line);
  1893. X        slot_free(&slot);
  1894. X        tty_hangup();
  1895. X        tty_close();
  1896. X        continue;
  1897. X    }
  1898. X
  1899. X
  1900. X    /*
  1901. X     * Check if it's for me.
  1902. X     */
  1903. X    if (lock_line(line, getpid()) != E_OK) {
  1904. X        debug("line was not free");
  1905. X        continue;
  1906. X    }
  1907. X    debug("line was for me");
  1908. X
  1909. X    /*
  1910. X     * Read commands from modem and take action.
  1911. X     */
  1912. X    while(1)
  1913. X    {
  1914. X        rc = mod_exp(MOD_ANY, RESET_TMOUT);
  1915. X        debug("got %d from modem", rc);
  1916. X
  1917. X        /*
  1918. X         * Got signal, do dialup.
  1919. X         */
  1920. X        if (signalled) {
  1921. X        debug("signaled in mod_exp, doing dialup");
  1922. X        dialup();
  1923. X        log("dialup failed");
  1924. X        break;
  1925. X        }
  1926. X
  1927. X        rc = hdl_connect(rc);
  1928. X        if (rc == E_RETRY) {
  1929. X        continue;
  1930. X        }
  1931. X        else {
  1932. X        break;
  1933. X        }
  1934. X    }
  1935. X
  1936. X    slot_free(&slot);
  1937. X    unlock_line(line);
  1938. X    tty_hangup();
  1939. X    tty_close();
  1940. X    debug("restarting");
  1941. X    }        
  1942. X
  1943. X    logerr("modempool: slipped out of main loop");
  1944. X    exit(1);
  1945. X}
  1946. X
  1947. X/**********************************************************
  1948. X *        H D L _ S I G N A L 
  1949. X *        -------------------
  1950. X *
  1951. X * Description:
  1952. X *    This gets called when a server is told to dialup.
  1953. X *
  1954. X **********************************************************/
  1955. static void hdl_signal(void)
  1956. X{
  1957. X#ifdef SV_INTERRUPT
  1958. X    /*
  1959. X     * Use sigvec if exists.
  1960. X     */
  1961. X    {  
  1962. X    struct sigvec vec;
  1963. X    vec.sv_handler = hdl_signal;
  1964. X    vec.sv_mask = 0;
  1965. X    vec.sv_flags = SV_INTERRUPT;
  1966. X    sigvec(SIG_SERVER, &vec, NULL);
  1967. X    }  
  1968. X#else
  1969. X    signal(SIG_SERVER, hdl_signal);
  1970. X#endif
  1971. X
  1972. X    signalled = 1;
  1973. X    debug("(signalled)");
  1974. X}
  1975. END_OF_FILE
  1976. if test 5892 -ne `wc -c <'modempool.c'`; then
  1977.     echo shar: \"'modempool.c'\" unpacked with wrong size!
  1978. fi
  1979. # end of 'modempool.c'
  1980. fi
  1981. if test -f 'modempool.h' -a "${1}" != "-c" ; then 
  1982.   echo shar: Will not clobber existing file \"'modempool.h'\"
  1983. else
  1984. echo shar: Extracting \"'modempool.h'\" \(6494 characters\)
  1985. sed "s/^X//" >'modempool.h' <<'END_OF_FILE'
  1986. X/*******************************************************************
  1987. X * 
  1988. X * Module: @(#)modempool.h    4.4 92/04/22
  1989. X *
  1990. X * Description:
  1991. X *    Header file fore the modempool package.    
  1992. X * 
  1993. X * Revision:
  1994. X *    Date    By        Reason    
  1995. X *    ----    --        ------    
  1996. X *    910414    Lars Berntzon    Created
  1997. X *
  1998. X *******************************************************************/
  1999. X#include "patchlevel.h"
  2000. X
  2001. static char SccsId_modempool_h[] = "@(#)modempool.h    4.4 92/04/22";
  2002. X
  2003. X#ifndef _MODEMPOOL_H
  2004. X#define _MODEMPOOL_H
  2005. X
  2006. X#ifdef DEBUG
  2007. X#  define USERS      "Users"
  2008. X#  define LINES      "Lines"
  2009. X#  define LOGFILE "log"
  2010. X#  define ERRLOGFILE "errlog"
  2011. X#  define GREETINGSFILE    "Greetings"
  2012. X#  define GREETINGSFILE    "Greetings"
  2013. X#  define SERVERDB    "serverdb"
  2014. X#  define LOCKFILE    "serverdb.lock"
  2015. X#else
  2016. X#  define USERS        "/etc/local/modempool/Users"
  2017. X#  define LINES        "/etc/local/modempool/Lines"
  2018. X#  define LOGFILE    "/etc/local/modempool/log"
  2019. X#  define ERRLOGFILE    "/etc/local/modempool/errlog"
  2020. X#  define GREETINGSFILE    "/etc/local/modempool/Greetings"
  2021. X#  define SERVERDB    "/etc/local/modempool/serverdb"
  2022. X#  define LOCKFILE    "/etc/local/modempool/serverdb.lock"
  2023. X#endif
  2024. X#define LOCKDIR    "/usr/spool/locks"
  2025. X
  2026. X#define E_OK        0    /* No errors                */
  2027. X#define E_FAIL        -1    /* Generic fail                */
  2028. X#define E_TMOUT         -2    /* Got timeout                */
  2029. X#define E_SYNTAX    -3    /* Syntax error                */
  2030. X#define E_OPEN        -4    /* Failed to open file            */
  2031. X#define E_READ        -5    /* Failed to read file            */
  2032. X#define E_WRITE        -6    /* Failed to write file            */
  2033. X#define E_LOCK        -7    /* Failed to lock            */
  2034. X#define E_UNLINK    -8    /* Failed to unlink            */
  2035. X#define E_PROC_EXIST    -9    /* Process alldready exist        */
  2036. X#define E_LOGIN        -10    /* Failed to login            */
  2037. X#define E_NOTFOUND    -11    /* Key not found            */
  2038. X#define E_EOF        -12    /* Reached enf of file/data        */
  2039. X#define E_RETRY        -13    /* Not completely wrong, try again    */
  2040. X
  2041. X#define INITSTRING "AT&FQ0E0S0=1&D2&C1\r"    /* Modem init string    */
  2042. X
  2043. X
  2044. X/*
  2045. X * Various messages to user.
  2046. X */
  2047. X#define MSG_LOGIN    "login: "
  2048. X#define MSG_NAME    "Name: "
  2049. X#define MSG_PASSWD    "Password: "
  2050. X#define MSG_ABORTED    "login aborted\r\n"
  2051. X#define MSG_LOGINFAIL    "login failed\r\n"
  2052. X#define MSG_HANGUP    "hanging up\r\n"
  2053. X#define MSG_TIMEOUT    "timed out\r\n"
  2054. X#define MSG_CALLING    "I will call you back, hang on.\r\n"
  2055. X#define MSG_NOLINES    "There are currently no free lines.\r\n"
  2056. X#define MSG_USAGE    "usage: modempool [-p prefix] [-i initstr] [-d] speed ttyxx\r\n"
  2057. X#define MSG_PHONE    "Phone: "
  2058. X
  2059. X/*
  2060. X * Return codes and arguments to/from mod_exp.
  2061. X */
  2062. X#define MOD_ANY            0    /* Wait for any of the below    */
  2063. X#define MOD_CONNECT        1
  2064. X#define MOD_CONNECT_300        2
  2065. X#define MOD_CONNECT_1200    3
  2066. X#define MOD_CONNECT_2400    4
  2067. X#define MOD_RING        5
  2068. X#define MOD_BUSY        6
  2069. X#define MOD_ERRO        7
  2070. X#define MOD_NO_CARRIER        8
  2071. X#define MOD_OK            9
  2072. X#define MOD_CONNECT_4800    10
  2073. X#define MOD_CONNECT_9600    11
  2074. X
  2075. X#define NAME_SIZE    200    /* Generic string size                  */
  2076. X#define MATCH_SIZE    400    /* Maximum size of expected data from modem   */
  2077. X#define MAX_RETRY    3
  2078. X#define OPEN_TMOUT    (10*60)    /* Timeout for opening the tty port          */
  2079. X#define LOGIN_TMOUT    30    /* Timeout for login                  */
  2080. X#define MODEM_TMOUT    1    /* Default timeout for avaiting modem answer  */
  2081. X#define RESET_TMOUT    180    /* Interval for resetting modem when waiting  */
  2082. X#define DIALUP_TMOUT    60    /* Time for dialing a number              */
  2083. X#define DIALUP_DELAY    15    /* Time to wait before dialing                */
  2084. X#ifdef RLOGIN
  2085. X#define N_FIELDS    4    /* Number if valid fields in user database    */
  2086. X#else
  2087. X#define N_FIELDS    3
  2088. X#endif
  2089. X
  2090. X#define SLOT_FREE        0    /* Server is free for allocation    */
  2091. X#define SLOT_BUSY        1    /* Server is busy dialing person    */
  2092. X#define SLOT_LOGIN        2    /* Server is handling login        */
  2093. X#define SLOT_FAULT        3    /* Server has detected fault        */
  2094. X
  2095. X#define SIG_SERVER        SIGUSR1
  2096. X
  2097. X/*
  2098. X * Types and structs.
  2099. X */
  2100. X
  2101. struct slot {
  2102. X    int id;            /* Id for this slot                  */
  2103. X    char line[15];        /* Line this server controls              */
  2104. X    char name[30];        /* Synonym for calling person                  */
  2105. X#ifdef RLOGIN
  2106. X    char host[20];        /* Host for rlogin.                  */
  2107. X#endif
  2108. X    int status;            /* Status of server, SLOT_FREE e.t.c.          */
  2109. X    int pid;            /* pid of server                  */
  2110. X    char phone[15];        /* Phone number this server should dial          */
  2111. X    int baud;            /* What baud to use when dialing          */
  2112. X};
  2113. typedef struct slot slot_t;    /* Type for slots */
  2114. X
  2115. X/*
  2116. X * Globals.
  2117. X */
  2118. extern char line[NAME_SIZE];    /* Name port this program is using          */
  2119. extern char portname[NAME_SIZE];/* Full pathname of port               */
  2120. extern char prefix[NAME_SIZE];    /* Prefix string before phone number          */
  2121. extern slot_t slot;        /* Slotid for this server in serverdb          */
  2122. extern int signalled;        /* Tells server it should dial a number       */
  2123. extern int port_fd;        /* File descriptor for open port          */
  2124. extern int debug_lvl;        /* Nonzero if debugging is active          */
  2125. extern char *initstr;        /* Modem initializing string            */
  2126. X
  2127. X/* support routines */
  2128. extern int debug(char *fmt, ...);
  2129. extern int debugnonl(char *fmt, ...);
  2130. extern int log(char *fmt, ...);
  2131. extern int logerr(char *fmt, ...);
  2132. extern void fatal(char *msg);
  2133. extern void usage(void);
  2134. extern int trig(int tmout);
  2135. extern int istimeout(void);
  2136. X
  2137. X/* db routines */
  2138. extern int db_find(char *file, char **ptrs, int n_ptrs,int key, char *key_val);
  2139. X
  2140. X/* mod routines */
  2141. extern mod_put(char *msg);
  2142. extern mod_exp(int cmd, int tmout);
  2143. extern mod_dial(char *prefix, char *phone);
  2144. extern int mod_setup(void);
  2145. X
  2146. X/* slot routines */
  2147. extern int slot_alloc(slot_t *sp);
  2148. extern int slot_free(slot_t *sp);
  2149. extern int slot_open(void);
  2150. extern int slot_close(void);
  2151. extern int slot_traverse(slot_t *sp);
  2152. extern int slot_read(slot_t *sp);
  2153. extern int slot_write(slot_t *sp);
  2154. extern int slot_lock(void);
  2155. extern int slot_unlock(void);
  2156. X
  2157. X/* tty routines */
  2158. extern int tty_open(char *filename, int baud, int flags);
  2159. extern int tty_close(void);
  2160. extern int tty_read(char *buf, int len);
  2161. extern int tty_write(char *buf, int len);
  2162. extern int tty_ndelay(int on);
  2163. extern int tty_hangup(void);
  2164. extern int tty_raw(void);
  2165. extern int tty_sane(void);
  2166. extern int tty_baud(int baud);
  2167. extern int tty_setup(void);
  2168. extern int tty_clocal(void);
  2169. extern int tty_echo(void);
  2170. extern int tty_noecho(void);
  2171. extern int tty_drain(void);
  2172. extern int tty_flush(void);
  2173. X
  2174. X/* lock routines */
  2175. extern int lock_line(char *line, int pid);
  2176. extern int unlock_line(char *line);
  2177. extern int relock_line(char *line);
  2178. extern int lock_wait(char *line);
  2179. X
  2180. X/* getargs */
  2181. extern int getargs(int *argc, char ***argv);
  2182. X
  2183. X/* dialup and login routines */
  2184. extern int do_login(slot_t *sp);
  2185. extern int callback(slot_t *sp);
  2186. X
  2187. X#endif /* _MODEMPOOL_H */
  2188. END_OF_FILE
  2189. if test 6494 -ne `wc -c <'modempool.h'`; then
  2190.     echo shar: \"'modempool.h'\" unpacked with wrong size!
  2191. fi
  2192. # end of 'modempool.h'
  2193. fi
  2194. if test -f 'modempool.te' -a "${1}" != "-c" ; then 
  2195.   echo shar: Will not clobber existing file \"'modempool.te'\"
  2196. else
  2197. echo shar: Extracting \"'modempool.te'\" \(4253 characters\)
  2198. sed "s/^X//" >'modempool.te' <<'END_OF_FILE'
  2199. X% @(#)modempool.te    4.4 92/04/21 - Modempool.
  2200. X\newcommand{\modempool}{{\em modempool\ }}
  2201. X\documentstyle{article}
  2202. X\begin{document}
  2203. X
  2204. X\title{Modempool}
  2205. X\author{Lars Berntzon}
  2206. X\maketitle
  2207. X
  2208. X\section*{Description}
  2209. X
  2210. Modempool is a modem server that does a security check of a calling user and then calls that
  2211. user back if he/she is permitted. 
  2212. Modempool works in two modes simultaniously, either it is listening for
  2213. incomming calls, or it will dial up a user if another \modempool server tells
  2214. it to do so.
  2215. X
  2216. When the first connection is made to the \modempool server the user will be
  2217. prompted for name and password, if not OK the user is disconnected and
  2218. a logg record is written.
  2219. otherwise \modempool will check the file {\em /etc/local/modempool/Users} to see
  2220. what phone number to use for calling the user, it then looks up another free
  2221. modempool server whom it tells to dialup the user, i.e. it does not call the user it
  2222. self but order another server to do so, the reason for this is that it enables
  2223. this port to be used again for a new connection.
  2224. X
  2225. This functionality is usefull for instance for sites that lacks many external phone numbers, 
  2226. but instead has many local lines that cannot be dialed from outside but can only be used for
  2227. dialing out.
  2228. X
  2229. Also it simplifies the administration of a modempool by having only one known telephone
  2230. number that everyone dials.
  2231. X
  2232. When the \modempool server is called it checks the connection baudrate and sets the
  2233. terminal port to that speed. This makes it possible to have cheap modems and still handle
  2234. multiple baudrate dialups. When the user later on is called the same baudrate will be used.
  2235. X
  2236. The way a serve finds out other free servers is done by looking in the file
  2237. X{\em /etc/local/modempool/serverdb} where all servers should present it self.
  2238. X
  2239. X
  2240. The program psc can be used to see how the lines is currently being used.
  2241. Output will be in the format:
  2242. X\begin{quote}
  2243. LINE    PID    STATUS        PHONE     BAUD   NAME   (HOST)
  2244. X\end{quote}
  2245. where
  2246. X\begin{description}
  2247. X   \item[Line]   The /dev/ttyxx line
  2248. X   \item[Pid]    Process id of \modempool server
  2249. X   \item[Status] Either free, busy, fault or login.
  2250. X   \item[Phone]  If server is busy, this is the dialed phone number.
  2251. X   \item[Baud]   If server if busy, it is running in this baudrate.
  2252. X   \item[Name]   Name of calling user. This is not the userid on the system but the
  2253. X         the name used for the \modempool server.
  2254. X   \item[Host]     This is only used if \modempool has been compiled with the -DRLOGIN option
  2255. X          and  tells what host the user is connected to.
  2256. X\end{description}
  2257. X
  2258. The user database {\em /etc/local/modempool/Users} looks like the passwd file and has the
  2259. following records:
  2260. X\begin{quote}
  2261. X   user:password:phone:[host]
  2262. X\end{quote}
  2263. where
  2264. X\begin{description}
  2265. X  \item[user]     Name of the user, it should not be user-id on the system but rather
  2266. X          a pseudonym.
  2267. X  \item[password] A unencrypted password for user to enter when \modempool server asks. Don't
  2268. X          users real Unix password.
  2269. X  \item[phone]      Telephone number for user. This can also be a slash-separated list
  2270. X          of valid phonenumbers in which case the user will be prompted for
  2271. X          which of the numbers to use.
  2272. X          
  2273. X          The special number {\em *} can be used 
  2274. X          to permit any number. In this case a special record is written to the
  2275. X          log, also here the user is prompted for number.
  2276. X  \item[host]      If \modempool is compiled with the -DRLOGIN option this field should
  2277. X          specify what host the user should be logged into.
  2278. X\end{description}
  2279. X
  2280. X\section*{Installation}
  2281. If you want modempool to automatically login users on their own (or other) machine,
  2282. the flag -DRLOGIN must also be set in CFLAGS.
  2283. After that you just type {\em make}
  2284. X
  2285. X
  2286. If everything goes well you should now install it into the {\em /etc/local/modempool} directory by
  2287. doing {\em make install}.
  2288. XFinally you should modify your initab or ttytab to start modempool for the connected modems.
  2289. X
  2290. Arguments to modempool is as follows:
  2291. X\begin{description}
  2292. X\item[-p prefix]    Specifies a prefix to prepend to telephone number, ex. 0w to get
  2293. X            a external line on many switchboards.
  2294. X\item[-i initstr]    Specifies a alternate modem initiation string.
  2295. X\item[-d]        Turn on debugging.
  2296. X\item[tty]        Specifies the modem tty device.
  2297. X\end{description}
  2298. X
  2299. X\end{document}
  2300. END_OF_FILE
  2301. if test 4253 -ne `wc -c <'modempool.te'`; then
  2302.     echo shar: \"'modempool.te'\" unpacked with wrong size!
  2303. fi
  2304. # end of 'modempool.te'
  2305. fi
  2306. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  2307.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  2308. else
  2309. echo shar: Extracting \"'patchlevel.h'\" \(177 characters\)
  2310. sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  2311. X/*
  2312. X * @(#)patchlevel.h    4.2 92/04/22 - Current release level.
  2313. X */
  2314. X#define PATCHLEVEL "4"
  2315. X#ifndef lint
  2316. static char SccsId_patchlevel_h[] = "@(#)patchlevel.h    4.2 92/04/22";
  2317. X#endif
  2318. END_OF_FILE
  2319. if test 177 -ne `wc -c <'patchlevel.h'`; then
  2320.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  2321. fi
  2322. # end of 'patchlevel.h'
  2323. fi
  2324. if test -f 'poolstat.1' -a "${1}" != "-c" ; then 
  2325.   echo shar: Will not clobber existing file \"'poolstat.1'\"
  2326. else
  2327. echo shar: Extracting \"'poolstat.1'\" \(480 characters\)
  2328. sed "s/^X//" >'poolstat.1' <<'END_OF_FILE'
  2329. X.\" @(#)poolstat.1    4.1 
  2330. X.TH POOLSTAT 1V "920421"
  2331. X.SH NAME
  2332. poolstat \- print status of the modempool
  2333. X.SH SYNOPSIS
  2334. X.B poolstat
  2335. X.SH DESCRIPTION
  2336. This command reads the modempool server database and prints each servers status.
  2337. Status can be one of 'free', 'login', 'busy' or 'fail'.
  2338. If status is fail check the errlog-file.
  2339. X.ne 8
  2340. X.SH FILES
  2341. X.PD 0
  2342. X.TP 20
  2343. X.B /etc/local/modempool/serverdb
  2344. Where all modempool servers register.
  2345. X.SH "SEE ALSO"
  2346. X.PD
  2347. X.BR modempool (1V)
  2348. X.br
  2349. X.ne 5
  2350. X.SH BUGS
  2351. X.LP
  2352. END_OF_FILE
  2353. if test 480 -ne `wc -c <'poolstat.1'`; then
  2354.     echo shar: \"'poolstat.1'\" unpacked with wrong size!
  2355. fi
  2356. # end of 'poolstat.1'
  2357. fi
  2358. if test -f 'poolstat.c' -a "${1}" != "-c" ; then 
  2359.   echo shar: Will not clobber existing file \"'poolstat.c'\"
  2360. else
  2361. echo shar: Extracting \"'poolstat.c'\" \(1579 characters\)
  2362. sed "s/^X//" >'poolstat.c' <<'END_OF_FILE'
  2363. X/********************************************************************
  2364. X * 
  2365. X * Module: @(#)poolstat.c    4.2 92/04/16
  2366. X *
  2367. X * Description:
  2368. X *     Lists status of all callback lines, uses the server data base file
  2369. X *     calltmp
  2370. X *
  2371. X * Revision:
  2372. X *    Ver    Date    By        Reason
  2373. X *    ---    ----    --        ------
  2374. X *    1    910118    Lars Berntzon    Created
  2375. X *
  2376. X ********************************************************************/
  2377. static char SccsId[] = "@(#)poolstat.c    4.2 92/04/16";
  2378. X#include <stdio.h>
  2379. X#include "modempool.h"
  2380. X
  2381. main()
  2382. X{
  2383. X#ifdef RLOGIN
  2384. X    static char headfmt[] = "%-15s %-5s %-10s %-15s %-5s %-8s %s\n";
  2385. X    static char realfmt[] = "%-15s %-5d %-10s %-15s %-5d %-8s %s\n";
  2386. X#else
  2387. X    static char headfmt[] = "%-15s %-5s %-10s %-15s %-5s %-8s\n";
  2388. X    static char realfmt[] = "%-15s %-5d %-10s %-15s %-5d %-8s\n";
  2389. X#endif
  2390. X    struct slot slot;
  2391. X    char *status;
  2392. X    int fd;
  2393. X
  2394. X    if ((fd = open(SERVERDB, 0)) < 0) {
  2395. X        fprintf(stderr, "failed to open server database\n");
  2396. X        exit(1);
  2397. X    }
  2398. X
  2399. X    printf(headfmt, "LINE", "PID", "STATUS", "PHONE", "BAUD", "NAME"
  2400. X#ifdef RLOGIN
  2401. X    ,"HOST"
  2402. X#endif
  2403. X    );
  2404. X    while(read(fd, &slot, sizeof slot) == sizeof slot) {
  2405. X    if (kill(slot.pid, 0) >= 0) {
  2406. X        switch (slot.status) {
  2407. X        case SLOT_FREE:
  2408. X        status = "free"; 
  2409. X        break;
  2410. X        case SLOT_BUSY:
  2411. X        status = "busy";
  2412. X        break;
  2413. X        case SLOT_LOGIN:
  2414. X        status = "login";
  2415. X        break;
  2416. X        case SLOT_FAULT:
  2417. X        status = "fault";
  2418. X        break;
  2419. X        default:
  2420. X        status = "(unknown)";
  2421. X        }
  2422. X        printf(realfmt, slot.line, slot.pid, status,
  2423. X               slot.phone, slot.baud, slot.name
  2424. X#ifdef RLOGIN
  2425. X           ,slot.host
  2426. X#endif
  2427. X           );
  2428. X    }
  2429. X    }
  2430. X}
  2431. END_OF_FILE
  2432. if test 1579 -ne `wc -c <'poolstat.c'`; then
  2433.     echo shar: \"'poolstat.c'\" unpacked with wrong size!
  2434. fi
  2435. # end of 'poolstat.c'
  2436. fi
  2437. if test -f 'slot.c' -a "${1}" != "-c" ; then 
  2438.   echo shar: Will not clobber existing file \"'slot.c'\"
  2439. else
  2440. echo shar: Extracting \"'slot.c'\" \(7868 characters\)
  2441. sed "s/^X//" >'slot.c' <<'END_OF_FILE'
  2442. X/*******************************************************************
  2443. X * 
  2444. X * Module: @(#)slot.c    4.2 92/04/16
  2445. X *
  2446. X * Description:
  2447. X *    Handle server database functions.
  2448. X *
  2449. X * Revision:
  2450. X *    Date    By            Reason    
  2451. X *    ----    --            ------    
  2452. X *    920306    Lars Berntzon        Created
  2453. X *
  2454. X *******************************************************************/
  2455. static char SccsId[] = "@(#)slot.c    4.2 92/04/16";
  2456. X
  2457. X#include <stdio.h>
  2458. X#include <string.h>
  2459. X#include <stdarg.h>
  2460. X#include <fcntl.h>
  2461. X#include <errno.h>
  2462. X
  2463. X#include "modempool.h"
  2464. X
  2465. X/*
  2466. X * Local stuff.
  2467. X */
  2468. static int slot_fd = -1;
  2469. static int lock_cnt = 0;
  2470. X
  2471. X/*******************************************************************
  2472. X *        S L O T _ A L L O C
  2473. X *        -------------------
  2474. X *
  2475. X * Description:
  2476. X *    Find a free server slot and allocate it.
  2477. X *
  2478. X * Return:
  2479. X *    id of allocated slot.
  2480. X *
  2481. X *******************************************************************/
  2482. int
  2483. slot_alloc(slot_t *sp)
  2484. X{
  2485. X    int id;
  2486. X
  2487. X    if (sp == NULL) {
  2488. X    logerr("slot_alloc: programming error: slot = NULL");
  2489. X    return E_FAIL;
  2490. X    }
  2491. X
  2492. X    if (slot_open() != E_OK) {
  2493. X    return E_FAIL;
  2494. X    }
  2495. X
  2496. X    slot_lock();
  2497. X    
  2498. X    for(sp->id = 0; read(slot_fd, sp, sizeof *sp) == sizeof *sp; sp->id++) {
  2499. X        /* If process owning slot does not exists do break */
  2500. X    if (kill(sp->pid, 0) < 0) break;
  2501. X    }
  2502. X
  2503. X    /* Fill in data */
  2504. X    slot_free(sp);
  2505. X
  2506. X    slot_unlock();
  2507. X
  2508. X    slot_close();
  2509. X
  2510. X    return E_OK;
  2511. X}
  2512. X
  2513. X/*******************************************************************
  2514. X *        S L O T _ F R E E
  2515. X *        -----------------
  2516. X *
  2517. X * Description:
  2518. X *    Empty and free a slot.
  2519. X *
  2520. X * Arguments:
  2521. X *    sp    - slot.
  2522. X *
  2523. X *******************************************************************/
  2524. int
  2525. slot_free(slot_t *sp)
  2526. X{
  2527. X    /*
  2528. X     * Check args.
  2529. X     */
  2530. X    if (sp == NULL) {
  2531. X    logerr("slot_free: programming error: sp = NULL");
  2532. X    return E_FAIL;
  2533. X    }
  2534. X
  2535. X    slot_lock();
  2536. X
  2537. X    strncpy(sp->line, line, sizeof sp->line);
  2538. X    sp->pid = getpid();
  2539. X    strncpy(sp->phone, "", sizeof sp->phone);
  2540. X    strncpy(sp->name, "", sizeof sp->name);
  2541. X#ifdef RLOGIN
  2542. X    strncpy(sp->host, "", sizeof sp->host);
  2543. X#endif
  2544. X    sp->status = SLOT_FREE;
  2545. X    sp->baud = 0;
  2546. X    slot_write(sp);
  2547. X
  2548. X    slot_unlock();
  2549. X}
  2550. X
  2551. X/*******************************************************************
  2552. X *        S L O T _ O P E N
  2553. X *        -----------------
  2554. X *
  2555. X * Description:
  2556. X *    Open server database file.
  2557. X *
  2558. X * Return:
  2559. X *    E_OK or E_FAIL
  2560. X *
  2561. X *******************************************************************/
  2562. int
  2563. slot_open(void)
  2564. X{
  2565. X    /*
  2566. X     * If allready opened, just rewind.
  2567. X     */
  2568. X    if (slot_fd >= 0) {
  2569. X        lseek(slot_fd, 0, 0);
  2570. X    return E_OK;
  2571. X    }
  2572. X
  2573. X    if ((slot_fd = open(SERVERDB, O_RDWR)) < 0 && 
  2574. X        (slot_fd = open(SERVERDB, O_RDWR | O_CREAT, 0777)) < 0) {
  2575. X    logerr("slot_open: failed");
  2576. X    return E_FAIL;
  2577. X    }
  2578. X    
  2579. X    return E_OK;
  2580. X}
  2581. X
  2582. X/*******************************************************************
  2583. X *        S L O T _ C L O S E
  2584. X *        -------------------
  2585. X *
  2586. X * Description:
  2587. X *    Close server database file.
  2588. X *
  2589. X *******************************************************************/
  2590. int
  2591. slot_close(void)
  2592. X{
  2593. X    if (slot_fd < 0) return E_OK;
  2594. X    close(slot_fd);
  2595. X    slot_fd = -1;
  2596. X
  2597. X    return E_OK;
  2598. X}
  2599. X
  2600. X/*******************************************************************
  2601. X *        S L O T _ F I N D
  2602. X *        -----------------
  2603. X *
  2604. X * Description:
  2605. X *    Read next slot from server database.
  2606. X *
  2607. X * Argument:
  2608. X *    sp    - Pointer to slot struct to receive data.
  2609. X *
  2610. X * Return:
  2611. X *    E_OK or E_FAIL
  2612. X *
  2613. X *******************************************************************/
  2614. int
  2615. slot_traverse(slot_t *sp)
  2616. X{
  2617. X    int rc;
  2618. X    
  2619. X    if (sp == NULL) {
  2620. X    logerr("slot_find: programming error: sp = NULL");
  2621. X    return E_FAIL;
  2622. X    }
  2623. X
  2624. X
  2625. X    /*
  2626. X     * Read next slot.
  2627. X     */
  2628. X    slot_lock();
  2629. X    while ((rc = read(slot_fd, sp, sizeof *sp)) == sizeof *sp)
  2630. X    {
  2631. X        /*
  2632. X     * If server alive, slot is found.
  2633. X     */
  2634. X    if (kill(sp->pid, 0) >= 0) {
  2635. X       break;
  2636. X    }
  2637. X    }
  2638. X    slot_unlock();
  2639. X
  2640. X    if (rc < 0) {
  2641. X        logerr("slot_find: failed to read slot");
  2642. X    return E_FAIL;
  2643. X    }
  2644. X    
  2645. X    if (rc != sizeof *sp) {
  2646. X    return E_EOF;
  2647. X    }
  2648. X
  2649. X    return E_OK;
  2650. X}
  2651. X
  2652. X/*******************************************************************
  2653. X *        S L O T _ R E A D
  2654. X *        -----------------
  2655. X *
  2656. X * Description:
  2657. X *    Read data from slot number.
  2658. X *
  2659. X * Arguments:
  2660. X *    sp    - Slot pointer where data goes.
  2661. X *
  2662. X * Return:
  2663. X *    E_OK or E_FAIL
  2664. X *
  2665. X *******************************************************************/
  2666. int
  2667. slot_read(slot_t *sp)
  2668. X{
  2669. X    int rc;
  2670. X
  2671. X    if (sp == NULL) {
  2672. X    logerr("slot_read: programming error: sp = NULL");
  2673. X    return E_FAIL;
  2674. X    }
  2675. X
  2676. X    slot_lock();
  2677. X    slot_open();
  2678. X    lseek(slot_fd, sp->id * sizeof *sp, 0);
  2679. X    rc = read(slot_fd, sp, sizeof *sp);
  2680. X    slot_close();
  2681. X    slot_unlock();
  2682. X
  2683. X    if (rc != sizeof *sp) 
  2684. X    {
  2685. X    logerr("slot_read: failed for slot #%d", sp->id);
  2686. X    return E_FAIL;
  2687. X    }
  2688. X    debug("slot_read: ok");
  2689. X
  2690. X    return E_OK;
  2691. X}
  2692. X
  2693. X/*******************************************************************
  2694. X *        S L O T _ W R I T E
  2695. X *        -------------------
  2696. X *
  2697. X * Description:
  2698. X *    Write data from slot into file.
  2699. X *
  2700. X * Arguments:
  2701. X *    sp    - Pointer to slot data.
  2702. X *
  2703. X * Return:
  2704. X *    E_OK or E_FAIL
  2705. X *
  2706. X *******************************************************************/
  2707. int
  2708. slot_write(slot_t *sp)
  2709. X{
  2710. X    int rc;
  2711. X    if (sp == NULL) {
  2712. X    logerr("slot_write: programming error: sp = NULL");
  2713. X    return E_FAIL;
  2714. X    }
  2715. X
  2716. X    slot_lock();
  2717. X    slot_open();
  2718. X    lseek(slot_fd, sp->id * sizeof *sp, 0);
  2719. X    rc = write(slot_fd, sp, sizeof *sp);
  2720. X    slot_close();
  2721. X    slot_unlock();
  2722. X
  2723. X    if (rc != sizeof *sp) 
  2724. X    {
  2725. X    logerr("slot_write: failed for slot #%d", sp->id);
  2726. X    return E_FAIL;
  2727. X    }
  2728. X    debug("slot_write: ok");
  2729. X
  2730. X    return E_OK;
  2731. X}
  2732. X
  2733. X/*******************************************************************
  2734. X *        S L O T _ L O C K
  2735. X *        -----------------
  2736. X *
  2737. X * Description:
  2738. X *    Lock the server database file, this to keep two
  2739. X *    server to update the file simultaniously. It also allows
  2740. X *    recursive locks. If this routine is called twise without
  2741. X *    calling slot_unlock a countr keeps track of the depth.
  2742. X *
  2743. X * Return:
  2744. X *    E_OK or E_FAIL.
  2745. X *
  2746. X *******************************************************************/
  2747. int
  2748. slot_lock(void)
  2749. X{
  2750. X    int retry;
  2751. X    int fd;
  2752. X
  2753. X    /*
  2754. X     * Alloc recursive slot locks.
  2755. X     */
  2756. X     if (lock_cnt++ > 0) {
  2757. X    debug("slot_lock: incrementing lock count");
  2758. X    return E_OK;
  2759. X     }
  2760. X
  2761. X    /* 
  2762. X     * Lock calltmp, if not succeded in half max tries, remove the lock.
  2763. X     * Thereafter try 5 times more to lock file.
  2764. X     */
  2765. X    for(retry = 0; retry < 10; retry++)
  2766. X    {
  2767. X    if ((fd = open(LOCKFILE, O_CREAT | O_EXCL, 0777)) >= 0)
  2768. X    {
  2769. X        debug("slot_lock: locked slot");
  2770. X        close(fd);
  2771. X        return E_OK;
  2772. X    }
  2773. X
  2774. X    if (errno != EEXIST)
  2775. X    {
  2776. X        logerr("slot_lock: failed to create lockfile (errno = %d)", errno);
  2777. X        return E_FAIL;
  2778. X    }
  2779. X
  2780. X    /*
  2781. X     * When tried half the times, remove the lockfile.
  2782. X     */
  2783. X    if (retry == 5) {
  2784. X        if (unlink(LOCKFILE) != 0) {
  2785. X        logerr("slot_lock: failed to unlink lockfile");
  2786. X        }
  2787. X        debug("slot_lock: forcibly removed lockfile");
  2788. X    }
  2789. X
  2790. X    sleep(1);
  2791. X    debug("slot_lock: retrying");
  2792. X    }
  2793. X
  2794. X    logerr("slot_lock: never succeded to lock file");
  2795. X    return E_FAIL;
  2796. X}
  2797. X
  2798. X/*******************************************************************
  2799. X *        S L O T _ U N L O C K
  2800. X *        ---------------------
  2801. X *
  2802. X * Description:
  2803. X *    Unlock the server database. If the database has been locked
  2804. X *    more than once, a counter is just decremented.
  2805. X *
  2806. X * Return:
  2807. X *    E_OK or E_FAIL.
  2808. X *
  2809. X *******************************************************************/
  2810. int
  2811. slot_unlock(void)
  2812. X{
  2813. X    /*
  2814. X     *    Check if allready unlocked.
  2815. X     */
  2816. X    if (lock_cnt <= 0) {
  2817. X    debug("slot_unlock: slot allready unlocked");
  2818. X    return E_OK;
  2819. X    }
  2820. X
  2821. X    /*
  2822. X     * Check for recursive locks.
  2823. X     */
  2824. X    if (--lock_cnt > 0) {
  2825. X    debug("slot_unlock: more locks exists"); 
  2826. X    return E_OK;
  2827. X    }
  2828. X
  2829. X    /*
  2830. X     * Do unlocking.
  2831. X     */
  2832. X    if (unlink(LOCKFILE) != 0) {
  2833. X    logerr("slot_unlock: failed to remove lockfile (errno = %d)", errno);
  2834. X    return E_FAIL;
  2835. X    }
  2836. X    debug("slot_unlock: slot unlocked");
  2837. X
  2838. X    return E_OK;
  2839. X}
  2840. END_OF_FILE
  2841. if test 7868 -ne `wc -c <'slot.c'`; then
  2842.     echo shar: \"'slot.c'\" unpacked with wrong size!
  2843. fi
  2844. # end of 'slot.c'
  2845. fi
  2846. if test -f 'support.c' -a "${1}" != "-c" ; then 
  2847.   echo shar: Will not clobber existing file \"'support.c'\"
  2848. else
  2849. echo shar: Extracting \"'support.c'\" \(4481 characters\)
  2850. sed "s/^X//" >'support.c' <<'END_OF_FILE'
  2851. X/*******************************************************************
  2852. X * 
  2853. X * Module: @(#)support.c    4.2
  2854. X *
  2855. X * Description:
  2856. X *    Handle various low level functions.
  2857. X *
  2858. X * Revision:
  2859. X *    Date    By            Reason    
  2860. X *    ----    --            ------    
  2861. X *    910414    Lars Berntzon        Created
  2862. X *      910124  Lars H Carlsson     Changed pid format to %10d\n
  2863. X *      910124  Lars H Carlsson        Changed mode of lockfile to 0444
  2864. X *    910129    Lars Berntzon        Changed to termio for eightbit tty.
  2865. X *      910224  Lars Berntzon        Newline right when loggin in.
  2866. X *      910227  Lars Berntzon           The loggfile now reopens everytime.
  2867. X *
  2868. X *******************************************************************/
  2869. static char SccsId[] = "@(#)support.c    4.2 92/04/16";
  2870. X
  2871. X#include <sys/types.h>
  2872. X#include <time.h>
  2873. X#include <stdio.h>
  2874. X#include <string.h>
  2875. X#include <signal.h>
  2876. X#include <setjmp.h>
  2877. X#include <ctype.h>
  2878. X#include <stdarg.h>
  2879. X#include <errno.h>
  2880. X
  2881. X#include "modempool.h"
  2882. X
  2883. X/* L o c a l   s t u f f */
  2884. static void call_env(int sig);     /* Signal handler        */
  2885. static char *curtime();        /* Gev current time in ascii    */
  2886. static jmp_buf env;        /* Timeout longjump buffer    */
  2887. static int tmout_flag = 0;    /* true if timeout occured    */
  2888. static int active_timeout = 0;    /* If trig is in action        */
  2889. X
  2890. X/*
  2891. X * Routines.
  2892. X */
  2893. void fatal(char *msg)
  2894. X{
  2895. X    logerr("fatal error: %s", msg);
  2896. X    exit(1);
  2897. X}
  2898. X
  2899. void usage(void)
  2900. X{
  2901. X    fatal(MSG_USAGE);
  2902. X}
  2903. X
  2904. static int unctrl(FILE *fp, char *str)
  2905. X{
  2906. X    int i;
  2907. X
  2908. X    /* Write output */
  2909. X    for(i = 0; str[i] != 0; i++) {
  2910. X    if (str[i] == '\r') fputs("\\r", fp);
  2911. X    else if (str[i] == '\n') fputs("\\n", fp);
  2912. X    else fputc(str[i], fp);
  2913. X    }
  2914. X
  2915. X    return E_OK;
  2916. X}
  2917. X
  2918. int debug(char *fmt, ...)
  2919. X{
  2920. X    FILE *fp = NULL;
  2921. X    va_list arg;
  2922. X    char str[300];
  2923. X
  2924. X    if(debug_lvl == 0) return E_OK;
  2925. X
  2926. X    /* Open logfile */
  2927. X    if ((fp = fopen(LOGFILE, "a")) == NULL) return E_FAIL;
  2928. X
  2929. X    va_start(arg, fmt);
  2930. X    vsprintf(str, fmt, arg);
  2931. X#ifdef DEBUG
  2932. X    unctrl(stdout, str);
  2933. X    fputs("\n\r", stdout);
  2934. X#endif
  2935. X    unctrl(fp, str);
  2936. X    fputc('\n', fp);
  2937. X
  2938. X    fclose(fp);
  2939. X
  2940. X    return E_OK;
  2941. X}
  2942. X
  2943. int debugnonl(char *fmt, ...)
  2944. X{
  2945. X    FILE *fp = NULL;
  2946. X    va_list arg;
  2947. X    char str[300];
  2948. X
  2949. X    if(debug_lvl == 0) return E_OK;
  2950. X
  2951. X    /* Open logfile */
  2952. X    if ((fp = fopen(LOGFILE, "a")) == NULL) return E_FAIL;
  2953. X
  2954. X    va_start(arg, fmt);
  2955. X    vsprintf(str, fmt, arg);
  2956. X#ifdef DEBUG
  2957. X    unctrl(stdout, str);
  2958. X#endif
  2959. X    unctrl(fp, str);
  2960. X
  2961. X    fclose(fp);
  2962. X
  2963. X    return E_OK;
  2964. X}
  2965. X
  2966. int log(char *fmt, ...)
  2967. X{
  2968. X    FILE *fp = NULL;
  2969. X    va_list arg;
  2970. X
  2971. X    /* Open logfile */
  2972. X    if ((fp = fopen(LOGFILE, "a")) == NULL) return E_FAIL;
  2973. X
  2974. X    /* Write output */
  2975. X    fprintf(fp, "%s %s: ", curtime(), line);
  2976. X    va_start(arg, fmt);
  2977. X#ifdef DEBUG
  2978. X    vfprintf(stdout, fmt, arg);
  2979. X    fprintf(stdout, "\n\r");
  2980. X#endif
  2981. X    vfprintf(fp, fmt, arg);
  2982. X    fprintf(fp, "\n");
  2983. X
  2984. X    fclose(fp);
  2985. X
  2986. X    return E_OK;
  2987. X}
  2988. X
  2989. int logerr(char *fmt, ...)
  2990. X{
  2991. X    static FILE *fp = NULL;
  2992. X    va_list arg;
  2993. X
  2994. X    /* Open logfile */
  2995. X    if ((fp = fopen(ERRLOGFILE, "a")) == NULL) return E_FAIL;
  2996. X
  2997. X    /* Write output */
  2998. X    fprintf(fp, "%s %s: ", curtime(), line);
  2999. X    va_start(arg, fmt);
  3000. X#ifdef DEBUG
  3001. X    vfprintf(stdout, fmt, arg);
  3002. X    fprintf(stdout, "\n\r");
  3003. X#endif
  3004. X    vfprintf(fp, fmt, arg);
  3005. X    fprintf(fp, "\n");
  3006. X
  3007. X    fclose(fp);
  3008. X
  3009. X    /*
  3010. X     * If program hangs, prevent it from filling the filesystem (in short time)
  3011. X     */
  3012. X    sleep(1);
  3013. X
  3014. X    return E_OK;
  3015. X}
  3016. X
  3017. static char *curtime()
  3018. X{
  3019. X    static char buf[50];
  3020. X    time_t t;
  3021. X    struct tm *tm;
  3022. X    /* Get time */
  3023. X    t = time(NULL);
  3024. X    tm = localtime(&t);
  3025. X    sprintf(buf, "%02d%02d%02d %02d:%02d:%02d",
  3026. X            tm->tm_year,
  3027. X            tm->tm_mon + 1,
  3028. X            tm->tm_mday,
  3029. X            tm->tm_hour,
  3030. X            tm->tm_min,
  3031. X            tm->tm_sec);
  3032. X
  3033. X    return buf;
  3034. X}
  3035. X
  3036. static void
  3037. call_env(int sig)
  3038. X{
  3039. X#ifdef SV_INTERRUPT
  3040. X   /*
  3041. X    * Use sigvec if exists.
  3042. X    */
  3043. X   {  
  3044. X    struct sigvec vec;
  3045. X    vec.sv_handler = SIG_IGN;
  3046. X    vec.sv_mask = 0;
  3047. X    vec.sv_flags = SV_INTERRUPT;
  3048. X    sigvec(SIGALRM, &vec, NULL);
  3049. X    }  
  3050. X#else
  3051. X    signal(SIGALRM, SIG_IGN);
  3052. X#endif
  3053. X    tmout_flag = 1;
  3054. X    active_timeout = 0;
  3055. X}
  3056. int
  3057. trig(int tmout)
  3058. X{
  3059. X    tmout_flag = 0;
  3060. X    active_timeout = 1;
  3061. X#ifdef SV_INTERRUPT
  3062. X   /*
  3063. X    * Use sigvec if exists.
  3064. X    */
  3065. X   {  
  3066. X    struct sigvec vec;
  3067. X    vec.sv_handler = call_env;
  3068. X    vec.sv_mask = 0;
  3069. X    vec.sv_flags = SV_INTERRUPT;
  3070. X    sigvec(SIGALRM, &vec, NULL);
  3071. X    }  
  3072. X#else
  3073. X    signal(SIGALRM, call_env);
  3074. X#endif
  3075. X    alarm(tmout);
  3076. X}
  3077. X
  3078. int
  3079. istimeout(void)
  3080. X{
  3081. X    int ret;
  3082. X
  3083. X    alarm(0);
  3084. X    active_timeout = 0;
  3085. X    ret = tmout_flag;
  3086. X    tmout_flag = 0;
  3087. X
  3088. X    return ret;
  3089. X}
  3090. END_OF_FILE
  3091. if test 4481 -ne `wc -c <'support.c'`; then
  3092.     echo shar: \"'support.c'\" unpacked with wrong size!
  3093. fi
  3094. # end of 'support.c'
  3095. fi
  3096. if test -f 'termios.c' -a "${1}" != "-c" ; then 
  3097.   echo shar: Will not clobber existing file \"'termios.c'\"
  3098. else
  3099. echo shar: Extracting \"'termios.c'\" \(808 characters\)
  3100. sed "s/^X//" >'termios.c' <<'END_OF_FILE'
  3101. X/*
  3102. X * Module:
  3103. X *        T E R M I O S
  3104. X *
  3105. X * Description:
  3106. X *    Emulate termios function.
  3107. X *
  3108. X */
  3109. static char SccsId[] = "@(#)termios.c    4.2 92/04/16";
  3110. X
  3111. X#include <sys/types.h>
  3112. X#include <termio.h>
  3113. X
  3114. int cfsetispeed(struct termio *ttybuf, int baud)
  3115. X{
  3116. X    return 0;
  3117. X}
  3118. X
  3119. int cfsetospeed(struct termio *ttybuf, int baud)
  3120. X{
  3121. X    ttybuf->c_cflag &= ~CBAUD;
  3122. X    ttybuf->c_cflag |= (baud & CBAUD);
  3123. X    return 0;
  3124. X}
  3125. X
  3126. int tcflush(int fd, int mode)
  3127. X{
  3128. X    return ioctl(fd, TCFLSH, 2);
  3129. X    return 0;
  3130. X}
  3131. X
  3132. int tcdrain(int fd)
  3133. X{
  3134. X    sleep(3);
  3135. X    return 0;
  3136. X}
  3137. X
  3138. int tcgetattr(int fd, struct termio *buf)
  3139. X{
  3140. X    if(ioctl(fd, TCGETA, buf) != 0) {
  3141. X    perror("ioclt(TCGETA)");
  3142. X    return -1;
  3143. X    }
  3144. X    return 0;
  3145. X}
  3146. X
  3147. int tcsetattr(int fd, int mode, struct termio *buf)
  3148. X{
  3149. X    if(ioctl(fd, TCSETA, buf) != 0) {
  3150. X    perror("ioclt(TCSETA)");
  3151. X    return -1;
  3152. X    }
  3153. X}
  3154. X
  3155. END_OF_FILE
  3156. if test 808 -ne `wc -c <'termios.c'`; then
  3157.     echo shar: \"'termios.c'\" unpacked with wrong size!
  3158. fi
  3159. # end of 'termios.c'
  3160. fi
  3161. if test -f 'termios.h' -a "${1}" != "-c" ; then 
  3162.   echo shar: Will not clobber existing file \"'termios.h'\"
  3163. else
  3164. echo shar: Extracting \"'termios.h'\" \(131 characters\)
  3165. sed "s/^X//" >'termios.h' <<'END_OF_FILE'
  3166. X#include <termio.h>
  3167. X#define TCIFLUSH    0    /* Dummy */
  3168. X#define TCSADRAIN    0
  3169. X#define TCSANOW        0
  3170. X#define termios        termio     /* Dangerous */
  3171. END_OF_FILE
  3172. if test 131 -ne `wc -c <'termios.h'`; then
  3173.     echo shar: \"'termios.h'\" unpacked with wrong size!
  3174. fi
  3175. # end of 'termios.h'
  3176. fi
  3177. if test -f 'tty.c' -a "${1}" != "-c" ; then 
  3178.   echo shar: Will not clobber existing file \"'tty.c'\"
  3179. else
  3180. echo shar: Extracting \"'tty.c'\" \(8930 characters\)
  3181. sed "s/^X//" >'tty.c' <<'END_OF_FILE'
  3182. X/*******************************************************************
  3183. X * 
  3184. X * Module: @(#)tty.c    4.2 92/04/16
  3185. X *
  3186. X * Description:
  3187. X *    Handle various tty functions.
  3188. X *
  3189. X * Revision:
  3190. X *    Date    By            Reason    
  3191. X *    ----    --            ------    
  3192. X *    920306    Lars Berntzon        Created
  3193. X *
  3194. X *******************************************************************/
  3195. static char SccsId[] = "@(#)tty.c    4.2 92/04/16";
  3196. X
  3197. X#include <stdio.h>
  3198. X#include <string.h>
  3199. X#include <fcntl.h>
  3200. X#include <errno.h>
  3201. X#include <termios.h>
  3202. X
  3203. X#include "modempool.h"
  3204. X
  3205. X/* L o c a l   s t u f f */
  3206. static int port = -1;
  3207. X
  3208. X/*******************************************************************
  3209. X *        T T Y _ O P E N
  3210. X *        ---------------
  3211. X *
  3212. X * Description:
  3213. X *    Open ttyport and set it right.
  3214. X *
  3215. X * Arguments:
  3216. X *    filename    - filename of tty device.
  3217. X *    baud        - Initial baudrate.
  3218. X *    flags        - Special flags like N_DELAY.
  3219. X *
  3220. X *******************************************************************/
  3221. int
  3222. tty_open(char *filename, int baud, int flags)
  3223. X{
  3224. X
  3225. X    /*
  3226. X     * If allready open, close it first.
  3227. X     */
  3228. X    if (port >= 0) {
  3229. X    tty_close();
  3230. X    }
  3231. X
  3232. X    /*
  3233. X     * Open with timeout.
  3234. X     */
  3235. X    trig(OPEN_TMOUT);
  3236. X    port = open(filename, O_RDWR | flags);
  3237. X    if(istimeout()) {
  3238. X    return E_TMOUT;
  3239. X    }
  3240. X
  3241. X    if (port < 0) {
  3242. X    logerr("tty_open: cant open port with flags %d: errno %d", flags, errno);
  3243. X    return -1;
  3244. X    }
  3245. X
  3246. X    /*
  3247. X     * Set default parameters.
  3248. X     */
  3249. X    tty_setup();
  3250. X    tty_local(flags & O_NDELAY);
  3251. X    tty_ndelay(0);
  3252. X    tty_baud(baud);
  3253. X    tty_raw();
  3254. X
  3255. X    return E_OK;
  3256. X}
  3257. X
  3258. X/*******************************************************************
  3259. X *        T T Y _ C L O S E
  3260. X *        -----------------
  3261. X *
  3262. X * Description:
  3263. X *    Close open tty.
  3264. X *
  3265. X *******************************************************************/
  3266. int
  3267. tty_close(void)
  3268. X{
  3269. X    if (port >= 0) {
  3270. X    close(port);
  3271. X    port = -1;
  3272. X    }
  3273. X    return E_OK;
  3274. X}
  3275. X
  3276. X/*******************************************************************
  3277. X *        T T Y _ R E A D
  3278. X *        ---------------
  3279. X *
  3280. X * Description:
  3281. X *    Read characters from tty.
  3282. X *
  3283. X *******************************************************************/
  3284. int
  3285. tty_read(char *buf, int len)
  3286. X{
  3287. X    return read(port, buf, len);
  3288. X}
  3289. X
  3290. X/*******************************************************************
  3291. X *        T T Y _ W R I T E
  3292. X *        -----------------
  3293. X *
  3294. X * Description:
  3295. X *    Write characters from tty.
  3296. X *
  3297. X *******************************************************************/
  3298. int
  3299. tty_write(char *buf, int len)
  3300. X{
  3301. X    return write(port, buf, len);
  3302. X}
  3303. X
  3304. X/*******************************************************************
  3305. X *        T T Y _ N D E L A Y
  3306. X *        -------------------
  3307. X *
  3308. X * Description:
  3309. X *    Control the O_NDELAY flag for tty.
  3310. X *
  3311. X * Arguments:
  3312. X *    on    - true means O_NDELAY is on.
  3313. X *
  3314. X *******************************************************************/
  3315. int
  3316. tty_ndelay(int on)
  3317. X{
  3318. X    int mode;
  3319. X
  3320. X    /*
  3321. X     * Turn off O_NDELAY
  3322. X     */
  3323. X    mode = fcntl(port, F_GETFL, 0);
  3324. X
  3325. X    if (on) {
  3326. X    mode |= O_NDELAY;
  3327. X    }
  3328. X    else {
  3329. X    mode &= ~O_NDELAY;
  3330. X    }
  3331. X
  3332. X    if (fcntl(port, F_SETFL, mode) != 0) {
  3333. X    logerr("tty_open: can't turn off O_NDELAY");
  3334. X    }
  3335. X
  3336. X    return E_OK;
  3337. X}
  3338. X
  3339. X/*******************************************************************
  3340. X *        H A N G U P
  3341. X *        -----------
  3342. X * Description:
  3343. X *    Hangup tty. After this the modem must be reopened before use.
  3344. X *
  3345. X * Arguments:
  3346. X *
  3347. X *******************************************************************/
  3348. int
  3349. tty_hangup(void)
  3350. X{
  3351. X    struct termios ttybuf;
  3352. X
  3353. X    tty_drain();
  3354. X    tcgetattr(port, &ttybuf);
  3355. X    cfsetispeed(&ttybuf, 0);
  3356. X    cfsetospeed(&ttybuf, B0);
  3357. X    tcsetattr(port, TCSADRAIN, &ttybuf);
  3358. X    sleep(3);
  3359. X
  3360. X    return E_OK;
  3361. X}
  3362. X
  3363. X/*******************************************************************
  3364. X *        T T Y _ S E T U P
  3365. X *        -----------------
  3366. X *
  3367. X * Description:
  3368. X *    Setup modempool favorite tty settings.
  3369. X *
  3370. X * Arguments:
  3371. X *
  3372. X *******************************************************************/
  3373. int
  3374. tty_setup(void)
  3375. X{
  3376. X    static struct termios ttybuf;
  3377. X
  3378. X    ttybuf.c_iflag = IGNPAR | ISTRIP | ICRNL | IXON  | IXANY; /* iflag */
  3379. X    ttybuf.c_oflag = OPOST | ONLCR | TAB3;                    /* oflag */
  3380. X    ttybuf.c_cflag = CS8 | CREAD | CLOCAL | HUPCL | B300;     /* cflag */
  3381. X    ttybuf.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;    /* lflag */
  3382. X    ttybuf.c_cc[0] = 3;
  3383. X    ttybuf.c_cc[1] = 28;
  3384. X    ttybuf.c_cc[2] = 127;
  3385. X    ttybuf.c_cc[3] = 24;
  3386. X    ttybuf.c_cc[4] = 4;
  3387. X    ttybuf.c_cc[5] = 0;
  3388. X    ttybuf.c_cc[6] = 0;
  3389. X    ttybuf.c_cc[7] = 0;
  3390. X    
  3391. X    tcsetattr(port, TCSANOW, &ttybuf);
  3392. X
  3393. X    return E_OK; 
  3394. X}
  3395. X
  3396. X/*******************************************************************
  3397. X *        T T Y _ S A N E
  3398. X *        ---------------
  3399. X *
  3400. X * Description:
  3401. X *    Like stty sane. Turns on canonic mode, i.e. user friendly
  3402. X *    mode.
  3403. X *
  3404. X * Arguments:
  3405. X *
  3406. X *******************************************************************/
  3407. int
  3408. tty_sane(void)
  3409. X{
  3410. X    struct termios ttybuf;
  3411. X
  3412. X    tcgetattr(port, &ttybuf);
  3413. X    ttybuf.c_iflag |= IGNPAR | ISTRIP | ICRNL | IXON | IXANY;
  3414. X    ttybuf.c_oflag |= OPOST | ONLCR;
  3415. X    ttybuf.c_lflag |= ISIG | ICANON;
  3416. X    ttybuf.c_cc[VEOF] = 4;
  3417. X    tcsetattr(port, TCSANOW, &ttybuf);
  3418. X    tty_echo();
  3419. X
  3420. X    return E_OK; 
  3421. X}
  3422. X
  3423. X/*******************************************************************
  3424. X *        T T Y _ R A W
  3425. X *        -------------
  3426. X *
  3427. X * Description:
  3428. X *    Turn tty back in raw mode. The opposite from tty_sane.
  3429. X *
  3430. X * Arguments:
  3431. X *
  3432. X *******************************************************************/
  3433. int
  3434. tty_raw(void)
  3435. X{
  3436. X    struct termios ttybuf;
  3437. X
  3438. X    tcgetattr(port, &ttybuf);
  3439. X    ttybuf.c_iflag &= ~IGNPAR & ~ISTRIP & ~ICRNL & ~IXON & ~IXANY;
  3440. X    ttybuf.c_oflag &= ~OPOST & ~ONLCR;
  3441. X    ttybuf.c_lflag &= ~ISIG & ~ICANON;
  3442. X    ttybuf.c_cc[VMIN] = 1;
  3443. X    tcsetattr(port, TCSANOW, &ttybuf);
  3444. X    tty_noecho();
  3445. X
  3446. X    return E_OK;
  3447. X}
  3448. X
  3449. X/*******************************************************************
  3450. X *        T T Y _ L O C A L
  3451. X *        -----------------
  3452. X *
  3453. X * Description:
  3454. X *    Control local mode.
  3455. X *
  3456. X * Arguments:
  3457. X *    mode    - True means tty turns local mode on.
  3458. X *
  3459. X *******************************************************************/
  3460. int
  3461. tty_local(int mode)
  3462. X{
  3463. X    struct termios ttybuf;
  3464. X
  3465. X    tcgetattr(port, &ttybuf);
  3466. X    if (mode) {
  3467. X    ttybuf.c_cflag |= CLOCAL;
  3468. X    }
  3469. X    else {
  3470. X    ttybuf.c_cflag &= ~CLOCAL;
  3471. X    }
  3472. X    tcsetattr(port, TCSANOW, &ttybuf);
  3473. X
  3474. X    return E_OK;
  3475. X}
  3476. X
  3477. X/*******************************************************************
  3478. X *        T T Y _ B A U D
  3479. X *        ---------------
  3480. X *
  3481. X * Description:
  3482. X *    Set baudrate for tty.
  3483. X *
  3484. X * Arguments:
  3485. X *    baud    - Integer baudrate value.
  3486. X *
  3487. X *******************************************************************/
  3488. int
  3489. tty_baud(int baud)
  3490. X{
  3491. X    struct termios ttybuf;
  3492. X    int tcbaud;
  3493. X    
  3494. X    switch(baud)
  3495. X    {
  3496. X    case 300:
  3497. X    tcbaud = B300;
  3498. X        break;
  3499. X
  3500. X    case 1200:
  3501. X    tcbaud = B1200;
  3502. X        break;
  3503. X
  3504. X    case 2400:
  3505. X    default:        
  3506. X    tcbaud = B2400;
  3507. X        break;
  3508. X
  3509. X    case 4800:
  3510. X    tcbaud = B4800;
  3511. X        break;
  3512. X        
  3513. X    case 9600:
  3514. X    tcbaud = B9600;
  3515. X        break;
  3516. X    }
  3517. X    tcgetattr(port, &ttybuf);
  3518. X    cfsetispeed(&ttybuf, 0);
  3519. X    cfsetospeed(&ttybuf, tcbaud);
  3520. X    tcsetattr(port, TCSANOW, &ttybuf);
  3521. X
  3522. X    return E_OK;
  3523. X}
  3524. X
  3525. X/*******************************************************************
  3526. X *        T T Y _ E C H O
  3527. X *        ---------------
  3528. X *
  3529. X * Description:
  3530. X *    Turns on echoing for tty.
  3531. X *
  3532. X * Arguments:
  3533. X *
  3534. X *******************************************************************/
  3535. int
  3536. tty_echo(void)
  3537. X{
  3538. X    struct termios ttybuf;
  3539. X
  3540. X    tcgetattr(port, &ttybuf);
  3541. X    ttybuf.c_lflag |= ECHO | ECHOE | ECHOK;
  3542. X    tcsetattr(port, TCSANOW, &ttybuf);
  3543. X
  3544. X    return E_OK; 
  3545. X}
  3546. X
  3547. X/*******************************************************************
  3548. X *        T T Y _ N O E C H O
  3549. X *        -------------------
  3550. X *
  3551. X * Description:
  3552. X *    Turns off echoing for tty.
  3553. X *
  3554. X * Arguments:
  3555. X *
  3556. X *******************************************************************/
  3557. int
  3558. tty_noecho(void)
  3559. X{
  3560. X    struct termios ttybuf;
  3561. X
  3562. X    tcgetattr(port, &ttybuf);
  3563. X    ttybuf.c_lflag &= ~ECHO & ~ECHOE & ~ECHOK;
  3564. X    tcsetattr(port, TCSANOW, &ttybuf);
  3565. X
  3566. X    return E_OK; 
  3567. X}
  3568. X
  3569. X/*******************************************************************
  3570. X *        T T Y _ D R A I N
  3571. X *        -----------------
  3572. X *
  3573. X * Description:
  3574. X *    Wait for output to drain.
  3575. X *
  3576. X *******************************************************************/
  3577. int
  3578. tty_drain(void)
  3579. X{
  3580. X    sleep(1);
  3581. X    tcdrain(port);
  3582. X    return E_OK;
  3583. X}
  3584. X
  3585. X/*******************************************************************
  3586. X *        T T Y _ F L U S H
  3587. X *        -----------------
  3588. X *
  3589. X * Description:
  3590. X *    Flush input data.
  3591. X *
  3592. X *******************************************************************/
  3593. int
  3594. tty_flush(void)
  3595. X{
  3596. X    tcflush(port, TCIFLUSH);
  3597. X    return E_OK;
  3598. X}
  3599. X
  3600. X/*******************************************************************
  3601. X *        T T Y _ R E D I R E C T
  3602. X *        -----------------------
  3603. X *
  3604. X * Description:
  3605. X *    Redirect stdin, stdout and stderr to port.
  3606. X *
  3607. X *******************************************************************/
  3608. int
  3609. tty_redirect(void)
  3610. X{
  3611. X    if (dup2(port, 0) != 0) {
  3612. X    logerr("dup!=0");
  3613. X    return E_FAIL;
  3614. X    }
  3615. X    if (dup2(port, 1) != 1) {
  3616. X    logerr("dup!=1");
  3617. X    return E_FAIL;
  3618. X    }
  3619. X    if (dup2(port, 2) != 2) {
  3620. X    logerr("dup!=2");
  3621. X    return E_FAIL;
  3622. X    }
  3623. X    return E_OK;
  3624. X}
  3625. END_OF_FILE
  3626. if test 8930 -ne `wc -c <'tty.c'`; then
  3627.     echo shar: \"'tty.c'\" unpacked with wrong size!
  3628. fi
  3629. # end of 'tty.c'
  3630. fi
  3631. if test -f 'utmplist.c' -a "${1}" != "-c" ; then 
  3632.   echo shar: Will not clobber existing file \"'utmplist.c'\"
  3633. else
  3634. echo shar: Extracting \"'utmplist.c'\" \(706 characters\)
  3635. sed "s/^X//" >'utmplist.c' <<'END_OF_FILE'
  3636. X#include <stdio.h>
  3637. X#include <sys/types.h>
  3638. X#include <utmp.h>
  3639. X
  3640. main()
  3641. X{
  3642. X    FILE *fp;
  3643. X    struct utmp buf;
  3644. X
  3645. X    if ((fp = fopen(UTMP_FILE, "r")) == NULL) {
  3646. X      fprintf(stderr, "failed to open UTMP\n");
  3647. X      exit(1);
  3648. X    }
  3649. X    while(fread(&buf, sizeof buf, 1, fp) == 1) {
  3650. X    printf("User: %s\n", buf.ut_user);
  3651. X    printf("Id: %s\n", buf.ut_id);
  3652. X    printf("Line: %s\n", buf.ut_line);
  3653. X    printf("Pid: %d\n", buf.ut_pid);
  3654. X    printf("Type: %d\n", buf.ut_type);
  3655. X    printf("Termination status: %d\n", buf.ut_exit.e_termination);
  3656. X    printf("Exit status: %d\n", buf.ut_exit.e_exit);
  3657. X    printf("Dead process exit status: %d\n", buf.ut_exit);
  3658. X    printf("Time entry was made: %d\n", buf.ut_time);
  3659. X    printf("\n");
  3660. X    }
  3661. X    fclose(fp);
  3662. X}
  3663. END_OF_FILE
  3664. if test 706 -ne `wc -c <'utmplist.c'`; then
  3665.     echo shar: \"'utmplist.c'\" unpacked with wrong size!
  3666. fi
  3667. # end of 'utmplist.c'
  3668. fi
  3669. echo shar: End of archive 1 \(of 1\).
  3670. cp /dev/null ark1isdone
  3671. MISSING=""
  3672. for I in 1 ; do
  3673.     if test ! -f ark${I}isdone ; then
  3674.     MISSING="${MISSING} ${I}"
  3675.     fi
  3676. done
  3677. if test "${MISSING}" = "" ; then
  3678.     echo You have the archive.
  3679.     rm -f ark[1-9]isdone
  3680. else
  3681.     echo You still need to unpack the following archives:
  3682.     echo "        " ${MISSING}
  3683. fi
  3684. ##  End of shell archive.
  3685. exit 0
  3686.