home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume32 / ecu / part09 < prev    next >
Encoding:
Text File  |  1992-09-13  |  56.9 KB  |  2,273 lines

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