home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / ispin / part09 < prev    next >
Encoding:
Text File  |  1992-02-01  |  56.2 KB  |  1,516 lines

  1. Newsgroups: comp.sources.unix
  2. From: sir-alan!ispin!lbartz@iuvax.cs.indiana.edu (Larry Bartz)
  3. Subject: v25i120: Indianapolis Standard Printer Interface for Networked printers, Part09/15
  4. Sender: sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: sir-alan!ispin!lbartz@iuvax.cs.indiana.edu (Larry Bartz)
  8. Posting-Number: Volume 25, Issue 120
  9. Archive-Name: ispin/part09
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 9 (of 15)."
  18. # Contents:  ISPIN/src/ISPIN.c.ac ISPIN/doc/LPinstall.doc
  19. #   ISPIN/misc/ISPIT.dr/README ISPIN/misc/ISPIT.dr/passwd.entry
  20. # Wrapped by socrates@indy6 on Tue Jan 28 15:26:56 1992
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'ISPIN/src/ISPIN.c.ac' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'ISPIN/src/ISPIN.c.ac'\"
  24. else
  25. echo shar: Extracting \"'ISPIN/src/ISPIN.c.ac'\" \(30636 characters\)
  26. sed "s/^X//" >'ISPIN/src/ISPIN.c.ac' <<'END_OF_FILE'
  27. X        signal(SIGRES, SIG_IGN);     /* ignore "restart" signal */
  28. X        signal(SIGBACK, SIG_IGN);   /* ignore "back-up" signal */
  29. X        signal(SIGSTOP, my_error);   /* trap "stop" signal */
  30. X#endif
  31. X  
  32. X  time_out = 1;
  33. X  return;
  34. X}
  35. X
  36. X
  37. Xnegotiate()
  38. X{
  39. X  int got_chars = 0;    /* how many chars were read? */
  40. X  int n = 0;
  41. X  ushort not_yet = 1;       /* while loop controller */
  42. X
  43. X
  44. X
  45. X
  46. X  /* set all of our list pointers to point at heads of the lists */
  47. X  busy_list = busy_curr = busy_head;
  48. X  dead_list = dead_curr = dead_head;
  49. X  quit_list = quit_curr = quit_head;
  50. X  disc_list = disc_curr = disc_head;
  51. X  expt_list = expt_curr = expt_head;
  52. X  send_list = send_curr = send_head;
  53. X
  54. X  /* advise IQUEUER of our current state */
  55. X  notify(CONNECTING);
  56. X
  57. X  /* commence negotiations. Read from the output file (device) */
  58. X  /* don't read so many chars that there isn't room left to NULL terminate */
  59. X
  60. X  /* Maybe there is no EXPECT/SEND necessary for this printer */
  61. X  /* Configuring no EXPECT/SEND allows specification of direct connect printer */
  62. X  if(expt_curr->next != NULL)
  63. X  {
  64. X  while(not_yet)
  65. X  {
  66. X
  67. X        signal(SIGALRM, my_error);
  68. X  time_out = 0;         /* assume no timeout */
  69. X  alarm(30);            /* wait a few seconds for characters      */
  70. X
  71. X
  72. X    /* set the no delay bit so we can do a quickie read */
  73. X    /* fcntl(out_file,F_SETFL,flgs_ndelay); */
  74. X
  75. X    got_chars = read(out_file,in_buf,(BUFSIZ -1));
  76. X    
  77. X    /* turn the delay bit back on, so we can accomodate flow control */
  78. X    /* fcntl(out_file,F_SETFL,flgs_delay); */
  79. X
  80. X
  81. X
  82. X  alarm(0);      /* turn off the alarm clock */
  83. X        signal(SIGALRM, SIG_IGN);
  84. X
  85. X  if(got_chars <= 0)
  86. X  {
  87. X      strcpy(in_buf,"gOt nO cHaRaCtERs aT aLl, sO nO mAtCh");
  88. X  }
  89. X  else
  90. X  {
  91. X    /* NULL terminate the string we received */
  92. X    in_buf[got_chars] = '\0';
  93. X  }
  94. X
  95. X/*****************************************************************************/
  96. X/* get rid of the non-printable chars we received */
  97. X
  98. X  check_char = keep_char = 0;
  99. X
  100. X  while(in_buf[check_char] != '\0')
  101. X  {
  102. X    if(isprint(in_buf[check_char]))
  103. X    {
  104. X      in_buf[keep_char++] = in_buf[check_char];
  105. X    }
  106. X    ++check_char;
  107. X  }
  108. X  in_buf[keep_char] = '\0';
  109. X/*****************************************************************************/
  110. X
  111. X
  112. X  /* is this string what we are hoping for? */
  113. X
  114. X  /* go to (not goto!) the next EXPECT string */
  115. X  if(expt_curr->next == NULL)
  116. X  {
  117. X    /* need to send out an error msg */
  118. X          /* format an error message */
  119. X          time(&tloc);
  120. X          nowtime = (struct tm *)localtime(&tloc);
  121. X          time_str = asctime(nowtime);
  122. X
  123. X          sprintf(errmsg,"ISPIN: printer %s: EXPECT: couldn't match <<%s>>\n\n",dest,in_buf);
  124. X          sprintf(errmsg2,"    USER: %s\n",from);
  125. X          strcat(errmsg,errmsg2);
  126. X          if(usr_addr)
  127. X          {
  128. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  129. X            strcat(errmsg,errmsg2);
  130. X          }
  131. X          if(port_open == 1)
  132. X          {
  133. X            sprintf(errmsg2,"     DEV: %s\n",GO_dev);
  134. X            strcat(errmsg,errmsg2);
  135. X          }
  136. X#ifdef NQ
  137. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  138. X#else
  139. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  140. X#endif
  141. X          strcat(errmsg,errmsg2);
  142. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  143. X          strcat(errmsg,errmsg2);
  144. X
  145. X         /* call the error routine, never come back */
  146. X         my_error(SYSERR);
  147. X
  148. X  }
  149. X  expt_curr = expt_curr->next;
  150. X  
  151. X  /* is this an "expect nothing" EXPECT string? */
  152. X  if(strlen(expt_curr->expt_strg) != 0)
  153. X  {
  154. X
  155. X
  156. X    /* is this a compound EXPECT-SEND-EXPECT string? */
  157. X    cpnd_send = strchr(expt_curr->expt_strg,'-');
  158. X    if(cpnd_send != NULLCHARPTR)
  159. X    {
  160. X
  161. X
  162. X      /* we have at least one dash */ 
  163. X      cpnd_expt = strrchr(expt_curr->expt_strg,'-');
  164. X      if(cpnd_send != cpnd_expt)
  165. X      {
  166. X        /* we have at least two dashes */
  167. X        /* move our pointers past the dashes */
  168. X        ++cpnd_send;
  169. X        ++cpnd_expt;
  170. X        /* now parse our original into three */
  171. X              /* get the first one */
  172. X              /* how many characters before the first dash ? */
  173. X              /* Allocate memory to store the string and */
  174. X              /* aim our pointer at it.                  */
  175. X              /* Need one extra byte for the terminating NULL */
  176. X              n = strcspn(expt_curr->expt_strg,"-");
  177. X              expt1 = (char *) calloc(1, (n + 1));
  178. X              strncpy(expt1,expt_curr->expt_strg,n);
  179. X              expt1[n] = '\0';
  180. X
  181. X
  182. X
  183. X              /* get the next one */
  184. X              /* how many characters before the next dash ? */
  185. X              /* Allocate memory to store the string and */
  186. X              /* aim our pointer at it.                  */
  187. X              /* Need one extra byte for the terminating NULL */
  188. X              n = strcspn(cpnd_send,"-");
  189. X              c_send = (char *) calloc(1, (n + 1));
  190. X              strncpy(c_send,cpnd_send,n);
  191. X              c_send[n] = '\0';
  192. X
  193. X
  194. X
  195. X              /* get the third one */
  196. X              /* how many characters after the last dash ? */
  197. X              /* Allocate memory to store the string and */
  198. X              /* aim our pointer at it.                  */
  199. X              /* Need one extra byte for the terminating NULL */
  200. X              expt2 =  (char *) calloc(1, ((strlen(cpnd_expt))+1));
  201. X              strcpy(expt2,cpnd_expt);
  202. X
  203. X
  204. X
  205. X              /* compare the first EXPECT to what we got */
  206. X              if(matcher(in_buf,expt1) == 1)
  207. X              {
  208. X                /* not a match */
  209. X
  210. X
  211. X                /* compare to BUSY and DEAD (in separate functions)     */
  212. X
  213. X
  214. X
  215. X                n = busyordead();
  216. X
  217. X                /* If it is neither BUSY nor DEAD, send the internal SEND,  */
  218. X                /* read for the second EXPECT of the compound construct,    */
  219. X                /* and test the second EXPECT just as normal, non-compound  */
  220. X                /* EXPECT.                                                  */
  221. X
  222. X              /* Doesn't match, is neither BUSY nor DEAD */
  223. X
  224. X              /* send the imbedded send string */
  225. X
  226. X
  227. X              n = write_net(c_send);
  228. X
  229. X
  230. X
  231. X              /* what's the answer? */
  232. X
  233. X        signal(SIGALRM, my_error);
  234. X  time_out = 0;         /* assume no timeout */
  235. X  alarm(30);            /* wait a few seconds for characters      */
  236. X
  237. X
  238. X    /* set the no delay bit so we can do a quickie read */
  239. X    /* fcntl(out_file,F_SETFL,flgs_ndelay); */
  240. X
  241. X    got_chars = read(out_file,in_buf,(BUFSIZ -1));
  242. X    
  243. X    /* turn the delay bit back on, so we can accomodate flow control */
  244. X    /* fcntl(out_file,F_SETFL,flgs_delay); */
  245. X
  246. X
  247. X
  248. X  alarm(0);      /* turn off the alarm clock */
  249. X        signal(SIGALRM, SIG_IGN);
  250. X
  251. X
  252. X              if(got_chars <= 0)
  253. X              /* if((got_chars <= 0)||(time_out)) */
  254. X              {
  255. X                  strcpy(in_buf,"gOt nO cHaRaCtERs aT aLl, sO nO mAtCh");
  256. X              }
  257. X              else
  258. X              {
  259. X                /* NULL terminate the string we received */
  260. X                in_buf[got_chars] = '\0';
  261. X              }
  262. X
  263. X
  264. X
  265. X/*****************************************************************************/
  266. X/* get rid of the non-printable chars we received */
  267. X
  268. X  check_char = keep_char = 0;
  269. X
  270. X  while(in_buf[check_char] != '\0')
  271. X  {
  272. X    if(isprint(in_buf[check_char]))
  273. X    {
  274. X      in_buf[keep_char++] = in_buf[check_char];
  275. X    }
  276. X    ++check_char;
  277. X  }
  278. X  in_buf[keep_char] = '\0';
  279. X/*****************************************************************************/
  280. X              /* compare the second EXPECT to what we got */
  281. X              if(matcher(in_buf,expt2) == 1)
  282. X              {
  283. X                /* no match on the second EXPECT
  284. X                /* not a match */
  285. X                /* compare to BUSY and DEAD (in separate functions)     */
  286. X
  287. X                n = busyordead();
  288. X                /* Doesn't match, is neither BUSY nor DEAD */
  289. X
  290. X                /* need to send out an error msg */
  291. X                /* format an error message */
  292. X                time(&tloc);
  293. X                nowtime = (struct tm *)localtime(&tloc);
  294. X                time_str = asctime(nowtime);
  295. X
  296. X                sprintf(errmsg,"ISPIN: printer %s:\n   EXPECTED: <<%s>>\n   RECEIVED: <<%s>>\n\n",dest,expt2,in_buf);
  297. X          sprintf(errmsg2,"    USER: %s\n",from);
  298. X          strcat(errmsg,errmsg2);
  299. X          if(usr_addr)
  300. X          {
  301. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  302. X            strcat(errmsg,errmsg2);
  303. X          }
  304. X          if(port_open == 1)
  305. X          {
  306. X            sprintf(errmsg2,"     DEV: %s\n",GO_dev);
  307. X            strcat(errmsg,errmsg2);
  308. X          }
  309. X#ifdef NQ
  310. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  311. X#else
  312. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  313. X#endif
  314. X          strcat(errmsg,errmsg2);
  315. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  316. X          strcat(errmsg,errmsg2);
  317. X
  318. X               /* call the error routine, never come back */
  319. X               my_error(SYSERR);
  320. X              }
  321. X
  322. X
  323. X              }
  324. X
  325. X
  326. X              /* if it does match, we just fall through */
  327. X              /* free the allocated memory */
  328. X              free(expt1);
  329. X              free(c_send);
  330. X              free(expt2);
  331. X      }
  332. X    }
  333. X    else
  334. X    {
  335. X      /* this is not a compound EXPECT-SEND-EXPECT */
  336. X      /* compare what we got to the EXPECT */
  337. X      if(matcher(in_buf,expt_curr->expt_strg) == 1)
  338. X      {
  339. X        /* not a match */
  340. X        /* compare to BUSY and DEAD (in separate functions)     */
  341. X
  342. X        n = busyordead();
  343. X
  344. X       /* Doesn't match, is neither BUSY nor DEAD */
  345. X       /* need to send out an error msg */
  346. X          /* format an error message */
  347. X          time(&tloc);
  348. X          nowtime = (struct tm *)localtime(&tloc);
  349. X          time_str = asctime(nowtime);
  350. X
  351. X          sprintf(errmsg,"ISPIN: printer %s:\n   EXPECTED: <<%s>>\n   RECEIVED: <<%s>>\n\n",dest,expt_curr->expt_strg,in_buf);
  352. X          sprintf(errmsg2,"    USER: %s\n",from);
  353. X          strcat(errmsg,errmsg2);
  354. X          if(usr_addr)
  355. X          {
  356. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  357. X            strcat(errmsg,errmsg2);
  358. X          }
  359. X          if(port_open == 1)
  360. X          {
  361. X            sprintf(errmsg2,"     DEV: %s\n",GO_dev);
  362. X            strcat(errmsg,errmsg2);
  363. X          }
  364. X#ifdef NQ
  365. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  366. X#else
  367. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  368. X#endif
  369. X          strcat(errmsg,errmsg2);
  370. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  371. X          strcat(errmsg,errmsg2);
  372. X
  373. X         /* call the error routine, never come back */
  374. X         my_error(SYSERR);
  375. X      }
  376. X
  377. X
  378. X      /* if it does match, we just fall through */
  379. X    }
  380. X
  381. X  }
  382. X  /* This is where normal write of SEND takes place. */
  383. X  /* After the last send, we'll set not_yet = 1.     */
  384. X
  385. X  /* take one step through the SEND list */
  386. X  if(send_curr->next != NULL)
  387. X  {
  388. X    send_curr = send_curr->next;
  389. X  }
  390. X
  391. X  /* don't write anything if it is intended as "send nothing" */
  392. X  if(strlen(send_curr->send_strg) != 0)
  393. X  {
  394. X    n = write_net(send_curr->send_strg);
  395. X
  396. X
  397. X  }
  398. X
  399. X  /* if this is the end of the SEND list, terminate the loop */
  400. X  if(send_curr->next == NULL)
  401. X  {
  402. X    not_yet = 0;
  403. X  }
  404. X
  405. X  /* the following right curly ends while(not_yet) */
  406. X  }
  407. X  }
  408. X  else
  409. X  {
  410. X
  411. X    /* We only listen for SIGHUP on a hard-wired printer.                   */
  412. X
  413. X    /* Now that the device is our control terminal, do something if SIGHUP. */
  414. X    /* If this is not our first time through, there is a chance that the    */
  415. X    /* GO_dev is not our control terminal. Remember, we only get one chance */
  416. X    /* to choose the control terminal (unless we fork, which could ruin our */
  417. X    /* relationship with our parent, the native queuer). If this is not our */
  418. X    /* first time here (due to a previous BUSY condition), IQUEUER could    */
  419. X    /* tell us to use a terminal other than our control terminal. In that   */
  420. X    /* case, we do not want to listen for SIGHUP which may be issued by a   */
  421. X    /* terminal we aren't even using.                                       */
  422. X
  423. X    if(strcmp(GO_dev,ctrl_tty) == 0)
  424. X    {
  425. X        signal(SIGHUP, my_error);
  426. X    }
  427. X
  428. X  }
  429. X
  430. X/* Remember, the funky Sequent SVAE won't let us do a half-baked mode. */
  431. X/* Now that we are patched through to the printer, go back to cooked   */
  432. X/* mode so that we can do ONLCR as we write.                           */
  433. X
  434. X  if(ioctl(out_file, TCGETA, &T_COOK) == -1)
  435. X  {
  436. X    /* need to send out an error msg */
  437. X          /* format an error message */
  438. X          time(&tloc);
  439. X          nowtime = (struct tm *)localtime(&tloc);
  440. X          time_str = asctime(nowtime);
  441. X
  442. X          sprintf(errmsg,"ISPIN: printer %s: ioctl %s: %s.\n",dest,GO_dev,sys_errlist[errno]);
  443. X          sprintf(errmsg2,"    USER: %s\n",from);
  444. X          strcat(errmsg,errmsg2);
  445. X          if(usr_addr)
  446. X          {
  447. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  448. X            strcat(errmsg,errmsg2);
  449. X          }
  450. X#ifdef NQ
  451. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  452. X#else
  453. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  454. X#endif
  455. X          strcat(errmsg,errmsg2);
  456. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  457. X          strcat(errmsg,errmsg2);
  458. X
  459. X         /* call the error routine, never come back */
  460. X         my_error(SYSERR);
  461. X
  462. X  }
  463. X
  464. X  if(raw < 1)
  465. X  {
  466. X    /* the flag for absolutely RAW is not set */
  467. X
  468. X    T_COOK.c_lflag |= (ICANON);
  469. X    T_COOK.c_oflag |= (OPOST|ONLCR);
  470. X    if(tab_expand > 0)
  471. X    {
  472. X      T_COOK.c_oflag |= (TAB3);
  473. X    }
  474. X  }
  475. X
  476. X  /* turn the delay bit on, so we can accomodate flow control */
  477. X  fcntl(out_file,F_SETFL,flgs_delay);
  478. X
  479. X
  480. X  if(ioctl(out_file, TCSETA, &T_COOK) == -1)
  481. X  {
  482. X    /* need to send out an error msg */
  483. X          /* format an error message */
  484. X          time(&tloc);
  485. X          nowtime = (struct tm *)localtime(&tloc);
  486. X          time_str = asctime(nowtime);
  487. X
  488. X          sprintf(errmsg,"ISPIN: printer %s: ioctl %s: %s.\n",dest,GO_dev,sys_errlist[errno]);
  489. X          sprintf(errmsg2,"    USER: %s\n",from);
  490. X          strcat(errmsg,errmsg2);
  491. X          if(usr_addr)
  492. X          {
  493. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  494. X            strcat(errmsg,errmsg2);
  495. X          }
  496. X#ifdef NQ
  497. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  498. X#else
  499. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  500. X#endif
  501. X          strcat(errmsg,errmsg2);
  502. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  503. X          strcat(errmsg,errmsg2);
  504. X
  505. X         /* call the error routine, never come back */
  506. X         my_error(SYSERR);
  507. X
  508. X  }
  509. X
  510. X  return(0);
  511. X}
  512. X
  513. X
  514. X/************************************************************************/
  515. X/* MATCHER                                                              */
  516. X/* This function receives (pointer to) the string to be checked. The    */
  517. X/* (pointer to) the string we hope to match is expected.                */
  518. X
  519. X
  520. X
  521. Xmatcher(received,expected)
  522. Xchar *received, *expected;
  523. X{
  524. X    char *ep_p;
  525. X    int esize;
  526. X
  527. X    esize = (strlen(received) + BUFSIZ);
  528. X
  529. X    ep_p =  (char *) calloc(1, esize);
  530. X
  531. X
  532. X
  533. X
  534. X
  535. X
  536. X      /* This is a regexp(5) call. See /usr/include/regexp.h */
  537. X      compile(expected, ep_p, &ep_p[esize - 1], '\0');
  538. X
  539. X
  540. X      /* This is a regexp(5) call. See /usr/include/regexp.h */
  541. X      if(step(received,ep_p) == 1)
  542. X      {
  543. X        /* success on match */
  544. X        free(ep_p);
  545. X        return(0);
  546. X      }
  547. X      else   
  548. X      {
  549. X        /* no match */
  550. X        free(ep_p);
  551. X        return(1);
  552. X      }
  553. X}
  554. X
  555. X
  556. Xsetuptty()
  557. X{
  558. X  /* We want to be able to recognize SIGHUP from the port we are using to */
  559. X  /* access the printer. In order for that to happen, that port must be   */
  560. X  /* our control terminal. Only a process group leader may determine its  */
  561. X  /* own control terminal, so this process must become its own process    */
  562. X  /* group leader. The setpgrp() call will see to that. Then the first    */
  563. X  /* terminal we open will become our control terminal. Of course, this   */
  564. X  /* can only come to pass as long as our terminal is not already the     */
  565. X  /* control terminal of another process group. This is the reason it's SO*/
  566. X  /* CRITICAL that the native queuer is never wise as to which tty we are */
  567. X  /* using. The best thing is to tell DQUEUER or LP (as your case may be) */
  568. X  /* that this member's device is /dev/null. This will avoid any fubar.   */
  569. X  /* It is also possible that the device we want is already the control   */
  570. X  /* terminal of another process group, in which case the kernel will not */
  571. X  /* allow it to become our control terminal. This is why we do not depend*/
  572. X  /* solely upon SIGHUP to let us know of a disconnect.                   */
  573. X
  574. X  int tmp_open;
  575. X
  576. X
  577. X  if(netloop == 0)
  578. X  {
  579. X    /* only if this is the first time through */
  580. X    setpgrp();
  581. X    strcpy(ctrl_tty,GO_dev);
  582. X  }
  583. X
  584. X
  585. X
  586. X  /* open the device */
  587. X  /* GO_dev is the device IQUEUER told us to use */
  588. X
  589. X        signal(SIGALRM, my_error);
  590. X  time_out = 0;         /* set up timeout for file open */
  591. X  alarm(10);            /* wait a few seconds for carrier      */
  592. X            /* 04/16/89: I found out via one of the beta test */
  593. X            /* sites that, depending upon how someone else    */
  594. X            /* chooses to pin their cables, a carrier may     */
  595. X            /* never come. So, we open with no delay.         */
  596. X  /***********************************************/
  597. X
  598. X#ifndef NQ
  599. X  if((netloop != 0)&&((strcmp(ctrl_tty,GO_dev) == 0)))
  600. X  {
  601. X    /* re-use the file descriptor we got the first time if same device */
  602. X    out_file = ctrltty;
  603. X  }
  604. X  else
  605. X#endif
  606. X  {
  607. X  out_file = open(GO_dev,O_RDWR|O_NDELAY);
  608. X  if((out_file == -1) || (time_out))
  609. X  {
  610. X    /* need to send out an error msg */
  611. X          /* format an error message */
  612. X          time(&tloc);
  613. X          nowtime = (struct tm *)localtime(&tloc);
  614. X          time_str = asctime(nowtime);
  615. X
  616. X          sprintf(errmsg,"ISPIN: printer %s: open %s: %s.\n",dest,GO_dev,sys_errlist[errno]);
  617. X          sprintf(errmsg2,"    USER: %s\n",from);
  618. X          strcat(errmsg,errmsg2);
  619. X          if(usr_addr)
  620. X          {
  621. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  622. X            strcat(errmsg,errmsg2);
  623. X          }
  624. X#ifdef NQ
  625. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  626. X#else
  627. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  628. X#endif
  629. X          strcat(errmsg,errmsg2);
  630. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  631. X          strcat(errmsg,errmsg2);
  632. X
  633. X         /* call the error routine, never come back */
  634. X         my_error(SYSERR);
  635. X
  636. X  }
  637. X  /***********************************************/
  638. X  alarm(0);      /* turn off the alarm clock */
  639. X        signal(SIGALRM, SIG_IGN);
  640. X  /***********************************************/
  641. X
  642. X  if(netloop == 0 )
  643. X  {
  644. X    ctrltty = out_file;
  645. X  }
  646. X
  647. X  flgs_ndelay = fcntl(out_file,F_GETFL,0);
  648. X  flgs_delay = (flgs_ndelay & ~(O_NDELAY));
  649. X  }
  650. X
  651. X  port_open = 1;
  652. X
  653. X  /* turn the delay bit on, so we can accomodate flow control */
  654. X  /* fcntl(out_file,F_SETFL,flgs_delay); */
  655. X
  656. X  if(ioctl(out_file, TCGETA, &T) == -1)
  657. X  {
  658. X    /* need to send out an error msg */
  659. X          /* format an error message */
  660. X          time(&tloc);
  661. X          nowtime = (struct tm *)localtime(&tloc);
  662. X          time_str = asctime(nowtime);
  663. X
  664. X          sprintf(errmsg,"ISPIN: printer %s: ioctl %s: %s.\n",dest,GO_dev,sys_errlist[errno]);
  665. X          sprintf(errmsg2,"    USER: %s\n",from);
  666. X          strcat(errmsg,errmsg2);
  667. X          if(usr_addr)
  668. X          {
  669. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  670. X            strcat(errmsg,errmsg2);
  671. X          }
  672. X#ifdef NQ
  673. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  674. X#else
  675. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  676. X#endif
  677. X          strcat(errmsg,errmsg2);
  678. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  679. X          strcat(errmsg,errmsg2);
  680. X
  681. X         /* call the error routine, never come back */
  682. X         my_error(SYSERR);
  683. X
  684. X  }
  685. X
  686. X  ioctl(out_file, TCGETA, &Tsav);
  687. X
  688. X  T.c_cflag &= ~CBAUD;
  689. X  switch(speed)
  690. X  {
  691. X    case 9600:
  692. X              T.c_cflag |= B9600;
  693. X              break;
  694. X    case 1200:
  695. X              T.c_cflag |= B1200;
  696. X              break;
  697. X    case 75: 
  698. X              T.c_cflag |= B75;
  699. X              break;
  700. X    case 110:
  701. X              T.c_cflag |= B110;
  702. X              break;
  703. X    case 134:
  704. X              T.c_cflag |= B134;
  705. X              break;
  706. X    case 150:
  707. X              T.c_cflag |= B150;
  708. X              break;
  709. X    case 200:
  710. X              T.c_cflag |= B200;
  711. X              break;
  712. X    case 300:
  713. X              T.c_cflag |= B300;
  714. X              break;
  715. X    case 600:
  716. X              T.c_cflag |= B600;
  717. X              break;
  718. X    case 1800:
  719. X              T.c_cflag |= B1800;
  720. X              break;
  721. X    case 2400:
  722. X              T.c_cflag |= B2400;
  723. X              break;
  724. X    case 4800:
  725. X              T.c_cflag |= B4800;
  726. X              break;
  727. X    case 19200:
  728. X              T.c_cflag |= B19200;
  729. X              break;
  730. X    default:
  731. X              T.c_cflag |= B9600;
  732. X              break;
  733. X  }
  734. X
  735. X  /***************************************************************************/
  736. X  /* The funky Sequent DYNIX SVAE can't do the "half-baked" mode which is so */
  737. X  /* convenient in a true Sys V environment. It has to be either cooked or   */
  738. X  /* raw. So, just to be portable ...                                        */
  739. X  /***************************************************************************/
  740. X
  741. X  T.c_iflag &= ~(INLCR|BRKINT|PARMRK|INPCK|ICRNL|IUCLC|IXOFF);
  742. X  T.c_iflag |= (IGNBRK|IGNPAR|ISTRIP|IGNCR|IXON);
  743. X  T.c_oflag &= ~(OLCUC|NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY|OCRNL|ONOCR|OFILL|OFDEL);
  744. X  T.c_oflag &= ~(OPOST|ONLCR);
  745. X  T.c_cflag &= ~(CSTOPB|PARENB);
  746. X  T.c_cflag &= ~(CLOCAL);
  747. X  T.c_cflag |= (CS8|HUPCL|CREAD);
  748. X  T.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHONL|XCASE|NOFLSH);
  749. X  T.c_cc[VMIN] = 0;
  750. X  T.c_cc[VTIME] = 75;
  751. X
  752. X  if(ioctl(out_file, TCSETA, &T) == -1)
  753. X  {
  754. X    /* need to send out an error msg */
  755. X          /* format an error message */
  756. X          time(&tloc);
  757. X          nowtime = (struct tm *)localtime(&tloc);
  758. X          time_str = asctime(nowtime);
  759. X
  760. X          sprintf(errmsg,"ISPIN: printer %s: ioctl %s: %s.\n",dest,GO_dev,sys_errlist[errno]);
  761. X          sprintf(errmsg2,"    USER: %s\n",from);
  762. X          strcat(errmsg,errmsg2);
  763. X          if(usr_addr)
  764. X          {
  765. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  766. X            strcat(errmsg,errmsg2);
  767. X          }
  768. X#ifdef NQ
  769. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  770. X#else
  771. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  772. X#endif
  773. X          strcat(errmsg,errmsg2);
  774. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  775. X          strcat(errmsg,errmsg2);
  776. X
  777. X         /* call the error routine, never come back */
  778. X         my_error(SYSERR);
  779. X
  780. X  }
  781. X
  782. X  /* save the raw setting so we can toggle later */
  783. X      ioctl(out_file, TCGETA, &T_RAW);
  784. X      T_RAW.c_cc[VMIN] = 0;
  785. X      T_RAW.c_cc[VTIME] = 15;
  786. X
  787. X  /* flush input and output queues for a nice clean tty */
  788. X  ioctl(out_file,TCFLSH,2);
  789. X
  790. X}
  791. X
  792. X
  793. Xmy_error(reason)
  794. Xint reason;
  795. X{
  796. X  switch(reason)
  797. X  {
  798. X    case NO_EXIT:
  799. X         if((logfile = fopen(LOGFILE,"a+")) != NULL)
  800. X         {
  801. X            fprintf(logfile,errmsg);
  802. X            fclose(logfile);
  803. X         }
  804. X            return(0);
  805. X      break;
  806. X    case SIGALRM:
  807. X        signal(SIGALRM, my_error);
  808. X
  809. X        /* take care of the signals */
  810. X        signal(SIGINT, SIG_IGN);    /* ignore "interrupt" signal <DEL> */
  811. X        signal(SIGHUP, SIG_IGN);    /* ignore "hang up" signal */
  812. X        signal(SIGQUIT, SIG_IGN);   /* ignore "quit" signal */
  813. X        signal(SIGTERM, my_error);
  814. X#ifdef NQ
  815. X        signal(SIGRES, SIG_IGN);     /* ignore "restart" signal */
  816. X        signal(SIGBACK, SIG_IGN);   /* ignore "back-up" signal */
  817. X        signal(SIGSTOP, my_error);   /* trap "stop" signal */
  818. X#endif
  819. X  
  820. X        time_out = 1;
  821. X      break;
  822. X    case SIGTERM:
  823. X  /************************************************************************/
  824. X  /* Reset traps on all signals!                                          */
  825. X  /* We don't want to be interrupted when we already know we're           */
  826. X  /* on our way out!                                                      */
  827. X  /************************************************************************/
  828. X
  829. X/* take care of the signals */
  830. X        signal(SIGINT, SIG_IGN);    /* ignore "interrupt" signal <DEL> */
  831. X        signal(SIGHUP, SIG_IGN);    /* ignore "hang up" signal */
  832. X        signal(SIGQUIT, SIG_IGN);   /* ignore "quit" signal */
  833. X        signal(SIGALRM, SIG_IGN);
  834. X        signal(SIGTERM, my_error);
  835. X#ifdef NQ
  836. X        signal(SIGRES, SIG_IGN);     /* ignore "restart" signal */
  837. X        signal(SIGBACK, SIG_IGN);   /* ignore "back-up" signal */
  838. X        signal(SIGSTOP, my_error);   /* ignore "stop" signal */
  839. X#endif
  840. X            /* format an error message */
  841. X            time(&tloc);
  842. X            nowtime = (struct tm *)localtime(&tloc);
  843. X            time_str = asctime(nowtime);
  844. X
  845. X            sprintf(errmsg,"ISPIN: printer %s: received SIGTERM.\n",dest);
  846. X          sprintf(errmsg2,"    USER: %s\n",from);
  847. X          strcat(errmsg,errmsg2);
  848. X          if(usr_addr)
  849. X          {
  850. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  851. X            strcat(errmsg,errmsg2);
  852. X          }
  853. X          if(port_open == 1)
  854. X          {
  855. X            sprintf(errmsg2,"     DEV: %s\n",GO_dev);
  856. X            strcat(errmsg,errmsg2);
  857. X          }
  858. X#ifdef NQ
  859. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  860. X#else
  861. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  862. X#endif
  863. X          strcat(errmsg,errmsg2);
  864. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  865. X          strcat(errmsg,errmsg2);
  866. X
  867. X         if((logfile = fopen(LOGFILE,"a+")) != NULL)
  868. X         {
  869. X            fprintf(logfile,errmsg);
  870. X            fclose(logfile);
  871. X         }
  872. X
  873. X         if(port_open == 1)
  874. X         {
  875. X           savd_errno = SIGTERM;
  876. X           stayt = QUITTING;
  877. X           if(quit_once > 0)
  878. X           {
  879. X             LONGJMP(kwit, quit_once);
  880. X           }
  881. X           else
  882. X           {
  883. X         ret_val = quit_net();
  884. X           }
  885. X         }
  886. X
  887. X         my_exit(reason);
  888. X      break;
  889. X    case SIGHUP:
  890. X    case DISCONNECTING:
  891. X    case TIMEOUT:
  892. X    case NET_TIME:
  893. X  /************************************************************************/
  894. X  /* Reset traps on all signals!                                          */
  895. X  /* We don't want to be interrupted when we already know we're           */
  896. X  /* on our way out!                                                      */
  897. X  /************************************************************************/
  898. X
  899. X/* take care of the signals */
  900. X        signal(SIGINT, SIG_IGN);    /* ignore "interrupt" signal <DEL> */
  901. X        signal(SIGHUP, my_error);
  902. X        signal(SIGQUIT, SIG_IGN);   /* ignore "quit" signal */
  903. X        signal(SIGALRM, SIG_IGN);
  904. X        signal(SIGTERM, my_error);
  905. X#ifdef NQ
  906. X        signal(SIGRES, SIG_IGN);     /* ignore "restart" signal */
  907. X        signal(SIGBACK, SIG_IGN);   /* ignore "back-up" signal */
  908. X        signal(SIGSTOP, my_error);   /* trap "stop" signal */
  909. X#endif
  910. X            /* format an error message */
  911. X            time(&tloc);
  912. X            nowtime = (struct tm *)localtime(&tloc);
  913. X            time_str = asctime(nowtime);
  914. X            switch(reason)
  915. X            {
  916. X              case SIGHUP:
  917. X                sprintf(errmsg,"ISPIN: printer %s: received SIGHUP, so looping.\n",dest);
  918. X              break;
  919. X              case DISCONNECTING:
  920. X                sprintf(errmsg,"ISPIN: printer %s: detected DISCONNECT, so looping.\n",dest);
  921. X              break;
  922. X              case TIMEOUT:
  923. X                sprintf(errmsg,"ISPIN: printer %s: write to printer timed out after %d secs, so looping.\n",dest, WRITEWAIT);
  924. X              break;
  925. X              case NET_TIME:
  926. X                if(stayt == CONNECTING)
  927. X                {
  928. X                  sprintf(errmsg,"ISPIN: printer %s: connecting negotiation write timed out after %d secs, so looping.\n",dest, NETWAIT);
  929. X                }
  930. X              break;
  931. X            }
  932. X          sprintf(errmsg2,"    USER: %s\n",from);
  933. X          strcat(errmsg,errmsg2);
  934. X          if(usr_addr)
  935. X          {
  936. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  937. X            strcat(errmsg,errmsg2);
  938. X          }
  939. X          if(port_open == 1)
  940. X          {
  941. X            sprintf(errmsg2,"     DEV: %s\n",GO_dev);
  942. X            strcat(errmsg,errmsg2);
  943. X          }
  944. X#ifdef NQ
  945. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  946. X#else
  947. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  948. X#endif
  949. X          strcat(errmsg,errmsg2);
  950. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  951. X          strcat(errmsg,errmsg2);
  952. X
  953. X         if((logfile = fopen(LOGFILE,"a+")) != NULL)
  954. X         {
  955. X            fprintf(logfile,errmsg);
  956. X            fclose(logfile);
  957. X         }
  958. X    /* If we get HUPed or disconnected, try again. Maybe it was a mistake. */
  959. X    if((netloop <= MAXNET_TRY)&&(stayt != QUITTING))
  960. X     {
  961. X       /* try again */
  962. X       again();
  963. X     }
  964. X     else
  965. X     {
  966. X       /* need to send out an error msg */
  967. X       /* format an error message */
  968. X       time(&tloc);
  969. X       nowtime = (struct tm *)localtime(&tloc);
  970. X       time_str = asctime(nowtime);
  971. X  
  972. X       if(stayt == QUITTING)
  973. X       {
  974. X         sprintf(errmsg,"ISPIN: printer %s: disconnecting write timed out after %d secs, so quitting.\n",dest, NETWAIT);
  975. X       }
  976. X       else
  977. X       {
  978. X         sprintf(errmsg,"ISPIN: printer %s: %d BUSY LOOPS, so quitting.\n",dest,netloop);
  979. X       }
  980. X          sprintf(errmsg2,"    USER: %s\n",from);
  981. X          strcat(errmsg,errmsg2);
  982. X          if(usr_addr)
  983. X          {
  984. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  985. X            strcat(errmsg,errmsg2);
  986. X          }
  987. X          if(port_open == 1)
  988. X          {
  989. X            sprintf(errmsg2,"     DEV: %s\n",GO_dev);
  990. X            strcat(errmsg,errmsg2);
  991. X          }
  992. X#ifdef NQ
  993. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  994. X#else
  995. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  996. X#endif
  997. X          strcat(errmsg,errmsg2);
  998. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  999. X          strcat(errmsg,errmsg2);
  1000. X
  1001. X       /* call the error routine, never come back */
  1002. X       /* INTENTIONALLY RECURSIVE */
  1003. X       my_error(MYERR);
  1004. X     }
  1005. X      break;
  1006. X#ifdef NQ
  1007. X    case SIGSTOP:
  1008. X  /************************************************************************/
  1009. X  /* Reset traps on all signals!                                          */
  1010. X  /* We don't want to be interrupted when we already know we're           */
  1011. X  /* on our way out!                                                      */
  1012. X  /************************************************************************/
  1013. X
  1014. X/* take care of the signals */
  1015. X        signal(SIGINT, SIG_IGN);    /* ignore "interrupt" signal <DEL> */
  1016. X        signal(SIGHUP, SIG_IGN);    /* ignore "hang up" signal */
  1017. X        signal(SIGQUIT, SIG_IGN);   /* ignore "quit" signal */
  1018. X        signal(SIGALRM, SIG_IGN);   /* ignore "alarm" signal */
  1019. X        signal(SIGTERM, my_error);
  1020. X        signal(SIGRES, SIG_IGN);     /* ignore "restart" signal */
  1021. X        signal(SIGBACK, SIG_IGN);   /* ignore "back-up" signal */
  1022. X        signal(SIGSTOP, my_error);   /* ignore "stop" signal */
  1023. X
  1024. X            /* format an error message */
  1025. X            time(&tloc);
  1026. END_OF_FILE
  1027. if test 30636 -ne `wc -c <'ISPIN/src/ISPIN.c.ac'`; then
  1028.     echo shar: \"'ISPIN/src/ISPIN.c.ac'\" unpacked with wrong size!
  1029. fi
  1030. # end of 'ISPIN/src/ISPIN.c.ac'
  1031. fi
  1032. if test -f 'ISPIN/doc/LPinstall.doc' -a "${1}" != "-c" ; then 
  1033.   echo shar: Will not clobber existing file \"'ISPIN/doc/LPinstall.doc'\"
  1034. else
  1035. echo shar: Extracting \"'ISPIN/doc/LPinstall.doc'\" \(17620 characters\)
  1036. sed "s/^X//" >'ISPIN/doc/LPinstall.doc' <<'END_OF_FILE'
  1037. X
  1038. X   The installation script and these following procedures must be
  1039. X   executed by the superuser.
  1040. X
  1041. X1. cd to ISPIN.rel_2.2/ISPIN/h
  1042. X   Edit the file localcnfg.h
  1043. X   Edit the SITELINE constant definition to reflect the name of your site.
  1044. X   Modify ONLY what is between the asterisks, keeping the overall width of
  1045. X   the line the same as what is already there.
  1046. X
  1047. X/********************************************************************/
  1048. X
  1049. X   SPECIAL NOTE for Sequent and Pyramid: all of the executables in 
  1050. X   this application MUST be COMPILED AND RUN in the "att" universe!
  1051. X
  1052. X/********************************************************************/
  1053. X
  1054. X2. cd to ISPIN.rel_2.2/ISPIN/install.
  1055. X   Edit the file "Makefile" and make sure the SPOOLER is set to the proper
  1056. X   value -
  1057. X         ZILOGNQ if your system is a Zilog which uses the nq spooler 
  1058. X         ZILOGLP if your system is a Zilog which uses the lp spooler
  1059. X         DYNIX if your system is a Sequent which uses the lp spooler
  1060. X         CCI if your system is a CCI with "dirent"-style directories
  1061. X         3B1 if your system is an AT&T 3B1 which uses the lp spooler
  1062. X         UNISYS if your system is a UNISYS 5000 which uses the lp spooler
  1063. X         LP if your system is another type of system which uses the lp spooler
  1064. X
  1065. X   Execute the command "make" to compile all of the C programs which are
  1066. X   used by ISPIN.
  1067. X
  1068. X3. You are now ready to install the C programs which were just compiled.
  1069. X   Take a look at the program "install.sh" to make sure your are comfortable
  1070. X   with what it does. Now, execute the command "make install" (make will execute
  1071. X   the program install.sh).
  1072. X
  1073. X4. Copy the executable iq to a directory to which your users have
  1074. X   a path for execution ( such as, generally, /usr/local/bin ).
  1075. X
  1076. X5. Make provision in your system start-up script(s) (i.e., /etc/rc2)
  1077. X   to invoke /usr/spool/lp/ISPIN/iqueuer (the daemon) every start-up.
  1078. X   Execute it now, just for the first start-up.
  1079. X
  1080. X   Sequent and Pyramid users make sure to call the iqueuer with "att".
  1081. X                 *
  1082. X                                * *
  1083. X                               *   *
  1084. X                              *     *
  1085. X                             *       *
  1086. X                                NOTE
  1087. X                                 *
  1088. X                                 *
  1089. X                                 *
  1090. X                                 *
  1091. X                                 *
  1092. X
  1093. X
  1094. X6. Edit your system's startup and (if any) re-start script(s). The
  1095. X   names of these scripts vary, but will almost always be something
  1096. X   like "/etc/rc", "/etc/rc_csh", "/etc/rc2". You get the idea. These
  1097. X   scripts usually also invoke other scripts along the way. Find the
  1098. X   point at which the script gets rid of "old" lock files (files
  1099. X   with names like "/usr/spool/uucp/LCK..tty*"). Usually the line
  1100. X   in the script says:
  1101. X                                 rm -f /usr/spool/uucp/LCK..tty*
  1102. X                            or:
  1103. X                                 rm -f /usr/spool/locks/LCK..tty*
  1104. X                            or:
  1105. X                                 rm -f /usr/spool/uucp//LCK/LCK..tty*
  1106. X
  1107. X   CHANGE IT TO READ:
  1108. X                                 rm -fr /usr/spool/uucp/LCK..tty*
  1109. X                            or:
  1110. X                                 rm -fr /usr/spool/locks/LCK..tty*
  1111. X                            or:
  1112. X                                 rm -fr /usr/spool/uucp//LCK/LCK..tty*
  1113. X
  1114. X   The reason for this change is that the lock files ISPIN creates
  1115. X   are actually directories. Adding the "r" flag to the rm(1) arg
  1116. X   list permits the removal of any such lock files which remain on
  1117. X   the system subsequent to an unexpected or otherwise ungraceful
  1118. X   shutdown.
  1119. X
  1120. X7. Choose the tty(s) through which ISPIN will contact printer(s).
  1121. X   Releases 2.0 (and later) of ISPIN support lock files.
  1122. X   The tty(s) you choose may be used for other purposes, such as cu(1)
  1123. X   and uucp(1) and also support of the ISPIN printer(s). You may, however,
  1124. X   support several such printers via one or more tty(s).
  1125. X   Also refer to your SA manual. As with any other port which supports
  1126. X   a printer, if the tty had previously been in use as a login port,
  1127. X   the getty must be permanently disabled.
  1128. X   
  1129. X   ISPIN does, however, cooperate quite well with uugetty. So if you 
  1130. X   have a need for bi-directionality (as I do with my little AT&T 3B1)
  1131. X   ISPIN is ready to oblige.
  1132. X
  1133. X8. Connect tty(s) to network. Have your Data Communications Specialist
  1134. X   do this while you read ALL of the documentation which came with this
  1135. X   release.
  1136. X
  1137. X   Seriously, I can't make specific recommendations for every possible
  1138. X   combo of cpu/data switch and printer/data switch. I will make a strong
  1139. X   general recommendation that you connect all valid modem control
  1140. X   signals. Don't try to fool the cpu or the switch by feeding their own
  1141. X   modem control signals back to them. If you do this, you'll make your
  1142. X   data communications less reliable, less fault-tolerant.
  1143. X
  1144. X   IN GENERAL: If the cpu is DTE and the data switch is DCE and you're
  1145. X   using RS-232 25-pin "D" connectors, the pinning will be 1 through 8
  1146. X   and 20, all straight through. If your cpu's ttys are DCE (and switch
  1147. X   also DCE), you'll need null modem adapter or null modem pinning.
  1148. X
  1149. X   Some switches do end-to-end modem signal mapping and the pins on which
  1150. X   certain signals are listened-for and asserted-upon are different from
  1151. X   "normal" RS-232. For some switches, this can also vary depending upon
  1152. X   how a given channel is configured.
  1153. X
  1154. X   Most switches I've seen or heard of (Tellabs, Equinox, David, Gandolph,
  1155. X   Mitron, etc) allow channels or groups of channels to be configured to
  1156. X   support software flow control, XON/XOFF. ISPIN needs this at both the
  1157. X   cpu and printer sides. By the way, the less-expensive "dumb" Equinox
  1158. X   which merely passes XON/XOFF from end-to-end with no internal buffering
  1159. X   is not adequate (you'll lose characters due to flow control problems).
  1160. X   The more sophisticated Equinox is fine.
  1161. X   
  1162. X   Our X.25 asynchronous pads allow this to be set "on the fly", during a 
  1163. X   connect session. Under this facility, we can turn on software flow control
  1164. X   via ISPIN's rtab entry for printing, and turn off software flow control 
  1165. X   from uucp's L.sys (or Systems) entry to allow uucp "G" protocol. 
  1166. X
  1167. X9. Connect printer(s) to network. Be sure to configure your printer(s) for 
  1168. X   software (XON/XOFF) flow control. Disable hardware (CTS/DTR) flow control.
  1169. X   The same goes for all links in your network hardware (the ports or
  1170. X   channels to which the cpu and printer are connected).
  1171. X
  1172. X   Some printers allow XON/XOFF flow control to be enabled or disabled,
  1173. X   but they won't let you disable hardware flow control. I'm thinking
  1174. X   specifically of the HP LaserJets, but there may be others. In these
  1175. X   cases, you'll have to disable hardware flow control through creative
  1176. X   pinning. In my case, the printer is DTE, my X.25 async pad is DCE, and
  1177. X   all signals are asserted-upon/listened-for on what we consider "normal"
  1178. X   RS-232 pin positions. Most of my pad-to-printer cables are straight
  1179. X   1-8 & 20. My cable for the HPLJ has pins 4 & 20 swapped.
  1180. X
  1181. X10. Edit the /usr/spool/lp/ISPIN/rtab to add a line of
  1182. X   connect info for each remote printer. If you have some experience
  1183. X   setting up a uucp L.sys (or HoneyDanBer's Systems) file, rtab
  1184. X   should be a snap.
  1185. X
  1186. X   The directory ISPIN.rel_2.2/ISPIN/install/lib_rtab contains a
  1187. X   README file. READ IT!
  1188. X
  1189. X   The rtab file supplied with this release includes extensive 
  1190. X   comment lines as documentation. Don't delete them. The rtab also
  1191. X   includes commented-out printer entries as examples. Take a look.
  1192. X   It's pretty straight-forward once you weed out the \p's and \d's.
  1193. X   Most of what I'm about to describe is also included in rtab's
  1194. X   comments. There are many IMPORTANT details included in rtab but
  1195. X   not addressed here.
  1196. X   
  1197. X
  1198. X   Notice that each entry is all one line. As you add an entry for your
  1199. X   printer(s), allow the line to wrap around. Line feed or carriage 
  1200. X   return terminates the entry. I have made no provision for escaping 
  1201. X   newline with a backslash.
  1202. X
  1203. X   Leading # comments-out the entire line. (Do not use blank lines.)
  1204. X
  1205. X   The first field is the name by which the printer will be known.
  1206. X   This name absolutely must be the same as the name by which the
  1207. X   native lp spooler knows the queue member. Your choice of printer name
  1208. X   is thus restricted to what is allowable under the lp regime.
  1209. X   See lpadmin(M).
  1210. X
  1211. X   The second field defines the serial port(s) through which ISPIN
  1212. X   may attempt to contact the printer. You chose these in item 6,
  1213. X   above. This entry specifies primary and subsequent ports,
  1214. X   separated by commas. A one port entry is just as acceptable.
  1215. X   Eleven ports is max.
  1216. X
  1217. X   The third field specifies the speed setting for the port.
  1218. X
  1219. X   The "-B" flag & arg fields define portions of various "network
  1220. X   busy" messages which may be encountered when ISPIN attempts
  1221. X   to negotiate through the network. In the case of one example, 
  1222. X   because we are calling out from the cpu, into a Tellabs data
  1223. X   switch, then out into the X.25 async pad, I have included unique
  1224. X   parts of "busy" messages from both the Tellabs and X.25 async pad
  1225. X   environments. The usage of the "-B" flag and arguments is, like
  1226. X   the other two flags, optional. 
  1227. X
  1228. X   I VERY STRONGLY suggest that your rtab entries include as many
  1229. X   of these "busy" flags and args as you can possibly identify. They
  1230. X   add immeasureably to the robustness of the application. Otherwise,
  1231. X   the ISPIN won't be able to re-attempt contact of a network-supported
  1232. X   printer which is currently being used by another ISPIN from the
  1233. X   same (or different) cpu, or (heaven forbid) by an MDQS process,
  1234. X   or which is otherwise busy for whatever reason. All looping which
  1235. X   occurs under these conditions is strictly under the control of
  1236. X   the ISPIN and the IQUEUER. The native lp spooler has no idea any 
  1237. X   re-try is going on. Of course, the native cancel command may terminate
  1238. X   the ISPIN at any time.
  1239. X
  1240. X   A "-I" flag and argument field defines a portion of a 
  1241. X   network message which would be encountered when/if the line, the
  1242. X   destination device, or some intermediate device is just plain dead.
  1243. X   Define "-I" flags only for messages which indicate network conditions
  1244. X   under which you would prefer that the requested print job simply
  1245. X   give up and terminate itself. 
  1246. X
  1247. X   I personally would prefer my jobs to re-try even under such conditions.
  1248. X   The looping algorithm for the "-B" cases described above is not
  1249. X   going to cause your system to thrash. So I say "let 'em loop".
  1250. X   You or the user who requested the print job should eventually notice
  1251. X   things are not moving along. If the job is looping, you'll have an
  1252. X   opportunity to correct the network problem or other problem and
  1253. X   never lose a print request. Of course, if network conditions are so
  1254. X   bad that you know the ISPIN will never get through, the job may be
  1255. X   terminated by the native cancel(1) command.
  1256. X
  1257. X   The arguments to the "-D" flags are unique protions of strings which
  1258. X   are messages we expect the network(s) to return when/if the printer
  1259. X   is powered-down or disconnected. After each burst of characters which
  1260. X   is written by ISPIN to the printer, ISPIN checks the port to see if 
  1261. X   there are any characters to be read. Normally there will be none.
  1262. X   If, however, the printer has been powered-down or otherwise disconnected,
  1263. X   we expect the network device to recognize the situation and give us
  1264. X   a message. If we have correctly specified parts of these messages as
  1265. X   args to the "-D" flags, the program will immediately detect the "disconnect"
  1266. X   situation and loop, attempting to re-establish contact with the printer.
  1267. X   Once the connection is re-established, the job will be printed in its
  1268. X   entirety. Since the letter "e" is the most frequently used letter in
  1269. X   the alphabet, I'll usually have a "-De" field. This way, if we're
  1270. X   disconnected from the printer and all the chars we send out are being
  1271. X   echoed back to ISPIN, we'll detect the error condition very quickly.
  1272. X
  1273. X   The "-Q" fields define, in sequence, what signals or 
  1274. X   messages should be issued to the network to accomplish a clean break
  1275. X   at the end of a successful connect session. Let your knowledge of 
  1276. X   your own local switch (if applicable) be your guide. What
  1277. X   do you have to enter at your keyboard to assure a clean break?
  1278. X   For the moment, ignore the \p's (1 sec pause) and \d's (3 sec delay).
  1279. X
  1280. X   In one example, remember, we went from cpu, to Tellabs, to X.25 async pad,
  1281. X   to the printer. Now to disconnect, we conduct a clean break of each
  1282. X   virtual connection under our control.
  1283. X   The first "-Q" argument is "\K", which rtab's documentation tells us
  1284. X   results in the issuance of a <BREAK>. This is the signal X.25 async pad needs
  1285. X   to put the printer's channel into command mode.
  1286. X   The next "-Q" argument is "clr" and carriage return, a readily recog-
  1287. X   nizable X.25 async pad command which drops the virtual connection.
  1288. X   The next two "-Q" flags and arguments issue <BREAK>bye to the local
  1289. X   Tellabs data switch. This is my locally defined disconnect sequence
  1290. X   for the Tellabs data switch in Indy.
  1291. X
  1292. X   Before we proceed to a discussion of the EXPECT and SEND sequences,
  1293. X   I'll explain the necessity for all of the pauses and delays. In my
  1294. X   testing, I found that when ISPIN is running on a lightly loaded cpu 
  1295. X   and conversing with the X.25 async pad, the program is capable of shifting
  1296. X   between writing to the network and reading from the network MUCH
  1297. X   faster than the network is capable of responding. Before long, the
  1298. X   EXPECT/SEND sequence gets lost. Rather than "hard code" the necessary
  1299. X   delays into the application, I chose to allow the specification of
  1300. X   pauses and delays by the user (you). This approach permits the greatest
  1301. X   amount of flexibility in implementation. Experiment for yourself.
  1302. X   Also, many printers need time to print the contents of their buffers
  1303. X   after all characters have been issued by the cpu, but before the network
  1304. X   connection is dropped. Increasing delay time in the first "-Q" sequence
  1305. X   is the answer. If the last several lines of a document are being lost,
  1306. X   try adding a "\w" or "\L" immediately after the first "-Q" flag.
  1307. X   If you need more or less pause or delay, adjust your rtab entry.
  1308. X
  1309. X   Now for the EXPECT/SEND sequences.
  1310. X   EXPECT and SEND are pairs.
  1311. X   You must begin with EXPECT.
  1312. X   You must end with a null SEND field.
  1313. X   The best way to figure out what you need to say in these sequences
  1314. X   is to call out through the port(s) you are using with cu(1).
  1315. X   Once you have made a successful connection all the way through to
  1316. X   the printer, any subsequent keyboard activity on your part should
  1317. X   show up on the printer.
  1318. X   In our example, notice the liberal usage of the compound construction,
  1319. X   EXPECT-SEND-EXPECT. This construct exactly mimics uucp's similar
  1320. X   feature. Use of this feature significantly enhances your chances of
  1321. X   making a successful connection.
  1322. X   There is a lot more info on rtab in rtab's comments.
  1323. X
  1324. X   The directory ISPIN.rel_2.2/ISPIN/install/lib_rtab contains a
  1325. X   README file. READ IT!
  1326. X
  1327. X11. Creation of a FIFO for each printer in /usr/spool/lp/ISPIN/FIFO
  1328. X   need not be done manually. The application will create a FIFO for
  1329. X   each queue member as needed.
  1330. X
  1331. X   If you observe the example rtab entry, you'll note the printer is
  1332. X   named "LSB1". The first time a request is issued to this queue member,
  1333. X   the FIFO /usr/spool/lp/ISPIN/FIFO/LSB1 will be created.
  1334. X
  1335. X12.Shut down the lp scheduler by executing:
  1336. X   lpshut
  1337. X
  1338. X13. Add each remote printer as a member of the native queuer by
  1339. X    executing:     lpadmin -pyour_printer_name -iispintrfce -v/dev/null
  1340. X
  1341. X    Observe the example entry in the rtab file. The example printer's
  1342. X    name is "LSB1". In this case, the appropriate lpadmin command is:
  1343. X
  1344. X                   lpadmin -pLSB1 -iispintrfce -v/dev/null
  1345. X
  1346. X    Two SIGNIFICANT items in this command:
  1347. X
  1348. X        - The "ispintrfce" argument to the "-i" flag assumes that the 
  1349. X      executable ispintrfce is in the current working directory.
  1350. X          The "make install" puts a copy in /usr/spool/lp/ISPIN.
  1351. X
  1352. X        - The device specified as the argument to the "-v" flag is 
  1353. X          /dev/null.
  1354. X
  1355. X          IT IS VITALLY IMPORTANT THAT THE NATIVE QUEUER DOES NOT
  1356. X          KNOW THE DEVICE(S) ISPIN WILL ACTUALLY BE USING.
  1357. X
  1358. X14. Use the lp-family commands "accept" and "enable" to activate the
  1359. X    new queue member.
  1360. X
  1361. X15. Re-start the lp scheduler by executing lpsched.
  1362. X
  1363. X16. Use the new printer.
  1364. X    The native lp and lpsched commands will function exactly normally
  1365. X    as they relate to the ISPIN-supported printer(s). cancel still retains
  1366. X    its control over the life and death of the print job.
  1367. X
  1368. X17. Also use the iq command to inquire the iqueuer daemon. In an active
  1369. X    IQUEUER/ISPIN situation, lpstat may show several print processes as
  1370. X    "now printing" simultaneously when you know they can't all possibly be
  1371. X    printing simultaneously. This situation could arise when/if several
  1372. X    ISPIN-supported members of the native queue have been configured by
  1373. X    you to all use the same tty for access out to the network. As far as
  1374. X    lp and lpstat are concerned, once the "backend" process has been
  1375. X    invoked, the process is "now printing". This is the situation the IQUEUER
  1376. X    daemon is designed to accomodate. IQUEUER manages the ISPINs which
  1377. X    are competing for the scarce resource. iq will show you which of the
  1378. X    ISPIN processes are actually running or are actually waiting.
  1379. X
  1380. X18. Look to /usr/spool/lp/ISPIN/log for ISPIN error messages and event
  1381. X    logging.
  1382. END_OF_FILE
  1383. if test 17620 -ne `wc -c <'ISPIN/doc/LPinstall.doc'`; then
  1384.     echo shar: \"'ISPIN/doc/LPinstall.doc'\" unpacked with wrong size!
  1385. fi
  1386. # end of 'ISPIN/doc/LPinstall.doc'
  1387. fi
  1388. if test -f 'ISPIN/misc/ISPIT.dr/README' -a "${1}" != "-c" ; then 
  1389.   echo shar: Will not clobber existing file \"'ISPIN/misc/ISPIT.dr/README'\"
  1390. else
  1391. echo shar: Extracting \"'ISPIN/misc/ISPIT.dr/README'\" \(4517 characters\)
  1392. sed "s/^X//" >'ISPIN/misc/ISPIT.dr/README' <<'END_OF_FILE'
  1393. X
  1394. Xrtab.entry     -  see do_ispit.sh. Notice that this rtab entry requires that
  1395. X                  this queue member be called by an lp(1) command which
  1396. X                  must include a sane value for the "-o" flag.
  1397. X                  The arg to the "-o" is used by ISPIN at the point in the
  1398. X                  rtab where "\U" appears.
  1399. X                  Note also the use of the "-R" flag for really raw output.
  1400. X
  1401. Xdo_ispit.sh    -  the shell script which is executed by the source system.
  1402. X
  1403. X                  The lp command line contains some interesting features.
  1404. X
  1405. X                  The string passed as the argument to the "-o" flag is
  1406. X                  actually made up of two arguments which are delimited by
  1407. X                  the "@" symbol. These two arguments are processed by
  1408. X                  the special interface script on the source system.
  1409. X
  1410. X                  The first "argument" to lp's "-o" flag is processed
  1411. X                  by ispin and inserted in a "sent" network negotiation 
  1412. X                  string where a "\U" appears. On the destination system,
  1413. X                  ispit.sh picks this up as the name of the output file.
  1414. X
  1415. X                  Also notice that the second "argument" to the "-o" flag
  1416. X                  is /tmp/$nowfile. This file is a named pipe, created "on
  1417. X                  the fly". The lp/interface file (special for this purpose)
  1418. X                  reads from the named pipe which was created and filled by
  1419. X                  do_ispit.sh.
  1420. X
  1421. X                  The "filename" argument to the lp command is /etc/passwd.
  1422. X                  This file is not actually transmitted by the ispit/ispin
  1423. X                  process. We use /etc/passwd as a placeholder on the 
  1424. X                  command line since lp will not queue a request without a
  1425. X                  valid non-null filename.
  1426. X
  1427. X                  do_ispit.sh requires three arguments:
  1428. X
  1429. X                  - First is the name of the source file to be transferred.
  1430. X                    
  1431. X                  - Second is the destination file name on the destination 
  1432. X                    system. This argument should be a full path name. All
  1433. X                    elements of the path must exist. The destination directory
  1434. X                    must be writable by the user "ispit" on the remote system.
  1435. X                    If this argument is less than a fully qualified path, the
  1436. X                    remote system will interpret the argument relative to
  1437. X                    ispit's home directory.
  1438. X
  1439. X                  - Third is the (lp) queue member which will process the
  1440. X                    request.
  1441. X
  1442. X                  On dual universe machines, the calls to "compress", "btoa",
  1443. X                  "cut", and "lp" may have to be preceded by the appropriate
  1444. X                  universe call. Path names to commands may also require 
  1445. X                  adjustment.
  1446. X
  1447. Xinterface      -  This shell script is the lp interface file for ispit on
  1448. X                  the source system.
  1449. X
  1450. Xeot_trap.c   * -  source for a filter program which watches for an ascii
  1451. X                  "EOT" character. eot_trap filters the input 
  1452. X                  on the receiving system. The source system's rtab entry
  1453. X                  for the "ispit" queue member sends EOT as the first action
  1454. X                  of the ispin quit sequence. eot_trap exits, ending the 
  1455. X                  login session, so ispit exits. This dependence upon
  1456. X                  EOT makes it IMPERATIVE that all output be converted by
  1457. X                  btoa(1). See do_ispit.sh.
  1458. X
  1459. Xispit.sh     * -  see passwd.entry, below. This is the script which is invoked
  1460. X                  upon login by and for the ispit user. Notice that ispit.sh
  1461. X                  expects (actually requires) that a variable
  1462. X                  "OF" is assigned a sane value. This value is passed at login
  1463. X                  time by the user "ispit". See rtab.entry for the "\U".
  1464. X
  1465. X                  NOTE: ispit.sh calls the executable "eot_trap", assuming
  1466. X                        that the executable is located in ispit's home
  1467. X                        directory. 
  1468. X
  1469. Xpasswd.entry * -  this is the /etc/passwd entry for the ispit user on the 
  1470. X                  destination machine. The last field of the entry is the full
  1471. X                  path name of the ispit.sh script. Change the location of
  1472. X                  ispit's home directory as you see fit.
  1473. X
  1474. X
  1475. X
  1476. X                  * - denotes this file, data, or program exists on the
  1477. X                      destination machine. All else exists on the source
  1478. X                      machine.
  1479. END_OF_FILE
  1480. if test 4517 -ne `wc -c <'ISPIN/misc/ISPIT.dr/README'`; then
  1481.     echo shar: \"'ISPIN/misc/ISPIT.dr/README'\" unpacked with wrong size!
  1482. fi
  1483. # end of 'ISPIN/misc/ISPIT.dr/README'
  1484. fi
  1485. if test -f 'ISPIN/misc/ISPIT.dr/passwd.entry' -a "${1}" != "-c" ; then 
  1486.   echo shar: Will not clobber existing file \"'ISPIN/misc/ISPIT.dr/passwd.entry'\"
  1487. else
  1488. echo shar: Extracting \"'ISPIN/misc/ISPIT.dr/passwd.entry'\" \(56 characters\)
  1489. sed "s/^X//" >'ISPIN/misc/ISPIT.dr/passwd.entry' <<'END_OF_FILE'
  1490. Xispit:9CKYrm.On.kVs:437:4::/zb/ispit:/zb/ispit/ispit.sh
  1491. END_OF_FILE
  1492. if test 56 -ne `wc -c <'ISPIN/misc/ISPIT.dr/passwd.entry'`; then
  1493.     echo shar: \"'ISPIN/misc/ISPIT.dr/passwd.entry'\" unpacked with wrong size!
  1494. fi
  1495. # end of 'ISPIN/misc/ISPIT.dr/passwd.entry'
  1496. fi
  1497. echo shar: End of archive 9 \(of 15\).
  1498. cp /dev/null ark9isdone
  1499. MISSING=""
  1500. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
  1501.     if test ! -f ark${I}isdone ; then
  1502.     MISSING="${MISSING} ${I}"
  1503.     fi
  1504. done
  1505. if test "${MISSING}" = "" ; then
  1506.     echo You have unpacked all 15 archives.
  1507.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1508. else
  1509.     echo You still need to unpack the following archives:
  1510.     echo "        " ${MISSING}
  1511. fi
  1512. ##  End of shell archive.
  1513. exit 0
  1514.  
  1515.