home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #20 / NN_1992_20.iso / spool / comp / sources / misc / 3936 < prev    next >
Encoding:
Text File  |  1992-09-13  |  57.1 KB  |  2,279 lines

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: wht@n4hgf.Mt-Park.GA.US (Warren Tucker)
  4. Subject:  v32i044:  ecu - ECU Asynchronous Communications v3.20, Part09/40
  5. Message-ID: <1992Sep13.153031.5048@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: 73ab2ecb6a11093cafcea4f9cb6b7c3c
  8. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  9. Organization: Sterling Software
  10. References: <csm-v32i036=ecu.141245@sparky.IMD.Sterling.COM>
  11. Date: Sun, 13 Sep 1992 15:30:31 GMT
  12. Approved: kent@sparky.imd.sterling.com
  13. Lines: 2264
  14.  
  15. Submitted-by: wht@n4hgf.Mt-Park.GA.US (Warren Tucker)
  16. Posting-number: Volume 32, Issue 44
  17. Archive-name: ecu/part09
  18. Environment: SCO,XENIX,ISC,SUNOS,SYSVR4,HDB,Curses
  19. Supersedes: ecu: Volume 21, Issue 53-89
  20.  
  21. ---- Cut Here and feed the following to sh ----
  22. #!/bin/sh
  23. # this is ecu320.09 (part 9 of ecu320)
  24. # do not concatenate these parts, unpack them in order with /bin/sh
  25. # file eculine.c continued
  26. #
  27. if test ! -r _shar_seq_.tmp; then
  28.     echo 'Please unpack part 1 first!'
  29.     exit 1
  30. fi
  31. (read Scheck
  32.  if test "$Scheck" != 9; then
  33.     echo Please unpack part "$Scheck" next!
  34.     exit 1
  35.  else
  36.     exit 0
  37.  fi
  38. ) < _shar_seq_.tmp || exit 1
  39. if test ! -f _shar_wnt_.tmp; then
  40.     echo 'x - still skipping eculine.c'
  41. else
  42. echo 'x - continuing file eculine.c'
  43. sed 's/^X//' << 'SHAR_EOF' >> 'eculine.c' &&
  44. X    char *lgets_timeout(LRWT *) - may be called by xmtr only
  45. X
  46. Xto1 and to2 are unsigned long values in milliseconds (not
  47. Xcurrently supported well under BSD4); to1 is the time to wait
  48. Xfor the first character, to2 the time to wait for subsequent
  49. Xcharacters.
  50. X
  51. Xif raw_flag 0,     non-printables are stripped from beginning
  52. X                   and end of received characters (i.e., modem
  53. X                   response reads); NULs discarded, parity stripped
  54. Xif raw_flag 1,     full raw read buffer returned
  55. X
  56. X0x80 in raw_flag indicates console interrupts should be enabled.
  57. Xif interrupt thus detected, the procedure returns "!Interrupted"
  58. Xwithout reseting variable 'interrupt'
  59. X
  60. Xbuffer is address to read chars into
  61. X
  62. Xbufsize is buffer max size (allowing room for terminating null)
  63. Xwhich should be at least 2 if raw_size includes 0x80 bit,
  64. Xelse at least 12 characters if 0x80 omitted.
  65. X
  66. Xcount is a int which, at return, receives the actual count read
  67. X
  68. Xzero_length_read_detected is a public that will set if the
  69. XDCD watcher is turned on and DCD is lost
  70. X
  71. X--------------------------------------------------------------------------*/
  72. Xchar *
  73. Xlgets_timeout(lrwt)
  74. XLRWT *lrwt;
  75. X{
  76. X/**************************/
  77. X#if !defined(WORKING_SELECT)
  78. X/**************************/
  79. X
  80. X    register actual_count = 0;
  81. X    register char *cptr = lrwt->buffer;
  82. X    register echo_flag = lrwt->echo_flag;
  83. X    int max_count = lrwt->bufsize;
  84. X    char *rtn_val;
  85. X    int timeout_counter;
  86. X    int qc1;
  87. X    int qc2;
  88. X    int raw_mode = lrwt->raw_flag & 0x0F;
  89. X    int check_sigint = (lrwt->raw_flag & 0x80);
  90. X    int old_ttymode = get_ttymode();    /* save original tty mode */
  91. X    int delim_len;
  92. X    long quantum;
  93. X    long ltmp;
  94. X
  95. X    delim_len = (lrwt->delim) ? strlen(lrwt->delim) : 0;
  96. X
  97. X    if((shm->Lbaud < 300) && lrwt->to2)
  98. X        if(lrwt->to2 < 300L) lrwt->to2 = 300L;
  99. X    else if((shm->Lbaud < 1200) && lrwt->to2)
  100. X        if(lrwt->to2 < 200L) lrwt->to2 = 100L;
  101. X
  102. X/* shortest interval */
  103. X    ltmp = (lrwt->to1 < lrwt->to2) ? lrwt->to1 : lrwt->to2;
  104. X
  105. X/* calculate wait quantum */
  106. X    quantum = ltmp / 10L;                /* try for ten ticks */
  107. X
  108. X#if defined(M_I386)
  109. X    if(quantum < 40L)
  110. X        quantum = 40L;
  111. X#else
  112. X    if(quantum < 20L)
  113. X        quantum = 20L;
  114. X#endif
  115. X    qc1 = lrwt->to1 / quantum;
  116. X    if(!qc1) qc1 = 1L;
  117. X    qc2 = lrwt->to2 / quantum;
  118. X    if(!qc2) qc2 = 1L;
  119. X
  120. X/* perform the lrtw function using nap() and rdchk()
  121. X   input: qc1 is first nap count (for first charcters) 
  122. X          qc2 is 2nd nap count (for subsequent characters) 
  123. X          quantum is the nap period in milliseconds
  124. X          cptr is char* to receive read string
  125. X          max_count is max number of characters incl null
  126. X          lrwt->raw_flag as described above
  127. X
  128. X  output: lrwt->count is actual count of return result
  129. X          lrwt->buffer is return read buffer
  130. X*/
  131. X    max_count--;                /* leave room for null */
  132. X
  133. X    if(check_sigint)
  134. X        ttymode(2);                /* let console interrupt long timeouts */
  135. X
  136. X    timeout_counter = qc1;        /* first timeout */ 
  137. X    *cptr = 0;                    /* init result string */
  138. X    while(timeout_counter--)
  139. X    {
  140. X        Nap(quantum);
  141. X
  142. X        if(check_sigint && sigint)
  143. X            goto INTERRUPTED;
  144. X
  145. X        while(lrdchk_xmtr())
  146. X        {
  147. X            zero_length_read_detected = 0;
  148. X            *cptr = lgetc_xmtr();
  149. X
  150. X            if(zero_length_read_detected)
  151. X                goto BOTTOM;
  152. X
  153. X            if(check_sigint && sigint)
  154. X                goto INTERRUPTED;
  155. X
  156. X            if(*cptr == 0)
  157. X                continue;
  158. X
  159. X            process_xmtr_rcvd_char(*cptr,echo_flag);
  160. X
  161. X            if(!raw_mode && (*cptr == CRET))
  162. X                    continue;
  163. X
  164. X            *++cptr = 0;
  165. X            if(++actual_count == 1)
  166. X            {
  167. X                if(!lrwt->to2)
  168. X                    break;
  169. X                timeout_counter = qc2;
  170. X            }
  171. X
  172. X            if(--max_count == 0)
  173. X                goto BOTTOM;
  174. X
  175. X            if(delim_len && (actual_count >= delim_len) &&
  176. X                    !strncmp(lrwt->delim,cptr - delim_len,delim_len))
  177. X                goto BOTTOM;
  178. X        }
  179. X    }
  180. X
  181. X/********************************/
  182. X#else /* do have WORKING_SELECT */
  183. X/********************************/
  184. X/* --- use select --- */
  185. X    register actual_count = 0;
  186. X    register char *cptr = lrwt->buffer;
  187. X    register max_count = lrwt->bufsize;
  188. X    register raw_mode = lrwt->raw_flag & 0x0F;
  189. X    register echo_flag = lrwt->echo_flag;
  190. X    int check_sigint = (lrwt->raw_flag & 0x80);
  191. X    int old_ttymode = get_ttymode();    /* save original tty mode */
  192. X    int fdmask;
  193. X    int delim_len;
  194. X    struct timeval tval;
  195. X    char *rtn_val;
  196. X
  197. X    delim_len = (lrwt->delim) ? strlen(lrwt->delim) : 0;
  198. X
  199. X    if((shm->Lbaud < 300) && lrwt->to2)
  200. X        if(lrwt->to2 < 300L) lrwt->to2 = 300L;
  201. X    else if((shm->Lbaud < 1200) && lrwt->to2)
  202. X        if(lrwt->to2 < 200L) lrwt->to2 = 100L;
  203. X
  204. X
  205. X/* perform the lrtw function
  206. X
  207. X  output: lrwt->count is actual count of return result
  208. X          lrwt->buffer is return read buffer
  209. X*/
  210. X    max_count--;                /* leave room for null */
  211. X
  212. X    if(check_sigint)
  213. X        ttymode(2);                /* let console interrupt long timeouts */
  214. X
  215. X    *cptr = 0;                    /* init result string */
  216. X    while(1)
  217. X    {
  218. X        if(check_sigint && sigint)
  219. X            goto INTERRUPTED;
  220. X
  221. X        errno = 0;
  222. X        fdmask = 1 << shm->Liofd; /* Liofd will always be <= 31, right? */
  223. X        if(actual_count)
  224. X        {
  225. X            tval.tv_sec = lrwt->to2 / 1000L;
  226. X            tval.tv_usec = (lrwt->to2 % 1000L) * 1000L;
  227. X        }
  228. X        else
  229. X        {
  230. X            tval.tv_sec = lrwt->to1 / 1000L;
  231. X            tval.tv_usec = (lrwt->to1 % 1000L) * 1000L;
  232. X        }
  233. X        if(select(shm->Liofd + 1,&fdmask,(int *)0,(int *)0,&tval) != 1)
  234. X        {
  235. X            if(errno == EINTR)
  236. X                continue;
  237. X            break;
  238. X        }
  239. X
  240. X        while(rdchk(shm->Liofd))
  241. X        {
  242. X            zero_length_read_detected = 0;
  243. X            *cptr = lgetc_xmtr();
  244. X
  245. X            if(zero_length_read_detected)
  246. X                goto BOTTOM;
  247. X
  248. X            if(check_sigint && sigint)
  249. X                goto INTERRUPTED;
  250. X
  251. X            if(*cptr == 0)
  252. X                continue;
  253. X
  254. X            process_xmtr_rcvd_char(*cptr,!!echo_flag);
  255. X
  256. X            if(!raw_mode && (*cptr == CRET))
  257. X                    continue;
  258. X
  259. X            *++cptr = 0;
  260. X            actual_count++;
  261. X
  262. X            if(--max_count == 0)
  263. X                goto BOTTOM;
  264. X
  265. X            if(delim_len && (actual_count >= delim_len) &&
  266. X                    !strncmp(lrwt->delim,cptr - delim_len,delim_len))
  267. X                goto BOTTOM;
  268. X        }
  269. X        if(!lrwt->to2)
  270. X            break;
  271. X    }
  272. X
  273. X#endif    /* WORKING_SELECT */
  274. X
  275. X/********* common post processing for select() / no select() ************/
  276. XBOTTOM:
  277. X    if(check_sigint)
  278. X        ttymode(old_ttymode);
  279. X    if(raw_mode)
  280. X    {
  281. X        lrwt->count = actual_count;
  282. X        return(lrwt->buffer);
  283. X    }
  284. X    cptr = lrwt->buffer;
  285. X    while(((*cptr > 0) && (*cptr < SPACE)) || (*cptr >= DEL))
  286. X        cptr++;
  287. X    rtn_val = cptr;
  288. X    actual_count = 0;
  289. X    while(((*cptr &= 0x7F) >= SPACE) && (*cptr < DEL))
  290. X    {
  291. X        cptr++;
  292. X        actual_count++;
  293. X    }
  294. X    *cptr = 0;
  295. X    strcpy(lrwt->buffer,rtn_val);
  296. X    lrwt->count = actual_count;
  297. X    return(lrwt->buffer);
  298. X
  299. XINTERRUPTED:
  300. X    ttymode(old_ttymode);
  301. X    strcpy(lrwt->buffer,"!Interrupted");
  302. X    lrwt->count = strlen(lrwt->buffer);
  303. X    return((char *)0);
  304. X
  305. X}    /* end of lgets_timeout */
  306. X
  307. X/*+-------------------------------------------------------------------------
  308. X    lgetc_timeout(msec) - may be called by xmtr only
  309. X
  310. X reads one character from line unless msec passes with no receipt.
  311. X return char if received, else -1 if timeout
  312. X--------------------------------------------------------------------------*/
  313. Xint
  314. Xlgetc_timeout(msec)
  315. Xlong msec;
  316. X{
  317. X    uchar rtn_char;
  318. X#if !defined(WORKING_SELECT)
  319. X    long timeout;
  320. X
  321. X    timeout = msec;
  322. X    while(!lrdchk_xmtr())
  323. X    {
  324. X        if(sigint)
  325. X            return(-1);
  326. X        if((timeout -= Nap(hzmsec)) <= 0)
  327. X            return(-1);
  328. X    }
  329. X
  330. X#else
  331. X
  332. X    int fdmask;
  333. X    struct timeval tval;
  334. X
  335. X    tval.tv_sec = msec / 1000L;
  336. X    tval.tv_usec = (msec % 1000L) * 1000L;
  337. X    fdmask = 1 << shm->Liofd; /* Liofd will always be <= 31, right? */
  338. X    if(select(shm->Liofd + 1,&fdmask,(int *)0,(int *)0,&tval) < 1)
  339. X        return(-1);
  340. X    if(!lrdchk_xmtr())
  341. X        return(-1);
  342. X    if(sigint)
  343. X        return(-1);
  344. X#endif
  345. X
  346. X    rtn_char = lgetc_xmtr();
  347. X    return(rtn_char);
  348. X
  349. X}    /* end of lgetc_timeout */
  350. X
  351. X/*+-------------------------------------------------------------------------
  352. X    llookfor(lookfor,msecs,echo_flag)
  353. Xreturn 1 if successful, else 0 if no match
  354. Xecho_flag: 0 no echo
  355. X           1 echo literally
  356. X           2 "make printable"
  357. X--------------------------------------------------------------------------*/
  358. Xint
  359. Xllookfor(lookfor,msecs,echo_flag)
  360. Xchar *lookfor;
  361. Xulong msecs;
  362. Xint echo_flag;
  363. X{
  364. X    register lookfor_len = strlen(lookfor);
  365. X    register lchar;
  366. X    char *lastfew = (char *)malloc(lookfor_len);
  367. X    int success_flag = 0;
  368. X    int old_ttymode = get_ttymode();
  369. X
  370. X    if(!lastfew)
  371. X    {
  372. X        pputs("memory exhausted\n");
  373. X        return(0);
  374. X    }
  375. X
  376. X    ttymode(2);
  377. X
  378. X    memset(lastfew,0,lookfor_len);
  379. X    while((lchar = lgetc_timeout(msecs)) >= 0)
  380. X    {
  381. X        if(!lchar)        /* skip nulls */
  382. X            continue;
  383. X        process_xmtr_rcvd_char(lchar,echo_flag);
  384. X        mem_cpy(lastfew,lastfew + 1,lookfor_len - 1);
  385. X        *(lastfew + lookfor_len - 1) = lchar;
  386. X        if(!strncmp(lastfew,lookfor,lookfor_len))
  387. X        {
  388. X            success_flag = 1;
  389. X            break;
  390. X        }
  391. X    }
  392. X    free(lastfew);
  393. X    ttymode(old_ttymode);
  394. X    return(success_flag);
  395. X}    /* end of llookfor */
  396. X
  397. X/*+-------------------------------------------------------------------------
  398. X    lquiet(msecs,echo_flag)
  399. X--------------------------------------------------------------------------*/
  400. Xvoid
  401. Xlquiet(msecs,echo_flag)
  402. Xulong msecs;
  403. Xint echo_flag;
  404. X{
  405. X    register lchar;
  406. X    int old_ttymode = get_ttymode();
  407. X
  408. X    ttymode(2);
  409. X    while((lchar = lgetc_timeout(msecs)) >= 0)
  410. X    {
  411. X        if(sigint)    /* if interrupt, return */
  412. X            break;
  413. X        if(!lchar)        /* skip nulls */
  414. X            continue;
  415. X        process_xmtr_rcvd_char(lchar,!!echo_flag);
  416. X    }
  417. X    ttymode(old_ttymode);
  418. X
  419. X}    /* end of lquiet */
  420. X
  421. X/*+-------------------------------------------------------------------------
  422. X    lflush(flush_type) -- flush line driver input &/or output buffers
  423. X
  424. X0 == input buffer
  425. X1 == output buffer
  426. X2 == both buffers
  427. X--------------------------------------------------------------------------*/
  428. Xvoid
  429. Xlflush(flush_type)
  430. Xint flush_type;
  431. X{
  432. X    switch(flush_type)
  433. X    {
  434. X        case 0:
  435. X            lgetc_count = 0;
  436. X            ioctl(shm->Liofd,TCFLSH,(char *)0); 
  437. X            break;
  438. X        case 1:
  439. X            ioctl(shm->Liofd,TCFLSH,(char *)1); 
  440. X            break;
  441. X        case 2:
  442. X            lgetc_count = 0;
  443. X            ioctl(shm->Liofd,TCFLSH,(char *)2); 
  444. X            break;
  445. X    }
  446. X}    /* end of lflush */
  447. X
  448. X/*+-------------------------------------------------------------------------
  449. X    lreset_ksr()
  450. X
  451. X  This procedure restores the termio for the
  452. X  comm line to the values in Ltermio
  453. X--------------------------------------------------------------------------*/
  454. Xvoid
  455. Xlreset_ksr()
  456. X{
  457. X    ioctl(shm->Liofd,TCSETA,(char *)Ltermio);
  458. X
  459. X}    /* end of lreset_ksr */
  460. X
  461. X/*+-------------------------------------------------------------------------
  462. X    ldraino(inflush_flag) - wait for output to drain
  463. X
  464. XIf inflush_flag is set, also flush input after output drains
  465. X--------------------------------------------------------------------------*/
  466. Xvoid
  467. Xldraino(inflush_flag)
  468. Xint inflush_flag;
  469. X{
  470. X#if defined(sun)
  471. X    int retries = 50;
  472. X    int outq_count;
  473. X    int old_outq_count = 0;
  474. X
  475. X    do {
  476. X        ioctl(shm->Liofd,TIOCOUTQ,&outq_count);
  477. X        if(!outq_count)
  478. X            break;
  479. X        if(old_outq_count == outq_count) /* don't hang if flow control lock */
  480. X            retries--;
  481. X        old_outq_count = outq_count;
  482. X        Nap(50);
  483. X    } while(outq_count && retries);
  484. X    if(inflush_flag)
  485. X        ioctl(shm->Liofd,TCFLSH,TCIFLUSH);
  486. X#else
  487. X    ioctl(shm->Liofd,(inflush_flag) ? TCSETAF : TCSETAW,(char *)Ltermio);
  488. X#endif
  489. X
  490. X}    /* end of ldraino */
  491. X
  492. X/*+-----------------------------------------------------------------------
  493. X    lputc(lchar) -- write lchar to comm line
  494. X------------------------------------------------------------------------*/
  495. Xvoid
  496. Xlputc(lchar)
  497. Xchar lchar;
  498. X{
  499. X    while(write(shm->Liofd,&lchar,1) < 0)
  500. X    {
  501. X        if(errno == EINTR)
  502. X            continue;
  503. X        pperror("lputc write error");
  504. X        termecu(TERMECU_XMTR_WRITE_ERROR);
  505. X    }
  506. X    shm->xmit_chars++;
  507. X    shm->xmit_chars_this_connect++;
  508. X}    /* end of lputc */
  509. X
  510. X/*+-----------------------------------------------------------------------
  511. X    lputc_paced(pace_msec,lchar) -- write lchar to comm line
  512. X  with time between each character 
  513. X------------------------------------------------------------------------*/
  514. Xvoid
  515. Xlputc_paced(pace_msec,lchar)
  516. Xregister pace_msec;
  517. Xchar lchar;
  518. X{
  519. X
  520. X    lputc(lchar);    
  521. X    Nap((long)(pace_msec ? pace_msec : LPUTS_NAP_COUNT));
  522. X
  523. X}    /* end of lputc_paced */
  524. X
  525. X/*+-----------------------------------------------------------------------
  526. X    lputs(string) -- write string to comm line
  527. X------------------------------------------------------------------------*/
  528. Xvoid
  529. Xlputs(string)
  530. Xregister char *string;
  531. X{
  532. X    while(*string)
  533. X        lputc(*string++);
  534. X}
  535. X
  536. X/*+-----------------------------------------------------------------------
  537. X    lputs_paced(pace_msec,string) -- write string to comm line
  538. X  with time between each character 
  539. X------------------------------------------------------------------------*/
  540. Xvoid
  541. Xlputs_paced(pace_msec,string)
  542. Xregister pace_msec;
  543. Xregister char *string;
  544. X{
  545. X    while(*string)
  546. X        lputc_paced(pace_msec,*string++);
  547. X
  548. X}    /* end of lputs_paced */
  549. X
  550. X/*+-------------------------------------------------------------------------
  551. X    valid_baud_rate(baud) -- returns (positive) baud rate selector
  552. Xor -1 if invalid baud rate
  553. X--------------------------------------------------------------------------*/
  554. Xvalid_baud_rate(baud)
  555. Xuint baud;
  556. X{
  557. X    switch(baud)
  558. X    {
  559. X        case 110: return(B110);
  560. X        case 300: return(B300);
  561. X        case 600: return(B600);
  562. X        case 1200: return(B1200);
  563. X        case 2400: return(B2400);
  564. X        case 4800: return(B4800);
  565. X        case 9600: return(B9600);
  566. X        case 19200: return(EXTA);
  567. X        case 38400: return(EXTB);
  568. X        default: return(-1);
  569. X    }
  570. X
  571. X}    /* end of valid_baud_rate */
  572. X
  573. X/*+-----------------------------------------------------------------------
  574. X    lset_baud_rate(ioctl_flag)
  575. X
  576. X  If 'ioctl_flag' is set, then perform ioctl call
  577. X  is executed after setting baud rate
  578. X------------------------------------------------------------------------*/
  579. Xlset_baud_rate(ioctl_flag)
  580. Xint ioctl_flag;
  581. X{
  582. X    int baud_selector = valid_baud_rate(shm->Lbaud);
  583. X
  584. X    if(shm->Liofd < 0)
  585. X        return(0);
  586. X
  587. X    if(baud_selector == -1)
  588. X        baud_selector = valid_baud_rate(shm->Lbaud = DEFAULT_BAUD_RATE);
  589. X
  590. X    shm->Lmodem_already_init = 0;
  591. X    Ltermio->c_cflag &= ~CBAUD;
  592. X    Ltermio->c_cflag |= baud_selector;
  593. X
  594. X    if(baud_selector < B300)
  595. X        Ltermio->c_cflag |= CSTOPB;
  596. X    else
  597. X        Ltermio->c_cflag &= ~CSTOPB;
  598. X
  599. X    if(ioctl_flag)
  600. X         ioctl(shm->Liofd,TCSETA,(char *)Ltermio);
  601. X    return(0);
  602. X
  603. X}    /* end of lset_baud_rate */
  604. X
  605. X/*+-------------------------------------------------------------------------
  606. X    display_hw_flow_config() - display hardware flow control configuration
  607. X--------------------------------------------------------------------------*/
  608. X#if defined(HW_FLOW_CONTROL) /* see ecu.h */
  609. Xvoid
  610. Xdisplay_hw_flow_config()
  611. X{
  612. X#undef ____HANDLED
  613. X#ifdef RTSFLOW /* SCO */
  614. X#define ____HANDLED
  615. X    pprintf("RTSFLOW %s CTSFLOW %s",
  616. X        (Ltermio->c_cflag & RTSFLOW) ? "on" : "off",
  617. X        (Ltermio->c_cflag & CTSFLOW) ? "on" : "off");
  618. X#ifdef CRTSFL
  619. X    pprintf(" CRTSFL %s",
  620. X        (Ltermio->c_cflag & CRTSFL) ? "on" : "off");
  621. X#endif /* CRTSFL */
  622. X    pprintf("\n");
  623. X#endif /* RTSFLOW */
  624. X
  625. X#ifdef RTSXOFF /* SVR4 */
  626. X#define ____HANDLED
  627. X    pprintf("RTSXOFF %s CTSXON %s\n",
  628. X        (hx_flag & RTSXOFF) ? "on" : "off",
  629. X        (hx_flag & CTSXON) ? "on" : "off");
  630. X#endif /* RTSXOFF */
  631. X
  632. X#if defined(CRTSCTS) /* sun */
  633. X#define ____HANDLED
  634. X    pprintf(" CRTSCTS %s\n",
  635. X        (Ltermio->c_cflag & CRTSCTS) ? "on" : "off");
  636. X#endif /* sun */
  637. X
  638. X#ifndef ____HANDLED
  639. Xporting_attention_needed_here; /* HW_FLOW_CONTROL but no recognized flags */
  640. X/*
  641. X * if you are reading this because of a compilation error, you may wish to
  642. X * go ahead and grep for 'RTSFLOW' and 'display_hw_flow_control' to find other
  643. X * hardware control dependencies (like in lRTSCTS_control() below).  This is
  644. X * the only rigrous test in ECU for making sure that if HW_FLOW_CONTROL is on
  645. X * we know what to do about it.
  646. X */
  647. X#endif /* ____HANDLED */
  648. X
  649. X}    /* end of display_hw_flow_config */
  650. X#endif /* HW_FLOW_CONTROL */
  651. X
  652. X/*+-------------------------------------------------------------------------
  653. X    lRTSCTS_control(flag)
  654. X--------------------------------------------------------------------------*/
  655. Xvoid
  656. XlRTSCTS_control(flag)
  657. Xint flag;
  658. X{
  659. X#ifdef RTSXOFF /* SVR4 */
  660. X    struct termiox flowctrl;
  661. X
  662. X    ioctl(shm->Liofd, TCGETX, &flowctrl);
  663. X    switch(flag)
  664. X    {
  665. X        case 0:
  666. X            flowctrl.x_hflag &= ~(RTSXOFF | CTSXON);
  667. X            Ltermio->c_iflag |= (IXOFF);
  668. X            break;
  669. X
  670. X        case 1:
  671. X            flowctrl.x_hflag |= CTSXON;
  672. X            flowctrl.x_hflag &= ~RTSXOFF;
  673. X            Ltermio->c_iflag &= ~(IXON | IXOFF | IXANY);
  674. X            break;
  675. X        case 2:
  676. X            flowctrl.x_hflag |= RTSXOFF;
  677. X            flowctrl.x_hflag &= ~CTSXON;
  678. X            Ltermio->c_iflag &= ~(IXON | IXOFF | IXANY);
  679. X            break;
  680. X        case 3:
  681. X            flowctrl.x_hflag |= (RTSXOFF | CTSXON);
  682. X            Ltermio->c_iflag &= ~(IXON | IXOFF | IXANY);
  683. X            break;
  684. X    }
  685. X    shm->Lxonxoff = Ltermio->c_iflag & (IXON|IXOFF);
  686. X    ioctl(shm->Liofd,TCSETA,(char *)Ltermio);
  687. X    ioctl(shm->Liofd, TCSETX, &flowctrl);
  688. X    hx_flag = flowctrl.x_hflag;
  689. X#else /* !SVR4 */
  690. X#if defined(RTSFLOW)    /* only SCO */
  691. X    switch(flag & 3)
  692. X    {
  693. X        case 0:
  694. X            Ltermio->c_iflag |= (IXOFF);
  695. X            Ltermio->c_cflag &= ~(RTSFLOW | CTSFLOW);
  696. X            break;
  697. X
  698. X        case 1:
  699. X            Ltermio->c_iflag &= ~(IXON | IXOFF | IXANY);
  700. X            Ltermio->c_cflag |= CTSFLOW;
  701. X            Ltermio->c_cflag &= ~RTSFLOW;
  702. X            break;
  703. X
  704. X        case 2:
  705. X            Ltermio->c_iflag &= ~(IXON | IXOFF | IXANY);
  706. X            Ltermio->c_cflag |= RTSFLOW;
  707. X            Ltermio->c_cflag &= ~CTSFLOW;
  708. X            break;
  709. X
  710. X        case 3:
  711. X            Ltermio->c_iflag &= ~(IXON | IXOFF | IXANY);
  712. X            Ltermio->c_cflag |= (RTSFLOW | CTSFLOW);
  713. X            break;
  714. X    }
  715. X#if defined(CRTSFL)
  716. X    if(flag & 4)
  717. X    {
  718. X        Ltermio->c_iflag &= ~(IXON | IXOFF | IXANY | RTSFLOW | CTSFLOW);
  719. X        Ltermio->c_cflag |= CRTSFL;
  720. X    }
  721. X#endif
  722. X    shm->Lxonxoff = Ltermio->c_iflag & (IXON|IXOFF);
  723. X    ioctl(shm->Liofd,TCSETA,(char *)Ltermio);
  724. X
  725. X#else
  726. X#if defined(CRTSCTS) /* sun */
  727. X    switch(flag)
  728. X    {
  729. X        case 0:
  730. X            Ltermio->c_iflag |= (IXOFF);
  731. X            Ltermio->c_cflag &= ~(CRTSCTS);
  732. X            break;
  733. X
  734. X        default:
  735. X            Ltermio->c_iflag &= ~(IXON | IXOFF | IXANY);
  736. X            Ltermio->c_cflag |= CRTSCTS;
  737. X            break;
  738. X
  739. X    }
  740. X    shm->Lxonxoff = Ltermio->c_iflag & (IXON|IXOFF);
  741. X    ioctl(shm->Liofd,TCSETA,(char *)Ltermio);
  742. X
  743. X#endif /* sun */
  744. X#endif /* RTSFLOW */
  745. X#endif /* SVR4 */
  746. X}    /* end of lRTSCTS_control */
  747. X
  748. X/*+-------------------------------------------------------------------------
  749. X    lnew_baud_rate(new_baud)
  750. X--------------------------------------------------------------------------*/
  751. Xint
  752. Xlnew_baud_rate(new_baud)
  753. Xuint new_baud;
  754. X{
  755. X    if(valid_baud_rate(new_baud) < 0)
  756. X        return(-1);
  757. X    if(shm->Lbaud != new_baud)
  758. X        shm->Lmodem_already_init = 0;
  759. X    shm->Lbaud = new_baud;
  760. X    lset_baud_rate(1);
  761. X    return(0);
  762. X}    /* end of lnew_baud_rate */
  763. X
  764. X/*+-----------------------------------------------------------------------
  765. X    lset_parity(ioctl_flag)
  766. X
  767. X  If 'ioctl_flag' is set, then perform ioctl call
  768. X  is executed after setting parity
  769. X------------------------------------------------------------------------*/
  770. Xvoid
  771. Xlset_parity(ioctl_flag)
  772. Xint ioctl_flag;
  773. X{
  774. X    if(shm->Liofd < 0)
  775. X        return;
  776. X
  777. X    Ltermio->c_cflag &= ~(CS8 | PARENB | PARODD);
  778. X    switch(to_lower(shm->Lparity))
  779. X    {
  780. X        case 'e':
  781. X            Ltermio->c_cflag |= CS7 | PARENB;
  782. X            Ltermio->c_iflag |= ISTRIP;
  783. X            break;
  784. X        case 'o':
  785. X            Ltermio->c_cflag |= CS7 | PARENB | PARODD;
  786. X            Ltermio->c_iflag |= ISTRIP;
  787. X            break;
  788. X        default:
  789. X            ff(se,"invalid parity: '%c' ... defaulting to no parity\r\n",
  790. X                to_lower(shm->Lparity));
  791. X        case 'n':
  792. X            shm->Lparity = 0;
  793. X        case 0:
  794. X            Ltermio->c_cflag |= CS8;
  795. X            Ltermio->c_iflag &= ~(ISTRIP);
  796. X            shm->Lparity = 0;
  797. X            break;
  798. X    }            
  799. X
  800. X    if(ioctl_flag)
  801. X        ioctl(shm->Liofd,TCSETA,(char *)Ltermio);
  802. X
  803. X}    /* end of lset_parity */
  804. X
  805. X/*+-------------------------------------------------------------------------
  806. X    lclear_xmtr_xoff()
  807. X--------------------------------------------------------------------------*/
  808. Xvoid
  809. Xlclear_xmtr_xoff()
  810. X{
  811. X    ioctl(shm->Liofd,TCXONC,(char *)1); /* restart xmtr output */
  812. X}    /* end of lclear_xmtr_xoff */
  813. X
  814. X/*+-------------------------------------------------------------------------
  815. X    lbreak()
  816. X--------------------------------------------------------------------------*/
  817. Xvoid
  818. Xlbreak()
  819. X{
  820. X    ioctl(shm->Liofd,TCSBRK,(char *)0);
  821. X}    /* end of lbreak */
  822. X
  823. X/*+-------------------------------------------------------------------------
  824. X    linst_err_text(lerr)
  825. X--------------------------------------------------------------------------*/
  826. Xchar *
  827. Xlinst_err_text(lerr)
  828. Xint lerr;
  829. X{
  830. X    static char lerr_s80[80];
  831. X    extern uchar last_ugstat;
  832. X    char *ugstat_text();
  833. X
  834. X    if(lopen_err_str[0])
  835. X        return(lopen_err_str);
  836. X
  837. X    switch(lerr)
  838. X    {
  839. X        case LINST_INVALID: return("invalid line name");
  840. X        case LINST_UNKPID: return("unknown pid is using line");
  841. X        case LINST_LCKERR: return("error creating lock file");
  842. X        case LINST_NODEV: return("line does not exist");
  843. X        case LINST_ALREADY: return("line already open!?");
  844. X        case LINST_OPNFAIL:
  845. X            sprintf(lerr_s80,"open error (%-.60s)",
  846. X                errno_text(errno));
  847. X            return(lerr_s80);
  848. X        case LINST_ENABLED: return("line enabled for incoming login");
  849. X        case LINST_ENABLED_IN_USE: return("line in use by incoming login");
  850. X        case LINST_DIALOUT_IN_USE: return("line in use by another dial out");
  851. X        case LINST_NOPTY: return("ptys not supported");
  852. X        case LINST_WEGOTIT: return("line is locked by this process");
  853. X        case LINST_ECUUNGETTY:
  854. X            sprintf(lerr_s80,"ecuungetty error (%-.45s)",
  855. X                ugstat_text(last_ugstat));
  856. X            return(lerr_s80);
  857. X        case LINST_ECUUNGETTY2:
  858. X            return("ecuungetty execution error");
  859. X        case LINST_NOTCHR:
  860. X            return("not a character special device");
  861. X    }
  862. X    if(lerr > 0)
  863. X        sprintf(lerr_s80,"pid %d using line",lerr);
  864. X    else
  865. X        sprintf(lerr_s80,"unknown line error %d",lerr);
  866. X    return(lerr_s80);
  867. X}    /* end of linst_err_text */
  868. X
  869. X/*+-------------------------------------------------------------------------
  870. X    lopen_failed(sig) - see lopen() below
  871. X--------------------------------------------------------------------------*/
  872. Xvoid
  873. Xlopen_failed(sig)
  874. Xint sig;
  875. X{
  876. X    if(sig != SIGALRM)
  877. X        ff(se,"error %d in lopen_failed: tell wht@n4hgf\r\n",sig);
  878. X    longjmp(_insurance_jmpbuf,1);
  879. X
  880. X}    /* end of lopen_failed */
  881. X
  882. X/*+----------------------------------------------------------------------
  883. X    lopen()
  884. Xreturns negative LINST_ codes if failure else positive pid using line
  885. Xelse 0 if successful open
  886. X------------------------------------------------------------------------*/
  887. Xint
  888. Xlopen()
  889. X{
  890. X    int itmp;
  891. X    struct stat ttystat;
  892. X
  893. X#ifdef SHARE_DEBUG
  894. X    char s80[80];
  895. X    sprintf(s80,"lopen Liofd=%d Lline=%s line_lock_status=%d",
  896. X        shm->Liofd,shm->Lline,
  897. X        line_lock_status(shm->Lline));
  898. X    ecu_log_event((int)xmtr_pid,s80);
  899. X#endif
  900. X
  901. X    /*
  902. X     * system independent checks
  903. X     */
  904. X    if(shm->Liofd >= 0)
  905. X        return(LINST_ALREADY);
  906. X    if(!strcmp(shm->Lline,"/dev/tty"))
  907. X        return(LINST_INVALID);
  908. X    if(stat(shm->Lline,&ttystat) < 0)
  909. X    {
  910. X        if(errno == ENOENT)
  911. X            return(LINST_NODEV);
  912. X        return(LINST_OPNFAIL);
  913. X    }
  914. X    if((ttystat.st_mode & S_IFMT) != S_IFCHR)
  915. X        return(LINST_NOTCHR);
  916. X    if(ulindex(shm->Lline,"pty") > -1)
  917. X        return(LINST_NOPTY);
  918. X
  919. X    /*
  920. X     * lock the tty 
  921. X     */
  922. X    if((itmp = lock_tty(shm->Lline)) && (itmp != LINST_WEGOTIT))
  923. X        return(itmp);
  924. X
  925. X    /*
  926. X     * if appropriate, make sure we have ungetty'd the line
  927. X     */
  928. X#if defined(USE_ECUUNGETTY)
  929. X    ungetty_return_all_but(shm->Lline);
  930. X    if(!in_ungetty_list(shm->Lline))
  931. X    {
  932. X        if(itmp = ungetty_get_line(shm->Lline))
  933. X        {
  934. X            sprintf(lopen_err_str,"ecuungetty error - %s",linst_err_text(itmp));
  935. X            unlock_tty(shm->Lline);
  936. X            return(itmp);
  937. X        }
  938. X    }
  939. X#endif
  940. X
  941. X    /*
  942. X     * rarely an open will hang despite our wisdom and prayer
  943. X     */
  944. X    if(setjmp(_insurance_jmpbuf))
  945. X    {
  946. X        alarm(0);
  947. X        signal(SIGALRM,SIG_IGN);
  948. X        errno = EIO;
  949. X        sprintf(lopen_err_str,"open error - %s",errno_text(errno));
  950. X        unlock_tty(shm->Lline);
  951. X        return(LINST_OPNFAIL);
  952. X    }
  953. X
  954. X    /*
  955. X     * open the tty using non-blocking I/O to bypass DCD wait
  956. X     * handle EAGAIN for SVR4 per kortcs!tim
  957. X     */
  958. X
  959. X    for (itmp=0; ; ++itmp)
  960. X    {
  961. X        signal(SIGALRM,lopen_failed);
  962. X#ifdef sun
  963. X        alarm(10);
  964. X#else
  965. X        alarm(5);
  966. X#endif
  967. X        shm->Liofd = open(shm->Lline,O_RDWR | O_NDELAY,0666);
  968. X        alarm(0);
  969. X        signal(SIGALRM,SIG_IGN);
  970. X        if(shm->Liofd >= 0)
  971. X            break;
  972. X        if((itmp < 5) && (errno == EAGAIN))
  973. X        {
  974. X            (void)signal(SIGALRM,SIG_DFL);
  975. X            alarm(0);
  976. X            sleep(2);
  977. X            continue;
  978. X        }
  979. X        if (errno == EACCES)
  980. X        {
  981. X            struct passwd *pw = getpwuid(ttystat.st_uid);
  982. X            endpwent();
  983. X            if(pw)
  984. X            {
  985. X                sprintf(lopen_err_str,
  986. X                    "cannot open line owned by %s (mode=%3o)",
  987. X                    pw->pw_name,ttystat.st_mode & 0777);
  988. X            }
  989. X            else
  990. X            {
  991. X                sprintf(lopen_err_str,
  992. X                    "open error - try chmod +rw %s",shm->Lline);
  993. X            }
  994. X        }
  995. X        else 
  996. X            sprintf(lopen_err_str,"open error - %s",errno_text(errno));
  997. X        unlock_tty(shm->Lline);
  998. X        return(LINST_OPNFAIL);
  999. X    }
  1000. X
  1001. X    /*
  1002. X     * turn off non-blocking I/O and set initial termio, including CLOCAL
  1003. X     */
  1004. X    fcntl(shm->Liofd,F_GETFL,&itmp);
  1005. X    itmp &= ~O_NDELAY;
  1006. X    fcntl(shm->Liofd,F_SETFL,itmp);
  1007. X
  1008. X    ioctl(shm->Liofd,TCGETA,(char *) Ltermio);
  1009. X    Ltermio->c_iflag = (IGNPAR | IGNBRK | shm->Lxonxoff);
  1010. X    Ltermio->c_oflag = 0;
  1011. X    Ltermio->c_cflag |= (CLOCAL | CREAD | HUPCL);
  1012. X    Ltermio->c_lflag = 0;
  1013. X    Ltermio->c_cc[VMIN]   = 1;
  1014. X    Ltermio->c_cc[VTIME]  = 1;
  1015. X    lset_baud_rate(0);        /* do not perform ioctl */
  1016. X    lset_parity(1);            /* do perform ioctl */
  1017. X
  1018. X#if defined(SVR4)
  1019. X    hx_flag = 0;            /* hardware flow control "memory" */
  1020. X#endif
  1021. X
  1022. X    lopen_err_str[0] = 0;    /* no error this time! */
  1023. X    return(0);
  1024. X
  1025. X}    /* end of lopen */
  1026. X
  1027. X/*+-------------------------------------------------------------------------
  1028. X    lclose_failed(sig) - see lclose() below
  1029. X--------------------------------------------------------------------------*/
  1030. Xvoid
  1031. Xlclose_failed(sig)
  1032. Xint sig;
  1033. X{
  1034. X    if(sig != SIGALRM)
  1035. X        ff(se,"error %d in lclose_failed: tell wht@n4hgf\r\n",sig);
  1036. X    longjmp(_insurance_jmpbuf,1);
  1037. X
  1038. X}    /* end of lclose_failed */
  1039. X
  1040. X/*+-----------------------------------------------------------------------
  1041. X    lclose() - close the line
  1042. X
  1043. XThe FAS driver and others hang on a close until all output for a line
  1044. Xhas drained.  Sometimes during a hangup, a noisy XOFF can be received.
  1045. XOther changeces for failure include a DCE which drops CTS and leaves
  1046. Xit off, locking the line up if there is output waiting to go out.
  1047. XTo make sure the line is actually closed in these situations, a SIGLARM
  1048. Xhandler is used.
  1049. X------------------------------------------------------------------------*/
  1050. Xvoid
  1051. Xlclose()
  1052. X{
  1053. X    struct termio ttio;
  1054. X    int attempt2 = 0;
  1055. X
  1056. X#ifdef SHARE_DEBUG
  1057. X    char s80[80];
  1058. X    sprintf(s80,"lclose Liofd=%d Lline=%s line_lock_status=%d",
  1059. X        shm->Liofd,shm->Lline,
  1060. X        line_lock_status(shm->Lline));
  1061. X    ecu_log_event((int)xmtr_pid,s80);
  1062. X#endif
  1063. X
  1064. X    if(shm->Liofd < 0)
  1065. X        return;
  1066. XATTEMPT: /* endless loop because we cannot get out anyway unless success */
  1067. X    signal(SIGALRM,lclose_failed);
  1068. X#ifdef sun
  1069. X    alarm(10);
  1070. X#else
  1071. X    alarm(5);
  1072. X#endif
  1073. X    if(setjmp(_insurance_jmpbuf))
  1074. X    {    /* close failed */
  1075. X        signal(SIGALRM,SIG_IGN);
  1076. X        alarm(0);
  1077. X        ff(se,"\r\nclose failed (remote XOFF?) ... retrying close\r\n");
  1078. X        lclear_xmtr_xoff();
  1079. X        ttio = *Ltermio;
  1080. X        ttio.c_iflag &= ~(IXON | IXOFF);
  1081. X        ttio.c_cflag &= (CSIZE | CSTOPB | CREAD | PARENB | PARODD);
  1082. X        ioctl(shm->Liofd,TCSETA,(char *)&ttio);
  1083. X        lflush(2);
  1084. X        attempt2 = 1;
  1085. X        goto ATTEMPT;
  1086. X    }
  1087. X    if(!attempt2)
  1088. X    {
  1089. X        lclear_xmtr_xoff();
  1090. X        ldraino(1);
  1091. X    }
  1092. X    lCLOCAL(1);
  1093. X    close(shm->Liofd);
  1094. X    signal(SIGALRM,SIG_IGN);
  1095. X    alarm(0);
  1096. X    unlock_tty(shm->Lline);
  1097. X    shm->Lmodem_already_init = 0;
  1098. X    shm->Lconnected = 0;
  1099. X    shm->Liofd = -1;
  1100. X
  1101. X}    /* end of lclose */
  1102. X
  1103. X/*+-------------------------------------------------------------------------
  1104. X    lflash_dtr() - flash DTR
  1105. X
  1106. XDTR is lowered for 300 msec and raised again.  After raising,
  1107. Xwe pause a while for a possibly slow DCE to rereap it's fecal material
  1108. X
  1109. Xexpects:  Ltermio - current termio status of line
  1110. X          shm->Liofd - current line fd
  1111. X          shm->Lline - /dev/ttyxx name of line
  1112. X
  1113. XOn SunOS and SVR4, an open/close of the line is required to get DTR back
  1114. Xup. SVR3 does not seem to need this (ISC asy, SCO sio, Uwe Doering's FAS)
  1115. Xbut we do it anyway
  1116. X--------------------------------------------------------------------------*/
  1117. Xvoid
  1118. Xlflash_dtr()
  1119. X{
  1120. X#undef NEED_REOPEN
  1121. X#if defined(sun) || defined(SVR4)
  1122. X#define NEED_REOPEN
  1123. X    int tempfd;
  1124. X#endif
  1125. X    struct termio b0t;
  1126. X
  1127. X    /*
  1128. X     * copy termio but CBAUD to B0
  1129. X     */
  1130. X    b0t = *Ltermio;
  1131. X    b0t.c_cflag &= ~CBAUD;    /* B0 */
  1132. X
  1133. X    /*
  1134. X     * drop DTR for a while
  1135. X     */
  1136. X    ioctl(shm->Liofd,TCSETA,(char *)&b0t);        /* drop DTR */
  1137. X
  1138. X    /*
  1139. X     * DTR will not come back on some systems without open/close line
  1140. X     */
  1141. X#ifdef NEED_REOPEN
  1142. X    if ((tempfd = open(shm->Lline, O_NDELAY | O_RDWR, 0666)) != -1)
  1143. X        close(tempfd);
  1144. X    else
  1145. X    {
  1146. X        int save_errno = errno;
  1147. X        char s128[128];
  1148. X        sprintf(s128,"FLASH DTR line reopen failed (%.80s)",
  1149. X            errno_text(errno));
  1150. X        ecu_log_event(shm->xmtr_pid,s128);
  1151. X        pputs(s128);
  1152. X        pputs("\n");
  1153. X        errno = save_errno;
  1154. X        termecu(TERMECU_LINE_OPEN_ERROR);
  1155. X    }
  1156. X#else
  1157. X    /*
  1158. X     * ensure DTR low for 300 msec
  1159. X     * (the tempfd open/close takes plenty long enough)
  1160. X     */
  1161. X    Nap(300L);
  1162. X#endif
  1163. X
  1164. X    /*
  1165. X     * reestablish baud rate 
  1166. X     * (raise DTR if the open/close line did not do it)
  1167. X     */
  1168. X    ioctl(shm->Liofd,TCSETA,(char *)Ltermio);    /* raise DTR */
  1169. X    Nap(300L);    /* nap to give a lazy DCE some time */
  1170. X
  1171. X#undef NEED_REOPEN
  1172. X
  1173. X}    /* end of lflash_dtr */
  1174. X
  1175. X/*+-------------------------------------------------------------------------
  1176. X    lxon_xoff(flag)
  1177. XIXON specifies whether or not we respond to xon/xoff characters
  1178. XIXOFF specifies whether or not we generate XON/XOFF characters
  1179. X--------------------------------------------------------------------------*/
  1180. Xvoid
  1181. Xlxon_xoff(flag)
  1182. Xint flag;
  1183. X{
  1184. X    if(flag & IXON)
  1185. X        Ltermio->c_iflag |= IXON;
  1186. X    else
  1187. X        Ltermio->c_iflag &= ~IXON;
  1188. X
  1189. X    if(flag & IXOFF)
  1190. X        Ltermio->c_iflag |= IXOFF;
  1191. X    else
  1192. X        Ltermio->c_iflag &= ~IXOFF;
  1193. X    shm->Lxonxoff = Ltermio->c_iflag & (IXON|IXOFF);
  1194. X    ioctl(shm->Liofd,TCSETA,(char *)Ltermio);
  1195. X#if 0
  1196. X    Nap(400L);
  1197. X#endif
  1198. X
  1199. X}    /* end of lflash_dtr */
  1200. X
  1201. X/*+-------------------------------------------------------------------------
  1202. X    lget_xon_xoff(ixon,ixoff)
  1203. X--------------------------------------------------------------------------*/
  1204. Xvoid
  1205. Xlget_xon_xoff(ixon,ixoff)
  1206. Xint *ixon;
  1207. Xint *ixoff;
  1208. X{
  1209. X    *ixon  = Ltermio->c_iflag & IXON;
  1210. X    *ixoff = Ltermio->c_iflag & IXOFF;
  1211. X}    /* end of lget_xon_xoff */
  1212. X
  1213. X/*+-------------------------------------------------------------------------
  1214. X    set_xon_xoff_by_arg(arg)
  1215. X--------------------------------------------------------------------------*/
  1216. Xint
  1217. Xset_xon_xoff_by_arg(arg)
  1218. Xchar *arg;
  1219. X{
  1220. X    if(ulcmpb(arg,"on") < 0)
  1221. X        shm->Lxonxoff = IXON | IXOFF;
  1222. X    else if(ulcmpb(arg,"off") < 0)
  1223. X        shm->Lxonxoff = 0;
  1224. X    else if(ulcmpb(arg,"out") < 0)
  1225. X        shm->Lxonxoff = IXON;
  1226. X    else if(ulcmpb(arg,"in") < 0)
  1227. X        shm->Lxonxoff = IXOFF;
  1228. X    else
  1229. X        return(-1);
  1230. X
  1231. X    Ltermio->c_iflag &= ~(IXON|IXOFF);
  1232. X    Ltermio->c_iflag |= shm->Lxonxoff;
  1233. X    ioctl(shm->Liofd,TCSETA,(char *)Ltermio);
  1234. X    return(0);
  1235. X
  1236. X}    /* end of set_xon_xoff_by_arg */
  1237. X
  1238. X/*+-------------------------------------------------------------------------
  1239. X    xon_status()
  1240. X--------------------------------------------------------------------------*/
  1241. Xchar *
  1242. Xxon_status()
  1243. X{
  1244. X    switch(shm->Lxonxoff)
  1245. X    {
  1246. X        case 0            : return("off");
  1247. X        case IXON         : return("in off, out on");
  1248. X        case        IXOFF : return("in on, out off");
  1249. X        case IXON | IXOFF : return("on");
  1250. X    }
  1251. X    return("logic error");
  1252. X}    /* end of xon_status */
  1253. X
  1254. X/*+-------------------------------------------------------------------------
  1255. X    lCLOCAL(flag) - set line CLOCAL state
  1256. X
  1257. Xflag == 0: turn off CLOCAL to catch DCD loss
  1258. X     == 1: turn on CLOCAL to ignore modem signals
  1259. X
  1260. Xdoes not let CLOCAL be turned off if not Lconnected
  1261. Xalso resets global zero_length_read_detected
  1262. X--------------------------------------------------------------------------*/
  1263. Xvoid
  1264. XlCLOCAL(flag)
  1265. Xint flag;
  1266. X{
  1267. X
  1268. X    if(flag)
  1269. X        Ltermio->c_cflag |= CLOCAL;
  1270. X    else if(shm->Lconnected)
  1271. X        Ltermio->c_cflag &= ~CLOCAL;
  1272. X    else
  1273. X        Ltermio->c_cflag |= CLOCAL;
  1274. X
  1275. X    zero_length_read_detected = 0;
  1276. X    lreset_ksr();    /* do the ioctl */
  1277. X
  1278. X#ifdef DEBUG_CLOCAL
  1279. X    {
  1280. X        char s128[128];
  1281. X        sprintf(s128,"lCLOCAL(%d) connected=%c CLOCAL set %o",
  1282. X            flag,shm->Lconnected?'y':'n',Ltermio->c_cflag & CLOCAL?1:0);
  1283. X        ecu_log_event((int)xmtr_pid,s128);
  1284. X        pprintf("%s\n",s128);
  1285. X    }
  1286. X#endif
  1287. X
  1288. X}    /* end of lCLOCAL */
  1289. X
  1290. X/*+-------------------------------------------------------------------------
  1291. X    ldcdwatch(flag) - set DCD watcher state
  1292. X--------------------------------------------------------------------------*/
  1293. Xvoid
  1294. Xldcdwatch(flag)
  1295. Xint flag;
  1296. X{
  1297. X    shm->Ldcdwatch = flag;
  1298. X    dcdwatch_set = 1;
  1299. X    lCLOCAL(!flag);
  1300. X}    /* end of ldcdwatch */
  1301. X
  1302. X/*+-------------------------------------------------------------------------
  1303. X    ldcdwatch_str(flagstr) - string version of ldcdwatch
  1304. X
  1305. Xreturn 0 if successful or -1 if bad flagstr
  1306. X--------------------------------------------------------------------------*/
  1307. Xint
  1308. Xldcdwatch_str(flagstr)
  1309. Xchar *flagstr;
  1310. X{
  1311. X    static STR_CLASSIFY sc[] = {
  1312. X        { "1",            1,DCDW_ON },
  1313. X        { "yes",        1,DCDW_ON },
  1314. X        { "on",            2,DCDW_ON },
  1315. X        { "0",            1,DCDW_ON },
  1316. X        { "no",            1,DCDW_OFF },
  1317. X        { "off",        3,DCDW_OFF },
  1318. X        { "terminate",    1,DCDW_TERMINATE },
  1319. X        { (char *)0,    0,-1 }
  1320. X    };
  1321. X    int token;
  1322. X
  1323. X    if((token = str_classify(sc,flagstr)) < 0)
  1324. X        return(-1);
  1325. X
  1326. X    ldcdwatch(token);
  1327. X    return(0);
  1328. X        
  1329. X}    /* end of ldcdwatch_str */
  1330. X
  1331. X/*+-------------------------------------------------------------------------
  1332. X    lzero_length_read_detected() - read from line returned zero length
  1333. X
  1334. XThis must mean CLOCAL was off and DCD is/went low.  We do different things
  1335. Xdepending in the xmtr and rcvr process
  1336. X
  1337. XIf we return, the condition has ben handled and reads may be retried
  1338. Xsafely or other appropriate operations performed; otherwise ECU is
  1339. Xterminated.
  1340. X--------------------------------------------------------------------------*/
  1341. Xvoid
  1342. Xlzero_length_read_detected()
  1343. X{
  1344. X
  1345. X    zero_length_read_detected = 1;
  1346. X    if(getpid() == xmtr_pid)    /* if we are in the transmitter */
  1347. X    {
  1348. X#ifdef DEBUG_CLOCAL
  1349. X        ecu_log_event((int)xmtr_pid,"lzero xmtr");
  1350. X        pprintf("lzero xmtr\n");
  1351. X#endif
  1352. X        if(shm->Lconnected)
  1353. X        {
  1354. X            extern ulong colors_current;
  1355. X            ulong colors_at_entry = colors_current;
  1356. X
  1357. X            fputs("\r\n",se);
  1358. X            setcolor(colors_notify);
  1359. X            fputs("[connection terminated]",se);
  1360. X            setcolor(colors_at_entry);
  1361. X            fputs("\r\n",se);
  1362. X            DCE_now_on_hook();    /* does a lCLOCAL(1); */
  1363. X        }
  1364. X        else
  1365. X            lCLOCAL(1);
  1366. X        Nap(1000L);
  1367. X        lflush(2);
  1368. X
  1369. X        if(shm->Ldcdwatch == DCDW_TERMINATE)
  1370. X            termecu(0);
  1371. X        shmx_unpause_rcvr();
  1372. X    }
  1373. X    else    /* we are in the receiver */
  1374. X    {
  1375. X#ifdef DEBUG_CLOCAL
  1376. X        ecu_log_event((int)xmtr_pid,"lzero rcvr");
  1377. X        pprintf("lzero rcvr\n");
  1378. X#endif
  1379. X        /*
  1380. X         * make line "safe" to read from immediately;
  1381. X         * however, if CLOCAL was set and we get a zero length read,
  1382. X         * we are in some kind of unknown trouble
  1383. X         */
  1384. X        if(Ltermio->c_cflag & CLOCAL)    /* zero len read with CLOCAL? */
  1385. X        {                                /* then die ECU */
  1386. X            errno = EIO;
  1387. X            termecu(TERMECU_LINE_READ_ERROR);
  1388. X        }
  1389. X        lCLOCAL(1);
  1390. X        shmr_notify_xmtr_of_DCD_loss();
  1391. X        pause();        /* wait for unpause */
  1392. X    }
  1393. X
  1394. X}    /* end of lzero_length_read_detected */
  1395. X
  1396. X/* vi: set tabstop=4 shiftwidth=4: */
  1397. X/* end of eculine.c */
  1398. SHAR_EOF
  1399. echo 'File eculine.c is complete' &&
  1400. chmod 0644 eculine.c ||
  1401. echo 'restore of eculine.c failed'
  1402. Wc_c="`wc -c < 'eculine.c'`"
  1403. test 39681 -eq "$Wc_c" ||
  1404.     echo 'eculine.c: original size 39681, current size' "$Wc_c"
  1405. rm -f _shar_wnt_.tmp
  1406. fi
  1407. # ============= eculock.c ==============
  1408. if test -f 'eculock.c' -a X"$1" != X"-c"; then
  1409.     echo 'x - skipping eculock.c (File already exists)'
  1410.     rm -f _shar_wnt_.tmp
  1411. else
  1412. > _shar_wnt_.tmp
  1413. echo 'x - extracting eculock.c (Text)'
  1414. sed 's/^X//' << 'SHAR_EOF' > 'eculock.c' &&
  1415. X#define HONEYDANBER /* means use ASCII pids in lock files */
  1416. X#if defined(SHARE_DEBUG)
  1417. X#define LOG_LOCKS
  1418. X#endif
  1419. X/*+-----------------------------------------------------------------------
  1420. X    eculock.c -- lock file management
  1421. X    wht@n4hgf.Mt-Park.GA.US
  1422. X
  1423. X  Defined functions:
  1424. X    create_lock_file(name)
  1425. X    lock_tty(line)
  1426. X    unlock_tty(line)
  1427. X
  1428. XLock files under SCO are supposed to use the direct line name
  1429. X(lower-case last letter); we create only the lower-case case, but
  1430. Xcheck for both.  I have most definitely seen somebody create an
  1431. Xupper-case lock file (somebody named getty).  But that was on a middle-
  1432. Xaged XENIX revision.
  1433. X------------------------------------------------------------------------*/
  1434. X/*+:EDITS:*/
  1435. X/*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 */
  1436. X/*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  1437. X/*:07-19-1992-22:09-wht@n4hgf-rename check_utmp to reserve_line and move it */
  1438. X/*:07-19-1992-21:54-wht@n4hgf-lock_tty does not effect ungetty_get anymore */
  1439. X/*:08-25-1991-14:39-wht@n4hgf-SVR4 port thanks to aega84!lh */
  1440. X/*:08-10-1991-17:39-wht@n4hgf-US_WEGOTIT handling */
  1441. X/*:08-09-1991-11:07-wht@n4hgf-configurable lock directory */
  1442. X/*:07-25-1991-12:56-wht@n4hgf-ECU release 3.10 */
  1443. X/*:10-16-1990-20:43-wht@n4hgf-add SHARE_DEBUG */
  1444. X/*:09-19-1990-19:36-wht@n4hgf-ecu_log_event now gets pid for log from caller */
  1445. X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  1446. X
  1447. X#include "ecu.h"
  1448. X
  1449. Xextern int errno;
  1450. Xextern char ungetty_ttyname[];
  1451. Xextern char lopen_err_str[];
  1452. X
  1453. X/*+-------------------------------------------------------------------------
  1454. X    create_lock_file(name)
  1455. X--------------------------------------------------------------------------*/
  1456. Xint
  1457. Xcreate_lock_file(name)
  1458. Xchar *name;
  1459. X{
  1460. X    register fd;
  1461. X    int pid = getpid();
  1462. X    char LTMP_fname[64];
  1463. X#if defined(HONEYDANBER)
  1464. X    char pid10str[12];
  1465. X#endif
  1466. X
  1467. X    errno = 0;
  1468. X    sprintf(LTMP_fname,"%s/LTMP.%05d",lock_dir_name,pid);
  1469. X    if((fd = creat(LTMP_fname,0444)) < 0)
  1470. X    {
  1471. X        if(errno == EACCES)
  1472. X        {
  1473. X            strcpy(lopen_err_str,"lock error - try chmod 0777 ");
  1474. X            strcat(lopen_err_str,lock_dir_name);
  1475. X        }
  1476. X        unlink(LTMP_fname);
  1477. X        return(-1);
  1478. X    }
  1479. X#if defined(HONEYDANBER)
  1480. X    sprintf(pid10str,"%10d\n",getpid());
  1481. X    write(fd,pid10str,11);
  1482. X#else
  1483. X    write(fd,(char *)&pid,sizeof(int));
  1484. X#endif
  1485. X
  1486. X    chmod(LTMP_fname,0444);    /* some programs seem to think writable
  1487. X                             * lock file is game for killing
  1488. X                             */
  1489. X    close(fd);
  1490. X
  1491. X    fd = link(LTMP_fname,name);        /* use 'fd' for link return code */
  1492. X    unlink(LTMP_fname);
  1493. X    chmod(name,0444);
  1494. X
  1495. X#if defined(LOG_LOCKS)
  1496. X    {
  1497. X        char s128[128];
  1498. X        extern char *errno_text();
  1499. X        sprintf(s128,"CRLOCK %s status=%d errno=%s",name,fd,errno_text(errno));
  1500. X        ecu_log_event(getpid(),s128);
  1501. X    }
  1502. X#endif
  1503. X
  1504. X    return(fd);
  1505. X}    /* end of create_lock_file */
  1506. X
  1507. X/*+-------------------------------------------------------------------------
  1508. X    lock_tty(line) - create lock files for tty line in 'line'
  1509. X
  1510. Xreturn 0 if locked else LINST_... error
  1511. X--------------------------------------------------------------------------*/
  1512. Xint
  1513. Xlock_tty(line)
  1514. Xchar *line;
  1515. X{
  1516. X    register linst = 0;
  1517. X    char lockname[128];
  1518. X
  1519. X    lockname[0] = 0;
  1520. X    errno = 0;
  1521. X
  1522. X    if(linst = make_lock_name(line,lockname))
  1523. X        goto RETURN;
  1524. X
  1525. X
  1526. X    if(create_lock_file(lockname))
  1527. X    {
  1528. X        if(linst = is_active_lock(lockname))
  1529. X        {
  1530. X            if(linst == LINST_WEGOTIT)
  1531. X            {
  1532. X                linst = 0;
  1533. X                goto RETURN;
  1534. X            }
  1535. X            ungetty_return_line(line);
  1536. X            errno = EACCES; /* for termecu() */
  1537. X            goto RETURN;
  1538. X        }
  1539. X        if(create_lock_file(lockname))
  1540. X        {
  1541. X            ungetty_return_line(line);
  1542. X            errno = EACCES; /* for termecu() */
  1543. X            {
  1544. X                linst = LINST_LCKERR;
  1545. X                goto RETURN;
  1546. X            }
  1547. X        }
  1548. X    }
  1549. X
  1550. XRETURN: ;
  1551. X
  1552. X#if defined(LOG_LOCKS)
  1553. X    {
  1554. X        extern char *errno_text();
  1555. X        char s128[128];
  1556. X        sprintf(s128,"LOCKTTY %s status %d errno=%s",line,
  1557. X            linst,errno_text(errno));
  1558. X        ecu_log_event(getpid(),s128);
  1559. X    }
  1560. X#endif
  1561. X
  1562. X    return(linst);
  1563. X
  1564. X}    /* end of lock_tty */
  1565. X
  1566. X/*+-----------------------------------------------------------------------
  1567. X    void unlock_tty(line)
  1568. X------------------------------------------------------------------------*/
  1569. Xvoid
  1570. Xunlock_tty(line)
  1571. Xchar *line;
  1572. X{
  1573. X    char lockname[128];
  1574. X
  1575. X    if(make_lock_name(line,lockname))
  1576. X    {
  1577. X        ff(se,"unlock_tty cannot build lock file for %s\r\n",line);
  1578. X        termecu(TERMECU_LOGIC_ERROR);
  1579. X    }
  1580. X
  1581. X    ungetty_return_line(line);
  1582. X    unlink(lockname);
  1583. X
  1584. X}    /* end of unlock_tty */
  1585. X
  1586. X/* end of eculock.c */
  1587. X/* vi: set tabstop=4 shiftwidth=4: */
  1588. SHAR_EOF
  1589. chmod 0644 eculock.c ||
  1590. echo 'restore of eculock.c failed'
  1591. Wc_c="`wc -c < 'eculock.c'`"
  1592. test 4275 -eq "$Wc_c" ||
  1593.     echo 'eculock.c: original size 4275, current size' "$Wc_c"
  1594. rm -f _shar_wnt_.tmp
  1595. fi
  1596. # ============= ecunumrev.c ==============
  1597. if test -f 'ecunumrev.c' -a X"$1" != X"-c"; then
  1598.     echo 'x - skipping ecunumrev.c (File already exists)'
  1599.     rm -f _shar_wnt_.tmp
  1600. else
  1601. > _shar_wnt_.tmp
  1602. echo 'x - extracting ecunumrev.c (Text)'
  1603. sed 's/^X//' << 'SHAR_EOF' > 'ecunumrev.c' &&
  1604. X/* #define ALPHA */
  1605. X/* #define BETA */
  1606. X/*+-----------------------------------------------------------------------
  1607. X    ecunumrev.c - revision numbers
  1608. X    wht@n4hgf.Mt-Park.GA.US
  1609. X
  1610. X  Defined functions:
  1611. X    build_revision_string()
  1612. X
  1613. X------------------------------------------------------------------------*/
  1614. X/*+:EDITS:*/
  1615. X/*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 */
  1616. X/*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  1617. X/*:11-16-1991-17:05-wht@n4hgf-better development "x" rev numbering */
  1618. X/*:08-28-1991-14:07-wht@n4hgf2-SVR4 cleanup by aega84!lh */
  1619. X/*:08-25-1991-14:39-wht@n4hgf-SVR4 port thanks to aega84!lh */
  1620. X/*:07-25-1991-12:56-wht@n4hgf-ECU release 3.10 */
  1621. X/*:07-12-1991-14:14-wht@n4hgf-GCC140 differentiation */
  1622. X/*:04-27-1991-01:52-wht@n4hgf-overhaul revision numbers */
  1623. X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  1624. X
  1625. X#include <stdio.h>
  1626. X#include <string.h>
  1627. X#include <malloc.h>
  1628. X#include "patchlevel.h"
  1629. X
  1630. X#if defined(M_UNIX)
  1631. X#undef M_XENIX
  1632. X#endif
  1633. X
  1634. Xchar *numeric_revision = "3";
  1635. X
  1636. X/*
  1637. X * this is not a patchlevel, but a "sub-patchlevel" to keep my life sane
  1638. X */
  1639. X#if defined(WHT) || defined(ALPHA) || defined(BETA)
  1640. Xchar *numeric_devrev = "00";
  1641. X#else
  1642. Xchar *numeric_devrev = "";
  1643. X#endif
  1644. Xchar *revstr = "";
  1645. X
  1646. X/*+-------------------------------------------------------------------------
  1647. X    build_revision_string()
  1648. X--------------------------------------------------------------------------*/
  1649. Xvoid
  1650. Xbuild_revision_string()
  1651. X{
  1652. X    int itmp;
  1653. X    char s128[128];
  1654. X
  1655. X    sprintf(s128,"%s%s.%02d",
  1656. X        (itmp = strlen(numeric_devrev)) ? 
  1657. X#ifdef ALPHA
  1658. X            "ALPHA-"
  1659. X#else
  1660. X#ifdef BETA
  1661. X            "BETA-"
  1662. X#else
  1663. X            "x"
  1664. X#endif
  1665. X#endif
  1666. X            : "",
  1667. X        numeric_revision,PATCHLEVEL);
  1668. X
  1669. X    if(itmp)
  1670. X    {
  1671. X        strcat(s128,".");
  1672. X        strcat(s128,numeric_devrev);
  1673. X    }
  1674. X
  1675. X    strcat(s128,"-");
  1676. X
  1677. X#if defined(M_I286)
  1678. X    strcat(s128,"286");
  1679. X#else
  1680. X#if defined(M_I386) || defined(i386) && (!defined(sun) && !defined(SVR4))
  1681. X    strcat(s128,"386");
  1682. X#    if defined(M_XENIX)
  1683. X#        if defined(WORKING_SELECT)
  1684. X             strcat(s128,"s");
  1685. X#        else
  1686. X             strcat(s128,"n");
  1687. X#        endif /* WORKING_SELECT */
  1688. X#    endif /* M_XENIX */
  1689. X#    if defined(M_UNIX)
  1690. X        strcat(s128,"u");
  1691. X#    endif /* M_UNIX */
  1692. X#    if defined(ISC)
  1693. X        strcat(s128,"i");
  1694. X#    endif /* ISC */
  1695. X#else
  1696. X#if defined(sun)
  1697. X    strcat(s128,"sun");
  1698. X#else
  1699. X#if defined(SVR4)
  1700. X#   if defined(ESIXSVR4)
  1701. X#      define found_one
  1702. X       strcat(s128,"eSVR4");
  1703. X#   endif
  1704. X#   if defined(ISCSVR4)
  1705. X#      define found_one
  1706. X       strcat(s128,"iSVR4");
  1707. X#   endif
  1708. X#   if !defined(found_one)
  1709. X       strcat(s128,"SVR4");
  1710. X#   endif /* found_one */
  1711. X#   undef    found_one
  1712. X#else
  1713. Xporting_attention_needed_here;
  1714. X#endif /* SVR4 */
  1715. X#endif /* sun */
  1716. X#endif /* M_I386 || i386 */
  1717. X#endif /* M_I286 */
  1718. X
  1719. X#if defined(__GNUC__)
  1720. X#if defined(GCC140)
  1721. X    strcat(s128,"G");
  1722. X#else
  1723. X    strcat(s128,"g");
  1724. X#endif
  1725. X#if __STDC__
  1726. X    strcat(s128,"A");
  1727. X#endif
  1728. X#endif /*  */
  1729. X
  1730. X#ifdef WHT
  1731. X    strcat(s128,"*");
  1732. X#endif /* WHT */
  1733. X
  1734. X#ifndef CONFIG
  1735. X    strcat(s128," wht@n4hgf");
  1736. X#endif
  1737. X
  1738. X    if(!(revstr = malloc(strlen(s128) + 1)))
  1739. X    {
  1740. X        fprintf(stderr,"out of memory so early!?\n");
  1741. X        exit(255);
  1742. X    }
  1743. X    strcpy(revstr,s128);
  1744. X
  1745. X}    /* end of build_revision_string */
  1746. X
  1747. X/* vi: set tabstop=4 shiftwidth=4: */
  1748. SHAR_EOF
  1749. chmod 0644 ecunumrev.c ||
  1750. echo 'restore of ecunumrev.c failed'
  1751. Wc_c="`wc -c < 'ecunumrev.c'`"
  1752. test 3060 -eq "$Wc_c" ||
  1753.     echo 'ecunumrev.c: original size 3060, current size' "$Wc_c"
  1754. rm -f _shar_wnt_.tmp
  1755. fi
  1756. # ============= ecupde.c ==============
  1757. if test -f 'ecupde.c' -a X"$1" != X"-c"; then
  1758.     echo 'x - skipping ecupde.c (File already exists)'
  1759.     rm -f _shar_wnt_.tmp
  1760. else
  1761. > _shar_wnt_.tmp
  1762. echo 'x - extracting ecupde.c (Text)'
  1763. sed 's/^X//' << 'SHAR_EOF' > 'ecupde.c' &&
  1764. X/*+-------------------------------------------------------------------------
  1765. X    ecupde.c - various PDE-related functions
  1766. X    wht@n4hgf.Mt-Park.GA.US
  1767. X
  1768. X  Defined functions:
  1769. X    call_logical_telno(logical)
  1770. X    choose_tty_for_pde(tpde)
  1771. X    copy_pde_to_Lvariables(tpde,trial)
  1772. X    logical_telno_to_pde(logical)
  1773. X    pde_dial(tpde)
  1774. X    pdetty_to_devtty(pdetty,devtty)
  1775. X    phdir_list_read()
  1776. X
  1777. X--------------------------------------------------------------------------*/
  1778. X/*+:EDITS:*/
  1779. X/*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 */
  1780. X/*:09-05-1992-14:17-wht@n4hgf-was starting rcvr process too early on connect */
  1781. X/*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  1782. X/*:05-13-1992-13:27-wht@n4hgf-active_pde use */
  1783. X/*:04-24-1992-21:59-wht@n4hgf-more SCO tty name normalizing */
  1784. X/*:12-02-1991-20:58-wht@n4hgf-breakout into separate module */
  1785. X
  1786. X#include "ecu.h"
  1787. X#include "esd.h"
  1788. X#include "var.h"
  1789. X#include "ecupde.h"
  1790. X#include "dvent.h"
  1791. X#include "termecu.h"
  1792. X#include "ecuerror.h"
  1793. X#include "utmpstatus.h"
  1794. X
  1795. XDVE *hdb_choose_Any();
  1796. XDVE *hdb_choose_Device();
  1797. XPDE *phdir_list_search();
  1798. Xchar *linst_err_text();
  1799. X
  1800. Xextern char errmsg[];
  1801. Xextern char *default_tty;
  1802. Xextern int windows_active;
  1803. X
  1804. Xchar phonedir_name[PHONEDIR_NAME_SIZE];
  1805. Xchar *phonedir_trigger = "#ECUPHONE\n";
  1806. X
  1807. X/*+-----------------------------------------------------------------------
  1808. X    phdir_list_read()
  1809. X
  1810. Xreturn 0 if entire list read, else 1 if error (error msg in errmsg)
  1811. X
  1812. Xif file does not exist, create it, asking confirm only if in
  1813. Xinteractive (curses) mode
  1814. X------------------------------------------------------------------------*/
  1815. Xint
  1816. Xphdir_list_read()
  1817. X{
  1818. X    register token_number;
  1819. X    register char *cptr;
  1820. X    register char *token;
  1821. X    int itmp;
  1822. X    char readpde_buf[128];
  1823. X    FILE *fp_phone;
  1824. X    PDE *tpde;
  1825. X    char *str_token();
  1826. X
  1827. X    if(!phonedir_name[0])
  1828. X    {
  1829. X        get_home_dir(phonedir_name);
  1830. X        strcat(phonedir_name,"/.ecu/phone");
  1831. X    }
  1832. X
  1833. XTRY_OPEN:
  1834. X    if(!(fp_phone = fopen(phonedir_name,"r")))
  1835. X    {
  1836. X        if(errno == ENOENT)
  1837. X        {
  1838. X            if(!want_pd_create(phonedir_name))
  1839. X            {
  1840. X                strcpy(errmsg,"non-existent file not created");
  1841. X                return(1);
  1842. X            }
  1843. X            if((itmp = open(phonedir_name,
  1844. X                O_RDWR | O_CREAT | O_TRUNC,0600)) >= 0)
  1845. X            {
  1846. X                write(itmp,phonedir_trigger,strlen(phonedir_trigger));
  1847. X                close(itmp);
  1848. X                if(windows_active)    /* if called under curses */
  1849. X                {
  1850. X                    dirw_bot_msg("created new (empty) directory file");
  1851. X                    ring_bell();
  1852. X                    Nap(1000L);
  1853. X                }
  1854. X                goto TRY_OPEN;
  1855. X            }
  1856. X            if(errno == ENOENT)
  1857. X            {
  1858. X                strcpy(errmsg,"~/.ecu directory nonexistent!");
  1859. X                ring_bell();
  1860. X                return(1);
  1861. X            }
  1862. X        }
  1863. X        strcpy(errmsg,errno_text(errno));
  1864. X        return(1);
  1865. X    }
  1866. X
  1867. X/* we have an open directory file */
  1868. X    if(!fgets(readpde_buf,sizeof(readpde_buf),fp_phone) ||
  1869. X        strcmp(readpde_buf,phonedir_trigger))
  1870. X    {
  1871. X        fclose(fp_phone);
  1872. X        strcpy(errmsg,"not an ECU phone directory (or is pre-rev-3)");
  1873. X        ring_bell();
  1874. X        return(1);
  1875. X    }
  1876. X
  1877. X    dirw_display_phonedir_name();
  1878. X    phdir_list_erase();        /* clear any previous directory */
  1879. X    while(fgets(readpde_buf,sizeof(readpde_buf),fp_phone))
  1880. X    {
  1881. X        if(readpde_buf[0] == '#')        /* comment? */
  1882. X            continue;
  1883. X        if(itmp = strlen(readpde_buf))    /* itmp = len; if > 0 ... */
  1884. X        {
  1885. X            itmp--;
  1886. X            readpde_buf[itmp] = 0;        /* ... strip trailing NL */
  1887. X        }
  1888. X        cptr = readpde_buf;                /* first call to str_token, -> buff */
  1889. X        while((*cptr == 0x20) || (*cptr == 0x09))
  1890. X            cptr++;                        /* strip leading spaces */
  1891. X        if(*cptr == 0)                    /* if line all blank, skip it */
  1892. X            continue;
  1893. X
  1894. X        if(!(tpde = (PDE *)malloc(sizeof(PDE ))))
  1895. X        {
  1896. X            fclose(fp_phone);
  1897. X            strcpy(errmsg,"Out of memory reading phone list");
  1898. X            return(1);
  1899. X        }
  1900. X
  1901. X        tpde->descr[0] = 0;
  1902. X        tpde->logical[0] = 0;
  1903. X        tpde->telno[0] = 0;
  1904. X        tpde->tty[0] = 0;
  1905. X        tpde->parity = 0;
  1906. X        tpde->baud = 2400;
  1907. X        tpde->redial = 0;
  1908. X        tpde->prev = (PDE *)0;
  1909. X        tpde->next = (PDE *)0;
  1910. X        tpde->debug_level = 0;
  1911. X        tpde->dcdwatch = 'n';        /* do not modify shm->Ldcdwatch */
  1912. X
  1913. X        token_number = 0;
  1914. X        while((token = str_token(cptr,":")))
  1915. X        {
  1916. X            cptr = (char *)0;    /* further calls to str_token need NULL */
  1917. X            switch(token_number)
  1918. X            {
  1919. X                case 0:        /* first field is logical name */
  1920. X                    strncpy(tpde->logical,token,sizeof(tpde->logical));
  1921. X                    tpde->logical[sizeof(tpde->logical) - 1] = 0;
  1922. X                    break;
  1923. X                case 1:        /* second field is tpde->telno phone number */
  1924. X                    strncpy(tpde->telno,token,sizeof(tpde->telno));
  1925. X                    tpde->telno[sizeof(tpde->telno) - 1] = 0;
  1926. X                    break;
  1927. X                case 2:        /* third field is line */
  1928. X                    strncpy(tpde->tty,token,sizeof(tpde->tty));
  1929. X                    tpde->tty[sizeof(tpde->tty) - 1] = 0;
  1930. X                    break;
  1931. X                case 3:        /* fourth field is baud rate */
  1932. X                    tpde->baud = atoi(token);
  1933. X                    break;
  1934. X                case 4:        /* fifth field is parity */
  1935. X                    switch(itmp = to_lower(token[0]))
  1936. X                    {
  1937. X                        case 'o':
  1938. X                        case 'e':
  1939. X                        case 'm':
  1940. X                        case 's':
  1941. X                            tpde->parity = itmp;
  1942. X                            break;
  1943. X                        default:
  1944. X                        case 'n':
  1945. X                            tpde->parity = 0;
  1946. X                            break;
  1947. X                    }
  1948. X                    break;
  1949. X                case 5:
  1950. X                    strncpy(tpde->descr,token,sizeof(tpde->descr));
  1951. X                    tpde->descr[sizeof(tpde->descr) - 1] = 0;
  1952. X                    break;
  1953. X                case 6:
  1954. X                    if((tpde->debug_level = (uchar)atoi(token)) > 9)
  1955. X                        tpde->debug_level = 9;
  1956. X                    break;
  1957. X                case 7:
  1958. X                    tpde->dcdwatch = to_lower(token[0]);
  1959. X                    break;
  1960. X            }    /* end of switch(token_number) */
  1961. X            token_number++;
  1962. X        }        /* end while not end of record */
  1963. X
  1964. X        phdir_list_add(tpde);
  1965. X
  1966. X    }            /* while records left to ready */
  1967. X
  1968. X    fclose(fp_phone);
  1969. X    return(0);
  1970. X}    /* end of phdir_list_read */
  1971. X
  1972. X/*+-------------------------------------------------------------------------
  1973. X    pde_dial(tpde) - dial using a pde (using procedure if configured)
  1974. X
  1975. XIf the tpde->logical points to a valid procedure, use it,
  1976. Xotherwise call DCE_dial()
  1977. X
  1978. Xreturns proc error code
  1979. X        $i0 value ($s0 is also set, BTW)
  1980. X
  1981. Xassumes rcvr process dead (rcvr_pid == -1)
  1982. X--------------------------------------------------------------------------*/
  1983. Xint
  1984. Xpde_dial(tpde)
  1985. Xregister PDE *tpde;
  1986. X{
  1987. X    int status = 0;
  1988. X    int restart_rcvr = need_rcvr_restart();
  1989. X    char *cptr;
  1990. X    extern int dcdwatch_set;    /* see ldcdwatch() in eculine.c */
  1991. X
  1992. X    dcdwatch_set = 0;
  1993. X
  1994. X    kill_rcvr_process(SIGUSR1);
  1995. X
  1996. X    if(proc_level || !find_procedure(tpde->logical))
  1997. X    {
  1998. X        if(copy_pde_to_Lvariables(tpde,0))
  1999. X        {
  2000. X            pprintf("%s: %s\n",tpde->logical,errmsg);
  2001. X            pprintf("Current line is %s (%s)\n",
  2002. X                shm->Lline,(shm->Liofd < 0) ? "closed" : "open");
  2003. X            status = eFATAL_ALREADY;
  2004. X        }
  2005. X        else
  2006. X            status = DCE_dial();
  2007. X    }
  2008. X    else
  2009. X    {
  2010. X        char *pargv[2];
  2011. X        pargv[0] = tpde->logical;
  2012. X        pargv[1] = "!MENU";
  2013. X        iv[0] = 0;
  2014. X        if(do_proc(2,pargv))
  2015. X            status = eFATAL_ALREADY;
  2016. X        else
  2017. X            status = (iv[0]) ? eConnectFailed : 0;
  2018. X    }
  2019. X
  2020. X    /*
  2021. X     * if we connected and a procedure did not change the DCD watcher,
  2022. X     * then use the dialing directory choice
  2023. X     */
  2024. X    if(!status && !dcdwatch_set)
  2025. X    {
  2026. X        cptr = (char *)0;
  2027. X        switch(tpde->dcdwatch)
  2028. X        {
  2029. X            case '0':    
  2030. X                ldcdwatch(DCDW_OFF); 
  2031. X                cptr = "OFF (ignore DCD loss)";
  2032. X                break;
  2033. X            case '1':    
  2034. X                ldcdwatch(DCDW_ON); 
  2035. X                cptr = "ON (detect DCD loss)";
  2036. X                break;
  2037. X            case 't':    
  2038. X                ldcdwatch(DCDW_TERMINATE); 
  2039. X                cptr = "TERMINATE (terminate ecu on DCD loss)";
  2040. X                break;
  2041. X            case 'n':    
  2042. X            default:    
  2043. X                break;
  2044. X        }
  2045. X        if(cptr)
  2046. X        {
  2047. X            ulong colors_save;
  2048. X            colors_save = colors_current;
  2049. X            setcolor(colors_notify);
  2050. X            pprintf("[DCD watcher set to %s]",cptr);
  2051. X            setcolor(colors_save);
  2052. X            fputs("\r\n",se);
  2053. X            pputs("\n");
  2054. X        }
  2055. X    }
  2056. X
  2057. X    if(restart_rcvr)
  2058. X        start_rcvr_process(1);
  2059. X
  2060. X    return(status);
  2061. X
  2062. X}    /* end of pde_dial */
  2063. X
  2064. X/*+-------------------------------------------------------------------------
  2065. X    pdetty_to_devtty(pdetty,devtty) -> pde tty field to complete pathname
  2066. X--------------------------------------------------------------------------*/
  2067. Xvoid
  2068. Xpdetty_to_devtty(pdetty,devtty)
  2069. Xchar *pdetty;
  2070. Xchar *devtty;
  2071. X{
  2072. X    strcpy(devtty,"/dev/");
  2073. X#ifdef M_SYSV
  2074. X    if(strncmp(pdetty,"tty",3))
  2075. X        strcat(devtty,"tty");
  2076. X#endif
  2077. X    strcat(devtty,pdetty);
  2078. X
  2079. X}    /* end of pdetty_to_devtty */
  2080. X
  2081. X/*+-------------------------------------------------------------------------
  2082. X    choose_tty_for_pde(tpde) - new pde might mandate switching line
  2083. X
  2084. XReturns 1 if new line open needed
  2085. X        0 if no new line open needed
  2086. X       -1 if request cannot be satisfied
  2087. X--------------------------------------------------------------------------*/
  2088. Xint
  2089. Xchoose_tty_for_pde(tpde)
  2090. Xregister PDE *tpde;
  2091. X{
  2092. X    int itmp = 0;
  2093. X    int rtn = 0;
  2094. X    DVE *tdve;
  2095. X    char newtty[64];
  2096. X
  2097. X#ifdef CHOOSE_DEBUG
  2098. X    char s256[256];
  2099. X    sprintf(s256,"choose_tty_for_pde '%s' %u",tpde->tty,tpde->baud);
  2100. X    ecu_log_event((int)xmtr_pid,s256);
  2101. X    errmsg[0] = 0;
  2102. X#endif
  2103. X
  2104. X    /*
  2105. X     * if desired line is Devices type 
  2106. X     */
  2107. X    if((tpde->tty[0] == '=') || (tpde->tty[0] == '/')) /* Devices device type */
  2108. X    {
  2109. X        if(!(tdve = hdb_choose_Device(tpde->tty,tpde->baud)))
  2110. X        {
  2111. X            sprintf(errmsg,"no idle line matches type '%s' at %u baud",
  2112. X                *tpde->tty ? tpde->tty : "Any",tpde->baud);
  2113. X            rtn = -1;
  2114. X            goto RETURN;
  2115. X        }
  2116. X        sprintf(newtty,"/dev/%s",tdve->line);
  2117. X        if((itmp = lock_tty(newtty)) && (itmp != LINST_WEGOTIT))
  2118. X        {
  2119. X            sprintf(errmsg,"%s (%s): %s",
  2120. X                tpde->tty,tdve->line,linst_err_text(itmp));
  2121. X            rtn = -1;
  2122. X            goto RETURN;
  2123. X        }
  2124. X        if((itmp = reserve_line(newtty)) && (itmp != LINST_WEGOTIT))
  2125. X        {
  2126. X            sprintf(errmsg,"%s: %s",newtty,linst_err_text(itmp));
  2127. X            rtn = -1;
  2128. X            goto RETURN;
  2129. X        }
  2130. X    }
  2131. X    /*
  2132. X     * if desired line is a specific tty
  2133. X     */
  2134. X    else if(tpde->tty[0])
  2135. X    {
  2136. X        pdetty_to_devtty(tpde->tty,newtty);
  2137. X        if((shm->Liofd > 0) && !strcmp(newtty,shm->Lline))
  2138. X        {
  2139. X            rtn = 0;    /* requesting line we already have */
  2140. X            goto RETURN;
  2141. X        }
  2142. X        if((itmp = lock_tty(newtty)) && (itmp != LINST_WEGOTIT))
  2143. X        {
  2144. X            sprintf(errmsg,"%s: %s",newtty,linst_err_text(itmp));
  2145. X            rtn = -1;
  2146. X            goto RETURN;
  2147. X        }
  2148. X        if((itmp = reserve_line(newtty)) && (itmp != LINST_WEGOTIT))
  2149. X        {
  2150. X            sprintf(errmsg,"%s: %s",newtty,linst_err_text(itmp));
  2151. X            rtn = -1;
  2152. X            goto RETURN;
  2153. X        }
  2154. X    }
  2155. X    /*
  2156. X     * if desired line is "Any" (any Devices type beginning with ACU)
  2157. X     */
  2158. X    else    /* "Any" */
  2159. X    {
  2160. X        tdve = hdb_choose_Any(tpde->baud);
  2161. X        if(!tdve)
  2162. X        {
  2163. X            sprintf(errmsg,"no idle ACU line at %u baud",tpde->baud);
  2164. X            rtn = -1;
  2165. X            goto RETURN;
  2166. X        }
  2167. X        sprintf(newtty,"/dev/%s",tdve->line);
  2168. X        if((itmp = lock_tty(newtty)) && (itmp != LINST_WEGOTIT))
  2169. X        {
  2170. X            sprintf(errmsg,"%s: %s",newtty,linst_err_text(itmp));
  2171. X            rtn = -1;
  2172. X            goto RETURN;
  2173. X        }
  2174. X        if((itmp = reserve_line(newtty)) && (itmp != LINST_WEGOTIT))
  2175. X        {
  2176. X            sprintf(errmsg,"%s: %s",newtty,linst_err_text(itmp));
  2177. X            rtn = -1;
  2178. X            goto RETURN;
  2179. X        }
  2180. X    }
  2181. X
  2182. X    rtn = !(!strcmp(newtty,shm->Lline) && (shm->Liofd != -1));
  2183. X    if(rtn)
  2184. X    {
  2185. X        lclose();
  2186. X        strcpy(shm->Lline,newtty);
  2187. X    }
  2188. X
  2189. X
  2190. XRETURN:
  2191. X
  2192. X#ifdef CHOOSE_DEBUG
  2193. X    sprintf(s256,"choose_tty_for_pde rtn=%d line='%s' errmsg='%s' itmp=%d",
  2194. X        rtn,shm->Lline,errmsg,itmp);
  2195. X    ecu_log_event((int)xmtr_pid,s256);
  2196. X#endif
  2197. X
  2198. X    return(rtn);
  2199. X
  2200. X}    /* end of choose_tty_for_pde */
  2201. X
  2202. X/*+-------------------------------------------------------------------------
  2203. X    copy_pde_to_Lvariables(tpde,trial)
  2204. X
  2205. X'trial' controls whether this is a dry run (setup) or a live request
  2206. Xif changing line, close old line and open new one
  2207. Xif cannot change line, return -1, else 0
  2208. X--------------------------------------------------------------------------*/
  2209. Xint
  2210. Xcopy_pde_to_Lvariables(tpde,trial)
  2211. Xregister PDE *tpde;
  2212. Xint trial;
  2213. X{
  2214. X    int reopen = 0;
  2215. X    int lerr;
  2216. X    DVE *tdve;
  2217. X
  2218. X#ifdef CHOOSE_DEBUG
  2219. X    char s80[80];
  2220. X    sprintf(s80,"copy_pde trial=%d Lline='%s' pdetty='%s'",
  2221. X        trial,shm->Lline,tpde->tty);
  2222. X    ecu_log_event((int)xmtr_pid,s80);
  2223. X#endif
  2224. X
  2225. X    enddvent();    /* krock safety */
  2226. X
  2227. X    if(!trial)
  2228. X    {
  2229. X        if((reopen = choose_tty_for_pde(tpde)) < 0)
  2230. X            return(-1);        /* errmsg[] updated */
  2231. X    }
  2232. X    else if((!tpde->tty[0]) || (!strcmp(tpde->tty,"Any")))
  2233. X    {
  2234. X        if(!(tdve = hdb_choose_Any(tpde->baud)))
  2235. X        {
  2236. X            strcpy(errmsg,"no idle line matches type 'Any'");
  2237. X            return(-1);
  2238. X        }
  2239. X        strcpy(shm->Lline,"/dev/");
  2240. X        strncat(shm->Lline,tdve->line,sizeof(shm->Lline) - 5);
  2241. X        shm->Lline[sizeof(shm->Lline) - 1] = 0;
  2242. X    }
  2243. X    else if((tpde->tty[0] == '/') || (tpde->tty[0] == '='))
  2244. X    {
  2245. X        if(!(tdve = hdb_choose_Device(tpde->tty,tpde->baud)))
  2246. X        {
  2247. X            sprintf(errmsg,"no idle line matches type '%s' at %u baud",
  2248. X                *tpde->tty ? tpde->tty : "Any",tpde->baud);
  2249. X            return(-1);
  2250. X        }
  2251. X        strcpy(shm->Lline,"/dev/");
  2252. X        strncat(shm->Lline,tdve->line,sizeof(shm->Lline) - 5);
  2253. X        shm->Lline[sizeof(shm->Lline) - 1] = 0;
  2254. X    }
  2255. X    else
  2256. X        pdetty_to_devtty(tpde->tty,shm->Lline);
  2257. X
  2258. X#ifdef CHOOSE_DEBUG
  2259. X    sprintf(s80,"copy_pde 2  Lline='%s' reopen=%d",shm->Lline,reopen);
  2260. X    ecu_log_event((int)xmtr_pid,s80);
  2261. X#endif
  2262. X
  2263. X    shm->Lbaud = tpde->baud;    
  2264. X    strcpy(shm->Llogical,tpde->logical);
  2265. X    strcpy(shm->Ldescr,tpde->descr);
  2266. X    strcpy(shm->Ltelno,tpde->telno);
  2267. X    if(!shm->Ldescr[0])
  2268. X        strcpy(shm->Ldescr,shm->Llogical);
  2269. X    shm->Lparity = tpde->parity;
  2270. SHAR_EOF
  2271. true || echo 'restore of ecupde.c failed'
  2272. fi
  2273. echo 'End of ecu320 part 9'
  2274. echo 'File ecupde.c is continued in part 10'
  2275. echo 10 > _shar_seq_.tmp
  2276. exit 0
  2277.  
  2278. exit 0 # Just in case...
  2279.