home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-07-31 | 12.3 KB | 577 lines | [TEXT/R*ch] |
- /*
- * @(#)sysdep.unix 1.11 87/09/29 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.unix gnuucp Version hoptoad-1.11";
- #endif
-
- #ifdef BSD
- /* Unix Berserkeley systems */
- #include <stdio.h>
- #include <ctype.h>
- #include <sgtty.h>
- #include <sys/param.h>
- #include <sys/file.h>
- #include <sys/time.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <strings.h>
- #include <sys/dir.h>
-
- #define dirent direct /* For POSIX compatability */
- extern char *strtok();
-
- #define UNIX
- #define NAMESIZE MAXPATHLEN
- #endif
-
- #ifdef SYSV
- /* Unix System V */
- #include <stdio.h>
- #include <ctype.h>
- #include <fcntl.h>
- #include <termio.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <string.h>
- #include <dirent.h> /* SVR3 -- older has to use PD version */
-
- #define UNIX
- #endif
-
- #include "uucp.h"
- #include "sysdep.h"
-
- /* Stuff common to all Unix systems */
- #define STDIN 0
- #define CONTROL "/usr/lib/uucp/gnuucp.ctl"
- #define O_BINARY 0 /* No distinction between text and binary */
-
- /*
- * Exported variables
- */
- char sysdep_control[] = CONTROL;
-
-
- /* Our variables */
- static jmp_buf alarming; /* For read timeouts */
-
- #ifdef BSD
- struct sgttyb atermio, btermio;
- #endif
- #ifdef SYSV
- struct termio atermio, btermio;
- #endif
-
- 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 */
-
- #ifdef BSD
- /* Berserkeley version */
- if (ontheline) {
- fdtty = STDIN;
- } else if ((fdtty = open(ttynam, O_RDWR)) < 0) {
- if (DEBUG_LEVEL(0)) perror(ttynam);
- exit(1);
- }
- ioctl(fdtty, TIOCGETP, &atermio);
- btermio = atermio;
- btermio.sg_flags |= RAW;
- btermio.sg_flags &= ~(ECHO|XTABS);
- if (!ontheline)
- btermio.sg_ispeed = btermio.sg_ospeed = damn_B(baud);
- ioctl(fdtty, TIOCSETN, &btermio);
- signal(SIGINT,sigint);
- #endif
-
- #ifdef SYSV
- /* Missed'em Five version */
- if (ontheline) {
- fdtty = STDIN;
- } else if ((fdtty = open(ttynam, O_RDWR)) < 0) {
- if (DEBUG_LEVEL(0)) perror(ttynam);
- exit(1);
- }
- ioctl(fdtty,TCGETA,&atermio);
- btermio = atermio;
- btermio.c_iflag = btermio.c_oflag = btermio.c_lflag = 0;
- btermio.c_cc[VMIN] = 1;
- btermio.c_cc[VTIME] = 0;
- if (!ontheline)
- btermio.c_cflag = (btermio.c_cflag & ~CBAUD) | damn_B(baud);
- ioctl(fdtty,TCSETA,&btermio);
- #endif
-
- signal(SIGINT,sigint);
- signal(SIGTERM,sigint);
- return SUCCESS;
- }
-
- /*
- * Open the serial line for an outgoing call.
- */
- int
- openout(ttynam, baud)
- char *ttynam;
- int baud;
- {
- char devname[PORTNAME_SIZE*2+SLOP];
-
- /* Set cleanup monitor */
- signal(SIGINT, sigint);
- signal(SIGTERM, sigint);
-
- /* Lock against several uucp's trying to use the same line */
- if (ttylock(ttynam) != SUCCESS)
- return FAIL;
-
- sprintf(devname, "/dev/%s", ttynam);
-
- #ifdef BSD
- /* Berserkeley version */
- if ((fdtty = open(devname, O_RDWR)) < 0) {
- if (DEBUG_LEVEL(0)) perror(devname);
- ttyunlock();
- return FAIL;
- }
- ioctl(fdtty, TIOCGETP, &atermio);
- btermio = atermio;
- btermio.sg_flags |= RAW;
- btermio.sg_flags &= ~(ECHO|XTABS);
- btermio.sg_ispeed = btermio.sg_ospeed = damn_B(baud);
- ioctl(fdtty, TIOCSETN, &btermio);
- #endif
-
- #ifdef SYSV
- /* Missed'em Five version */
- if ((fdtty = open(devname, O_RDWR)) < 0) {
- if (DEBUG_LEVEL(0)) perror(devname);
- return FAIL;
- }
- ioctl(fdtty,TCGETA,&atermio);
- btermio = atermio;
- btermio.c_iflag = btermio.c_oflag = btermio.c_lflag = 0;
- btermio.c_cc[VMIN] = 1;
- btermio.c_cc[VTIME] = 0;
- btermio.c_cflag = (btermio.c_cflag & ~CBAUD) | damn_B(baud);
- ioctl(fdtty,TCSETA,&btermio);
- #endif
-
- 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 serial port (e.g. drop DTR).
- */
-
- void
- sigint()
- {
-
- logit("INTERRUPTED", "terminating");
- hangup();
- exit(0);
- }
-
-
-
- /* Real simple for Unix */
- xwrite(buf,ctr)
- char *buf;
- int ctr;
- {
- return write(fdtty, buf, ctr);
- }
-
-
- /*
- * Serial port reading routines
- */
- sigalrm()
- {
- longjmp(alarming, 1);
- }
-
- /*
- * FIXME: This is really slow; it does 4 system calls per byte!
- */
- int
- xgetc()
- {
- char data;
- int status;
-
- signal(SIGALRM,sigalrm);
- alarm(BYTE_TIMEOUT);
- if (setjmp(alarming) == 0)
- {
- status = read(fdtty,&data,1);
- alarm(0);
- if (status == 1) /* the read worked, returning 1 char */
- return(data & 0xFF);
- }
- /* Error on serial port, or timeout. */
- return(EOF);
- }
-
- /*
- * hangup(): hang up the 'fone.
- */
- int
- hangup()
- {
-
- /* Restore terminal settings on dialout line */
- #ifdef BSD
- ioctl(fdtty, TIOCSETN, &atermio);
- #endif
-
- #ifdef SYSV
- ioctl(fdtty,TCSETA,&atermio);
- #endif
-
- if (0 != close(fdtty)) {
- if(DEBUG_LEVEL(0)) perror("closing tty");
- }
-
- ttyunlock();
-
- sleep(2); /* To be sure DTR stays down that long */
- }
-
-
- /*
- * 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];
- static int count = 0;
-
- if (ourpid == 0)
- ourpid = getpid();
- (void) sprintf(tname, "TM.u%d.%d", ourpid, count++);
- DEBUG(7, "Using temp file %s\n", tname);
- return tname;
- }
-
-
- /*
- * Transform a filename from a uucp packet (in Unix format) into a local
- * filename that will work in the local file system.
- */
- char *
- munge_filename(name)
- register char *name;
- {
- register char *p;
- static char buffer[NAMESIZE+SLOP];
- int len, hostlen;
-
- DEBUG(7, "Munge_filename input: %s\n", name);
-
- /* FIXME: Security checking goes here! */
-
- if (name[0] == '~') {
- /* Handle user-relative names -- ~ or ~uucp turns to Pubdir */
- if (name[1] == '/')
- p = &name[1];
- else if (!strncmp("~uucp/", name, 6))
- p = &name[5];
- else {
- p = NULL; /* Neither of the above */
- goto out;
- }
- strcpy(buffer, Pubdir);
- strcat(buffer, p);
- p = buffer;
- goto out;
- }
-
- #ifdef SUBDIR
- /* Berkeley Unix subdirectory hack.
- * Full pathnames go through OK.
- * D.myname* -> D.myname/D.myname*
- * D.* -> D./D.*
- * C.* -> C./C.*
- * LCK.* -> LCK..*
- * otherwise left alone (e.g. X.*, STST.*).
- * FIXME: I hear Honey Danber has a slightly different scheme.
- * In particular, STST's go in a directory.
- */
- if (name[0] != '/') {
- if (name[1] == '.' &&
- (name[0] == 'C' || name[0] == 'D')) {
- len = strlen(name);
- hostlen = strlen(Myname);
- if (hostlen > 7) hostlen = 7;
- /* Check D.mynameAxxxx case */
- if (name[0] == 'D' && len == hostlen + 2 + 5 &&
- !strncmp(&name[2], Myname, hostlen))
- len = 2 + hostlen; /* "D."+name */
- else
- len = 2; /* Just "D." */
- strcpy(buffer, name);
- buffer[len] = '/';
- strcpy(buffer+len+1, name);
- p = buffer;
- goto out;
- }
- if (strncmp("LCK.", name, 4) == 0 &&
- strcmp("LCK.XQT", name) != 0) {
- /* For some reason, old uucp uses "LCK..xxx" rather
- * than "LCK.xxx". Except for LCK.XQT. Foo.
- */
- strcpy(buffer, "LCK..");
- strcpy(buffer+5, name+4);
- p = buffer;
- goto out;
- }
- }
- #endif
-
- p = name; /* Let it through as-is. */
-
- out:
- DEBUG(7, "Munge_filename output: %s\n", p);
- return p;
- }
-
- /*
- * Uucp work queue scan.
- *
- * gotsome = work_scan(hostname, type);
- * workfile = work_next();
- * void work_done();
- */
-
- /*
- * Local variables of the work queue scanner -- not visible to outsiders
- *
- * Workhost and worktype are always null-terminated; keeping their lengths
- * is just a performance hack. Workprefix is NOT null terminated; various
- * people copy things after it and use the whole string. Workprefix is
- * exactly workplen long; to append something, strcpy(workprefix+workplen, ...)
- */
- #define MAX_TYPE 10
- static DIR *workdir = (DIR *)NULL;
- static struct dirent *workfile;
- static char workhost[MAX_HOST+1];
- static int workhlen;
- static char worktype[MAX_TYPE+1];
- static int worktlen;
- static char workfirst = 0;
- /* FIXME, at the moment this can be local to work_scan() */
- static char workprefix[MAX_TYPE+1+MAX_HOST+1+MAX_TYPE+1+MAX_HOST+6+SLOP];
- /* D . hoptoad / D . hoptoad N1234\0 */
- static int workplen;
-
- void
- work_done()
- {
- if (workdir)
- closedir(workdir);
- workdir = (DIR *) NULL;
- workfile = (struct dirent *) NULL;
- workfirst = 0;
- }
-
-
- int
- work_scan(host, type)
- char *host;
- char *type;
- {
- char *p;
-
- if (!host)
- host = "";
-
- /* If called twice in a row, don't thrash the disk again */
- if (strcmp(workhost, host) == SAME &&
- strcmp(worktype, type) == SAME && 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 */
- worktlen = strlen(type);
- if (worktlen > sizeof (worktype) -1) abort();
- strcpy(worktype, type);
-
- /* Figure out which subdirectory this class of files is in. */
- /* FIXME: doesn't handle "all D. files" since D.myname is separate. */
- sprintf(workprefix, "%s.%s", worktype, workhost);
- p = munge_filename(workprefix);
- strcpy(workprefix, p);
- p = index(workprefix, '/');
- if (p)
- workplen = 1 + p - workprefix; /* Prefix ends after '/' */
- else
- workplen = 0; /* No / in munged; hence no dir */
- workprefix[workplen] = '\0';
- DEBUG(8, "Work prefix is =%s=\n", workprefix);
-
- strcpy(workprefix+workplen, ".");
- workdir = opendir(workprefix); /* Open whatever directory */
- if (workdir == NULL) {
- DEBUG(0, "Can't open queue directory %s\n", workprefix);
- return 0; /* No work */
- }
-
- return work_look();
- }
-
-
- static int
- work_look()
- {
- int len;
-
- for (;;) {
- workfile = readdir(workdir);
- if (workfile == NULL) {
- DEBUG(7, "work_look: end of dir\n", 0);
- work_done();
- return 0; /* No work */
- }
- DEBUG(8, "work_look readdir %s\n", workfile->d_name);
-
- /* Is it the right type? */
- if (strncmp(workfile->d_name, worktype, worktlen) == SAME
- && workfile->d_name[worktlen] == '.') {
- /* see if it matches the hostname */
- len = strlen(workfile->d_name);
- /* "C" "." "hoptoad" "Xnnnn" */
- if (workhlen == 0 ||
- (len == worktlen + 1 + workhlen + 5 &&
- !strncmp(workhost, workfile->d_name+2, workhlen))
- ) {
- /* Found an entry! */
- /* FIXME, check grade letter! */
- DEBUG(7, "work_look found %s\n", workfile->d_name);
- return 1; /* Found work */
- }
- }
- }
- /* NOTREACHED */
- }
-
-
- char *
- work_next()
- {
- static char buffer[NAMESIZE+SLOP];
-
- if (!workfirst) {
- if (!workfile || !work_look())
- return (char *)NULL;
- }
- workfirst = 0;
-
- if (strncmp("LCK..", workfile->d_name, 5) == 0) {
- /*
- * For some reason, old uucp uses "LCK..xxx" rather
- * than "LCK.xxx" like it does everywhere else.
- * We return the "LCK.xxx" form.
- */
- strcpy(buffer, "LCK.");
- strcpy(buffer+4, workfile->d_name+5);
- return buffer;
- }
- return workfile->d_name;
- }
-
- /*
- * Routine to return a string that gives the current date and time, and
- * identifies the current process, if on a multiprocess system.
- */
- char *
- time_and_pid()
- {
- long clock;
- struct tm *tm;
- 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;
- }
-