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

  1. Newsgroups: comp.sources.unix
  2. From: sir-alan!ispin!lbartz@iuvax.cs.indiana.edu (Larry Bartz)
  3. Subject: v25i119: Indianapolis Standard Printer Interface for Networked printers, Part08/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 119
  9. Archive-Name: ispin/part08
  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 8 (of 15)."
  18. # Contents:  ISPIN/src/ISPIN.c.ab ISPIN/install/rtab
  19. #   ISPIN/doc/OLD-DOCS/README.beta.2 ISPIN/misc/ISPIT.dr/do_ispit.sh
  20. #   ISPIN/misc/ISPIT.dr/interface
  21. # Wrapped by socrates@indy6 on Tue Jan 28 15:26:52 1992
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. if test -f 'ISPIN/src/ISPIN.c.ab' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'ISPIN/src/ISPIN.c.ab'\"
  25. else
  26. echo shar: Extracting \"'ISPIN/src/ISPIN.c.ab'\" \(27709 characters\)
  27. sed "s/^X//" >'ISPIN/src/ISPIN.c.ab' <<'END_OF_FILE'
  28. X
  29. X                    /* Put our new-found data in the newly allocated storage */
  30. X                    /* after first aiming the pointer at more new storage.   */
  31. X                    /* string begins at tokptr[2] */
  32. X                    dead_curr->dead_strg = (char *) calloc(1, ((strlen(&tokptr[2]))+1));
  33. X                    strcpy(dead_curr->dead_strg,&tokptr[2]);
  34. X
  35. X
  36. X
  37. X
  38. X
  39. X                    /* terminate the list */
  40. X                    dead_curr->next = NULL;
  41. X                    break;
  42. X                  case 'Q':
  43. X                    /* QUIT */
  44. X                    while(quit_curr->next != NULL) /* until end o'list */
  45. X                    {
  46. X                      /* walk down the list */
  47. X                      quit_curr = quit_curr->next;
  48. X                    }
  49. X
  50. X                    /* don't really use the head for data storage */
  51. X                    /* allocate a new one */
  52. X                    quit_list = (struct quit_list *) calloc(1,sizeof(struct quit_list));
  53. X
  54. X                    /* link it */
  55. X                    quit_curr->next = quit_list;
  56. X
  57. X                    /* make the new list member the current list member */
  58. X                    quit_curr = quit_list;
  59. X
  60. X                    /* Put our new-found data in the newly allocated storage */
  61. X                    /* after first aiming the pointer at more new storage.   */
  62. X                    /* string begins at tokptr[2] */
  63. X                    quit_curr->quit_strg = (char *) calloc(1, ((strlen(&tokptr[2]))+1));
  64. X                    strcpy(quit_curr->quit_strg,&tokptr[2]);
  65. X
  66. X
  67. X
  68. X
  69. X
  70. X                    /* terminate the list */
  71. X                    quit_curr->next = NULL;
  72. X                    break;
  73. X                  case 'D':
  74. X                    /* DISCONNECT */
  75. X                    while(disc_curr->next != NULL) /* until end o'list */
  76. X                    {
  77. X                      /* walk down the list */
  78. X                      disc_curr = disc_curr->next;
  79. X                    }
  80. X
  81. X                    /* don't really use the head for data storage */
  82. X                    /* allocate a new one */
  83. X                    disc_list = (struct disc_list *) calloc(1,sizeof(struct disc_list));
  84. X
  85. X                    /* link it */
  86. X                    disc_curr->next = disc_list;
  87. X
  88. X                    /* make the new list member the current list member */
  89. X                    disc_curr = disc_list;
  90. X
  91. X                    /* Put our new-found data in the newly allocated storage */
  92. X                    /* after first aiming the pointer at more new storage.   */
  93. X                    /* string begins at tokptr[2] */
  94. X                    disc_curr->disc_strg = (char *) calloc(1, ((strlen(&tokptr[2]))+1));
  95. X                    strcpy(disc_curr->disc_strg,&tokptr[2]);
  96. X
  97. X
  98. X
  99. X
  100. X
  101. X                    /* terminate the list */
  102. X                    disc_curr->next = NULL;
  103. X                    break;
  104. X                  case 'L':
  105. X                    /* LOGGING enabled */
  106. X                    ++logging;
  107. X                    break;
  108. X                  case 'R':
  109. X                    /* absolutely RAW output */
  110. X                    ++raw;
  111. X                    break;
  112. X                  case 'T':
  113. X                    /* TAB EXPANSION enabled */
  114. X                    if(raw < 1)
  115. X                    {
  116. X                      ++tab_expand;
  117. X                    }
  118. X                    break;
  119. X                }
  120. X                break;
  121. X              default:
  122. X                switch(toggle)
  123. X                {
  124. X                  case 0:
  125. X                    /* EXPECT */
  126. X                    toggle = 1;   /* switch the EXPECT/SEND toggle */
  127. X                    while(expt_curr->next != NULL) /* until end o'list */
  128. X                    {
  129. X                      /* walk down the list */
  130. X                      expt_curr = expt_curr->next;
  131. X                    }
  132. X
  133. X                    /* don't really use the head for data storage */
  134. X                    /* allocate a new one */
  135. X                    expt_list = (struct expt_list *) calloc(1,sizeof(struct expt_list));
  136. X
  137. X                    /* link it */
  138. X                    expt_list->prev = expt_curr;
  139. X                    expt_curr->next = expt_list;
  140. X
  141. X                    /* make the new list member the current list member */
  142. X                    expt_curr = expt_list;
  143. X
  144. X                    /* Put our new-found data in the newly allocated storage */
  145. X                    /* after first aiming the pointer at more new storage.   */
  146. X                    expt_curr->expt_strg = (char *) calloc(1, ((strlen(tokptr))+1));
  147. X                    strcpy(expt_curr->expt_strg,tokptr);
  148. X
  149. X                    /* terminate the list */
  150. X                    expt_curr->next = NULL;
  151. X                    break;
  152. X                  case 1:
  153. X                    /* SEND */
  154. X                    toggle = 0;   /* switch the EXPECT/SEND toggle */
  155. X                    while(send_curr->next != NULL) /* until end o'list */
  156. X                    {
  157. X                      /* walk down the list */
  158. X                      send_curr = send_curr->next;
  159. X                    }
  160. X
  161. X                    /* don't really use the head for data storage */
  162. X                    /* allocate a new one */
  163. X                    send_list = (struct send_list *) calloc(1,sizeof(struct send_list));
  164. X
  165. X                    /* link it */
  166. X                    send_list->prev = send_curr;
  167. X                    send_curr->next = send_list;
  168. X
  169. X                    /* make the new list member the current list member */
  170. X                    send_curr = send_list;
  171. X
  172. X                    /* Put our new-found data in the newly allocated storage */
  173. X                    /* after first aiming the pointer at more new storage.   */
  174. X                    send_curr->send_strg = (char *) calloc(1, ((strlen(tokptr))+1));
  175. X                    strcpy(send_curr->send_strg,tokptr);
  176. X
  177. X                    /* terminate the list */
  178. X                    send_curr->next = NULL;
  179. X                    break;
  180. X                }
  181. X                break;
  182. X            }
  183. X            break;
  184. X        }
  185. X      }
  186. X      return(0);
  187. X    }
  188. X    else
  189. X    {
  190. X      return(1);
  191. X    }
  192. X  }
  193. X  else
  194. X  {
  195. X    return(1);
  196. X  }
  197. X}
  198. X
  199. X
  200. X/****************************************************************************/
  201. X/*  notify               author = bartz                            112988   */
  202. X/****************************************************************************/
  203. X/*                                                                          */
  204. X/*   subroutine to notify secondary queuer of our state and (maybe) await   */
  205. X/*   acknowledgement                                                        */
  206. X/*                                                                          */
  207. X/****************************************************************************/
  208. X/*                                                                          */
  209. X/*   description -  This function sends a message to the secondary queuer   */
  210. X/*                  via a FIFO from which only the secondary queuer is      */
  211. X/*                  reading. We then read from a private FIFO through       */
  212. X/*                  which only the secondary queuer will write. The         */
  213. X/*                  message we send notifies the secondary queuer of our    */
  214. X/*                  state and of our needs. The message the secondary       */
  215. X/*                  queuer (IQUEUER) sends us gives us our marching         */
  216. X/*                  orders.                                                 */
  217. X/*                                                                          */
  218. X/*                                                                          */
  219. X/*   how invoked - notify(state)                                            */
  220. X/*                 int state;                                               */
  221. X/*                                                                          */
  222. X/*                                                                          */
  223. X/*                                                                          */
  224. X/*                                                                          */
  225. X/*                                                                          */
  226. X/****************************************************************************/
  227. X
  228. Xnotify(state)
  229. Xint state;
  230. X{
  231. X
  232. X  /* set a global variable to retain current state */
  233. X  stayt = state;
  234. X
  235. X  switch(state)
  236. X  {
  237. X    case HERE:
  238. X      /* tell IQUEUER we're here */
  239. X      /* construct the message */
  240. X
  241. X      /* what type of message? */
  242. X      req_msg.typ.intgr = HERE;
  243. X
  244. X      /* what is my pid? */
  245. X      req_msg.my_pid.intgr = getpid();
  246. X
  247. X      /* get the inode of the device(s) we want */
  248. X
  249. X      for(ret_val = 0;ret_val <= 10; ++ret_val)
  250. X      {
  251. X        if(strcmp(dev_ray[ret_val].name,"NONE") != 0)
  252. X        {
  253. X          if(stat(dev_ray[ret_val].name,stat_buf))
  254. X          {
  255. X            /* need to send out an error msg */
  256. X            /* format an error message */
  257. X            time(&tloc);
  258. X            nowtime = (struct tm *)localtime(&tloc);
  259. X            time_str = asctime(nowtime);
  260. X
  261. X            sprintf(errmsg,"ISPIN: printer %s: stat %s: %s.\n",dest,dev_ray[ret_val].name,sys_errlist[errno]);
  262. X            sprintf(errmsg2,"    USER: %s\n",from);
  263. X            strcat(errmsg,errmsg2);
  264. X          if(usr_addr)
  265. X          {
  266. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  267. X            strcat(errmsg,errmsg2);
  268. X          }
  269. X#ifdef NQ
  270. X            sprintf(errmsg2,"    FILE: %s\n",fyle);
  271. X#else
  272. X            sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  273. X#endif
  274. X            strcat(errmsg,errmsg2);
  275. X            sprintf(errmsg2,"    TIME: %s\n",time_str);
  276. X            strcat(errmsg,errmsg2);
  277. X
  278. X            /* call the error routine, never come back */
  279. X            my_error(SYSERR);
  280. X          }
  281. X          dev_ray[ret_val].inode = (int)stat_buf->st_ino;
  282. X        }
  283. X    else
  284. X    {
  285. X      dev_ray[ret_val].inode = 0;
  286. X    }
  287. X      }
  288. X
  289. X      req_msg.dev1_inod.intgr = dev_ray[0].inode;
  290. X      req_msg.dev2_inod.intgr = dev_ray[1].inode;
  291. X      req_msg.dev3_inod.intgr = dev_ray[2].inode;
  292. X      req_msg.dev4_inod.intgr = dev_ray[3].inode;
  293. X      req_msg.dev5_inod.intgr = dev_ray[4].inode;
  294. X      req_msg.dev6_inod.intgr = dev_ray[5].inode;
  295. X      req_msg.dev7_inod.intgr = dev_ray[6].inode;
  296. X      req_msg.dev8_inod.intgr = dev_ray[7].inode;
  297. X      req_msg.dev9_inod.intgr = dev_ray[8].inode;
  298. X      req_msg.dev10_inod.intgr = dev_ray[9].inode;
  299. X      req_msg.dev11_inod.intgr = dev_ray[10].inode;
  300. X
  301. X      /* identify the requesting user */
  302. X      if((pass = getpwnam(from)) != NULL)
  303. X      {
  304. X        req_msg.uid.intgr = pass->pw_uid;
  305. X        endpwent();
  306. X      }
  307. X      else
  308. X      {
  309. X        req_msg.uid.intgr = (int)getuid();
  310. X      }
  311. X
  312. X#ifdef LP
  313. X      /* If this process is running as setuid to root (uid == 0),
  314. X         then setuid to the requesting user.      05/09/91  LSB   */
  315. X      if(geteuid() == 0)
  316. X      {
  317. X        setgid(pass->pw_gid);
  318. X        setuid(pass->pw_uid);
  319. X      }
  320. X#endif
  321. X
  322. X      /* this is loop 0 */
  323. X      req_msg.loop.intgr = 0;
  324. X
  325. X      /* fill the msg_buf from the structure of unions */
  326. X      count1 = count2 = 0;
  327. X
  328. X      while(count1 < intsize)
  329. X      {
  330. X        msg_buf[count2++] = req_msg.typ.chr[count1++];
  331. X      }
  332. X      count1 = 0;
  333. X
  334. X      while(count1 < intsize)
  335. X      {
  336. X        msg_buf[count2++] = req_msg.my_pid.chr[count1++];
  337. X      }
  338. X      count1 = 0;
  339. X
  340. X      while(count1 < intsize)
  341. X      {
  342. X        msg_buf[count2++] = req_msg.my_fifo.chr[count1++];
  343. X      }
  344. X      count1 = 0;
  345. X
  346. X      while(count1 < intsize)
  347. X      {
  348. X        msg_buf[count2++] = req_msg.dev1_inod.chr[count1++];
  349. X      }
  350. X      count1 = 0;
  351. X
  352. X      while(count1 < intsize)
  353. X      {
  354. X        msg_buf[count2++] = req_msg.dev2_inod.chr[count1++];
  355. X      }
  356. X      count1 = 0;
  357. X
  358. X      while(count1 < intsize)
  359. X      {
  360. X        msg_buf[count2++] = req_msg.dev3_inod.chr[count1++];
  361. X      }
  362. X      count1 = 0;
  363. X
  364. X      while(count1 < intsize)
  365. X      {
  366. X        msg_buf[count2++] = req_msg.dev4_inod.chr[count1++];
  367. X      }
  368. X      count1 = 0;
  369. X
  370. X      while(count1 < intsize)
  371. X      {
  372. X        msg_buf[count2++] = req_msg.dev5_inod.chr[count1++];
  373. X      }
  374. X      count1 = 0;
  375. X
  376. X      while(count1 < intsize)
  377. X      {
  378. X        msg_buf[count2++] = req_msg.dev6_inod.chr[count1++];
  379. X      }
  380. X      count1 = 0;
  381. X
  382. X      while(count1 < intsize)
  383. X      {
  384. X        msg_buf[count2++] = req_msg.dev7_inod.chr[count1++];
  385. X      }
  386. X      count1 = 0;
  387. X
  388. X      while(count1 < intsize)
  389. X      {
  390. X        msg_buf[count2++] = req_msg.dev8_inod.chr[count1++];
  391. X      }
  392. X      count1 = 0;
  393. X
  394. X      while(count1 < intsize)
  395. X      {
  396. X        msg_buf[count2++] = req_msg.dev9_inod.chr[count1++];
  397. X      }
  398. X      count1 = 0;
  399. X
  400. X      while(count1 < intsize)
  401. X      {
  402. X        msg_buf[count2++] = req_msg.dev10_inod.chr[count1++];
  403. X      }
  404. X      count1 = 0;
  405. X
  406. X      while(count1 < intsize)
  407. X      {
  408. X        msg_buf[count2++] = req_msg.dev11_inod.chr[count1++];
  409. X      }
  410. X      count1 = 0;
  411. X
  412. X      while(count1 < intsize)
  413. X      {
  414. X        msg_buf[count2++] = req_msg.uid.chr[count1++];
  415. X      }
  416. X      count1 = 0;
  417. X
  418. X      while(count1 < intsize)
  419. X      {
  420. X        msg_buf[count2++] = req_msg.loop.chr[count1++];
  421. X      }
  422. X      count1 = 0;
  423. X      count2 = 0;
  424. X
  425. X      /* the message is ready to go, so send it */
  426. X
  427. X      write(outfifo,msg_buf,to_iqrsiz);
  428. X
  429. X      /* Now wait for a response, in the form of a work order. */
  430. X      /* A blocking read will allow the kernel to put us to sleep until... */
  431. X
  432. X      chars_got = read(infifo,msg_buf,to_ispinsiz);
  433. X      if(chars_got < 1)
  434. X      {
  435. X        close(infifo);
  436. X        if((infifo = open(inFIFO,O_RDONLY)) == -1)
  437. X        {
  438. X          /* need to send out an error msg */
  439. X                /* format an error message */
  440. X                time(&tloc);
  441. X                nowtime = (struct tm *)localtime(&tloc);
  442. X                time_str = asctime(nowtime);
  443. X
  444. X                sprintf(errmsg,"ISPIN: printer %s: open %s: %s.\n",dest,inFIFO,sys_errlist[errno]);
  445. X          sprintf(errmsg2,"    USER: %s\n",from);
  446. X          strcat(errmsg,errmsg2);
  447. X          if(usr_addr)
  448. X          {
  449. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  450. X            strcat(errmsg,errmsg2);
  451. X          }
  452. X#ifdef NQ
  453. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  454. X#else
  455. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  456. X#endif
  457. X          strcat(errmsg,errmsg2);
  458. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  459. X          strcat(errmsg,errmsg2);
  460. X
  461. X               /* call the error routine, never come back */
  462. X               my_error(SYSERR);
  463. X
  464. X        }
  465. X        chars_got = read(infifo,msg_buf,to_ispinsiz);
  466. X      }
  467. X
  468. X      /* back from the read, so proceed */
  469. X      /* fill the structure of unions from the msg_buf */
  470. X      while(count1 < intsize)
  471. X      {
  472. X        cmd_msg.orders.chr[count1++] = msg_buf[count2++];
  473. X      }
  474. X      count1 = 0;
  475. X
  476. X      while(count1 < intsize)
  477. X      {
  478. X        cmd_msg.iq_pid.chr[count1++] = msg_buf[count2++];
  479. X      }
  480. X      count1 = 0;
  481. X
  482. X      while(count1 < intsize)
  483. X      {
  484. X        cmd_msg.dev_use_ino.chr[count1++] = msg_buf[count2++];
  485. X      }
  486. X      count1 = 0;
  487. X
  488. X      while(count1 < intsize)
  489. X      {
  490. X        cmd_msg.pad1.chr[count1++] = msg_buf[count2++];
  491. X      }
  492. X      count1 = 0;
  493. X      count2 = 0;
  494. X
  495. X      /* the way things look now (12/06/88), the only message we'll get is GO */
  496. X      /* otherwise, I'd put in a switch on cmd_msg.orders right here.          */
  497. X
  498. X
  499. X      /* IQUEUER chose which device we are to use */
  500. X      for(ret_val = 0;ret_val <= 10; ++ret_val)
  501. X      {
  502. X        if(cmd_msg.dev_use_ino.intgr == dev_ray[ret_val].inode)
  503. X        {
  504. X          strcpy(GO_dev,dev_ray[ret_val].name);
  505. X      /* set a flag to indicate success */
  506. X      count1 = 1;
  507. X        }
  508. X      }
  509. X      if(count1 == 0)
  510. X      {
  511. X        /* big problems */
  512. X        /* need to send out an error msg */
  513. X          /* format an error message */
  514. X          time(&tloc);
  515. X          nowtime = (struct tm *)localtime(&tloc);
  516. X          time_str = asctime(nowtime);
  517. X
  518. X          sprintf(errmsg,"ISPIN: printer %s: goofy inode from IQUEUER.\n",dest);
  519. X          sprintf(errmsg2,"    USER: %s\n",from);
  520. X          strcat(errmsg,errmsg2);
  521. X          if(usr_addr)
  522. X          {
  523. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  524. X            strcat(errmsg,errmsg2);
  525. X          }
  526. X#ifdef NQ
  527. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  528. X#else
  529. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  530. X#endif
  531. X          strcat(errmsg,errmsg2);
  532. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  533. X          strcat(errmsg,errmsg2);
  534. X
  535. X         /* call the error routine, never come back */
  536. X         my_error(MYERR);
  537. X
  538. X      }
  539. X      
  540. X      break;
  541. X
  542. X    case BUSY:
  543. X   /* Assign an initial value to GO_dev string, so log messages which use */
  544. X   /* it make sense. Also so we don't dump core trying to strcat from a   */
  545. X   /* memory address which is undefined.                    05/09/90 LSB  */
  546. X   sprintf(GO_dev,"undefined");
  547. X
  548. X      /* what type of message? */
  549. X      req_msg.typ.intgr = BUSY;
  550. X
  551. X      /* that's all we have to change from the previous message */
  552. X
  553. X      /* the message is ready to go, so send it */
  554. X
  555. X      /* fill the msg_buf from the structure of unions */
  556. X      count1 = count2 = 0;
  557. X
  558. X      while(count1 < intsize)
  559. X      {
  560. X        msg_buf[count2++] = req_msg.typ.chr[count1++];
  561. X      }
  562. X      count1 = 0;
  563. X
  564. X      while(count1 < intsize)
  565. X      {
  566. X        msg_buf[count2++] = req_msg.my_pid.chr[count1++];
  567. X      }
  568. X      count1 = 0;
  569. X
  570. X      while(count1 < intsize)
  571. X      {
  572. X        msg_buf[count2++] = req_msg.my_fifo.chr[count1++];
  573. X      }
  574. X      count1 = 0;
  575. X
  576. X      while(count1 < intsize)
  577. X      {
  578. X        msg_buf[count2++] = req_msg.dev1_inod.chr[count1++];
  579. X      }
  580. X      count1 = 0;
  581. X
  582. X      while(count1 < intsize)
  583. X      {
  584. X        msg_buf[count2++] = req_msg.dev2_inod.chr[count1++];
  585. X      }
  586. X      count1 = 0;
  587. X
  588. X      while(count1 < intsize)
  589. X      {
  590. X        msg_buf[count2++] = req_msg.dev3_inod.chr[count1++];
  591. X      }
  592. X      count1 = 0;
  593. X
  594. X      while(count1 < intsize)
  595. X      {
  596. X        msg_buf[count2++] = req_msg.dev4_inod.chr[count1++];
  597. X      }
  598. X      count1 = 0;
  599. X
  600. X      while(count1 < intsize)
  601. X      {
  602. X        msg_buf[count2++] = req_msg.dev5_inod.chr[count1++];
  603. X      }
  604. X      count1 = 0;
  605. X
  606. X      while(count1 < intsize)
  607. X      {
  608. X        msg_buf[count2++] = req_msg.dev6_inod.chr[count1++];
  609. X      }
  610. X      count1 = 0;
  611. X
  612. X      while(count1 < intsize)
  613. X      {
  614. X        msg_buf[count2++] = req_msg.dev7_inod.chr[count1++];
  615. X      }
  616. X      count1 = 0;
  617. X
  618. X      while(count1 < intsize)
  619. X      {
  620. X        msg_buf[count2++] = req_msg.dev8_inod.chr[count1++];
  621. X      }
  622. X      count1 = 0;
  623. X
  624. X      while(count1 < intsize)
  625. X      {
  626. X        msg_buf[count2++] = req_msg.dev9_inod.chr[count1++];
  627. X      }
  628. X      count1 = 0;
  629. X
  630. X      while(count1 < intsize)
  631. X      {
  632. X        msg_buf[count2++] = req_msg.dev10_inod.chr[count1++];
  633. X      }
  634. X      count1 = 0;
  635. X
  636. X      while(count1 < intsize)
  637. X      {
  638. X        msg_buf[count2++] = req_msg.dev11_inod.chr[count1++];
  639. X      }
  640. X      count1 = 0;
  641. X
  642. X      while(count1 < intsize)
  643. X      {
  644. X        msg_buf[count2++] = req_msg.uid.chr[count1++];
  645. X      }
  646. X      count1 = 0;
  647. X
  648. X      while(count1 < intsize)
  649. X      {
  650. X        msg_buf[count2++] = req_msg.loop.chr[count1++];
  651. X      }
  652. X      count1 = 0;
  653. X      count2 = 0;
  654. X
  655. X      /* the message is ready to go, so send it */
  656. X
  657. X      write(outfifo,msg_buf,to_iqrsiz);
  658. X
  659. X      /* Now wait for a response, in the form of a work order. */
  660. X      /* A blocking read will allow the kernel to put us to sleep until... */
  661. X
  662. X      chars_got = read(infifo,msg_buf,to_ispinsiz);
  663. X      if(chars_got < 1)
  664. X      {
  665. X        close(infifo);
  666. X        if((infifo = open(inFIFO,O_RDONLY)) == -1)
  667. X        {
  668. X          /* need to send out an error msg */
  669. X                /* format an error message */
  670. X                time(&tloc);
  671. X                nowtime = (struct tm *)localtime(&tloc);
  672. X                time_str = asctime(nowtime);
  673. X
  674. X                sprintf(errmsg,"ISPIN: printer %s: open %s: %s.\n",dest,inFIFO,sys_errlist[errno]);
  675. X          sprintf(errmsg2,"    USER: %s\n",from);
  676. X          strcat(errmsg,errmsg2);
  677. X          if(usr_addr)
  678. X          {
  679. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  680. X            strcat(errmsg,errmsg2);
  681. X          }
  682. X#ifdef NQ
  683. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  684. X#else
  685. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  686. X#endif
  687. X          strcat(errmsg,errmsg2);
  688. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  689. X          strcat(errmsg,errmsg2);
  690. X
  691. X               /* call the error routine, never come back */
  692. X               my_error(SYSERR);
  693. X
  694. X        }
  695. X        chars_got = read(infifo,msg_buf,to_ispinsiz);
  696. X      }
  697. X
  698. X
  699. X      /* back from the read, so proceed */
  700. X      /* fill the structure of unions from the msg_buf */
  701. X      while(count1 < intsize)
  702. X      {
  703. X        cmd_msg.orders.chr[count1++] = msg_buf[count2++];
  704. X      }
  705. X      count1 = 0;
  706. X
  707. X      while(count1 < intsize)
  708. X      {
  709. X        cmd_msg.iq_pid.chr[count1++] = msg_buf[count2++];
  710. X      }
  711. X      count1 = 0;
  712. X
  713. X      while(count1 < intsize)
  714. X      {
  715. X        cmd_msg.dev_use_ino.chr[count1++] = msg_buf[count2++];
  716. X      }
  717. X      count1 = 0;
  718. X
  719. X      while(count1 < intsize)
  720. X      {
  721. X        cmd_msg.pad1.chr[count1++] = msg_buf[count2++];
  722. X      }
  723. X      count1 = 0;
  724. X      count2 = 0;
  725. X
  726. X      /* the way things look now (12/06/88), the only message we'll get is GO */
  727. X      /* otherwise, I'd put in a switch on cmd_msg.orders right here.          */
  728. X
  729. X      /* IQUEUER chose which device we are to use */
  730. X      for(ret_val = 0;ret_val <= 10; ++ret_val)
  731. X      {
  732. X        if(cmd_msg.dev_use_ino.intgr == dev_ray[ret_val].inode)
  733. X        {
  734. X          strcpy(GO_dev,dev_ray[ret_val].name);
  735. X      /* set a flag to indicate success */
  736. X      count1 = 1;
  737. X        }
  738. X      }
  739. X      if(count1 == 0)
  740. X      {
  741. X        /* big problems */
  742. X        /* need to send out an error msg */
  743. X          /* format an error message */
  744. X          time(&tloc);
  745. X          nowtime = (struct tm *)localtime(&tloc);
  746. X          time_str = asctime(nowtime);
  747. X
  748. X          sprintf(errmsg,"ISPIN: printer %s: goofy inode from IQUEUER.\n",dest);
  749. X          sprintf(errmsg2,"    USER: %s\n",from);
  750. X          strcat(errmsg,errmsg2);
  751. X          if(usr_addr)
  752. X          {
  753. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  754. X            strcat(errmsg,errmsg2);
  755. X          }
  756. X#ifdef NQ
  757. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  758. X#else
  759. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  760. X#endif
  761. X          strcat(errmsg,errmsg2);
  762. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  763. X          strcat(errmsg,errmsg2);
  764. X
  765. X         /* call the error routine, never come back */
  766. X         my_error(MYERR);
  767. X
  768. X      }
  769. X
  770. X      break;
  771. X
  772. X
  773. X    case DONE:
  774. X    case TROUBLE:
  775. X      /* tell IQUEUER we're finished */
  776. X      /* construct the message */
  777. X
  778. X      /* what type of message? */
  779. X      req_msg.typ.intgr = DONE;
  780. X
  781. X      /* that's all we have to change from the previous message */
  782. X
  783. X      /* the message is ready to go, so send it */
  784. X
  785. X      /* fill the msg_buf from the structure of unions */
  786. X      count1 = count2 = 0;
  787. X
  788. X      while(count1 < intsize)
  789. X      {
  790. X        msg_buf[count2++] = req_msg.typ.chr[count1++];
  791. X      }
  792. X      count1 = 0;
  793. X
  794. X      while(count1 < intsize)
  795. X      {
  796. X        msg_buf[count2++] = req_msg.my_pid.chr[count1++];
  797. X      }
  798. X      count1 = 0;
  799. X
  800. X      while(count1 < intsize)
  801. X      {
  802. X        msg_buf[count2++] = req_msg.my_fifo.chr[count1++];
  803. X      }
  804. X      count1 = 0;
  805. X
  806. X      while(count1 < intsize)
  807. X      {
  808. X        msg_buf[count2++] = req_msg.dev1_inod.chr[count1++];
  809. X      }
  810. X      count1 = 0;
  811. X
  812. X      while(count1 < intsize)
  813. X      {
  814. X        msg_buf[count2++] = req_msg.dev2_inod.chr[count1++];
  815. X      }
  816. X      count1 = 0;
  817. X
  818. X      while(count1 < intsize)
  819. X      {
  820. X        msg_buf[count2++] = req_msg.dev3_inod.chr[count1++];
  821. X      }
  822. X      count1 = 0;
  823. X
  824. X      while(count1 < intsize)
  825. X      {
  826. X        msg_buf[count2++] = req_msg.dev4_inod.chr[count1++];
  827. X      }
  828. X      count1 = 0;
  829. X
  830. X      while(count1 < intsize)
  831. X      {
  832. X        msg_buf[count2++] = req_msg.dev5_inod.chr[count1++];
  833. X      }
  834. X      count1 = 0;
  835. X
  836. X      while(count1 < intsize)
  837. X      {
  838. X        msg_buf[count2++] = req_msg.dev6_inod.chr[count1++];
  839. X      }
  840. X      count1 = 0;
  841. X
  842. X      while(count1 < intsize)
  843. X      {
  844. X        msg_buf[count2++] = req_msg.dev7_inod.chr[count1++];
  845. X      }
  846. X      count1 = 0;
  847. X
  848. X      while(count1 < intsize)
  849. X      {
  850. X        msg_buf[count2++] = req_msg.dev8_inod.chr[count1++];
  851. X      }
  852. X      count1 = 0;
  853. X
  854. X      while(count1 < intsize)
  855. X      {
  856. X        msg_buf[count2++] = req_msg.dev9_inod.chr[count1++];
  857. X      }
  858. X      count1 = 0;
  859. X
  860. X      while(count1 < intsize)
  861. X      {
  862. X        msg_buf[count2++] = req_msg.dev10_inod.chr[count1++];
  863. X      }
  864. X      count1 = 0;
  865. X
  866. X      while(count1 < intsize)
  867. X      {
  868. X        msg_buf[count2++] = req_msg.dev11_inod.chr[count1++];
  869. X      }
  870. X      count1 = 0;
  871. X
  872. X      while(count1 < intsize)
  873. X      {
  874. X        msg_buf[count2++] = req_msg.uid.chr[count1++];
  875. X      }
  876. X      count1 = 0;
  877. X
  878. X      while(count1 < intsize)
  879. X      {
  880. X        msg_buf[count2++] = req_msg.loop.chr[count1++];
  881. X      }
  882. X      count1 = 0;
  883. X      count2 = 0;
  884. X
  885. X      /* the message is ready to go, so send it */
  886. X
  887. X      write(outfifo,msg_buf,to_iqrsiz);
  888. X
  889. X
  890. X      /* Don't wait for a response */
  891. X
  892. X      break;
  893. X
  894. X    default:
  895. X      /* pass current state to IQUEUER */
  896. X      /* construct the message */
  897. X
  898. X      /* what type of message? */
  899. X      req_msg.typ.intgr = state;
  900. X
  901. X      /* that's all we have to change from the previous message */
  902. X
  903. X      /* the message is ready to go, so send it */
  904. X
  905. X      /* fill the msg_buf from the structure of unions */
  906. X      count1 = count2 = 0;
  907. X
  908. X      while(count1 < intsize)
  909. X      {
  910. X        msg_buf[count2++] = req_msg.typ.chr[count1++];
  911. X      }
  912. X      count1 = 0;
  913. X
  914. X      while(count1 < intsize)
  915. X      {
  916. X        msg_buf[count2++] = req_msg.my_pid.chr[count1++];
  917. X      }
  918. X      count1 = 0;
  919. X
  920. X      while(count1 < intsize)
  921. X      {
  922. X        msg_buf[count2++] = req_msg.my_fifo.chr[count1++];
  923. X      }
  924. X      count1 = 0;
  925. X
  926. X      while(count1 < intsize)
  927. X      {
  928. X        msg_buf[count2++] = req_msg.dev1_inod.chr[count1++];
  929. X      }
  930. X      count1 = 0;
  931. X
  932. X      while(count1 < intsize)
  933. X      {
  934. X        msg_buf[count2++] = req_msg.dev2_inod.chr[count1++];
  935. X      }
  936. X      count1 = 0;
  937. X
  938. X      while(count1 < intsize)
  939. X      {
  940. X        msg_buf[count2++] = req_msg.dev3_inod.chr[count1++];
  941. X      }
  942. X      count1 = 0;
  943. X
  944. X      while(count1 < intsize)
  945. X      {
  946. X        msg_buf[count2++] = req_msg.dev4_inod.chr[count1++];
  947. X      }
  948. X      count1 = 0;
  949. X
  950. X      while(count1 < intsize)
  951. X      {
  952. X        msg_buf[count2++] = req_msg.dev5_inod.chr[count1++];
  953. X      }
  954. X      count1 = 0;
  955. X
  956. X      while(count1 < intsize)
  957. X      {
  958. X        msg_buf[count2++] = req_msg.dev6_inod.chr[count1++];
  959. X      }
  960. X      count1 = 0;
  961. X
  962. X      while(count1 < intsize)
  963. X      {
  964. X        msg_buf[count2++] = req_msg.dev7_inod.chr[count1++];
  965. X      }
  966. X      count1 = 0;
  967. X
  968. X      while(count1 < intsize)
  969. X      {
  970. X        msg_buf[count2++] = req_msg.dev8_inod.chr[count1++];
  971. X      }
  972. X      count1 = 0;
  973. X
  974. X      while(count1 < intsize)
  975. X      {
  976. X        msg_buf[count2++] = req_msg.dev9_inod.chr[count1++];
  977. X      }
  978. X      count1 = 0;
  979. X
  980. X      while(count1 < intsize)
  981. X      {
  982. X        msg_buf[count2++] = req_msg.dev10_inod.chr[count1++];
  983. X      }
  984. X      count1 = 0;
  985. X
  986. X      while(count1 < intsize)
  987. X      {
  988. X        msg_buf[count2++] = req_msg.dev11_inod.chr[count1++];
  989. X      }
  990. X      count1 = 0;
  991. X
  992. X      while(count1 < intsize)
  993. X      {
  994. X        msg_buf[count2++] = req_msg.uid.chr[count1++];
  995. X      }
  996. X      count1 = 0;
  997. X
  998. X      while(count1 < intsize)
  999. X      {
  1000. X        msg_buf[count2++] = req_msg.loop.chr[count1++];
  1001. X      }
  1002. X      count1 = 0;
  1003. X      count2 = 0;
  1004. X
  1005. X      /* the message is ready to go, so send it */
  1006. X
  1007. X      write(outfifo,msg_buf,to_iqrsiz);
  1008. X
  1009. X
  1010. X      /* Don't wait for a response */
  1011. X
  1012. X      break;
  1013. X  }
  1014. X}
  1015. X
  1016. X
  1017. Xtimeout(sig)
  1018. Xint sig;
  1019. X{
  1020. X        signal(SIGALRM, my_error);
  1021. X
  1022. X  /* take care of the signals */
  1023. X        signal(SIGINT, SIG_IGN);    /* ignore "interrupt" signal <DEL> */
  1024. X        signal(SIGHUP, SIG_IGN);    /* ignore "hang up" signal */
  1025. X        signal(SIGQUIT, SIG_IGN);   /* ignore "quit" signal */
  1026. X        signal(SIGTERM, my_error);
  1027. X#ifdef NQ
  1028. END_OF_FILE
  1029. if test 27709 -ne `wc -c <'ISPIN/src/ISPIN.c.ab'`; then
  1030.     echo shar: \"'ISPIN/src/ISPIN.c.ab'\" unpacked with wrong size!
  1031. fi
  1032. # end of 'ISPIN/src/ISPIN.c.ab'
  1033. fi
  1034. if test -f 'ISPIN/install/rtab' -a "${1}" != "-c" ; then 
  1035.   echo shar: Will not clobber existing file \"'ISPIN/install/rtab'\"
  1036. else
  1037. echo shar: Extracting \"'ISPIN/install/rtab'\" \(18364 characters\)
  1038. sed "s/^X//" >'ISPIN/install/rtab' <<'END_OF_FILE'
  1039. X# PUT YOUR NEW RTAB ENTRIES ABOVE HERE. SEPARATE EACH ENTRY WITH A COMMENT
  1040. X# LINE OR TWO FOR EASIER READING.
  1041. X#
  1042. X#
  1043. X#NAME;DEVICE(s);SPEED;FLAGS;EXPECT;SEND;...;EXPECT;SEND;
  1044. X#
  1045. X# GENERAL INFORMATION:  A leading "#" makes the current line a comment. 
  1046. X#                       Blank lines are not valid - use a line with only a 
  1047. X#                       "#" instead.
  1048. X#                       Maximum line length is BUFSIZ for your cpu; plenty.
  1049. X#                       Line feed or carriage return terminates the line.
  1050. X#                       Allow long lines to wrap around.
  1051. X#
  1052. X# DELIMETER: The field delimiter is the semi-colon. The use of a field
  1053. X#            delimiter drags the syntax of the table away from the uucp-like
  1054. X#            format we were looking for. The positive side of the trade-off
  1055. X#            is that the delimiter makes it much easier for the user to specify
  1056. X#            tabs and spaces in the EXPECT/SEND pairs when or if necessary.
  1057. X#
  1058. X# CARRIAGE RETURNS: Uucp will generally tag its own carriage return on the end
  1059. X#                   of any sent string. The user is responsible (under Honey-
  1060. X#                   DanBer uucp, at least) for specifying when a carriage 
  1061. X#                   return should NOT be sent at the end of a string. 
  1062. X#                   In our case, however, WYSIWYG (what you see is what you
  1063. X#                   get). So if you want a carriage return to be issued at
  1064. X#                   any point, make a carriage return (a REAL <ctrl>M or a \r)
  1065. X#                   part of the string to be sent.
  1066. X#
  1067. X#
  1068. X# NAME is a required entry. NAME must match the name by which the
  1069. X# queuer knows the printer (LP), or the argument to the "-P" flag which
  1070. X# must be specified on the appropriate line in /usr/spool/queuer/config
  1071. X# (NQ).
  1072. X#
  1073. X#
  1074. X# DEVICE is a required entry. At least the primary device must be shown
  1075. X# in this field. A total of eleven devices may be specified. They can be used
  1076. X# as alternative routes to the printer. If ISPIN is unable to contact
  1077. X# the printer via the first device because IQUEUER has determined it is
  1078. X# busy, ISPIN will attempt to contact the printer via the subsequent
  1079. X# devices. If contact via the other devices is also blocked,
  1080. X# the print request will be queued in the shortest of IQUEUER's virtual
  1081. X# queues for the devices.
  1082. X# Within the DEVICES field, the primary and subsequent device are separated
  1083. X# by commas. No white space allowed. From one to eleven devices may be
  1084. X# defined.
  1085. X#
  1086. X#
  1087. X# SPEED is a required entry. Valid entries include
  1088. X#
  1089. X#                                                  50
  1090. X#                                                  75
  1091. X#                                                  110
  1092. X#                                                  134
  1093. X#                                                  150
  1094. X#                                                  200
  1095. X#                                                  300
  1096. X#                                                  600
  1097. X#                                                  1200
  1098. X#                                                  1800
  1099. X#                                                  2400
  1100. X#                                                  4800
  1101. X#                                                  9600
  1102. X#                                                  19200
  1103. X#
  1104. X# Any other value in this field will be considered nonsense.
  1105. X# The SPEED parameter must match the speed of the port to the
  1106. X# network connection through which the remote printer will
  1107. X# be addressed. The primary and subsequent devices must all
  1108. X# be the same speed. No white space allowed.
  1109. X#
  1110. X# Other tty communication parameters are presently hard-coded as:
  1111. X# 
  1112. X# 8  data bits
  1113. X# 1  stop bit
  1114. X# NO parity
  1115. X#
  1116. X# This seems to have suited everyone so far. If it causes you a pain,
  1117. X# let me know.
  1118. X#
  1119. X# FLAGS
  1120. X#
  1121. X# The seven flags and their associated arguments are optional but their
  1122. X# inclusion will help assure a successful network negotiation, assist in
  1123. X# the diagnosis of problems, and permit tuning of the behavior of the ispin
  1124. X# process.
  1125. X#
  1126. X# -Bstring
  1127. X# The "-B" flag allows specification as many "busy" strings as necessary.
  1128. X# What do we do in case of network busy? A "busy" condition could be 
  1129. X# encountered at any link in the net. The administrator should specify
  1130. X# a key string from each busy msg which may be encountered. The key word(s)
  1131. X# will vary from Tellabs, to X.25 async pad, Mitron, whatever. If more than one 
  1132. X# type of networking system will be encountered, multiple "busy" flags
  1133. X# and strings should be specified. If a designated busy situation is 
  1134. X# encountered, the ISPIN process will sleep a while (number of seconds
  1135. X# specified at compile time), quit the network, close the port, notify the
  1136. X# IQUEUER it has encountered "busy", then await another go ahead message 
  1137. X# from the IQUEUER.
  1138. X#
  1139. X# -Istring
  1140. X# The "-I" flag allows specification of as many "inactive" strings as necessary.
  1141. X# Inactive condition is just a FAILURE, so no looping is permitted. 
  1142. X# If a network negotiation fails due to an identified inactive condition,
  1143. X# the failure error message will so specify. The sysadm, datacom, and user
  1144. X# should rectify the inactive condition before the user re-requests.
  1145. X# Beta testing has shown that this flag is usually not necessary.
  1146. X#
  1147. X# -Qstring
  1148. X# the "-Q" flag and argument allows specification of as many "quit" strings
  1149. X# as necessary. These will be issued at the conlusion of the print job in the
  1150. X# sequence they are shown in the table. The purpose of these "quit" strings
  1151. X# is to allow the job to sever the network virtual connections in a clean and
  1152. X# logical manner. This is also the place to issue any post-printing commands
  1153. X# to the printer, such as to return it to a "standard" configuration if
  1154. X# necessary.
  1155. X#
  1156. X# -Dstring
  1157. X# The "-D" flag and argument allows the specification of a string the network
  1158. X# will send us when/if the printer is powered-down or otherwise disconnected.
  1159. X# After each burst of characters, the program will check to see if there are
  1160. X# any characters to be read. Under normal conditions, there will be none.
  1161. X# If the printer has been powered-down or disconnected, we expect the network
  1162. X# to somehow signify the event with a particular message or other readable
  1163. X# response. These possible responses are specified as argument(s) to the "-D" 
  1164. X# flag. ISPIN's reaction to this condition is to loop and try to re-establish
  1165. X# the connection. 
  1166. X#
  1167. X# -L
  1168. X# This flag takes no argument. If the -L flag is present, event logging is
  1169. X# enabled. ISPIN will write an entry to its log file for each file which is
  1170. X# printed. If the -L flag is absent, only error messages will be written to
  1171. X# the log file.
  1172. X#
  1173. X# -R
  1174. X# This flag takes no argument. If the -R flag is present, the tty through
  1175. X# which ISPIN communicates will be set so that it DOES NOT transmit the
  1176. X# "newline" (ascii "LF", or octal \012) as the newline/carriage return pair.
  1177. X# Note that the LF/LF-CR conversion is the default condition if -R is not
  1178. X# present. For most printers, DO NOT USE THIS FLAG. This flag is included
  1179. X# specifically for supporting the transmission of binary information (such
  1180. X# as would be the case with raster graphics).
  1181. X#
  1182. X# -T
  1183. X# This flag takes no argument. If the -T flag is present, tabs will be
  1184. X# expanded to spaces on output. If -R flag is present, -T has no effect.
  1185. X#
  1186. X# EXPECT SEND
  1187. X#
  1188. X# ISPIN supports uucp's EXPECT-SEND-EXPECT construct and logic. That is,
  1189. X# if there is an EXPECT string which contains two dashes, the string will
  1190. X# be parsed such that everything up to the first dash is expected. If it is
  1191. X# not received, the chars which lie between the dashes will be sent. Then, what
  1192. X# remains beyond the second dash is expected. Alternatively, if the first
  1193. X# expected string IS received, the remainder of the construct is ignored.
  1194. X#
  1195. X# ISPIN does support the HoneyDanBer-style faked ascii representation
  1196. X# of special characters (two-character pairs such as "\N" for the null
  1197. X# character, "\n" for the newline character, and "\t" for tab), as well as
  1198. X# the "\###" octal representation of ascii characters.
  1199. X# The set of such characters and the associated actions follows:
  1200. X#
  1201. X#           \N
  1202. X#             send a NULL
  1203. X#
  1204. X#           \b
  1205. X#             send a backspace
  1206. X#
  1207. X#           \L
  1208. X#             loaf 30 seconds
  1209. X#
  1210. X#           \w
  1211. X#             wait 10 seconds
  1212. X#
  1213. X#           \d
  1214. X#             delay 3 seconds
  1215. X#
  1216. X#           \p
  1217. X#             pause a second
  1218. X#
  1219. X#           \n
  1220. X#             send a newline
  1221. X#
  1222. X#           \e
  1223. X#             send "escape"
  1224. X#
  1225. X#           \r
  1226. X#             send a carriage return
  1227. X#
  1228. X#           \s
  1229. X#             send a space
  1230. X#
  1231. X#           \t
  1232. X#             send a tab
  1233. X#
  1234. X#           \f
  1235. X#             send a formfeed
  1236. X#
  1237. X#           \K
  1238. X#             send BREAK
  1239. X#
  1240. X#           \E
  1241. X#             send two EOT and newline pairs
  1242. X#
  1243. X#           \D
  1244. X#             send a DELETE
  1245. X#
  1246. X#           \U
  1247. X#             send the user-supplied string. The string is passed to 
  1248. X#             ISPIN via the "dest" argument to nq's "-d" flag, or
  1249. X#             via the "option" argument to lp's "-o" flag
  1250. X#
  1251. X#           \###
  1252. X#             not literally "###" but three digits which will be 
  1253. X#             interpreted as an octal representation of the character
  1254. X#             which is to be sent, such as \007 for ascii BEL, and
  1255. X#             \033 for ESCAPE.
  1256. X#             MUST BE THREE, and ONLY THREE DIGITS.
  1257. X#
  1258. X#
  1259. X# It is NOT possible to specify a null EXPECT or SEND string by placing the
  1260. X# field delimeter ";" (semicolon) which terminates the string IMMEDIATELY
  1261. X# adjacent to the delimeter which marks the beginning of the string.
  1262. X# This is because of a quirk of the C strtok function we are using to parse
  1263. X# the rtab entry.
  1264. X#
  1265. X# It is possible to "fake" null SEND and EXPECT sequences thusly:
  1266. X#
  1267. X#       NULL SEND string:         ;\p;
  1268. X#                                        A timing pause of any duration,
  1269. X#                                        with no other characters results
  1270. X#                                        proper parsing but no characters
  1271. X#                                        sent.
  1272. X#
  1273. X#       NULL EXPECT string:       ; -;
  1274. X#                                        This is quirky, but it works. 
  1275. X#                                        This gets parsed as "Expect a
  1276. X#                                        space. If not received, send 
  1277. X#                                        nothing".
  1278. X#
  1279. X#
  1280. X#
  1281. X# Keep in mind that we are treating all WHITE SPACE as SIGNIFICANT.
  1282. X# If you put space(s), or tabs(s), or anything else within a field, that
  1283. X# that is what will be expected or sent.
  1284. X# WYSIWYG. What you see is what you get!
  1285. X#
  1286. X# Each received string will be compared to the "expect", each 
  1287. X# of the "busy" strings and each of the "inactive" strings.
  1288. X# The flags are optional. If none are configured, then any 
  1289. X# deviation from the "EXPECT/SEND" sequence will be treated as a FAILURE.
  1290. X#
  1291. X# The EXPECT/SEND pairs must be set up as PAIRS in the sequence ;EXPECT;SEND;
  1292. X# Since most printers do not issue any sort of acknowledgement message, the 
  1293. X# last EXPECT will be issued by the network. Terminate the sequence with a
  1294. X# null SEND, even though we know that upon receiving the final EXPECT, we
  1295. X# are connected. The terminating SEND must be "closed" with a terminating ";".
  1296. X#
  1297. X# RESTRICTIONS
  1298. X#
  1299. X# Any field, the first character of which is a "-" (dash), will be inter-
  1300. X# preted as a FLAG field. The second character of such a field MUST be 
  1301. X# "B", "Q", "I", "D", "L", or "R". Any other field, the first character
  1302. X# of which is a "-" (dash), is ignored.
  1303. X#
  1304. X# EXAMPLES - The examples are "quoted-out" with a leading "#" for your
  1305. X#            convenience.
  1306. X#
  1307. X#NAME  DEVICE               SPEED       FLAGS                     EXPECT SEND
  1308. X# This the rtab entry for my printer. The printer is hung from the pad, and the
  1309. X# cpu is connected to the Tellabs switch. The printer's name is LSB1. We may
  1310. X# access it from two possible ports. The speed is 9600. I have configured three
  1311. X# possible "busy" messages, and one "inactive" message. The "quit" sequence
  1312. X# makes a clean break from the pad (with <BREAK>clr), then from my switch
  1313. X# (with <BREAK>bye). The EXPECT/SEND sequence goes like this: expect "System?"
  1314. X# (part of my switch's login herald). If you don't get it, send <BREAK>bye,
  1315. X# then expect "System?" again. send "pacout", which is a dial sequence to
  1316. X# access X.25 async pad through our switch. expect "connect" (info message from
  1317. X# our switch). If you don't get it, send a carriage return, then expect "pad>",
  1318. X# which is the prompt from the pad. Send a carriage return. expect "pad>". If we
  1319. X# don't get it, send <BREAK>clr, then expect "pad>". send the "connect" command
  1320. X# and network address of the printer. expect the pad's message which indicates
  1321. X# a successful connection. If we don't get it, send the connect command and 
  1322. X# address again, and expect a successful connection message. The next "send"
  1323. X# is simply a 3 second delay. The sequence MUST be terminated by a NULL "send",
  1324. X# and since we don't expect the printer to give any indication that we are
  1325. X# connected, the last "send" is preceded by an NULL "expect".
  1326. X#
  1327. X# PLEASE NOTE the liberal sprinkling of 1 second pauses and 3 second delays.
  1328. X# Believe it or not, even the lowly Zilog is capable of executing the ISPIN
  1329. X# code faster than the network is able to resond. The pauses and delays keep
  1330. X# us from getting ahead of the network so we don't get lost.
  1331. X#
  1332. X# PLEASE NOTE: I have chopped this entry into separate lines so you may print
  1333. X# it. A REAL rtab entry must be all one line.
  1334. X#
  1335. X#LSB1;/dev/ttyhd,/dev/ttyi8;9600;-Busy;-Bcongestion;-Bremote dte;-BFound;-Inacti
  1336. X#ve;-Q\d\d\d\d\d\d\d\p\K\p;-Q\pclr\r\d;-Q\p\K\p;-Q\pbye\p;-DConnection cleared;-
  1337. X#Dpad>;-DSystem?;System?-\K\pbye\r\p-System?;\ppacout\r\d;connect;\p\r\d;pad>-\p
  1338. X#\K\pclr\r\d-pad>;\pconnect\s00000099999999\r\d;pened-\p\K\pclr\r\pconnect\s0000
  1339. X#0099999999\r\d-pened;\d;;;
  1340. X#
  1341. X#
  1342. X#
  1343. X#
  1344. X# This is an rtab entry to go out from the cpu, through the Tellabs, to a
  1345. X# printer which hangs from the Tellabs switch. The printer's name is netind2.
  1346. X# In this case, we may only access it via one port. The speed is 9600. The one
  1347. X# "busy" message and one "inactive" messages are messages we may expect from
  1348. X# Tellabs. The "quit" sequence for this switch is <BREAK>bye. The first EXPECT 
  1349. X# is a compound construction in which we look for "System?". If we don't get it,
  1350. X# we send <BREAK>bye and carriage return, then expect "System?" again. Next,
  1351. X# we send the link/channel combo which is the printer's address. We expect 
  1352. X# a "connect" message (switch's info messages are turned on). If we don't get
  1353. X# it, we send the link/channel combo again, then expect the "connect" message.
  1354. X#
  1355. X# The final non-NULL send is SOMETHING SPECIAL because the printer in this
  1356. X# example is a Centronics C-351, a printer IRS bought by the metric ton a few
  1357. X# years ago. The C-351, when attached to the network (both the Tellabs and the
  1358. X# X.25 async pad, in our experience) apparently detects a parity error at the
  1359. X# instant the virtual connection (VC) is established. The C-351's response to
  1360. X# this condition is to print a "@". You can't stop it by setting the dip
  1361. X# switches to ignore parity. So, if you don't want this junk character in 
  1362. X# your hard copy, simply formfeed past the page which the C-351 has just spat
  1363. X# upon.
  1364. X#
  1365. X# PLEASE NOTE the liberal sprinkling of 1 second pauses and 3 second delays.
  1366. X# Believe it or not, even the lowly Zilog is capable of executing the ISPIN
  1367. X# code faster than the network is able to resond. The pauses and delays keep
  1368. X# us from getting ahead of the network so we don't get lost.
  1369. X#
  1370. X# PLEASE NOTE: I have chopped this entry into separate lines so you may print
  1371. X# it. A REAL rtab entry must be all one line.
  1372. X#
  1373. X#netind2;/dev/tty8;9600;-Busy;-Iinactive;-Q\p\K\p;-Q\pbye\p;-DSystem?;System?-\K
  1374. X#\pbye\r\p-System?;\p135/2.2\r\d;connect-\p135/2.2\r\d-connect;\d\f;;;
  1375. X#
  1376. X#
  1377. X#
  1378. X#
  1379. X# This is an example of an rtab entry in the case where both the cpu and the
  1380. X# printer are directly connected to X.25 async pad.  It is different than the
  1381. X# rtab entry that was sent out with earlier versions of this application.
  1382. X# The X.25 pad disconnect sequence is changed from normal <BREAK>clr command to 
  1383. X# <CTRL>Z via the "set recall = 26" command. This change was made because
  1384. X# the <BREAK> causes Qume printers to print a garbage character.
  1385. X
  1386. X#
  1387. X# PLEASE NOTE: I have chopped this entry into separate lines so you may print
  1388. X# it. A REAL rtab entry must be all one line and doesn't have # symbols in it.
  1389. X#
  1390. X#netind3;/dev/ttyhd,/dev/ttyi8;9600;-L;-Bcongest;-Bmote dte;-Q\w\032\dcl
  1391. X#r\r\d;-DConnection cleared;-Dpad>;pad>-\p\K\pclr\r-pad>;\r\p;pad>-\p\K\pclr\r\
  1392. X#d-pad>;set recall=26\r\p;pad>-\r\d-pad>;\pconnect\s00000099999999\r\d;pened-\p\
  1393. X#K\pclr\r\dset recall=26\r\p\pconnect\s00000099999999\r\d-pened;\d;;;
  1394. X#
  1395. X#
  1396. X#
  1397. X#
  1398. X# This is an example of an rtab entry for the case where both a 
  1399. X# cpu and the printer are directly connected to the X.25 pad. It is different
  1400. X# than the rtab entry that was sent out with earlier versions of this 
  1401. X# application. It is the same as the preceding example except that the 
  1402. X# disconnect argument "-De" is also included. Since the letter "e" is the
  1403. X# most frequently used letter in the alphabet, the "-De" will assure that
  1404. X# a disconnected print job (chars we sent out are being echoed back to us
  1405. X# because the network has reverted to command mode) will be detected sooner.
  1406. X#
  1407. X#netind3;/dev/ttyhd,/dev/ttyi8;9600;-L;-Bcongest;-Bmote dte;-Q\w\032\dclr\r\d
  1408. X#;-DConnection cleared;-Dpad>;-De;pad>-\p\K\pclr\r\d-pad>;\r\p;pad>-\p\K\pcl
  1409. X#r\r\d-pad>;set recall=26\r\p;pad>-\r\d-pad>;\pconnect\s00000099999999\r\d;pened
  1410. X#-\p\K\pclr\r\dset recall=26\r\p\pconnect\s00000099999999\r\d-pened;\d;;;
  1411. X#
  1412. X#
  1413. X#
  1414. X# This is an example rtab entry for a printer which is hard wired to the cpu
  1415. X# at tty15. Although sending print jobs to hard wired printers through ISPIN
  1416. X# costs a little more in terms of overhead, there are a couple of valid
  1417. X# reasons for doing so. Under the NQ/DQUEUER native spooler, you might choose
  1418. X# the ISPIN backend to support hardwired printers just to avoid the costly
  1419. X# and clunky status reporting which is performed by the native "/usr/lib/text"
  1420. X# backend. Under the LP spooler, you might choose the ISPIN interface to
  1421. X# support hardwired printers because ISPIN offers an opportunuty to issue both
  1422. X# pre- and post-printing commands to the printer.
  1423. X#
  1424. X#netind4;/dev/tty15;9600;;;
  1425. X#
  1426. X#
  1427. X# NOTE:
  1428. X#       SEE ISPIN/install/lib_rtab/README for further info and more examples
  1429. X#
  1430. X#
  1431. END_OF_FILE
  1432. if test 18364 -ne `wc -c <'ISPIN/install/rtab'`; then
  1433.     echo shar: \"'ISPIN/install/rtab'\" unpacked with wrong size!
  1434. fi
  1435. # end of 'ISPIN/install/rtab'
  1436. fi
  1437. if test -f 'ISPIN/doc/OLD-DOCS/README.beta.2' -a "${1}" != "-c" ; then 
  1438.   echo shar: Will not clobber existing file \"'ISPIN/doc/OLD-DOCS/README.beta.2'\"
  1439. else
  1440. echo shar: Extracting \"'ISPIN/doc/OLD-DOCS/README.beta.2'\" \(4265 characters\)
  1441. sed "s/^X//" >'ISPIN/doc/OLD-DOCS/README.beta.2' <<'END_OF_FILE'
  1442. X
  1443. X
  1444. X
  1445. X        date:     February 14, 1989
  1446. X
  1447. X        to:       ISPIN Beta Test Site Volunteer
  1448. X
  1449. X        from:     Chief, Operations Branch, Information Systems Division, 35:IS
  1450. X
  1451. X        subject:  Indianapolis Standard Printer Interface (for Network printers)
  1452. X                  BETA Test release 2
  1453. X
  1454. X
  1455. X        I'm calling this the second version of the beta test release of
  1456. X        ISPIN. 
  1457. X
  1458. X        The biggest difference between this release and the first is that 
  1459. X        this second release compiles and executes on several more hardware
  1460. X        platforms. This is not due to extensive modification of the initial
  1461. X        issue. Only subtle adjustments to the IQUEUER.c and ISPIN.c were
  1462. X        necessary. ISPIN has been successfully installed and tested on:
  1463. X
  1464. X                                     Zilog Model 31
  1465. X                                     Zilog Model 32
  1466. X                                     Zilog Model 130
  1467. X                                     AT&T  3B1
  1468. X                                     Sequent Balance B8
  1469. X                                     Pyramid (whatever they have at
  1470. X                                              Atlanta Service Center)
  1471. X
  1472. X        This second release contains a few functional improvements as well.
  1473. X        Almost all of the error messages which an ISPIN may write to its
  1474. X        logfile now identify the printer. The error message written when
  1475. X        a network negotiation fails now reflects what was expected and what
  1476. X        was received. The functions which read the rtab and conduct the
  1477. X        network negotiation now permit the specification of a formfeed in
  1478. X        the rtab entry. Signal handling has been beefed up in the area of
  1479. X        intelligently handling SIGHUP.
  1480. X
  1481. X
  1482. X        The tape upon which I have transmitted the application was created
  1483. X        in cpio format. cd to a directory in which you want this release to
  1484. X        be written, then      cpio -iudmvB < your_nine_track_drive
  1485. X
  1486. X        The result of this cpio will be the creation of a directory named
  1487. X        ISPIN.beta.2. ISPIN.beta.2 will contain two subdirectories, namely
  1488. X        ISPI and ISPIN.
  1489. X
  1490. X        ISPIN contains the source code, install documents, and install
  1491. X        scripts for the new ISPIN application. Of course, the ISPIN
  1492. X        application serves as a BACKEND for either of two native
  1493. X        queuer/spoolers, lp or dqueuer. For this second release, I have
  1494. X        organized the directory ISPIN and its contents into subdirectories
  1495. X        using standard names "doc" (for documentation files), "h" (for header
  1496. X        files), "install" (where install scripts exist, and from which they
  1497. X        must be executed), "obj" (where the executables will be placed as
  1498. X        they are compiled), and "src" (where the source code resides).
  1499. X
  1500. X        The ISPI directory contains the freshest version of our ISPI
  1501. X        application. ISPI is an application which serves as a FRONTEND
  1502. X        for the two queuer/spoolers. The ISPI application is fully self-
  1503. X        contained, with its own source code, documentation, etc. Use it
  1504. X        if you like, or don't use it. I sent ISPI along because we have
  1505. X        found it to be an extremely useful tool to support the native
  1506. X        queuer/spoolers.
  1507. X
  1508. X        ISPIN and ISPI are TWO SEPARATE AND DISTINCT APPLICATIONS.
  1509. X        Neither depends upon the other for functionality. You may use ISPIN
  1510. X        without ISPI. You may use ISPI without ISPIN.
  1511. X
  1512. X        The documentation of the formal type is sparse, but the code is
  1513. X        overflowing with comments. Read everything in the "doc" directory
  1514. X        to get a general idea of what is going on in ISPIN and
  1515. X        its related entities.
  1516. X
  1517. X        If you are installing this application under ZEUS 3.21 and its
  1518. X        nq/xq/dqueuer queuer family, read NQinstall.doc.
  1519. X
  1520. X        If you are installing this application under System V UNIX and
  1521. X        the lp spooler, read LPinstall.doc.
  1522. X
  1523. X        If you have previously installed the initial release of ISPIN, the
  1524. X        install directory contains update scripts so you don't have to go
  1525. X        through a complete install.
  1526. X
  1527. X
  1528. X        Feedback is what I need. Please communicate whatever observations
  1529. X        you may have soon and often.
  1530. X
  1531. X
  1532. X  
  1533. X                                                         Larry Bartz
  1534. X
  1535. X
  1536. END_OF_FILE
  1537. if test 4265 -ne `wc -c <'ISPIN/doc/OLD-DOCS/README.beta.2'`; then
  1538.     echo shar: \"'ISPIN/doc/OLD-DOCS/README.beta.2'\" unpacked with wrong size!
  1539. fi
  1540. # end of 'ISPIN/doc/OLD-DOCS/README.beta.2'
  1541. fi
  1542. if test -f 'ISPIN/misc/ISPIT.dr/do_ispit.sh' -a "${1}" != "-c" ; then 
  1543.   echo shar: Will not clobber existing file \"'ISPIN/misc/ISPIT.dr/do_ispit.sh'\"
  1544. else
  1545. echo shar: Extracting \"'ISPIN/misc/ISPIT.dr/do_ispit.sh'\" \(1687 characters\)
  1546. sed "s/^X//" >'ISPIN/misc/ISPIT.dr/do_ispit.sh' <<'END_OF_FILE'
  1547. X#!/bin/sh
  1548. X# do_ispit.sh         08/07/91     LSB
  1549. X# When you install this in an accessible path, call it "ispit". This will
  1550. X# assure compatibility with possible future executables.
  1551. X# requires three args:
  1552. X# $1 is file to be xferred: could be a directory, could be more than one
  1553. X#                           file if all enclosed in double quote
  1554. X#
  1555. X# $2 is destination file name (full path on remote system, or relative to
  1556. X# ispit's home directory on the remote system)
  1557. X#
  1558. X# $3 is the lp queue member to use (for destination system)
  1559. X#
  1560. X# so:
  1561. X#     ispit source_file destination_file destination_system_queue_member
  1562. X#
  1563. X# examples:
  1564. X#
  1565. X# send testfile to /tmp/testfile on queue indy6:
  1566. X#     ispit testfile /tmp/testfile indy6
  1567. X#
  1568. X# send directory UUGETTY and all contents to /tmp/UUG.cp.Z.a on queue indy6:
  1569. X#     ispit UUGETTY /tmp/UUG.cp.Z.a indy6
  1570. X#
  1571. X# send all files whose names contain "ind" to /tmp/ind.cp.Z.a on queue indy6:
  1572. X#     ispit "`ls *ind*`" /tmp/ind.cp.Z.a indy6
  1573. X#
  1574. X# nowfile (not an argument) is the name of the named pipe in /tmp we'll use
  1575. X#
  1576. X#
  1577. Xnowfile=`/bin/date +%m%d%y`.`/bin/date +%H%M%S`
  1578. Xecho "ISPIT REQUEST" >> /tmp/ispit.log
  1579. Xdate >> /tmp/ispit.log
  1580. Xecho "        user: "`id`  >> /tmp/ispit.log
  1581. Xecho "      source: "$1  >> /tmp/ispit.log
  1582. Xecho " destination: "$2  >> /tmp/ispit.log
  1583. Xecho "       queue: "$3  >> /tmp/ispit.log
  1584. Xecho "        pipe: /tmp/"$nowfile  >> /tmp/ispit.log
  1585. X/bin/rm -f /tmp/$nowfile
  1586. X/etc/mknod /tmp/$nowfile p
  1587. X/bin/chmod 666 /tmp/$nowfile
  1588. Xfind $1 ! -type p -print|/bin/cpio -oc|/usr/local/bin/compress|/usr/local/bin/btoa > /tmp/$nowfile &
  1589. X/usr/bin/lp -d$3 -o$2@/tmp/$nowfile /etc/passwd
  1590. X# Yes, I do mean /etc/passwd! It's here as a necessary argument to fool lp.
  1591. END_OF_FILE
  1592. if test 1687 -ne `wc -c <'ISPIN/misc/ISPIT.dr/do_ispit.sh'`; then
  1593.     echo shar: \"'ISPIN/misc/ISPIT.dr/do_ispit.sh'\" unpacked with wrong size!
  1594. fi
  1595. # end of 'ISPIN/misc/ISPIT.dr/do_ispit.sh'
  1596. fi
  1597. if test -f 'ISPIN/misc/ISPIT.dr/interface' -a "${1}" != "-c" ; then 
  1598.   echo shar: Will not clobber existing file \"'ISPIN/misc/ISPIT.dr/interface'\"
  1599. else
  1600. echo shar: Extracting \"'ISPIN/misc/ISPIT.dr/interface'\" \(545 characters\)
  1601. sed "s/^X//" >'ISPIN/misc/ISPIT.dr/interface' <<'END_OF_FILE'
  1602. X#!/bin/sh
  1603. X# 08/07/91 LSB
  1604. X# This interface script usable for ISPIT file transfer protocol
  1605. Xecho "ISPIT FILE TRANSFER" >> /tmp/ispit.log
  1606. Xdate >> /tmp/ispit.log
  1607. Xecho "      lp job id : "$1 >> /tmp/ispit.log
  1608. Xecho "requesting user : "$2 >> /tmp/ispit.log
  1609. Xecho "    destination : "`echo $5|/usr/bin/cut -d@ -f1` >> /tmp/ispit.log
  1610. Xecho "           pipe : "`echo $5|/usr/bin/cut -d@ -f2` >> /tmp/ispit.log
  1611. Xexec /usr/spool/lp/ISPIN/ispin `/bin/basename $0|/usr/bin/tr -d "[\012*]"` $1 $2 "" 1 `echo $5|/usr/bin/cut -d@ -f1` `echo $5|/usr/bin/cut -d@ -f2`
  1612. END_OF_FILE
  1613. if test 545 -ne `wc -c <'ISPIN/misc/ISPIT.dr/interface'`; then
  1614.     echo shar: \"'ISPIN/misc/ISPIT.dr/interface'\" unpacked with wrong size!
  1615. fi
  1616. # end of 'ISPIN/misc/ISPIT.dr/interface'
  1617. fi
  1618. echo shar: End of archive 8 \(of 15\).
  1619. cp /dev/null ark8isdone
  1620. MISSING=""
  1621. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
  1622.     if test ! -f ark${I}isdone ; then
  1623.     MISSING="${MISSING} ${I}"
  1624.     fi
  1625. done
  1626. if test "${MISSING}" = "" ; then
  1627.     echo You have unpacked all 15 archives.
  1628.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1629. else
  1630.     echo You still need to unpack the following archives:
  1631.     echo "        " ${MISSING}
  1632. fi
  1633. ##  End of shell archive.
  1634. exit 0
  1635.  
  1636.