home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-07-31 | 13.9 KB | 657 lines | [TEXT/R*ch] |
- /*
- * @(#)sysdep.msdos 1.6 87/09/23 Copyright 1987 Free Software Foundation, Inc.
- *
- * Copying and use of this program are controlled by the terms of the
- * GNU Emacs General Public License.
- */
-
- #ifndef lint
- char sysdep_version[] = "@(#)sysdep.msdos gnuucp Version hoptoad-1.6";
- #endif
-
- /* Microsoft DOS */
- #include "includes.h"
- #include "uucp.h"
- #include "sysdep.h"
-
- /* Structure for find first/next (find()).
- * NOTE: the DPB pointer is a double word
- * character pointer; here it is declared as a
- * long, to avoid problems with the various
- * size of char *'s.
- */
-
- struct _xfbuf {
- char s_attrib; /* Search attribute */
-
- /* These do not need to be initialized */
- char drive; /* 0 == current, 1 == A: ... */
- char fcbname[11]; /* FCB name, */
- unsigned ent;
- long dpb_ptr;
- unsigned dirstart;
-
- /* These are returned by DOS */
- char f_attrib; /* found attribute, */
- unsigned time; /* Packed time, */
- unsigned date; /* Packed date */
- long fsize; /* file size, */
- char name[13]; /* found name */
- };
-
- #define GET_TIME 0x2c /* DOS function number for get_time */
- #define DOS_INT 0x21 /* DOS interrupt number */
-
- typedef struct timetype {
- unsigned hour;
- unsigned minute;
- unsigned sec;
- unsigned hsec;
- } TIME, *TIME_PTR;
-
-
- /*
- * Note that NAMESIZE should be the max length of a file name, including
- * all its directories, drive specifiers, extensions, and the like.
- * E.g. on a Unix with 14-char file names, NAMESIZE is several hundred
- * characters, since the 14-char names can be nested.
- */
- /* FIXME, these should all be uppercase. */
- /* FIXME, these are duplicated from includes.h */
- #define FNAMESIZE sizeof("FILENAME") /* 8 chars */
- #define NAMESIZE 128 /* full path size */
- #define UFNAMESIZE 5 /* uux id size */
-
-
- /* Our variables */
-
- char hayesinit[] = "\r\r\rATZX1S0=1\r";
-
- int fdtty; /* File descriptor for tty line */
-
- void sigint(); /* Forward declaration */
-
- /*
- * Translation between integer baud rates and Unix baud rates (grumble)
- */
- static struct baudtab {
- int baudrate, damn_B_code;
- } baudtab[] = {
- 50, B50,
- 75, B75,
- 110, B110,
- 134, B134,
- 150, B150,
- 200, B200,
- 300, B300,
- 600, B600,
- 1200, B1200,
- 1800, B1800,
- 2400, B2400,
- 4800, B4800,
- 9600, B9600,
- 19200, B19200,
- 38400, B38400,
- };
-
- static int
- damn_B(baud)
- {
- register struct baudtab *b;
-
- for (b = baudtab; b->baudrate < baud; b++) continue;
- if (b->baudrate == baud)
- return b->damn_B_code;
- return EXTB; /* Maybe this'll get clocking from the modem */
- }
-
- /*
- * Open the serial line for an incoming call.
- * Argument of NULL or empty string means stdin.
- */
- int
- openline(ttynam, baud)
- char *ttynam;
- int baud;
- {
- int ontheline = !(ttynam && ttynam[0]); /* FIXME, this is garbage */
-
- #ifndef COMPORT
- if ((fdtty = open(ttynam, O_RDWR)) < 0)
- {
- printf("Cannot open %s for read/write %d\n",
- ttynam, errno);
- exit(1);
- }
- #else
- set_tty(COMM1, damn_B(baud), CS8, MENBL);
- printf("uucico : initializing modem.\n");
- xwrite(hayesinit, sizeof(hayesinit)-1);
-
- printf("uucico : waiting for call\n");
- while ((get_msr() & CD) == 0) {
- if (kbhit() != 0) {
- printf("uucico : aborting at user's request.");
- set_tty(0,0,0,MDSBL); /* Hang up */
- sleep(2);
- reset_tty();
- exit(1);
- }
- }
- printf("uucico : inbound call detected\n");
- init_comm();
- inp_flush();
- sleep(2);
- #endif
- signal(SIGINT,sigint);
- return SUCCESS;
- }
-
- /*
- * openout() -- open line for dialout
- */
- int
- openout(ttynam, baud)
- char *ttynam;
- int baud;
- {
-
- #ifdef COMPORT
- set_tty(COMM1, damn_B(baud), CS8, MENBL);
- DEBUG(2,"initializing modem.\n", 0);
- xwrite(hayesinit, sizeof(hayesinit)-1);
- init_comm();
- inp_flush();
- sleep(2);
- #else
- if ((fdtty = open(ttynam, O_RDWR)) < 0)
- {
- if (debug > 0) {
- printf("Cannot open %s for read/write %d\n",
- ttynam, errno);
- }
- exit(1);
- }
- FIXME, do stty() here.
- #endif
- signal(SIGINT,sigint);
- return SUCCESS;
- }
-
- /*
- * Basement level I/O routines
- *
- * xwrite() writes a character string to the serial port
- * xgetc() returns a character from the serial port, or an EOF for timeout.
- * sigint() restores the state of the serial port on exit.
- * hangup() hangs up the 'fone (e.g. drops DTR).
- */
-
- void
- sigint()
- {
- /* Restore terminal settings on dialout line */
- hangup();
- exit(0);
- }
-
- xwrite(buf,ctr)
- char *buf;
- int ctr;
- {
- int i;
-
- #ifndef COMPORT
- return write(fdtty,buf,ctr);
- #else
- for (i=0;i<=ctr;i++) {
- outp_char(buf[i]);
- }
- return ctr;
- #endif
- }
-
-
-
- /*
- * Serial port reading routine
- */
- int
- xgetc()
- {
- char data;
-
- #ifndef COMPORT
- /* Warning: No timeouts... */
- read(fdtty,&data,1);
- return(data & 0xFF);
- #else
- int i;
- unsigned s;
- TIME n;
-
- i = 0;
- get_time(&n);
- s = n.sec;
-
- /*
- * Implement timeouts by staring at the clock while we wait.
- * When the second hand moves, bump our counter. This is a lot
- * easier than figuring out the time when we'd time out (in hours,
- * minutes, and seconds!) and comparing against that, which is
- * what people tend to do in Unix where the time is just an integer
- * number of seconds.
- */
- while (i < BYTE_TIMEOUT) {
- while (s == n.sec) {
- if(inp_cnt() != 0) {
- data = inp_char();
- return (data & 0xFF);
- }
- get_time (&n);
- }
- s = n.sec;
- ++i;
- }
- return(EOF);
- #endif
- }
-
- /*
- * Hang up the 'fone.
- */
- int
- hangup()
- {
- /* Restore terminal settings on dialout line */
- static char a[] = "+++",
- o[] = "OK",
- h[] = "ATH0\r";
- int retry = 5;
-
- while (instr(o, strlen(o)) && retry--)
- xwrite(a, strlen(a)-1);
-
- xwrite(h, strlen(h)-1);
- if (instr(o, strlen(o)) || !retry)
- DEBUG(0, "uucico: problem hanging up\n", 0);
-
- #ifndef COMPORT
- close(fdtty);
- #else
- set_tty(0,0,0,MDSBL); /* Hang up like a nice programme */
- reset_tty(); /* Pop the serial port's pram off */
- uninit_comm(); /* Uninit the interrupt */
- #endif
- sleep(3); /* Wait with DTR down */
- exit(0);
- }
-
- /* CP/M and MSDOS and ST need these routines. Probably should use
- * the new names, but for now...
- */
- bzero(s, cnt)
- register char *s;
- register int cnt;
- {
- register int i;
- for (i = 0; i < cnt; i++) {
- *s++ = '\0';
- }
- }
-
- bcopy(from, to, cnt)
- register char *from;
- register char *to;
- register int cnt;
- {
- register int i;
- for (i = 0; i < cnt; i++) {
- *to++ = *from++;
- }
- }
-
- /*
- * Function to clean up all the loose ends if the user wishes to
- * abort UUSLAVE
- */
- int handler()
- {
-
- printf("\nAborting UUSLAVE\n");
- #ifdef COMPORT
- set_tty(0,0,0,MDSBL); /* drop DTR to hang up */
- sleep(2); /* let it settle */
- reset_tty(); /* put the port back in condition it
- was before running the programme */
- #endif
- exit(1); /* AWWAAAYY! */
- }
-
- #ifdef COMPORT
- /*
- * MSDOS routines for handling the comm port.
- *
- * get_time(n)
- * TIME_PTR n;
- *
- * fills timetype structure n with current time using DOS interrupt 21
- *
- */
-
- get_time(n)
- TIME_PTR n;
- {
- union REGS inregs;
- union REGS outregs;
-
- inregs.h.ah = GET_TIME;
-
- int86(DOS_INT, &inregs, &outregs);
-
- n->hour = outregs.h.ch;
- n->minute = outregs.h.cl;
- n->sec = outregs.h.dh;
- n->hsec = outregs.h.dl;
-
- return(0);
- }
-
- sleep(x)
- int x;
- {
- int i;
- unsigned s;
- TIME n; /* current time record */
-
- i = 0;
- get_time(&n);
- s = n.sec;
-
- while (i < x){
- while (s == n.sec)
- get_time(&n);
- s = n.sec;
- ++i;
- }
- }
- #endif
-
-
-
-
- /*
- * Returns 1 if a matching file was found, 0 if not.
- */
- find(pathname,flag,pxfbuf)
- char *pathname;
- int flag;
- struct _xfbuf *pxfbuf;
- {
- union REGS inregs, outregs;
-
- inregs.x.dx = (unsigned int) pxfbuf;
- inregs.h.ah = 26;
- intdos(&inregs,&outregs); /* set up DTA */
-
- inregs.x.dx = (unsigned int) pathname;
- inregs.x.cx = 22; /* the search atribute */
- if (flag == 0)
- inregs.h.ah = 78; /* if this is the first time FIND FIRST */
- else {
- inregs.h.ah = 79; /* if this is not the first time FIND NEXT */
- flag = 1;
- }
-
- intdos(&inregs,&outregs);
-
- if ((outregs.x.ax == 18) || (outregs.x.ax == 3))
- return (0);
-
- return(1);
-
- }
-
- /*
- * Create a temporary file name for receiving a file into.
- * "name" is the name we will actually eventually want to use for the file.
- * We currently ignore it, but some OS's that can't move files around
- * easily might want to e.g. put the temp file into the same directory
- * that this file is going into.
- *
- * FIXME:
- * This interface should be able to return a "possible" filename, and
- * be re-called if the name is already in use, to get another.
- * This avoids checking here whether the name is good -- saving system calls.
- */
- char *
- temp_filename(name)
- register char *name;
- {
- static char tname[NAMESIZE];
- char *t;
- if ((t = tmpnam(NULL)) != NULL && !curtemp)
- bcopy(t,tname,strlen(t));
- else
- sprintf(tname,"%s/%s/uutemp.$$$", spool_path, host_name);
- DEBUG(2,"Using temp file %s\n", tname);
- return tname;
- }
-
-
- /*
- * Transform a filename from Unix format into a local
- * filename that will work in the local file system.
- *
- * E.g. LCK..hoptoad --> hoptoad\.LCK
- * C.hoptoadA1234 --> hoptoad\A1234.C
- * etc.
- * FIXME: this is not done for anything but C. and D. files currently.
- * It does NOT work for LCK. and STST. files!
- */
- char *
- munge_filename(name)
- register char *name;
- {
- register char *p;
-
- static char buffer[NAMESIZE+SLOP];
- char mname[MAX_HOST]; /* master's name */
- char cwdir[NAMESIZE]; /* current working director */
- char ufname[UFNAMESIZE + 1]; /* distinctive 5 char UU file ID */
- int i; /* counter */
-
- /* FIXME there is a problem when host names are shorter than six chars */
- /* ok, fixed, gmp (see also getname() ) */
-
- DEBUG(4,"Munge_filename input: %s\n", name);
-
- if (name[0] == '/' || name[0] == '~' || name[1] != '.') {
- /* Don't munge things that start with / or ~, or which
- * aren't uucp internal file names with 2nd char dot */
- #ifdef NOTDEF
- /* This bit of code was in local_send_file. I'm not sure why.
- * If it belongs anywhere, it belongs here, but I don't see why it exists.
- * If it's going to stay here, it needs a bit of conversion.
- */
- if (strstr(srcnam, "/\\"))
- strcpy (temp, srcnam); /* if already contains path info */
- else {
- strcpy (temp, host_name);
- strcat (temp, "\\");
- strcat (temp, srcnam); /* otherwise ref to hosts' subdir */
- }
- #endif
- p = name;
- } else {
- /*
- * This is a uucp-internal C., D., or other name.
- * Munge the hell out of it. For MSDOS, we can't
- * handle the 14-character names of Unix, so change
- * it to:
- *
- * L.hostGNNNN -> host/GNNNN.L
- */
- bzero(cwdir, sizeof cwdir);
- bzero(ufname, sizeof ufname);
-
- i = strlen(name);
- strncpy(mname, &name[2], i - (2 + UFNAMESIZE));
- mname[i - (2 + UFNAMESIZE)] = '\0';
-
- strcpy(buffer, spool_path);
- strcat(buffer, "/");
- strcat(buffer, mname); /* get host's directory name */
-
- /*
- * Quick (?) test to see if we already have a directory
- * for this host.
- */
- getcwd(cwdir,NAMESIZE); /* save current directory */
- if (chdir(buffer) == -1) { /* If new dir doesn't exist, */
- if (mkdir(buffer) == -1) { /* ... make one */
- DEBUG(0, "Can't make new directory %s\n", buffer);
- } else {
- DEBUG(4, "Making new directory %s\n", buffer);
- }
- } else
- chdir(cwdir); /* pop back to the home directory */
-
- /* build actual file name */
- p = buffer + strlen(buffer);
- for(i = 0; i <= UFNAMESIZE; i++)
- ufname[UFNAMESIZE - i] = name[strlen(name) - i];
-
- *p++ = '/';
- strncpy(p, &name[i - UFNAMESIZE], UFNAMESIZE); /* GNNNN */
- strcat(p, ".");
- p[strlen(p)] = name[0]; /* C, D, X */
- p = buffer;
- }
-
- DEBUG(4, "Munge_filename output: %s\n", p);
- return p;
- }
-
- /*
- * Uucp work queue scan. For calling sequences, see sysdep.h.
- */
- static DIR *workdir = (DIR *)NULL;
- static struct _xfbuf xfbuf;
- static int workfile; /* Do we have one in xfbuf? */
- static char workhost[MAX_HOST+1];
- static int workhlen;
- static char workfirst = 0;
-
- void
- work_done()
- {
- if (workdir)
- closedir(workdir);
- workdir = (DIR *) NULL;
- workfile = 0;
- workfirst = 0;
- }
-
-
- int
- work_scan(host, type)
- char *host;
- char *type; /* E.g. "C", "X", "LCK" */
- {
-
- /* Null argument produces all hostnames */
- if (!host || *host) host="*";
-
- /* If called twice in a row, don't thrash the disk again */
- if (!strcmp(workhost, host) && workfile)
- return 1;
-
- if (workdir) work_done(); /* Clean up prev call */
-
- workfirst = 1; /* Initialize for work_next */
- workhlen = strlen(host);
- if (workhlen > sizeof (workhost) -1) abort();
- strcpy(workhost, host);
- if (workhlen > 7) workhlen = 7; /* Unix uucp limit */
-
- strncpy(tempnam, workhost, workhlen);
- strcpy(tempnam+workhlen, "/*.");
- strcat(tempnam+workhlen+ 3, type);
-
- workfile = find(tempnam, FALSE, &xfbuf);
- if (!workfile) {
- DEBUG(8, "work_scan readdir null\n", 0);
- work_done();
- return 0; /* No work */
- }
- return 1;
- }
-
-
- static int
- work_look()
- {
- int len;
-
- for (;;) {
- workfile = find(tempnam, TRUE, &xfbuf);
- if (!workfile) {
- DEBUG(8, "work_look readdir null\n", 0);
- work_done();
- return 0; /* No work */
- }
- DEBUG(8, "work_look readdir %s\n", xfbuf.name);
- /* FIXME, check grade letter! */
- return 1; /* Found work */
- }
- /* NOTREACHED */
- }
-
-
- char *
- work_next()
- {
- /* Space for: "TYPE.hostnameA1234" */
- static char subhack[6 +MAX_HOST + UFNAMESIZE + SLOP];
-
- if (!workfirst) {
- if (!workfile || !work_look())
- return (char *)NULL;
- }
- workfirst = 0;
-
- /* FIXME, This probably fails for STST and LCK files. */
- p = index(xfbuf.name, '.');
- if (!p) abort(); /* There must be a filename extension */
- *p = '\0';
- sprintf(subhack, "%s.%s%s", p+1, workhost, xfbuf.name);
- return subhack;
- }
-
- /*
- * Routine to return a string that gives the current date and time, and
- * identifies the current process, if on a multiprocess system.
- *
- * MSDOS multitasking is only a year away, so keep the getpid()...
- */
- char *
- time_and_pid()
- {
- long clock;
- struct tm *tm;
- static int ourpid = 0;
- static char format[] = "%d/%d-%d:%02d:%02d-%d";
- static char outbuf[sizeof(format)];
-
- (void) time(&clock);
- tm = localtime(&clock);
- if (ourpid == 0)
- ourpid = getpid();
- sprintf(outbuf, format,
- tm->tm_mon+1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec,
- ourpid);
- return outbuf;
- }
-