📄 eculine.c
字号:
lopen()returns negative LINST_ codes if failure else positive pid using lineelse 0 if successful open------------------------------------------------------------------------*/intlopen(){ int itmp; struct stat ttystat;#ifdef SHARE_DEBUG char s80[80]; sprintf(s80,"lopen Liofd=%d Lline=%s line_lock_status=%d", shm->Liofd,shm->Lline, line_lock_status(shm->Lline)); ecu_log_event((int)xmtr_pid,s80);#endif /* * system independent checks */ if(shm->Liofd >= 0) return(LINST_ALREADY); if(!strcmp(shm->Lline,"/dev/tty")) return(LINST_INVALID); if(stat(shm->Lline,&ttystat) < 0) { if(errno == ENOENT) return(LINST_NODEV); return(LINST_OPNFAIL); } if((ttystat.st_mode & S_IFMT) != S_IFCHR) return(LINST_NOTCHR); if(ulindex(shm->Lline,"pty") > -1) return(LINST_NOPTY); /* * lock the tty */ if((itmp = lock_tty(shm->Lline)) && (itmp != LINST_WEGOTIT)) return(itmp); /* * if appropriate, make sure we have ungetty'd the line */#if defined(USE_ECUUNGETTY) ungetty_return_all_but(shm->Lline); if(!in_ungetty_list(shm->Lline)) { if(itmp = ungetty_get_line(shm->Lline)) { sprintf(lopen_err_str,"ecuungetty error - %s",linst_err_text(itmp)); unlock_tty(shm->Lline); return(itmp); } }#endif /* * rarely an open will hang despite our wisdom and prayer */ if(setjmp(_insurance_jmpbuf)) { alarm(0); signal(SIGALRM,SIG_IGN); errno = EIO; sprintf(lopen_err_str,"open error - %s",errno_text(errno)); unlock_tty(shm->Lline); return(LINST_OPNFAIL); } /* * open the tty using non-blocking I/O to bypass DCD wait * handle EAGAIN for SVR4 per kortcs!tim */ for (itmp=0; ; ++itmp) { signal(SIGALRM,lopen_failed);#ifdef sun alarm(10);#else alarm(5);#endif shm->Liofd = open(shm->Lline,O_RDWR | O_NDELAY,0666); alarm(0); signal(SIGALRM,SIG_IGN); if(shm->Liofd >= 0) break; if((itmp < 5) && (errno == EAGAIN)) { (void)signal(SIGALRM,SIG_DFL); alarm(0); sleep(2); continue; } if (errno == EACCES) { struct passwd *pw = getpwuid(ttystat.st_uid); endpwent(); if(pw) { sprintf(lopen_err_str, "cannot open line owned by %s (mode=%3o)", pw->pw_name,ttystat.st_mode & 0777); } else { sprintf(lopen_err_str, "open error - try chmod +rw %s",shm->Lline); } } else sprintf(lopen_err_str,"open error - %s",errno_text(errno)); unlock_tty(shm->Lline); return(LINST_OPNFAIL); } /* * turn off non-blocking I/O and set initial termio, including CLOCAL */ fcntl(shm->Liofd,F_GETFL,&itmp); itmp &= ~O_NDELAY; fcntl(shm->Liofd,F_SETFL,itmp); ioctl(shm->Liofd,TCGETA,(char *) Ltermio); Ltermio->c_iflag = (IGNPAR | IGNBRK | shm->Lxonxoff); Ltermio->c_oflag = 0; Ltermio->c_cflag |= (CLOCAL | CREAD | HUPCL); Ltermio->c_lflag = 0; Ltermio->c_cc[VMIN] = 1; Ltermio->c_cc[VTIME] = 1; lset_baud_rate(0); /* do not perform ioctl */ lset_parity(1); /* do perform ioctl */#if defined(SVR4) hx_flag = 0; /* hardware flow control "memory" */#endif lopen_err_str[0] = 0; /* no error this time! */ return(0);} /* end of lopen *//*+------------------------------------------------------------------------- lclose_failed(sig) - see lclose() below--------------------------------------------------------------------------*/voidlclose_failed(sig)int sig;{ if(sig != SIGALRM) ff(se,"error %d in lclose_failed: tell wht@n4hgf\r\n",sig); longjmp(_insurance_jmpbuf,1);} /* end of lclose_failed *//*+----------------------------------------------------------------------- lclose() - close the lineThe FAS driver and others hang on a close until all output for a linehas drained. Sometimes during a hangup, a noisy XOFF can be received.Other changeces for failure include a DCE which drops CTS and leavesit off, locking the line up if there is output waiting to go out.To make sure the line is actually closed in these situations, a SIGLARMhandler is used.------------------------------------------------------------------------*/voidlclose(){ struct termio ttio; int attempt2 = 0;#ifdef SHARE_DEBUG char s80[80]; sprintf(s80,"lclose Liofd=%d Lline=%s line_lock_status=%d", shm->Liofd,shm->Lline, line_lock_status(shm->Lline)); ecu_log_event((int)xmtr_pid,s80);#endif if(shm->Liofd < 0) return;ATTEMPT: /* endless loop because we cannot get out anyway unless success */ signal(SIGALRM,lclose_failed);#ifdef sun alarm(10);#else alarm(5);#endif if(setjmp(_insurance_jmpbuf)) { /* close failed */ signal(SIGALRM,SIG_IGN); alarm(0); ff(se,"\r\nclose failed (remote XOFF?) ... retrying close\r\n"); lclear_xmtr_xoff(); ttio = *Ltermio; ttio.c_iflag &= ~(IXON | IXOFF); ttio.c_cflag &= (CSIZE | CSTOPB | CREAD | PARENB | PARODD); ioctl(shm->Liofd,TCSETA,(char *)&ttio); lflush(2); attempt2 = 1; goto ATTEMPT; } if(!attempt2) { lclear_xmtr_xoff(); ldraino(1); } lCLOCAL(1); close(shm->Liofd); signal(SIGALRM,SIG_IGN); alarm(0); unlock_tty(shm->Lline); shm->Lmodem_already_init = 0; shm->Lconnected = 0; shm->Liofd = -1;} /* end of lclose *//*+------------------------------------------------------------------------- lflash_dtr() - flash DTRDTR is lowered for 300 msec and raised again. After raising,we pause a while for a possibly slow DCE to rereap it's fecal materialexpects: Ltermio - current termio status of line shm->Liofd - current line fd shm->Lline - /dev/ttyxx name of lineOn SunOS and SVR4, an open/close of the line is required to get DTR backup. SVR3 does not seem to need this (ISC asy, SCO sio, Uwe Doering's FAS)but we do it anyway--------------------------------------------------------------------------*/voidlflash_dtr(){#undef NEED_REOPEN#if defined(sun) || defined(SVR4)#define NEED_REOPEN int tempfd;#endif struct termio b0t; /* * copy termio but CBAUD to B0 */ b0t = *Ltermio; b0t.c_cflag &= ~CBAUD; /* B0 */ /* * drop DTR for a while */ ioctl(shm->Liofd,TCSETA,(char *)&b0t); /* drop DTR */ /* * DTR will not come back on some systems without open/close line */#ifdef NEED_REOPEN if ((tempfd = open(shm->Lline, O_NDELAY | O_RDWR, 0666)) != -1) close(tempfd); else { int save_errno = errno; char s128[128]; sprintf(s128,"FLASH DTR line reopen failed (%.80s)", errno_text(errno)); ecu_log_event(shm->xmtr_pid,s128); pputs(s128); pputs("\n"); errno = save_errno; termecu(TERMECU_LINE_OPEN_ERROR); }#else /* * ensure DTR low for 300 msec * (the tempfd open/close takes plenty long enough) */ Nap(300L);#endif /* * reestablish baud rate * (raise DTR if the open/close line did not do it) */ ioctl(shm->Liofd,TCSETA,(char *)Ltermio); /* raise DTR */ Nap(300L); /* nap to give a lazy DCE some time */#undef NEED_REOPEN} /* end of lflash_dtr *//*+------------------------------------------------------------------------- lxon_xoff(flag)IXON specifies whether or not we respond to xon/xoff charactersIXOFF specifies whether or not we generate XON/XOFF characters--------------------------------------------------------------------------*/voidlxon_xoff(flag)int flag;{ if(flag & IXON) Ltermio->c_iflag |= IXON; else Ltermio->c_iflag &= ~IXON; if(flag & IXOFF) Ltermio->c_iflag |= IXOFF; else Ltermio->c_iflag &= ~IXOFF; shm->Lxonxoff = Ltermio->c_iflag & (IXON|IXOFF); ioctl(shm->Liofd,TCSETA,(char *)Ltermio);#if 0 Nap(400L);#endif} /* end of lflash_dtr *//*+------------------------------------------------------------------------- lget_xon_xoff(ixon,ixoff)--------------------------------------------------------------------------*/voidlget_xon_xoff(ixon,ixoff)int *ixon;int *ixoff;{ *ixon = Ltermio->c_iflag & IXON; *ixoff = Ltermio->c_iflag & IXOFF;} /* end of lget_xon_xoff *//*+------------------------------------------------------------------------- set_xon_xoff_by_arg(arg)--------------------------------------------------------------------------*/intset_xon_xoff_by_arg(arg)char *arg;{ if(ulcmpb(arg,"on") < 0) shm->Lxonxoff = IXON | IXOFF; else if(ulcmpb(arg,"off") < 0) shm->Lxonxoff = 0; else if(ulcmpb(arg,"out") < 0) shm->Lxonxoff = IXON; else if(ulcmpb(arg,"in") < 0) shm->Lxonxoff = IXOFF; else return(-1); Ltermio->c_iflag &= ~(IXON|IXOFF); Ltermio->c_iflag |= shm->Lxonxoff; ioctl(shm->Liofd,TCSETA,(char *)Ltermio); return(0);} /* end of set_xon_xoff_by_arg *//*+------------------------------------------------------------------------- xon_status()--------------------------------------------------------------------------*/char *xon_status(){ switch(shm->Lxonxoff) { case 0 : return("off"); case IXON : return("in off, out on"); case IXOFF : return("in on, out off"); case IXON | IXOFF : return("on"); } return("logic error");} /* end of xon_status *//*+------------------------------------------------------------------------- lCLOCAL(flag) - set line CLOCAL stateflag == 0: turn off CLOCAL to catch DCD loss == 1: turn on CLOCAL to ignore modem signalsdoes not let CLOCAL be turned off if not Lconnectedalso resets global zero_length_read_detected--------------------------------------------------------------------------*/voidlCLOCAL(flag)int flag;{ if(flag) Ltermio->c_cflag |= CLOCAL; else if(shm->Lconnected) Ltermio->c_cflag &= ~CLOCAL; else Ltermio->c_cflag |= CLOCAL; zero_length_read_detected = 0; lreset_ksr(); /* do the ioctl */#ifdef DEBUG_CLOCAL { char s128[128]; sprintf(s128,"lCLOCAL(%d) connected=%c CLOCAL set %o", flag,shm->Lconnected?'y':'n',Ltermio->c_cflag & CLOCAL?1:0); ecu_log_event((int)xmtr_pid,s128); pprintf("%s\n",s128); }#endif} /* end of lCLOCAL *//*+------------------------------------------------------------------------- ldcdwatch(flag) - set DCD watcher state--------------------------------------------------------------------------*/voidldcdwatch(flag)int flag;{ shm->Ldcdwatch = flag; dcdwatch_set = 1; lCLOCAL(!flag);} /* end of ldcdwatch *//*+------------------------------------------------------------------------- ldcdwatch_str(flagstr) - string version of ldcdwatchreturn 0 if successful or -1 if bad flagstr--------------------------------------------------------------------------*/intldcdwatch_str(flagstr)char *flagstr;{ static STR_CLASSIFY sc[] = { { "1", 1,DCDW_ON }, { "yes", 1,DCDW_ON }, { "on", 2,DCDW_ON }, { "0", 1,DCDW_ON }, { "no", 1,DCDW_OFF }, { "off", 3,DCDW_OFF }, { "terminate", 1,DCDW_TERMINATE }, { (char *)0, 0,-1 } }; int token; if((token = str_classify(sc,flagstr)) < 0) return(-1); ldcdwatch(token); return(0); } /* end of ldcdwatch_str *//*+------------------------------------------------------------------------- lzero_length_read_detected() - read from line returned zero lengthThis must mean CLOCAL was off and DCD is/went low. We do different thingsdepending in the xmtr and rcvr processIf we return, the condition has ben handled and reads may be retriedsafely or other appropriate operations performed; otherwise ECU isterminated.--------------------------------------------------------------------------*/voidlzero_length_read_detected(){ zero_length_read_detected = 1; if(getpid() == xmtr_pid) /* if we are in the transmitter */ {#ifdef DEBUG_CLOCAL ecu_log_event((int)xmtr_pid,"lzero xmtr"); pprintf("lzero xmtr\n");#endif if(shm->Lconnected) { extern ulong colors_current; ulong colors_at_entry = colors_current; fputs("\r\n",se); setcolor(colors_notify); fputs("[connection terminated]",se); setcolor(colors_at_entry); fputs("\r\n",se); DCE_now_on_hook(); /* does a lCLOCAL(1); */ } else lCLOCAL(1); Nap(1000L); lflush(2); if(shm->Ldcdwatch == DCDW_TERMINATE) termecu(0); shmx_unpause_rcvr(); } else /* we are in the receiver */ {#ifdef DEBUG_CLOCAL ecu_log_event((int)xmtr_pid,"lzero rcvr"); pprintf("lzero rcvr\n");#endif /* * make line "safe" to read from immediately; * however, if CLOCAL was set and we get a zero length read, * we are in some kind of unknown trouble */ if(Ltermio->c_cflag & CLOCAL) /* zero len read with CLOCAL? */ { /* then die ECU */ errno = EIO; termecu(TERMECU_LINE_READ_ERROR); } lCLOCAL(1); shmr_notify_xmtr_of_DCD_loss(); pause(); /* wait for unpause */ }} /* end of lzero_length_read_detected *//* vi: set tabstop=4 shiftwidth=4: *//* end of eculine.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -