/* 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 #include #include #include #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 or */ 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 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; }