housel@en.ecn.purdue.edu (Peter S. Housel) (07/03/89)
echo 'x - dcpunix.c' sed 's/^X//' <<'**-dcpunix.c-EOF-**' >dcpunix.c X/* X * dcpunix.c - Unix/Minix support for dcp X * Peter S. Housel X */ X X#include <stdio.h> X#include <ctype.h> X#include <sgtty.h> X#include <dial.h> X#include <signal.h> X#include "dcp.h" X Xextern char *_merr_list[]; Xextern int merrno; X Xint timedout; /* set when alarm goes off */ Xint swritefd; /* fd for serial write */ Xint sreadfd; /* fd for serial read */ XCALL call; /* dial(3) structure */ X Xint ontime() X{ X signal(SIGALRM, ontime); X timedout = 1; X return 0; X} X Xswrite(data, num) Xchar *data; int num; X{ X return write(swritefd, data, num); X} X Xint sread(data, num, timeout) Xchar *data; int num, timeout; X{ X int ret; X X if(timeout) X alarm(timeout); X else X alarm(2); X signal(SIGALRM, ontime); X X ret = read(sreadfd, data, num); X alarm(0); X if(ret < 0) X return 0; X return ret; X} X Xint sread2(data, num) Xchar *data; int num; X{ X return read(sreadfd, data, num); X} X Xshell(command, inname, outname, errname) Xchar *command; Xchar *inname; Xchar *outname; Xchar *errname; X{ X int waitstat; X int fd; X X printmsg(M_INFO, "shell: %s < %s > %s", command, inname, outname); X X if(strncmp(command, "rmail", 5) != 0 && strncmp(command, "rnews", 5) != 0) X { X printmsg(M_ERROR, "illegal command \"%s\"", command); X return; X } X X switch(fork()) X { X case -1: X printmsg(M_ERROR, "couldn't fork"); X return; X case 0: X if(strlen(inname) != 0) X { X fd = open(inname, 0); X dup2(fd, 0); X if(fd > 0) X close(fd); X printmsg(M_INFO, "Changed infile to %s, fd=%d", inname, fd); X } X if(strlen(outname) != 0) X { X fd = creat(outname, 0644); X dup2(fd, 1); X if(fd > 1) X close(fd); X } X execl("/bin/sh", "sh", "-c", command, (char *)0); X printmsg(M_ERROR, "couldn't exec shell"); X exit(1); X default: X wait(&waitstat); X if(waitstat != 0) X printmsg(M_ERROR, "xqt status of 0x%x for command \"%s\"", X command); X } X} X Xint initline() X{ X struct sgttyb ttyb; X X sreadfd = 0; /* standard input */ X swritefd = 1; /* standard output */ X X gtty(sreadfd, &ttyb); /* set raw mode */ X ttyb.sg_flags |= RAW; X ttyb.sg_flags &= ~(XTABS | EVENP | ODDP | CRMOD | ECHO | CBREAK); X stty(sreadfd, &ttyb); X X return 0; X} X X Xint dcpdial(dev, speed, tel) Xchar *dev, *speed, *tel; X{ X call.baud = call.speed = atoi(speed); X call.line = dev; X call.telno = tel; X call.modem = 0; X X printmsg(M_CALL, "Dialing at speed %d", call.speed); X if(tel != NULL) X printmsg(M_CALL, "Calling phone# %s", call.telno); X if((sreadfd = swritefd = dial(&call)) < 0) X { X printmsg(M_ERROR, "dial failed, merror=%s (%d)", X _merr_list[-merrno], merrno); X return FALSE; X } X X return TRUE; X} X Xdcpundial() X{ X if(swritefd > 2) X hangup(swritefd); X} **-dcpunix.c-EOF-** echo 'x - dcputil.c' sed 's/^X//' <<'**-dcputil.c-EOF-**' >dcputil.c X/* X * dcputil.c X * X * Revised^2 edition of dcp Peter Housel Nov '88 X * X * Revised editition of dcp Stuart Lynne May/87 X * X * Copyright (c) Richard H. Lamb 1985, 1986, 1987 X * Changes Copyright (c) Stuart Lynne 1987 X * X * miscellaneous utility functions X */ X#include "dcp.h" X#include <ctype.h> X#include <pwd.h> X X/* X * |uucpname()| returns a pointer to the local host's UUCP nodename. X * There are several possible means of determining this, depending X * on the operating system version. For now, this version just reads X * one line from the |NODENAME| file, which is usually either "/etc/cpu" X * or "/etc/uucpname". X */ Xchar *uucpname() X{ X FILE *uufile; X static char uuname[SITENAMELEN]; X X if(NULL == (uufile = fopen(NODENAME, "r"))) X return ""; X fgets(uuname, sizeof uuname, uufile); X uuname[strlen(uuname) - 1] = '\0'; /* remove '\n' */ X fclose(uufile); X X return uuname; X} X X/* X * |printmsg(level, format, ...)| prints an error or debugging message X * into the system error log file. If not remote, also print to standard X * error. All messages at levels less than or equal to the current X * |debuglevel| are printed. X */ X/* VARARGS1 */ Xprintmsg(level, fmt, a1, a2, a3, a4, a5) Xint level; Xchar *fmt; Xchar *a1, *a2, *a3, *a4, *a5; X{ X char msg[512]; X X if(level <= debuglevel) X { X sprintf(msg, fmt, a1, a2, a3, a4, a5); X strcat(msg, "\n"); X if(remote == MASTER && debuglevel > 0) X fputs(msg, stderr); X fputs(msg, logfile); X } X} X X/* X * visib(data, length) prints the buffer of character data in "visible" X * format. Printable characters (except '\') are printed as themselves, X * special control characters (CR, LF, BS, HT) are printed in the usual X * escape format, and others are printed using 3-digit octal escapes. X * The usual warning about return value pointing to a static buffer which X * is overwritten on each call applies here. X */ Xchar *visib(data, len) Xchar *data; int len; X{ X static char buf[256]; X char c, *p; X X p = buf; X while(len--) X { X c = *data++; X if(isascii(c) && (isprint(c) || ' ' == c)) X *p++ = c; X else if('\n' == c) X {*p++ = '\\'; X *p++ = 'n'; X } X else if('\t' == c) X {*p++ = '\\'; X *p++ = 't'; X } X else if('\r' == c) X {*p++ = '\\'; X *p++ = 'r'; X } X else if('\b' == c) X {*p++ = '\\'; X *p++ = 'b'; X } X else X {sprintf(p, "\\%03o", c); X p += 4; X } X } X *p = '\0'; X return buf; X} X X/* X * |getargs(str, argv)| breaks up |str|, which should be a string of X * whitespace-separated fields, and places a pointer to each field X * into the array pointed to by |argv|. The number of fields is X * returned. X */ Xint getargs(str, argv) Xchar *str; char *argv[]; X{ X int nflds = 0; X X while(*str && isspace(*str)) /* leading space */ X ++str; X X while(*str && '\n' != *str) X { X ++nflds; /* field */ X *argv++ = str; X X while(*str && !isspace(*str)) /* skip to end of field */ X ++str; X *str++ = '\0'; /* and terminate it with a null */ X X while(*str && isspace(*str)) /* trailing space */ X ++str; X } X X return nflds; X} X X/* X * |expandtilde(filename)| expands |filename| using the usual "~" convention. X * That is, "~user" expands to the home directory of "user". "~" by itself X * expands to the home directory of the effective userid, which in this X * case is usually the /usr/spool/uucppublic directory. Care is taken not X * to overflow the (static) name buffer. X */ Xchar *expandtilde(filename) Xchar *filename; X{ X struct passwd *pw, *getpwnam(), *getpwuid(); X static char namebuf[PATHLEN]; X char *p; X X if('~' != *filename) X return filename; X X ++filename; X p = namebuf; X while(*filename && '/' != *filename && (p - namebuf) < PATHLEN) X *p++ = *filename++; X *p = '\0'; X X if(strlen(namebuf) == 0) X pw = getpwuid(geteuid()); X else X pw = getpwnam(namebuf); X X if(NULL == pw) X return NULL; X X if(strlen(pw->pw_dir) + strlen(filename) + 1 > PATHLEN) X return NULL; X strcpy(namebuf, pw->pw_dir); X strcat(namebuf, filename); X return namebuf; X} **-dcputil.c-EOF-** echo 'x - dcpxfer.c' sed 's/^X//' <<'**-dcpxfer.c-EOF-**' >dcpxfer.c X/* X * dcpxfer.c X * X * Revised edition of dcp X * X * Stuart Lynne May/87 X * X * Copyright (c) Richard H. Lamb 1985, 1986, 1987 Changes Copyright (c) Stuart X * Lynne 1987 X * X * "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 X * file send routines X */ X#include "dcp.h" X#include <ctype.h> X Xextern int errno; Xextern char *sys_errlist[]; X Xstatic unsigned char rpacket[MAXPACK]; Xstatic unsigned char spacket[MAXPACK]; X X/***************SEND PROTOCOL****************/ X X/* X * s d a t a X * X * Send File Data X */ Xsdata() X{ X while(TRUE) X { X if((size = fread(spacket, 1, pktsize, fp)) <= 0) /* Get data */ X return ('Z'); /* If EOF set state to that */ X if((*sendpkt) (spacket, size, 0)) X return (0); /* send data */ X } X X return ('D'); /* sent data, stay in state D */ X} X X X/* X * s b r e a k X * X */ Xsbreak() X{ X int len, i; X X if(sendmsg("H") < 0) X return (0); X if(getmsg(spacket) < 0) X return 0; X printmsg(M_CONVERSE, "Switch modes: %s", spacket); X if(spacket[1] == 'N') X return ('G'); X return ('Y'); X} X X X/* X * s e o f X * X * Send End-Of-File. X */ Xseof() X{ X int len, i; X X fclose(fp); X fp = NULL; X X if((*sendpkt) (spacket, 0, 0) < 0) /* length zero packet indicates EOF */ X return (0); X if(getmsg(spacket) < 0) X return (0); /* receive CY or CN */ X if(strncmp(spacket, "CY", 2)) X return (0); /* couldn't send file */ X X unlink(fromfile); X printmsg(M_TRANSFER, "Transfer of %s completed.", fromfile); X X /* X * fprintf( syslog, "%s!%s (%d/%d-%d:%d:%d) -> %ld / %ld secs", host, id, X * size, secs ); X */ X X return ('F'); /* go get the next file to send */ X} X X/* X * s f i l e X * X * Send File Header. X */ Xsfile() X{ X int i, len; X char *cp; X X if(fp == NULL) X { /* If not already open, */ X printmsg(M_SPOOL, "looking for next file..."); X if(getfile()) X { /* get next file from current work */ X fclose(fw); X unlink(cfile); /* close and delete completed workfile */ X fw = NULL; X return ('B'); /* end sending session */ X } X X X printmsg(M_SPOOL, "Opening %s for sending.", fromfile); X fp = fopen(fromfile, "r"); /* open the file to be sent */ X if(fp == NULL) X { /* If bad file pointer, give up */ X printmsg(M_ERROR, "Cannot open file %s.", fromfile); X return ('A'); X } X } X else X return ('A'); /* If something's already open, we're in trouble */ X printmsg(M_SPOOL, "Sending %s as %s", fromfile, tofile); X if(sendmsg(tofile) < 0) X return (0); /* send 'S fromfile tofile user - tofile 0666'. */ X if(getmsg(spacket) < 0) X return (0); X if (spacket[1] != 'Y') X return ('A'); /* If otherside says no-quit */ X return ('D'); X} X X/* X * s i n i t X * X * Send Initiate: send this host's parameters and get other side's back. X */ Xsinit() X{ X if((*openpk) ()) X return ('A'); X return ('B'); X} X X X/* X * X * getfile X * X * getfile reads the next line from the presently open workfile (cfile) and X * determines from this the next file to be sent (file). If there are no more X * TRUE is returned. A fix for "R from to 0666" should be done here to X * recieve files in addition to sending them. The appropriate "state X * letter" i.e. "R" should be returned to the send "master" or "slave" X * state switching table in "dcp.c" I did not implement this since the X * majority of uucp transactions appear to be "S from to 0666" type. X * RHLamb 1/87 X */ Xgetfile() X{ X int i; X char line[132], buf[132]; X register char *cp; X X if(fgets(line, BUFSIZ, fw) == (char *) NULL) X return (TRUE); X X sscanf(line, "%*c %*s %*s %*s %*s %s", buf); X sprintf(fromfile, "%s/%s", SPOOLDIR, buf); X X for(i = 0, cp = line; *cp != '\0'; i++, cp++) X { X if(strncmp(cp, "0666", 4) == 0) X break; X } X cp += 4; X *cp = '\0'; X strcpy(tofile, line); X printmsg(M_SPOOL, "getfile: fromfile=%s, tofile=%s.", fromfile, tofile); X return (FALSE); X} X X X/*********************** MISC SUB SUB PROTOCOL *************************/ X X/* X * X * schkdir X * scan the dir X */ Xschkdir() X{ X char c; X X c = scandir(); X if(c == 'Q') X { X return ('Y'); X } X if (c == 'S') X { X sprintf(rpacket, "HN"); X if((*sendpkt) (rpacket, 0, 1)) X return (0); X } X return ('B'); X} X X/* X * endp() end protocol X * X */ Xendp() X{ X (void) sendmsg("HY"); X (*closepk) (); X return ('P'); X} X X X X/***********************RECIEVE PROTOCOL**********************/ X X/* X * r d a t a X * X * Receive Data X */ Xrdata() X{ X int len; X X if ((*getpkt) (rpacket, &len)) X return (0); X X if(len == 0) X { X fclose(fp); X /* we ought to do the copy in a temp file, and move it here */ X if(sendmsg("CY") < 0) X return (0); X printmsg(M_TRANSFER, "transfer complete"); X return ('F'); X } X X if(fwrite(rpacket, len, 1, fp) != 1) /* Write the data to the file */ X return (0); X return ('D'); /* Remain in data state */ X} X X X/* X * r f i l e X * X * Receive File Header X */ Xrfile() X{ X char buf[256]; X char *flds[10]; X int numflds; X X int len, i; X char tmpfilename[256]; /* Holds the converted file name */ X char *cp; X X printmsg(M_TRANSFER, "rfile entered"); X X if(getmsg(buf) < 0) X return 0; X X if(buf[0] == 'H') X return ('C'); X X printmsg(M_TRANSFER, "rfile: buf %d \"%s\"", len, buf); X X /* X * Convert upper case to lower X * for(cp = buf; *cp != '\0';cp++) X * if(isupper(*cp)) X * tolower(*cp); X */ X X numflds = getargs(buf, flds); X X cp = flds[2]; X printmsg(M_INFO, "rfile: receive file \"%s\"", cp); X X /* check for ~/ destination -> /usr/spool/uucppublic */ X if (strncmp(cp, "~/", 2) == SAME) X sprintf(tmpfilename, "%s%s", PUBDIR, cp + 1); X else X sprintf(tmpfilename, "%s/%s", SPOOLDIR, cp); X printmsg(M_INFO, "rfile: receive file \"%s\"", tmpfilename); X X /* check for dirname only */ X cp = tmpfilename + strlen(tmpfilename) - 1; X if (*cp == '\n') X *cp-- = '\0'; X X if(*cp == '/') X { X cp = rindex(flds[1], '/'); X if(cp == (char *) NULL) X cp = flds[1]; X else X cp++; X X strcat(tmpfilename, cp); X } X X strcpy(tofile, tmpfilename); X printmsg(M_TRANSFER, "rfile: receive file \"%s\"", tofile); X X if((fp = fopen(tofile, "w")) == NULL) X { /* Try to open a new file */ X printmsg(M_ERROR, "cannot create %s err=%s", tofile, sys_errlist[errno]); X return ('A'); /* Give up if can't */ X } X printmsg(M_TRANSFER, "Receiving %s as %s", flds[1], tofile); X if(sendmsg("SY") < 0) X return (0); X return ('D'); /* Switch to data state */ X} X X/* X * r i n i t X * X * Receive Initialization X */ Xrinit() X{ X if ((*openpk) ()) X return (0); X return ('F'); X} X X X/* X * |getmsg()| recieves a null-terminated "conversation-level" message X * from the communications channel. This may require one or more packets, X * but all of them will be "long-data" packets containing a full 64 bytes. X */ Xint getmsg(dest) Xchar *dest; X{ X int len; X X while(1) X { X if((*getpkt)(dest, &len) < 0) X return -1; X *(dest + len) = '\0'; /* make sure it's terminated */ X if(strlen(dest) != len) X break; /* we reached the terminator */ X dest += len; X } X X return 0; X} X X/* X * |sendmsg(message)| sends a null-terminated "conversation-level" message. X */ Xint sendmsg(message) Xchar *message; X{ X int len; X len = strlen(message) + 1; /* total length including '\0' */ X X while(1) X { X if((*sendpkt)(message, 0, 1) < 0) /* send with padding */ X return -1; X if((len -= pktsize) <= 0) X break; X message += pktsize; X } X return 0; X} **-dcpxfer.c-EOF-** mkdir lib.uucp; cd lib.uucp echo 'x - lib.uucp/' echo 'x - L-devices' sed 's/^X//' <<'**-L-devices-EOF-**' >L-devices X#type line foo baud brand X#----- ------ ------ ------ ------ XACU tty1 foo 1200 promodem **-L-devices-EOF-** echo 'x - L.sys' sed 's/^X//' <<'**-L.sys-EOF-**' >L.sys Xnoname Any ACU 1200 867-5309 "" "" ogin:--ogin: uucp ssword: FATCHANCE **-L.sys-EOF-** echo 'x - LOGFILE' sed 's/^X//' <<'**-LOGFILE-EOF-**' >LOGFILE **-LOGFILE-EOF-** echo 'x - SPOOLSEQ' sed 's/^X//' <<'**-SPOOLSEQ-EOF-**' >SPOOLSEQ X1 **-SPOOLSEQ-EOF-** cd .. mkdir modemcap; cd modemcap echo 'x - modemcap/' echo 'x - Makefile' sed 's/^X//' <<'**-Makefile-EOF-**' >Makefile X# Your library directory. XLIBDIR=/usr/lib X# Your local command directory. XLBIN=/usr/housel/bin X# OSFLAG=-DUNIX_S5 # For System V machines. XOSFLAG=-DUNIX_V7 # For Version 7 machines. X# For those poor people who need ranlib X# RANLIB=ranlib $(LIBDIR)/libmodemcap.a X# Standard Bourne shell. XSHELL=/bin/sh X XCFLAGS=$(OSFLAG) -LIB X# CFLAGS=-O X# LDFLAGS=-s X XOFILES=mgetent.s mgetstr.s mgetflag.s mgetnum.s mdial.s merror.s \ X initmodem.s hangup.s dial.s dialvars.s X XCFILES=mgetent.c mgetstr.c mgetflag.c mgetnum.c mdial.c merror.c \ X initmodem.c hangup.c dial.c dialvars.c X XLFILES= hangup.s\ X dial.s\ X dialvars.s\ X initmodem.s\ X mgetent.s\ X mgetstr.s\ X mgetflag.s\ X mgetnum.s\ X mdial.s\ X merror.s\ X Xall: libmodemcap.a X Xlibmodemcap.a: $(LFILES) X ar r libmodemcap.a $(LFILES) X Xinstall: all call X cp modemcap.h /usr/include X cp modemcap /etc/modemcap X cp modemtype /etc/modemtype X cp libmodemcap.a $(LIBDIR) X chmod 644 /usr/include/modemcap.h /etc/modemcap /etc/modemtype $(LIBDIR)/libmodemcap.a X cp call $(LBIN)/call X chmod 711 $(LBIN)/call X Xcall: call.c libmodemcap.a X cc $(LDFLAGS) $(CFLAGS) call.c libmodemcap.a scanf.s -o call X Xinitmodem.s: initmodem.c /usr/include/modemcap.h X Xmdial.s: mdial.c /usr/include/modemcap.h X Xhangup.s: hangup.c /usr/include/modemcap.h X Xdial.s: dial.c /usr/include/modemcap.h X Xshar: README $(CFILES) makefile modemcap modemtype modemcap.h call.c X shar README makefile modemcap modemtype modemcap.h $(CFILES) call.c > modem.shar **-Makefile-EOF-** echo 'x - README' sed 's/^X//' <<'**-README-EOF-**' >README XThis package is a modem independent dial(3) package. It provides a device Xindependent method for dialing and manipulating modems. The format of the Xdescription file is the ever present ;-) termcaps format. You may want to Xread the modemcap file to see just what capabilities are present. X XThis is Release 1.1 of this software. Please bear in mind that I haven't Xreleased this to the public before this release. X X--< Start of the legal conditions of this software >-- X XThis software is copyright 1987 John F. Haugh II, all rights reserved. XUse, duplication and disclosure subject to the terms and conditions of Xthe license agreement below. This notice is intended to have legal Xsignificance, and not to be taken lightly. If you have any questions, Xplease contact the author at the address below. This copyright covers Xthe entire software distribution it is enclosed with. Removing this Xcopyright is a violation of federal copyright law. Please consult an Xattorney if you have any questions regarding the legal ramifications of Xthis agreement. X XThis software is licensed subject to the following terms and conditions. XIn order that this product may expand into the universe to fill the current X(void) in this area, it is my intention that this software be widely Xdistributed, and maintained in a consistent fashion. To this end, you Xare authorized to redistribute this software in either source or binary Xformat, provided that, this agreement is retained as part of the release, Xno direct profit is realized from the sale or transfer of this software, Xand that credit is given the author for this work. To facilitate this Xpackage coming into acceptance, you must provide library versions of this Xsoftware and any documentation included with this package when distributing Xbinary versions embedded in your products. Paying royalties would be Xnice and you won't do it anyway, so don't even pretend to be nice people Xunless you really want me to stay on top of this thing. Author retains Xall rights to derived works, and as a condition to your making modifications Xto the source code, you are required by this agreement to provide detailed Xnotes concerning the actual modifications and the motivation behind the Xmodification itself. Making the documentation look better is a nice idea Xalso. And since I'm very lazy, please send me your documentation. You Xdon't have to, but standardized documentation is a Good Thing. X XThe author provides this software without warrantee. The user accepts by Xuse all responsibility for the performance (or lack thereof ;-) of this Xsoftware, including loss of profits, reputation, or job. X X--< End of the legal stuff, now for the documentation. >-- X Xcall.c - a test program. do a `make all' to create the library and compile Xthe call program. read all the documentation before trying it out. X Xdial(3L) - a version of the standard dial(3) command which should be fairly Xcompatible with the one in your manual ... has both dial() and undial() Xroutines. see your manpage for more details. X Xhangup.c/hangup(3L) - a routine that attempts to absolutely hangup a modem. Xit uses the modem capabilities database to figure out the best way to Xhangup a modem. it supports both hangup on DTR and hangup on command. X Xinitmodem.c/initmodem(3L) - this routine takes a character pointer to a Xmodem name as it appears in the database and a file descriptor from a Xopen() call, and loads the database information. after the database is Xloaded, the modem is placed in the command mode. beware, initmodem() Xmay make an alarm(2) call if the InitializationDelay requirement is present. X Xmdial.c/mdial(3L) - this routine builds a dial command string to give Xto the dialer. this is the weakest routine in the package, because i don't Xhave that many different modems around here, and hayes is pretty damned Xcommon, so i don't see many others. the first argument is a character string Xtelephone number, digits only, or if you understand your modem (boo on me) Xyou can put in pause commands. the second argument is a file descriptor Xfrom an open() call. this routine _will_ be the first to get fixed. X Xmerror.c/merror(3L) - this routine is a modemcap replacement for perror. Xan `int merrno' variable is maintained by the routines. after an error Xreturn, you can call merror with a character pointer just like perror(3) Xand have a message printed on your standard error output. X Xmgetent.c/mgetent(3L) - this is a low level routine you shouldn't be Xcalling anyway. it works like tgetent(3), only different. mostly, it Xdoesn't have the neat things. the first argument is a pointer to a Xcharacter buffer where the entry will be placed. the second argument Xis a pointer to the modem name. X Xmgetflag.c/mgetflag(3L) - just like tgetflag. this is a low level Xroutine you might just want to use. in particular, `if (mgetflag ("hc"))' Xtests for modem hanging up on DTR being negated. `if (HC)' does the Xsame thing after mgetent() ... X Xmgetnum.c/mgetnum(3L) - just like tgetnum. don't see much use for using Xit. X Xmgetstr.c/mgetstr(3L) - just like tgetstr, except it has a few quirks. Xoctal escapes are all three digits. the format '^c' where 'c' is some Xcharacter, only works with upper case letters. correctly at least. Xain't no way to get a null into the string, no how. X X/etc/modemcap - a modem capabilities database. read the file for more Xdetails. X X/etc/modemtype - a modem/port mapping table. look at the example file. X Xyou will need to make entries for your devices in the L-devices file. Xthe speed listed must be a legal speed according to the modemcap file. Xany compilation errors or warnings should be brought to my attention. i Xdidn't get any the last time i compiled all this stuff. X Xthe source is well enough (i'm lieing) documented for anyone to fix. Xplease don't add your local improvement. if you insist, make the mods Xand send me context diffs. i'll tell you what i think about the change. Xremember, according to the license you must let me in on what you are Xdoing. this is in everyones best interest. X X--< End of the documentation, now for my personal philosophical b.s. >-- X XIt is not my intention to limit the use of this software or your profits, Xexcept where such use is inconsistent with the spirit of humanity, whatever Xthe hell that means. I don't care how much money you make selling your Xnew terminal program, just don't go jacking the price up because you Xhave added this thing. I will only work on this package if I get feedback Xand I have some motivation, other than being a nice guy. I think I've been Xnice enough by putting this thing out there. If what you want makes sense Xin a real way, I will probably include your suggestions, and if you are Xpolite, I might just give you credit ;-) So don't be a jerk and pretend Xthat anyone actually works for free. I have a car note just like you. X XBy way of this license and the legal mumbo-jumbo, I hope to keep people Xfrom ripping me off, and totally trashing and perverting the integrity Xof the code. Please, don't construe this agreement to be limiting in Xa negative way. I hope to provide just enough limits to keep the code Xconsistent and portable across all machine environments, and hopefully, Xyou will use this thing enough that it becomes better and more useful Xand fills the need for such a thing. Who knows, we both might just make Xsome money off of this thing. X X-- XJohn F. Haugh II QUOTE: "The important thing is to not stop X7825 McCallum Blvd. questioning" -- Albert Einstein XApt. 510 TELCO: (214) 250-3311 XDallas, TX 75252 UUCP: { backbone } !ihnp4!killer!jfh **-README-EOF-** echo 'x - README.housel' sed 's/^X//' <<'**-README.housel-EOF-**' >README.housel XAll of this stuff is modified from jfh@rpp368.dallas.tx.us's package, Xso that it more closely follows the dial(3) manual page. Some things Xwere changed just because I wanted them to be done that way. **-README.housel-EOF-** echo 'x - call.c' sed 's/^X//' <<'**-call.c-EOF-**' >call.c X#include <dial.h> X#include <stdio.h> X XCALL call; X Xmain (argc, argv) Xint argc; Xchar **argv; X{ X if (strcmp (argv[0], "call") == 0) X exit (do_call (argc, argv)); X else if (strcmp (argv[0], "hangup") == 0) X exit (do_hup (argc, argv)); X X fprintf (stderr, "usage: call tty baud telno\n"); X fprintf (stderr, " hangup tty baud\n"); X exit (1); X} X Xdo_call (argc, argv) Xint argc; Xchar **argv; X{ X int fd; X X if (argc < 4) { X fprintf (stderr, "usage: call tty baud telno\n"); X exit (1); X } X call.line = argv[1]; X call.baud = atoi (argv[2]); X call.telno = argv[3]; X X fd = dial (&call); X if (fd < 0) { X merror (argv[0]); X exit (2); X } X undial (fd); X return (0); X} X Xdo_hup (argc, argv) Xint argc; Xchar **argv; X{ X int fd; X X if (argc < 3) { X fprintf (stderr, "usage: hangup tty baud\n"); X exit (1); X } X call.line = argv[1]; X call.baud = atoi (argv[2]); X X fd = dial (&call); X if (fd < 0) { X merror (argv[0]); X exit (2); X } X hangup (fd); X undial (fd); X return (0); X} **-call.c-EOF-** echo 'x - dial.c' sed 's/^X//' <<'**-dial.c-EOF-**' >dial.c X#include <sgtty.h> X#include <dial.h> X#include <signal.h> X#include <stdio.h> X#include "modemcap.h" X Xstatic char lockfile[64]; Xstatic int modemfd = -1; Xextern int merrno; X Xstatic findline(callp, brand) XCALL *callp; Xchar *brand; X{ X int exists = 0; /* device exists at some baud rate */ X int tried = 0; /* found a device but it was locked */ X static char l_line[DVC_LEN+1]; /* tty device name */ X char l_type[DVC_LEN+1]; /* ACU, DIR, etc. */ X int l_baud; /* tty baud rate */ X char buf[128]; /* L-devices line buffer */ X FILE *fp; /* L-devices file pointer */ X int fd; /* device lock file descriptor */ X char *strcpy (), X *strcat (); X X if((fp = fopen (LDEVS, "r")) == NULL) X return (merrno = NO_Ldv); X X while(fgets(buf, sizeof buf, fp) != NULL) X { X if(buf[0] == '#') /* ignore comment lines */ X continue; X X if(sscanf (buf, "%s%s%*s%d%s", l_type, l_line, &l_baud, brand) != 4) X continue; /* mangled line */ X X if(callp->telno != NULL) /* we're going to dial */ X { X if(strcmp (l_type, "ACU") != 0) X continue; /* not a dialer line */ X X if(callp->line != NULL) /* device specified? */ X if(strcmp (l_line, callp->line) != 0) X continue; /* wrong device */ X X exists++; /* say device exists at some baud rate */ X X if(l_baud != callp->speed) /* does it use the right speed? */ X continue; X } X else if(callp->line != NULL) X { X if(strcmp(l_type, "DIR") != 0) X continue; /* not a dialer line */ X X if(strcmp(l_line, callp->line) != 0) X continue; /* wrong device */ X X callp->baud = l_baud; /* use line's baud rate */ X } X X ++tried; /* found device at desired baud rate*/ X strcat(strcpy(lockfile, LOCK), l_line); X X if(access(lockfile, 0) == 0 || (fd = creat (lockfile, 0)) == -1) X continue; /* couldn't create lock */ X X close (fd); /* created lock, now close descriptor */ X fclose (fp); X callp->line = l_line; X return (1); X } X X if(tried) X return (merrno = DV_NT_A); X else if(exists) X return (merrno = ILL_BD); X else X return (merrno = DV_NT_K); X} X X Xstatic struct speedlist { X int value; X int name; X} speeds[] = { X { 0, 0}, X { 110, B110}, X { 300, B300}, X/* { 600, B600}, */ X { 1200, B1200}, X { 2400, B2400}, X { 4800, B4800}, X { 9600, B9600}, X/* {19200, EXTA}, */ X/* {38400, EXTB}, */ X { -1, -1} X}; X Xstatic findspeed(speed) Xint speed; X{ X register struct speedlist *ps; X X for (ps = speeds; ps->value >= 0; ps++) X if (ps->value == speed) X return (ps->name); X X return (0); X} X X#ifdef CATCH Xalarmcatch () X{ X long timebuf[2]; X X time (&timebuf[0]); X timebuf[1] = timebuf[0]; X X utime (lockfile, timebuf); X signal (SIGALRM, alarmcatch); X alarm (3600); X} X Xhupcatch () X{ X close (modemfd); X unlink (lockfile); X signal (SIGHUP, SIG_DFL); X} X#endif CATCH X Xint dial (call) XCALL *call; X{ X char modemline[64]; /* device name */ X char modemname[16]; /* modemcap name of modem */ X char *strcpy (), X *strcat (); X#ifdef UNIX_S5 X struct termio termio; X#endif X#ifdef UNIX_V7 X struct sgttyb termio; X#endif X int fd; X int err; X X modemname[0] = '\0'; X X fd = -1; /* channel illegal until line is opened */ X X if ((err = findline (call, modemname)) <= 0) X goto error; X X if (modemname[0] == '\0') { /* can't determine the type of modem */ X printf("can't determine modem type\n"); X err = DV_NT_K; X goto error; X } X X strcat(strcpy(modemline, DEVDIR), call->line); X if ((fd = open (modemline, O_RDWR)) < 0) { /* can't open modem line */ X err = L_PROB; X goto error; X } X#ifdef UNIX_S5 X if (call->attr != (struct termio *) 0) { /* set attributes */ X if (ioctl (fd, TCSETA, call->attr) == -1) { /* some ioctl() problem */ X err = L_PROB; X goto error; X } X } else { X ioctl (fd, TCGETA, &termio); X if ((termio.c_cflag = findspeed (call->baud)) == 0) { X err = ILL_BD; X goto error; X } X termio.c_cflag |= (CS8|CREAD|HUPCL); X termio.c_iflag = 0; X termio.c_oflag = 0; X termio.c_lflag = 0; X termio.c_cc[VMIN] = 1; X termio.c_cc[VTIME] = 1; X if (ioctl (fd, TCSETA, &termio) == -1) { X err = L_PROB; X goto error; X } X } X#endif X#ifdef UNIX_V7 X if (call->attr != (struct sgttyb *) 0) { /* set attributes */ X if (gtty (fd, call->attr) == -1) { /* some gtty() problem */ X err = L_PROB; X goto error; X } X } else { X gtty (fd, &termio); X if ((termio.sg_ispeed = findspeed (call->baud)) == 0) { X err = ILL_BD; X goto error; X } X termio.sg_ospeed = termio.sg_ispeed; X termio.sg_flags = RAW|ANYP; X termio.sg_erase = -1; X termio.sg_kill = -1; X if (stty (fd, &termio) == -1) { X err = L_PROB; X goto error; X } X } X#endif X initmodem (modemname, fd); /* setup modemcap variables */ X if (call->telno == NULL) /* no phone number, connection complete */ X goto okay; X X if (! DI) { /* modem has no ACU!!! */ X err = A_PROB; /* no ACU to attach to */ X goto error; X } X if (BD != call->baud) { /* is connection desired at high speed? */ X if (BL != call->baud){/* is connection desired at low speed? */ X err = ILL_BD; /* modem can't handle this speed */ X goto error; X } X BD = BL; /* set baud to low baud rate */ X CO = CL; /* set connect reply to low baud reply */ X } X if (err = mdial (call->telno, fd)) /* some error trying to dial */ X goto error; X#ifdef CATCH X signal (SIGALRM, alarmcatch); /* set catcher for ALARM clock */ X signal (SIGHUP, hupcatch); /* set catcher for HANG UP */ X alarm (3600); /* set clock to touch lock in 1 hour */ X#endif CATCH X Xokay: X return (modemfd = fd); X Xerror: X if(lockfile[0]) /* don't unlink '.'! */ X unlink (lockfile); X if (fd > 2) X close (fd); X return (merrno = err); X} X Xvoid undial (fd) Xint fd; X{ X if (fd > 2) X close (fd); X X if(lockfile[0]) X unlink (lockfile); X#ifdef CATCH X alarm (0); X#endif CATCH X} **-dial.c-EOF-**