📄 condevs.c
字号:
#ifndef lintstatic char *sccsid = "@(#)condevs.c 4.2 Ultrix 9/7/90";#endif lint/************************************************************************ * * * Copyright (c) 1983-1990 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * Here are various dialers to establish the machine-machine connection. * conn.c/condevs.c was glued together by Mike Mitchell. * The dialers were supplied by many people, to whom we are grateful. * * --------------------------------------------------------------------- * NOTE: * There is a bug that occurs at least on PDP11s due to a limitation of * setjmp/longjmp. If the routine that does a setjmp is interrupted * and longjmp-ed to, it loses its register variables (on a pdp11). * What works is if the routine that does the setjmp * calls a routine and it is the *subroutine* that is interrupted. * * Anyway, in conclusion, condevs.c is plagued with register variables * that are used inside * if (setjmp(...)) { * .... * } * * THE FIX: In dnopn(), for example, delete the 'register' Devices *dev. * (That was causing a core dump; deleting register fixed it.) * Also for dnopn delete 'register' int dnf... . * In pkopn, delete 'register' flds... . * There may be others, especially mcm's version of hysopen. * You could just delete all references to register, that is safest. * This problem might not occur on 4.1bsd, I am not sure. * Tom Truscott * * Larry Cohen - 4/11/85 - add shared line code. * * marc@decvax - Add ability for diropn to request which protocol to use. * * lp@decvax - Added generic dialer interface 2/22/85 * * decvax!larry - revamped df03/df02 code , should run on ULTRIX/11. * * - cleaned up hayes smartmodem code, resets before trying, * converts dialer characters to standard uucp dialing * characters. * * - split out external definitions for dialing routines. Should * be possible to add new dialer code without recompiling other * source modules (except condefs.c). * * - only df02/03, hayes, and direct connect code * has been tested significantly. * */#include <sys/types.h>#include <errno.h>#include <setjmp.h>#include <signal.h>#include <sgtty.h>#include "uucp.h"#include <sys/file.h>extern int Dcf; /* so clsacu will work */extern char devSel[]; /* name to pass to delock() in close */extern int errno, next_fd;extern jmp_buf Sjbuf;extern int alarmtr();int nulldev(), nodev(), Acuopn(), diropn(), dircls();/*** * nulldev a null device (returns CF_DIAL) */int nulldev(){ return(CF_DIAL);}/*** * nodev a null device (returns CF_NODEV) */int nodev(){ return(CF_NODEV);}/* * The first things in this file are the generic devices. * Generic devices look through L-devices and call the CU_open routines for * appropriate devices. Some things, like the Unet interface, or direct * connect, do not use the CU_open entry. ACUs must search to find the' * right routine to call. *//*** * diropn(flds) connect to hardware line * char *flds[]; * * return codes: * >0 - file number - ok * FAIL - failed */diropn(flds)register char *flds[];{ register int dcr, status; int ret; struct Devices dev; char dcname[20]; char msg[50]; FILE *dfp; dfp = fopen(DEVFILE, "r"); ASSERT(dfp != NULL, "CAN'T OPEN", DEVFILE, 0);nextd: while ((status = rddev(dfp, &dev)) != FAIL) { if (strcmp(flds[F_CLASS], dev.D_class) != SAME) continue; if (strcmp(flds[F_PHONE], dev.D_line) != SAME) continue; if (mlock(dev.D_line) != FAIL) break; } if (status == FAIL) { fclose(dfp); return(CF_NODEV); } /* Does this line want to use a different protocol ? */ if (dev.D_proto[0] != '\0') Prefproto = dev.D_proto[0]; sprintf(dcname, "/dev/%s", dev.D_line); if (setjmp(Sjbuf)) { delock(dev.D_line); fclose(dfp); return(FAIL); } signal(SIGALRM, alarmtr); alarm(10); getnextfd(); errno = 0;#ifdef ONDELAY dcr = open(dcname, O_RDWR|O_NDELAY); /* read/write */#else dcr = open(dcname, 2); /* read/write */#endif next_fd = -1; if (dcr < 0 && errno == EACCES) logent(dcname, "CAN'T OPEN"); if (dcr < 0 && errno == EBUSY) { logent(dcname, "Direct line already in use"); goto nextd; } fclose(dfp); alarm(0); if (dcr < 0) { delock(dev.D_line); return(FAIL); }#ifdef ULTRIX if (ioctl(dcr, TIOCSINUSE)<0 && errno==EALREADY) { logent(dcname, "SHARED LINE IN USE"); close(dcr); delock(dev.D_line); return(FAIL); } { /* * The following code occurs throughout condevs.c in about * a dozen places. The old code did a getpgrp() call to get * the current process group, then did the TIOCSPGRP to set * the modem line to match that of the current process (us). * This fails when programs (illegally) open /dev/console and * assign it a process group, such that subsequent daemons which * start up from the console terminal will inherit the bogus * process group. The dnet_spawner and /usr/lib/lpd are two * of the known culprits. Our workaround is to set our process * group to our own pid, and use that instead. */ int pgrp = getpid(); /* XXX: was getpgrp(), not getpid() */ int temp = 0; ret=setpgrp(pgrp, pgrp); /* XXX: first pgrp is really our pid */ if (ret < 0) DEBUG(6,"setpgrp failed, errno=%d\n", errno); /* ensure correct process group if run in background by cron */ ioctl(dcr, TIOCSPGRP, &pgrp);#ifdef ONDELAY /* ignore modem signals - reset to default mode on last close */ ret = ioctl(dcr, TIOCNMODEM, &temp); if (ret < 0) DEBUG(6,"ioctl(TIOCNMODEM), errno=%d\n", errno);#endif }#endif fflush(stdout); fixline(dcr, dev.D_speed); strcpy(devSel, dev.D_line); /* for latter unlock */ sprintf(msg, "%s, fd= %d",devSel, dcr); logent(msg, "using device"); CU_end = dircls; return(dcr);}dircls(fd)register int fd;{ if (fd > 0) { ioctl(fd, TIOCCINUSE); close(fd); delock(devSel); } }#ifdef DATAKIT#include <dk.h>#define DKTRIES 2/*** * dkopn(flds) make datakit connection * * return codes: * >0 - file number - ok * FAIL - failed */dkopn(flds)char *flds[];{ int dkphone; register char *cp; register ret, i; if (setjmp(Sjbuf)) return(FAIL); signal(SIGALRM, alarmtr); dkphone = 0; cp = flds[F_PHONE]; while(*cp) dkphone = 10 * dkphone + (*cp++ - '0'); DEBUG(4, "dkphone (%d) ", dkphone); for (i = 0; i < DKTRIES; i++) { getnextfd(); ret = dkdial(D_SH, dkphone, 0); next_fd = -1; DEBUG(4, "dkdial (%d)\n", ret); if (ret > -1) break; } return(ret);}#endif#ifdef PNET/*** * pnetopn(flds) * * call remote machine via Purdue network * use dial string as host name, speed as socket number * Author: Steve Bellovin */pnetopn(flds)char *flds[];{ int fd; int socket; register char *cp; fd = pnetfile(); DEBUG(4, "pnet fd - %d\n", fd); if (fd < 0) { logent("AVAILABLE DEVICE", "NO"); return(CF_NODEV); } socket = 0; for (cp = flds[F_CLASS]; *cp; cp++) socket = 10*socket + (*cp - '0'); DEBUG(4, "socket - %d\n", socket); if (setjmp(Sjbuf)) { DEBUG(4, "pnet timeout - %s\n", flds[F_PHONE]); return(FAIL); } signal(SIGALRM, alarmtr); DEBUG(4, "host - %s\n", flds[F_PHONE]); alarm(15); if (pnetscon(fd, flds[F_PHONE], socket) < 0) { DEBUG(4, "pnet connect failed - %s\n", flds[F_PHONE]); return(FAIL); } alarm(0); return(fd);}#endif PNET#ifdef UNET/*** * unetopn -- make UNET (tcp-ip) connection * * return codes: * >0 - file number - ok * FAIL - failed *//* Default port of uucico server */#define DFLTPORT 33unetopn(flds)register char *flds[];{ register int ret, port; int unetcls(); port = atoi(flds[F_PHONE]); if (port <= 0 || port > 255) port = DFLTPORT; DEBUG(4, "unetopn host %s, ", flds[F_NAME]); DEBUG(4, "port %d\n", port); if (setjmp(Sjbuf)) { logent("tcpopen", "TIMEOUT"); endhnent(); /* see below */ return(CF_DIAL); } signal(SIGALRM, alarmtr); alarm(30); ret = tcpopen(flds[F_NAME], port, 0, TO_ACTIVE, "rw"); alarm(0); endhnent(); /* wave magic wand at 3com and incant "eat it, bruce" */ if (ret < 0) { DEBUG(5, "tcpopen failed: errno %d\n", errno); logent("tcpopen", "FAILED"); return(CF_DIAL); } CU_end = unetcls; return(ret);}/* * unetcls -- close UNET connection. */unetcls(fd)register int fd;{ DEBUG(4, "UNET CLOSE called\n", 0); if (fd > 0) { /* disable this until a timeout is put in if (ioctl(fd, UIOCCLOSE, STBNULL)) logent("UNET CLOSE", "FAILED"); */ close(fd); DEBUG(4, "closed fd %d\n", fd); }}#endif UNET#ifdef MICOM/* * micopn: establish connection through a micom. * Returns descriptor open to tty for reading and writing. * Negative values (-1...-7) denote errors in connmsg. * Be sure to disconnect tty when done, via HUPCL or stty 0. */micopn(flds)register char *flds[];{ extern errno; char *rindex(), *fdig(), dcname[20]; int dh, ok = 0, speed; register struct condev *cd; register FILE *dfp; struct Devices dev; dfp = fopen(DEVFILE, "r"); ASSERT(dfp != NULL, "Can't open", DEVFILE, 0); signal(SIGALRM, alarmtr); dh = -1; for(cd = condevs; ((cd->CU_meth != NULL)&&(dh < 0)); cd++) { if (snccmp(flds[F_LINE], cd->CU_meth) == SAME) { fseek(dfp, (off_t)0, 0); while(rddev(dfp, &dev) != FAIL) { if (strcmp(flds[F_CLASS], dev.D_class) != SAME) continue; if (snccmp(flds[F_LINE], dev.D_type) != SAME) continue; if (mlock(dev.D_line) == FAIL) continue; sprintf(dcname, "/dev/%s", dev.D_line); getnextfd(); alarm(10); if (setjmp(Sjbuf)) { delock(dev.D_line); logent(dev.D_line,"micom open TIMEOUT"); dh = -1; break; } dh = open(dcname, 2); alarm(0); next_fd = -1; if (dh > 0) { break; } devSel[0] = '\0'; delock(dev.D_line); } } } fclose(dfp); if (dh < 0) return(CF_NODEV); speed = atoi(fdig(flds[F_CLASS])); fixline(dh, speed); sleep(1); /* negotiate with micom */ if (speed != 4800) /* damn their eyes! */ write(dh, "\r", 1); else write(dh, " ", 1); DEBUG(4, "wanted %s ", "NAME"); ok = expect("NAME", dh); DEBUG(4, "got %s\n", ok ? "?" : "that"); if (ok == 0) { write(dh, flds[F_PHONE], strlen(flds[F_PHONE])); sleep(1); write(dh, "\r", 1); DEBUG(4, "wanted %s ", "GO"); ok = expect("GO", dh); DEBUG(4, "got %s\n", ok ? "?" : "that"); } if (ok != 0) { if (dh > 2) close(dh); DEBUG(4, "micom failed\n", ""); delock(dev.D_line); return(CF_DIAL); } else DEBUG(4, "micom ok\n", ""); CU_end = cd->CU_clos; strcat(devSel, dev.D_line); /* for later unlock */ return(dh);}miccls(fd)register int fd;{ if (fd > 0) { close(fd); delock(devSel); } }#endif MICOM/*** * Acuopn - open an ACU and dial the number. The condevs table * will be searched until a dialing unit is found that is * free. * * return codes: >0 - file number - o.k. * FAIL - failed */char devSel[20]; /* used for later unlock() */#ifdef GENERICchar gbuf[1024];#endifAcuopn(flds)register char *flds[];{ char phone[MAXPH+1]; register struct condev *cd, *gencd, *tcd; register int fd; register FILE *dfp; struct Devices dev; char msg[100]; int ret = CF_NODEV; extern int gendialer; int havebrand, isgen; exphone(flds[F_PHONE], phone); devSel[0] = '\0'; DEBUG(4, "Dialing %s\n", phone); dfp = fopen(DEVFILE, "r"); ASSERT(dfp != NULL, "Can't open", DEVFILE, 0); for(cd = condevs; cd->CU_meth != NULL; cd++) { if (prefix(cd->CU_meth, flds[F_LINE])) { fseek(dfp, (off_t)0, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -