📄 edown.c
字号:
/************************************************************* * File: tools/edown.c * Purpose: ASCII-file downloader * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970518 Start of revision history *//* * Although this file contains ifdef's for MSDOS, I have found that * it doesn't port very well. So for now I recommend that you don't * try to use this program on MSDOS (or Win95). */#include <stdio.h>#include <fcntl.h>#ifdef MSDOS#include <bios.h>#include <dos.h>#define read xread#define write xwrite#else#include <termio.h>#endif#include <ctype.h>#define ACK 0x06#define MAXREC 600 /* maximum length of record */char *getenv();struct brate { char *str; int value; };#ifdef MSDOS#define B50 0#define B75 0#define B110 _COM_110#define B134 0#define B200 0#define B150 _COM_150#define B300 _COM_300#define B600 _COM_600#define B1200 _COM_1200#define B1800 0#define B2400 _COM_2400#define B4800 _COM_4800#define B9600 _COM_9600#define B19200 0#define B38400 0#endifstruct brate btable[] = { {"50",B50}, {"75",B75}, {"110",B110}, {"134",B134}, {"200",B200}, {"150",B150}, {"300",B300}, {"600",B600}, {"1200",B1200}, {"1800",B1800}, {"2400",B2400}, {"4800",B4800}, {"9600",B9600}, {"19200",B19200}, {"38400",B38400}, {0}};int printfreq;char *usage[] = { "usage: edown -p# [device] [brate] < <file>", "\t-p\tdefine frequency of status messages", "\tdevice\tdevice name", "\tbrate\tbaudrate", 0};/*** Download ASCII text files to a target system from stdin using** ETX/ACK protocol. Each line transmitted by edown is terminated by** an ETX character. Edown then waits indefinitely for an ACK character** from the target system, before transmitting the next line.**** The baudrate and device may be specified using the two environment** variables DLBAUD & DLPORT. If the baudrate is not specified, 9600** baud will be used. There is no default for the device name.*/main(argc,argv) int argc; char *argv[];{char c,buf[MAXREC];int i,fd,line,len,reqdBrate,j;unsigned long secs,prev,t0,t1;char *device, *Bopt;#ifndef MSDOSstruct termio tbuf;#endifBopt = getenv("DLBAUD");device = getenv("DLPORT");for (i=1;i<argc;i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'p' : sscanf(&argv[i][2],"%d",&printfreq); break; default: printf("edown: bad option: %s\n",argv[i]); case 'h' : for (j=0;usage[j];j++) printf("%s\n",usage[j]); exit(1); } } else if (isdigit(argv[i][0])) Bopt = argv[i]; else device = argv[i]; } if (device == 0) { printf("edown: device not specified\n"); exit(-1); }if (Bopt == 0) Bopt = "9600";for (i=0;btable[i].str != 0;i++) { if (!strcmp(Bopt,btable[i].str)) break; }if (btable[i].str == 0 || btable[i].value == 0) { printf("%s: unrecognized baud rate\n",Bopt); exit(-1); }reqdBrate = btable[i].value;#ifdef MSDOS#define PORTSETTINGS (_COM_CHR8|_COM_STOP1|_COM_NOPARITY)fd = device[3]-'1';_bios_serialcom(_COM_INIT,fd,btable[i].value|PORTSETTINGS);#elsefd = open(device,O_RDWR);if (fd == -1) { printf("edown: can't open %s\n",device); exit(-1); }/* set device characteristics */if (ioctl(fd, TCGETA, &tbuf) == -1) { fprintf(stderr,"ioctl(TCGETA) failed\n"); exit(-1); }tbuf.c_iflag &= ~(BRKINT|IGNPAR);tbuf.c_lflag &= ~(ISIG|ICANON|ECHO);tbuf.c_oflag = 0;tbuf.c_cflag &= ~CBAUD;tbuf.c_cflag |= reqdBrate;tbuf.c_cc[VEOF] = 1; /* one char */tbuf.c_cc[VEOL] = 0; /* no wait */if (ioctl(fd, TCSETAF, &tbuf) == -1) { fprintf(stderr,"ioctl(TCSETAF) failed\n"); exit(-1); }#endifline = prev = 0;t0 = time(0L);while (gets(buf)) { line++; /* current line number */ len = strlen(buf); /* make sure the line isn't too long */ if (len >= MAXREC) { fprintf(stderr,"line %d too long\n",line); exit(-1); } /* write a line */ if (write(fd,buf,len) != len) { fprintf(stderr,"bad write of line %d to device\n",line); exit(-1); } /* send ETX */ if (write(fd,"\003",1) != 1) { fprintf(stderr,"bad write of ETX to device\n"); exit(-1); } /* wait for ACK */ for (;;) { c = 0; if (read(fd,&c,1) != 1) { fprintf(stderr,"bad read from device\n"); exit(-1); } c &= 0x7f; /* mask out parity */ if (c != 0) break; } if (c != ACK) { fprintf(stderr, "Bad acknowledgment %02x line %d \n",c, line); exit(-1); } /* print status line every printfreq lines */ if (printfreq == 0) { /* or every 2 secs */ secs = time(0L); if (secs > prev+2) { prev = secs; printf("%5d records\r",line); fflush(stdout); } } else { if ((line % printfreq) == 0) { printf("%5d records\r",line); fflush(stdout); } } }t1 = time(0L);printf("Done: total %d records transferred in ",line);if (t1-t0 >= 60) printf("%d minutes %d seconds\n",(t1-t0)/60,(t1-t0)%60);else printf("%d seconds\n",t1-t0);}#ifdef MSDOSxread(fd,buf,cnt)int fd,cnt;char *buf;{int i,c,r;for (i=0;i<cnt;i++) { do { r = _bios_serialcom(_COM_STATUS,fd,0); } while ((r&0x100)==0); c = _bios_serialcom(_COM_RECEIVE,fd,0); if ((c&0xff00) != 0) { fprintf(stderr,"%x:xread error\n",c); exit(-1); } *buf++ = c&0xff; }return(i);}xwrite(fd,buf,cnt)int fd,cnt;char *buf;{int c,i,r;for (i=0;i<cnt;i++) { c = *buf++;#if 0 r = _bios_serialcom(_COM_SEND,fd,c);#else r = com_send(fd,c);#endif if ((r&0x8000) != 0) { fprintf(stderr,"%x:xwrite error\n",r); exit(-1); } }return(i);}com_send(fd,c)int fd,c;{union _REGS inregs,outregs;for (;;) { inregs.h.ah = 0x03; inregs.x.dx = fd; _int86(0x14,&inregs,&outregs); if ((outregs.h.ah&0x62)==0x60) break; }inregs.h.ah = 0x01;inregs.h.al = c;inregs.x.dx = fd;_int86(0x14,&inregs,&outregs);return((outregs.h.ah<<8)|outregs.h.al);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -