home *** CD-ROM | disk | FTP | other *** search
- /*
- For best results in visual layout while viewing this file, set
- tab stops to every 8 columns.
- */
-
- /*
- ibmpc/ulib.c
-
- DCP system-dependent library
-
- Services provided by ulib.c:
-
- - login
- - UNIX commands simulation
- - serial I/O
- - rnews
- */
-
- /*
- * Modified by Stephen C. Trier (sct@po.CWRU.Edu)
- * January - April, 1990
- *
- * Added support for external rmail and rnews commands.
- * External rmail is mandatory; external rnews is not.
- *
- * DTR now stays low long enough to make smart modem hang
- * up. This was needed for multiple-host support.
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <process.h>
- #include <fcntl.h>
-
- #include "dcp.h"
-
- extern int rmsg();
- extern void wmsg();
-
- /*
- login - login handler
- */
-
- /* Currently a dumb login handler for PC in slave mode. */
-
- char login(void)
- {
- char line[132];
-
- for ( ; ; ) {
-
- msgtime = 9999; /* make it very long */
- while (rmsg(line, 0) == -1); /* wait for a <CR> or <NL> */
- msgtime = 2 * MSGTIME;
-
- wmsg("Login:", 0);
- if (rmsg(line, 0) == -1)
- continue;
- printmsg(0, "login: login=%s", line);
-
- wmsg("Password:", 0);
- if (rmsg(line, 0) == -1)
- continue;
- printmsg(14, "login: password=%s", line);
-
- if (equal(line, "uucp"))
- break;
-
- }
- printmsg(14, "login: logged in");
-
- return 'I';
-
- } /*login*/
-
-
- /*
- notimp - "perform" Unix commands which aren't implemented
- */
-
- static int notimp(argc, argv)
- int argc;
- char *argv[];
- {
- int i = 1;
-
- printmsg(0, "shell: command '%s' not implemented", *argv);
- while (i < argc)
- printmsg(6, "shell: argv[%d]=\"%s\"", i++, *argv++);
-
- return 0;
-
- } /*notimp*/
-
-
- /*
- shell - simulate a Unix command
-
- Only the 'rmail' and 'rnews' command are currently supported.
- */
-
- void shell(command, inname, outname, errname)
- char *command;
- char *inname, *outname, *errname;
- {
- extern int rmail(), rnews();
-
- char *argv[50];
- int argc;
- int (*proto)();
-
- argc = getargs(command, argv);
-
- if (debuglevel >= 6) {
- char **argvp = argv;
- int i = 0;
- while (i < argc)
- printmsg(6, "shell: argv[%d]=\"%s\"", i++, *argvp++);
- }
-
- if (equal(argv[0], "rmail"))
- proto = rmail;
- else if (equal(argv[0], "rnews"))
- proto = rnews;
- else
- proto = notimp;
-
- if (*inname != '\0') {
- char localname[64];
- importpath(localname, inname);
- if (freopen(localname, "rb", stdin) == nil(FILE)) {
- extern int errno;
- printmsg(0, "shell: couldn't open %s (%s), errno=%d.",
- inname, localname, errno);
- }
- }
-
- (*proto)(argc, argv);
-
- freopen("con", "r", stdin);
-
- } /*shell*/
-
-
- /* IBM-PC I/O routines */
-
- /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
-
- /*************** BASIC I/O ***************************/
- /* Saltzers serial package (aka Info-IBMPC COM_PKG2):
- * Some notes: When packets are flying in both directions, there seems to
- * be some interrupt handling problems as far as receiving. Checksum errors
- * may therefore occur often even though we recover from them. This is
- * especially true with sliding windows. Errors are very few in the VMS
- * version. RH Lamb
- */
-
- #include "comm\comm.h"
-
- #define STOPBIT 1
- #define LINELOG "LineData.Log" /* log serial line data here */
-
- static int log_handle;
- static FILE *log_stream;
-
- /*
- openline - open the serial port for I/O
- */
-
- int openline(name, baud)
- char *name, *baud;
- {
- int value;
-
- printmsg(15, "openline: %s, %s", name, baud);
-
- sscanf(name, "COM%d", &value);
- select_port(value);
- save_com();
- install_com();
- open_com(atoi(baud), 'D', 'N', STOPBIT, 'D');
- dtr_on();
-
- /* log serial line data only if log file already exists */
- log_handle = open(LINELOG, O_WRONLY | O_TRUNC | O_BINARY);
- if (log_handle != -1) {
- printmsg(15, "logging serial line data to %s", LINELOG);
- log_stream = fdopen(log_handle, "wb");
- }
-
- return 0;
-
- } /*openline*/
-
-
- /*
- sread - read from the serial port
- */
-
- /* Non-blocking read essential to "g" protocol.
- See "dcpgpkt.c" for description.
- This all changes in a multi-tasking system. Requests for
- I/O should get queued and an event flag given. Then the
- requesting process (e.g. gmachine()) waits for the event
- flag to fire processing either a read or a write.
- Could be implemented on VAX/VMS or DG but not MS-DOS. */
-
- int sread(buffer, wanted, timeout)
- char *buffer;
- int wanted, timeout;
- {
- long start;
-
- start = time(nil(long));
- for ( ; ; ) {
- int pending;
- pending = r_count_pending();
- printmsg(20, "sread: pending=%d, wanted=%d", pending, wanted);
- if (pending >= wanted) { /* got enough in the buffer? */
- int i;
- for (i = 0; i < wanted; i++)
- *buffer++ = receive_com();
- if (log_handle != -1) {
- buffer -= wanted;
- for (i = 0; i < wanted; i++) {
- fputc(0x01, log_stream); /* 1 for writes */
- fputc(*buffer++, log_stream);
- }
- }
- return pending;
- } else {
- int elapsed;
- elapsed = time(nil(long)) - start;
- if (elapsed >= timeout)
- return pending;
- }
- }
-
- } /*sread*/
-
-
- /*
- swrite - write to the serial port
- */
-
- int swrite(data, len)
- char *data;
- int len;
- {
- int i;
-
- for (i = 0; i < len; i++)
- send_com(*data++);
-
- if (log_handle != -1) {
- data -= len;
- for (i = 0; i < len; i++) {
- fputc(0x02, log_stream); /* 2 for writes */
- fputc(*data++, log_stream);
- }
- }
-
- return len;
-
- } /*swrite*/
-
-
- /*
- ssendbrk - send a break signal out the serial port
- */
-
- void ssendbrk(duration)
- int duration;
- {
-
- printmsg(12, "ssendbrk: %d", duration);
-
- break_com();
-
- } /*ssendbrk*/
-
-
- /*
- closeline - close the serial port down
- */
-
- void closeline(void)
- {
- int far *stats;
-
- dtr_off();
- close_com();
- restore_com();
- sleep(3); /* Make sure modem hangs up [SCT] */
-
- if (log_handle != -1) { /* close serial line log file */
- fclose(log_stream);
- close(log_handle);
- };
-
- stats = com_errors();
- printmsg(3, "\nBuffer overflows: %d", stats[COM_EOVFLOW]);
- printmsg(3, "Receive overruns: %d", stats[COM_EOVRUN]);
- printmsg(3, "Break chars: %d", stats[COM_EBREAK]);
- printmsg(3, "Framing errors: %d", stats[COM_EFRAME]);
- printmsg(3, "Parity errors: %d", stats[COM_EPARITY]);
- printmsg(3, "Transmit errors: %d", stats[COM_EXMIT]);
- printmsg(3, "DSR errors: %d", stats[COM_EDSR]);
- printmsg(3, "CTS errors: %d\n", stats[COM_ECTS]);
-
- } /*closeline*/
-
-
- #ifndef __TURBOC__
- /*
- sleep() - wait n seconds
-
- Simply delay until n seconds have passed.
- */
-
- void sleep(interval)
- int interval;
- {
- long start;
-
- start = time(nil(long));
- while ((time(nil(long)) - start) < interval);
-
- } /*sleep*/
- #endif /*__TURBOC__*/
-
-
- /*
- SIOSpeed - re-specify the speed of an opened serial port
- */
-
- void SIOSpeed(baud)
- char *baud;
- {
-
- dtr_off();
- close_com();
- open_com(atoi(baud), 'D', 'N', STOPBIT, 'D');
- dtr_on();
-
- } /*SIOSpeed*/
-
-
- /*
- * rnews - receive incoming news
- *
- * I added provisions for a stand-alone rnews, with fallback to the normal
- * UUPC rnews. I do not receive news, so I have not been able to test this
- * feature. I hope it works. If you try it, please send me a note saying
- * how it works. -- Stephen Trier (sct@po.cwru.edu)
- *
- * rnews uses a static variable to tell it if any previous spawn of rnews
- * failed. If it did, it will use the internal rnews. This keeps the
- * routine from trying to spawn rnews for every single incoming news article,
- * unless there is an rnews there to receive them. -- Stephen Trier
- */
-
- int rnews(int argc, char *argv[]) /* SCT */
- {
- static int temp = 0;
-
- argv[argc] = NULL;
-
- if (temp != -1)
- temp = spawnvp(P_WAIT, "rnews", argv);
- switch (temp) {
- case 0:
- break;
- case -1:
- printmsg(2, "Can't find rnews in path. Using internal rnews.");
- temp = old_rnews(argc, argv);
- break;
- default:
- printmsg(1, "rnews returns %d", temp);
- break;
- }
-
- return temp;
- }
-
- /*
- * This is the original UUPC rnews, modified so that it handles
- * binary data correctly. -- SCT
- */
- int old_rnews(argc, argv)
- int argc;
- char *argv[];
- {
- static int count = 1;
- char filename[132], format[128], buf[BUFSIZ];
- #ifndef OLD_RNEWS
- size_t charsread;
- #endif
- FILE *f;
- long now = time(nil(long));
-
- mkfilename(format, newsdir, "%08.8lX.%03.3d"); /* make pattern first */
- sprintf(filename, format, now, count++); /* build real file name */
-
- printmsg(6, "rnews: putting incoming news into %s", filename);
- if ((f = FOPEN(filename, "w", BINARY)) == nil(FILE)) {
- printmsg(0, "rnews: can't open %s (%d)", filename, errno);
- return -1;
- }
-
- #ifdef OLD_RNEWS
- while (fgets(buf, BUFSIZ, stdin) != nil(char))
- fputs(buf, f);
- #else
- while ((charsread = fread(buf, (size_t) 1, (size_t) BUFSIZ, stdin)) != 0)
- fwrite(buf, (size_t) 1, charsread, f);
- #endif
-
- fclose(f);
-
- return 0;
-
- } /*rnews*/
-
-
- /*
- * rmail - Call external rmail program (SCT)
- */
-
- #include <errno.h>
-
- int rmail(int argc, char *argv[])
- {
- int temp;
-
- argv[argc] = NULL;
-
- temp = spawnvp(P_WAIT, "rmail", argv);
- switch (temp) {
- case 0:
- break;
- case -1:
- printmsg(0, "Error while forking rmail: %s", sys_errlist[errno]);
- break;
- default:
- printmsg(1, "rmail returns %d", temp);
- break;
- }
-
- return temp;
- }