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

  1. Newsgroups: comp.sources.unix
  2. From: sir-alan!ispin!lbartz@iuvax.cs.indiana.edu (Larry Bartz)
  3. Subject: v25i118: Indianapolis Standard Printer Interface for Networked printers, Part07/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 118
  9. Archive-Name: ispin/part07
  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 7 (of 15)."
  18. # Contents:  ISPIN/src/ISPIN.c.aa ISPIN/doc/TECH.doc
  19. #   ISPIN/doc/OLD-DOCS/README.beta.1 ISPIN/doc/OLD-DOCS/rel_1.2.fixes
  20. #   ISPIN/misc/ISPIT.dr/ispit.sh
  21. # Wrapped by socrates@indy6 on Tue Jan 28 15:26:48 1992
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. if test -f 'ISPIN/src/ISPIN.c.aa' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'ISPIN/src/ISPIN.c.aa'\"
  25. else
  26. echo shar: Extracting \"'ISPIN/src/ISPIN.c.aa'\" \(38857 characters\)
  27. sed "s/^X//" >'ISPIN/src/ISPIN.c.aa' <<'END_OF_FILE'
  28. X/****************************************************************************/
  29. X/* ISPIN                                                                    */
  30. X/*                                                                          */
  31. X/* Indianapolis Standard Printer Interface (for Network printers)           */
  32. X/****************************************************************************/
  33. X/*                                                                          */
  34. X/*  Copyright (C) 1991                                                      */
  35. X/*  Larry Bartz                                                             */
  36. X/*  Internal Revenue Service                                                */
  37. X/*  Indianapolis District Office                                            */
  38. X/*                                                                          */
  39. X/*  This program is free software; you can redistribute it and/or modify    */
  40. X/*  it under the terms of the GNU General Public License as published by    */
  41. X/*  the Free Software Foundation, version 1.                                */
  42. X/*                                                                          */
  43. X/*  This program is distributed in the hope that it will be useful,         */
  44. X/*  but WITHOUT ANY WARRANTY; without even the implied warranty of          */
  45. X/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           */
  46. X/*  GNU General Public License for more details.                            */
  47. X/*                                                                          */
  48. X/*  You should have received a copy of the GNU General Public License       */
  49. X/*  along with this program; if not, write to the Free Software             */
  50. X/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
  51. X/*                                                                          */
  52. X/****************************************************************************/
  53. X/*                                                                          */
  54. X/* COMMENTS                                                                 */
  55. X/*                                                                          */
  56. X/* See common.h and ispin.h                                                 */
  57. X/*                                                                          */
  58. X/****************************************************************************/
  59. X/*                                                                          */
  60. X/* DEFINES                                                                  */
  61. X/*                                                                          */
  62. X/* #define DEBUG                                                            */
  63. X/*                                                                          */
  64. X/****************************************************************************/
  65. X/*                                                                          */
  66. X/* INCLUDES                                                                 */
  67. X/*                                                                          */
  68. X#include "../h/common.h"
  69. X#include "../h/ispin.h"
  70. X/*                                                                          */
  71. X/*                                                                          */
  72. X/*                                                                          */
  73. X/****************************************************************************/
  74. X/*                                                                          */
  75. X/* DATA TYPES, VARIABLES, ETC                                               */
  76. X/*                                                                          */
  77. X/* See common.h and ispin.h                                                 */
  78. X/*                                                                          */
  79. X/****************************************************************************/
  80. X/*                                                                          */
  81. X/*                                                                          */
  82. X/*                                                                          */
  83. Xmain(argc,argv)
  84. Xint argc;
  85. Xchar *argv[];
  86. X
  87. X{
  88. X
  89. X#ifdef DEBUG
  90. X          /* format an error message */
  91. X          time(&tloc);
  92. X          nowtime = (struct tm *)localtime(&tloc);
  93. X          time_str = asctime(nowtime);
  94. X          strcpy(errmsg,"ISPIN: getting started. time:\n");
  95. X          strcat(errmsg,"                            ");
  96. X          strcat(errmsg,time_str);
  97. X          strcat(errmsg,"\n");
  98. X         if((logfile = fopen(LOGFILE,"a+")) != NULL)
  99. X         {
  100. X            fprintf(logfile,errmsg);
  101. X            fclose(logfile);
  102. X         }
  103. X#endif
  104. X
  105. X
  106. X
  107. X/* take care of the signals */
  108. X        signal(SIGINT, SIG_IGN);    /* ignore "interrupt" signal <DEL> */
  109. X        signal(SIGHUP, SIG_IGN);    /* ignore "hang up" signal */
  110. X                                    /*************************************/
  111. X                                    /* Ignore SIGHUP until setuptty().   */
  112. X                                    /* We don't want some unknown tty to */
  113. X                                    /* HUP us. When we get to setuptty(),*/
  114. X                                    /* we'll do a setpgrp() to make this */
  115. X                                    /* proc the grp leader. The next tty */
  116. X                                    /* we open will become the control   */
  117. X                                    /* terminal. Then we'll re-enable    */
  118. X                                    /* SIGHUP with action my_error().    */
  119. X                                    /* This will enable us to intelli-   */
  120. X                                    /* gently loop if the printer HUPs.  */
  121. X                                    /* We're sure no other process group */
  122. X                                    /* will have the tty as its control  */
  123. X                                    /* terminal because IQUEUER won't let*/
  124. X                                    /* us have it until the previous     */
  125. X                                    /* ISPIN is finished with it.        */
  126. X                                    /* This little procedure is the      */
  127. X                                    /* reason it's SO CRITICAL that none */
  128. X                                    /* of the ttys which may be used by  */
  129. X                                    /* ISPIN may be made known to the na-*/
  130. X                                    /* tive queuer via lpadmin (LP) or   */
  131. X                                    /* /usr/spool/queuer/config (NQ). If */
  132. X                                    /* either dqueuer (NQ) or lp (LP)    */
  133. X                                    /* knew about the tty we want to use,*/
  134. X                                    /* they would assume it as their own */
  135. X                                    /* control terminal, thus possibly   */
  136. X                                    /* ruining any chance we might have  */
  137. X                                    /* had to choose our own.            */
  138. X                                    /*************************************/
  139. X        signal(SIGQUIT, SIG_IGN);   /* ignore "quit" signal */
  140. X        signal(SIGALRM, SIG_IGN);
  141. X        signal(SIGTERM, my_error);
  142. X#ifdef NQ
  143. X        signal(SIGRES, SIG_IGN);     /* ignore "restart" signal */
  144. X        signal(SIGBACK, SIG_IGN);   /* ignore "back-up" signal */
  145. X        signal(SIGSTOP, my_error);   /* trap "stop" signal */
  146. X#endif
  147. X
  148. X   /* Assign an initial value to GO_dev string, so log messages which use */
  149. X   /* it make sense. Also so we don't dump core trying to strcat from a   */
  150. X   /* memory address which is undefined.                    05/09/90 LSB  */
  151. X   sprintf(GO_dev,"undefined");
  152. X
  153. X   /* format a default error message */
  154. X   time(&tloc);
  155. X   nowtime = (struct tm *)localtime(&tloc);
  156. X   time_str = asctime(nowtime);
  157. X   strcpy(errmsg,"ISPIN: undefined error. time:\n");
  158. X   strcat(errmsg,"                        ");
  159. X   strcat(errmsg,time_str);
  160. X   strcat(errmsg,"\n");
  161. X
  162. X/* Parse the arguments.                                                       */
  163. X/*                                                                            */
  164. X/* If NQ, dqueuer will invoke the backend with file descriptors and options.  */
  165. X/* See backend(M) of Zeus 3.21 Reference Manual.                              */
  166. X/*                                                                            */
  167. X/* If LP, lp  will invoke the backend with printer name, id, user, title,     */
  168. X/* copies, options, file(s). The backend's standard input is /dev/null.       */
  169. X/* Standard out and standard error are both directed to the printer.          */
  170. X/* See discussion of lp interface programs in your System V UNIX box's        */
  171. X/* administration manual (such as pages LP4-15 through LP4-18 of AT&T         */
  172. X/* 3B2 Administration Manual).                                                */
  173. X/*                                                                            */
  174. X/* The two parse functions will each fill the same global variables, so that  */
  175. X/* we may consider the program somewhat homogenous after this point.          */
  176. X/*                                                                            */
  177. X#ifdef NQ
  178. X  parse_NQ(argc,argv);
  179. X  if(no_input)
  180. X  {
  181. X   /* format an error message */
  182. X   time(&tloc);
  183. X   nowtime = (struct tm *)localtime(&tloc);
  184. X   time_str = asctime(nowtime);
  185. X
  186. X   sprintf(errmsg,"ISPIN: printer %s no input file to print.\n",dest);
  187. X   sprintf(errmsg2,"    USER: %s\n",from);
  188. X   strcat(errmsg,errmsg2);
  189. X   sprintf(errmsg2,"    TIME: %s\n",time_str);
  190. X   strcat(errmsg,errmsg2);
  191. X
  192. X   /* call the error routine, never come back */
  193. X   my_error(MYERR);
  194. X  }
  195. X#else
  196. X  parse_LP(argc,argv);
  197. X#endif
  198. X
  199. X#ifdef DEBUG
  200. X          /* format an error message */
  201. X          time(&tloc);
  202. X          nowtime = (struct tm *)localtime(&tloc);
  203. X          time_str = asctime(nowtime);
  204. X          sprintf(errmsg,"ISPIN: printer %s passed parse_LP. time:\n",dest);
  205. X          strcat(errmsg,"                            ");
  206. X          strcat(errmsg,time_str);
  207. X          strcat(errmsg,"\n");
  208. X         if((logfile = fopen(LOGFILE,"a+")) != NULL)
  209. X         {
  210. X            fprintf(logfile,errmsg);
  211. X            fclose(logfile);
  212. X         }
  213. X#endif
  214. X
  215. X
  216. X/* read the table to get network connection info                              */
  217. X  status = read_tbl();
  218. X  if(status == 1)
  219. X  {
  220. X   /* format an error message */
  221. X   time(&tloc);
  222. X   nowtime = (struct tm *)localtime(&tloc);
  223. X   time_str = asctime(nowtime);
  224. X
  225. X   sprintf(errmsg,"ISPIN: printer %s not in rtab.\n",dest);
  226. X          sprintf(errmsg2,"    USER: %s\n",from);
  227. X          strcat(errmsg,errmsg2);
  228. X          if(usr_addr)
  229. X          {
  230. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  231. X            strcat(errmsg,errmsg2);
  232. X          }
  233. X#ifdef NQ
  234. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  235. X#else
  236. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  237. X#endif
  238. X          strcat(errmsg,errmsg2);
  239. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  240. X          strcat(errmsg,errmsg2);
  241. X
  242. X   /* call the error routine, never come back */
  243. X   my_error(MYERR);
  244. X  }
  245. X
  246. X#ifdef DEBUG
  247. X          /* format an error message */
  248. X          time(&tloc);
  249. X          nowtime = (struct tm *)localtime(&tloc);
  250. X          time_str = asctime(nowtime);
  251. X          sprintf(errmsg,"ISPIN: printer %s passed read_tbl. time:\n",dest);
  252. X          strcat(errmsg,"                            ");
  253. X          strcat(errmsg,time_str);
  254. X          strcat(errmsg,"\n");
  255. X         if((logfile = fopen(LOGFILE,"a+")) != NULL)
  256. X         {
  257. X            fprintf(logfile,errmsg);
  258. X            fclose(logfile);
  259. X         }
  260. X#endif
  261. X
  262. X
  263. X  /* otherwise, okay. proceed */
  264. X
  265. X/* open the communication fifos */
  266. X  open_fifos();
  267. X
  268. X#ifdef DEBUG
  269. X          /* format an error message */
  270. X          time(&tloc);
  271. X          nowtime = (struct tm *)localtime(&tloc);
  272. X          time_str = asctime(nowtime);
  273. X          sprintf(errmsg,"ISPIN: printer %s passed open_fifos. time:\n",dest);
  274. X          strcat(errmsg,"                            ");
  275. X          strcat(errmsg,time_str);
  276. X          strcat(errmsg,"\n");
  277. X         if((logfile = fopen(LOGFILE,"a+")) != NULL)
  278. X         {
  279. X            fprintf(logfile,errmsg);
  280. X            fclose(logfile);
  281. X         }
  282. X#endif
  283. X
  284. X
  285. X/* Notify the secondary queuer of our existence. Wait for goahead.            */
  286. X  notify(HERE);
  287. X
  288. X#ifdef DEBUG
  289. X          /* format an error message */
  290. X          time(&tloc);
  291. X          nowtime = (struct tm *)localtime(&tloc);
  292. X          time_str = asctime(nowtime);
  293. X          sprintf(errmsg,"ISPIN: printer %s passed notify. time:\n",dest);
  294. X          strcat(errmsg,"                            ");
  295. X          strcat(errmsg,time_str);
  296. X          strcat(errmsg,"\n");
  297. X         if((logfile = fopen(LOGFILE,"a+")) != NULL)
  298. X         {
  299. X            fprintf(logfile,errmsg);
  300. X            fclose(logfile);
  301. X         }
  302. X#endif
  303. X
  304. X/* This is where we re-commence if we have to loop. */
  305. X/* Changed to setjmp/longjmp style. No! It is NOT the same as a GOTO! */
  306. X/* The longjmp back to here is in the again() function. */
  307. X/* 07/27/90  LSB */
  308. XSETJMP(agayn);
  309. X
  310. X/* Secure and set up the output device.                                       */
  311. X  setuptty();
  312. X
  313. X
  314. X#ifdef DEBUG
  315. X          /* format an error message */
  316. X          time(&tloc);
  317. X          nowtime = (struct tm *)localtime(&tloc);
  318. X          time_str = asctime(nowtime);
  319. X          sprintf(errmsg,"ISPIN: printer %s passed setuptty. time:\n",dest);
  320. X          strcat(errmsg,"                            ");
  321. X          strcat(errmsg,time_str);
  322. X          strcat(errmsg,"\n");
  323. X          strcat(errmsg,GO_dev);
  324. X          strcat(errmsg,"\n");
  325. X         if((logfile = fopen(LOGFILE,"a+")) != NULL)
  326. X         {
  327. X            fprintf(logfile,errmsg);
  328. X            fclose(logfile);
  329. X         }
  330. X#endif
  331. X
  332. X/* Negotiate the network connection. If we can't get through, error out       */
  333. X/* down there.                                                                */
  334. X  negotiate();
  335. X
  336. X
  337. X#ifdef DEBUG
  338. X          /* format an error message */
  339. X          time(&tloc);
  340. X          nowtime = (struct tm *)localtime(&tloc);
  341. X          time_str = asctime(nowtime);
  342. X          sprintf(errmsg,"ISPIN: printer %s passed negotiate. time:\n",dest);
  343. X          strcat(errmsg,"                            ");
  344. X          strcat(errmsg,time_str);
  345. X          strcat(errmsg,"\n");
  346. X          strcat(errmsg,GO_dev);
  347. X          strcat(errmsg,"\n");
  348. X         if((logfile = fopen(LOGFILE,"a+")) != NULL)
  349. X         {
  350. X            fprintf(logfile,errmsg);
  351. X            fclose(logfile);
  352. X         }
  353. X#endif
  354. X
  355. X/* Do the job. Send from the input file to the output file.                   */
  356. X/* do a loop here in the LP case for each output file                         */
  357. X#ifdef NQ
  358. X        i_stream = fdopen(RFFD,"r");
  359. X        if(i_stream != NULL)
  360. X        {
  361. X          do_it();
  362. X          fclose(i_stream);
  363. X          close(RFFD);
  364. X        }
  365. X        else
  366. X        {
  367. X          /* format an error message */
  368. X          time(&tloc);
  369. X          nowtime = (struct tm *)localtime(&tloc);
  370. X          time_str = asctime(nowtime);
  371. X
  372. X          sprintf(errmsg,"ISPIN: printer: %s file %s: %s.\n",dest,fyle,sys_errlist[errno]);
  373. X          sprintf(errmsg2,"    USER: %s\n",from);
  374. X          strcat(errmsg,errmsg2);
  375. X          if(usr_addr)
  376. X          {
  377. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  378. X            strcat(errmsg,errmsg2);
  379. X          }
  380. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  381. X          strcat(errmsg,errmsg2);
  382. X          if(port_open == 1)
  383. X          {
  384. X            sprintf(errmsg2,"     DEV: %s\n",GO_dev);
  385. X            strcat(errmsg,errmsg2);
  386. X          }
  387. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  388. X          strcat(errmsg,errmsg2);
  389. X
  390. X         /* call the error routine, never come back */
  391. X         my_error(SYSERR);
  392. X        }
  393. X#else
  394. X
  395. X        while(numfiles > 0)
  396. X        {
  397. X
  398. X          --numfiles;
  399. X
  400. X
  401. X            if((i_stream = fopen(fyles[numfiles],"r")) != NULL)
  402. X            {
  403. X
  404. X
  405. X              do_it();
  406. X              fclose(i_stream);
  407. X            }
  408. X            else
  409. X            {
  410. X            /* format an error message */
  411. X            time(&tloc);
  412. X            nowtime = (struct tm *)localtime(&tloc);
  413. X            time_str = asctime(nowtime);
  414. X
  415. X          sprintf(errmsg,"ISPIN: printer: %s file %s: %s.\n",dest,fyles[numfiles],sys_errlist[errno]);
  416. X          sprintf(errmsg2,"    USER: %s\n",from);
  417. X          strcat(errmsg,errmsg2);
  418. X          if(usr_addr)
  419. X          {
  420. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  421. X            strcat(errmsg,errmsg2);
  422. X          }
  423. X          sprintf(errmsg2,"    FILE: %s\n",fyles[numfiles]);
  424. X          strcat(errmsg,errmsg2);
  425. X          if(port_open == 1)
  426. X          {
  427. X            sprintf(errmsg2,"     DEV: %s\n",GO_dev);
  428. X            strcat(errmsg,errmsg2);
  429. X          }
  430. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  431. X          strcat(errmsg,errmsg2);
  432. X
  433. X           /* Call the error routine, but come back.                 */
  434. X           /* We don't want to bomb off the whole thing just because */
  435. X           /* one of possibly many files might not exist.            */
  436. X
  437. X           /* However, we'll save errno to use later when we exit,   */
  438. X           /* so that lpsched will know we encountered a problem.    */
  439. X           /* This will permit the "-m" flag of lp to work properly, */
  440. X           /* notifying the user that his request was not entirely   */
  441. X           /* successful.                         05/09/90  LSB      */
  442. X           /* We have to make sure savd_errno won't have the same    */
  443. X           /* value as other "reason"s we pass to my_exit().         */
  444. X           savd_errno = (errno + 255);
  445. X
  446. X           ret_val = my_error(NO_EXIT);
  447. X            }
  448. X          }
  449. X          
  450. X#endif
  451. X
  452. X#ifdef DEBUG
  453. X          /* format an error message */
  454. X          time(&tloc);
  455. X          nowtime = (struct tm *)localtime(&tloc);
  456. X          time_str = asctime(nowtime);
  457. X          sprintf(errmsg,"ISPIN: printer %s passed do_it. time:\n",dest);
  458. X          strcat(errmsg,"                            ");
  459. X          strcat(errmsg,time_str);
  460. X          strcat(errmsg,"\n");
  461. X          strcat(errmsg,GO_dev);
  462. X          strcat(errmsg,"\n");
  463. X         if((logfile = fopen(LOGFILE,"a+")) != NULL)
  464. X         {
  465. X            fprintf(logfile,errmsg);
  466. X            fclose(logfile);
  467. X         }
  468. X#endif
  469. X
  470. X
  471. X/* all done */
  472. X        if(port_open == 1)
  473. X        {
  474. X              stayt = DISCONNECTING;
  475. X          ret_val = quit_net();
  476. X        }
  477. X  my_exit(0);
  478. X
  479. X}
  480. X
  481. X
  482. X
  483. X#ifdef NQ
  484. X/****************************************************************************/
  485. X/*  parse_NQ             author = loftin, hacker = bartz           073088   */
  486. X/****************************************************************************/
  487. X/*                                                                          */
  488. X/*   subroutine to get options passed to spooler backend                    */
  489. X/*                                                                          */
  490. X/****************************************************************************/
  491. X/*                                                                          */
  492. X/*   description -                                                          */
  493. X/*       This subroutine scans and stores-off the arguments passed to the   */
  494. X/*       backend (i.e., argv[]) by dqueuer(M).                              */
  495. X/*                                                                          */
  496. X/*   how invoked - parse_NQ(argc, argv)                                     */
  497. X/*                 int  argc;                                               */
  498. X/*                 char *argv[];                                            */
  499. X/*                                                                          */
  500. X/*   inputs - none                                                          */
  501. X/*                                                                          */
  502. X/*   outputs - none                                                         */
  503. X/*                                                                          */
  504. X/*   subroutines (in addition to standard C) - none                         */
  505. X/*                                                                          */
  506. X/*   comments -                                                             */
  507. X/*       Freely given by Mark Loftin, this routine was originally named     */
  508. X/*       "getoptns". Adapted for use with ISPIN by Larry Bartz.             */
  509. X/*                                                                          */
  510. X/*       This backend recognizes one flag and argument in addition          */
  511. X/*       to those passed to it by dqueuer. The "-P" flag and its            */
  512. X/*       argument (que:dev) MUST be included in the config file, as         */
  513. X/*       shown below.                                                       */
  514. X/*                                                                          */
  515. X/*       Queue descriptor                                                   */
  516. X/*       Comment                                                            */
  517. X/*       Device descriptor                                                  */
  518. X/*       Comment                                                            */
  519. X/*       Device descriptor                                                  */
  520. X/*                                                                          */
  521. X/*                                                                          */
  522. X/*                                                                          */
  523. X/*       Qremote,R,N,F                                                      */
  524. X/*       # GAR-1, Gary, IN POD, Qume 11/55                                  */
  525. X/*       DGAR-1,R,/dev/tty15,/usr/spool/queuer/ISPI/ISPIN -P GAR-1          */
  526. X/*       # LAF-1, Lafayette, IN POD, Centronics LW855                       */
  527. X/*       DLAF-1,R,/dev/tty15,/usr/spool/queuer/ISPI/ISPIN -P LAF-1          */
  528. X/*                                                                          */
  529. X/*                                                                          */
  530. X/*                                                                          */
  531. X/*       See Zeus Reference Manual "backend(M)", and Zilog Systems          */
  532. X/*       Administrator Manual (for ZEUS 3.21) 7.2.3, "Configuration         */
  533. X/*       File Description."                                                 */
  534. X/*                                                                          */
  535. X/*                                                                          */
  536. X/*                                                                          */
  537. X/****************************************************************************/
  538. X
  539. Xparse_NQ(argc, argv)
  540. Xint  argc;
  541. Xchar *argv[];
  542. X
  543. X{
  544. X        register int x;         /* general purpose index register */
  545. X        extern short optind;    /*  \  used to get */
  546. X        extern char *optarg;    /*   > options and */
  547. X        short  opt;             /*  /  arguments   */
  548. X
  549. X
  550. X        while ((opt=getopt(argc, argv, "Bf:c:P:F:s:t:d:b")) != EOF)
  551. X        {
  552. X                switch(opt)
  553. X                {
  554. X                        case 'B':
  555. X                                no_input = 1;
  556. X                                break;
  557. X                        case 'f':
  558. X                                fyle = optarg;
  559. X                                /* we will only get one file from dqueuer */
  560. X                                break;
  561. X                        case 'c':
  562. X                                sscanf(optarg, "%d", &prtimes);
  563. X                                break;
  564. X                        case 'P':
  565. X                                dest = optarg;
  566. X                                break;
  567. X                        case 'F':
  568. X                                from = optarg;
  569. X                                break;
  570. X                        case 's':
  571. X                                sptime = optarg;
  572. X                                break;
  573. X                        case 't':
  574. X                                title = optarg;
  575. X                                break;
  576. X                        case 'd':
  577. X                                usr_strng = optarg;
  578. X                                ++usr_addr;
  579. X                                break;
  580. X                        case 'b':
  581. X                                banner = 1;
  582. X                                break;
  583. X                        case '?':
  584. X                         default:
  585. X                                break;
  586. X                }
  587. X        }
  588. X
  589. X
  590. X        /* Since we're choosing our output file from the specifications given */
  591. X        /* in rtab, we don't want the file descriptor dqueuer passed to us.   */
  592. X
  593. X        close(SFFD);
  594. X
  595. X        /* Since we have chosen not to update the status file, close it.      */
  596. X
  597. X        close(STATUSFD);
  598. X
  599. X        return(0);
  600. X}
  601. X#endif
  602. X
  603. X
  604. X
  605. X
  606. X
  607. X#ifdef LP
  608. X/****************************************************************************/
  609. X/*  parse_LP             author = bartz                            073088   */
  610. X/****************************************************************************/
  611. X/*                                                                          */
  612. X/*   subroutine to parse options passed to spooler backend                  */
  613. X/*                                                                          */
  614. X/****************************************************************************/
  615. X/*                                                                          */
  616. X/*   description -                                                          */
  617. X/*       This subroutine scans and stores-off the arguments passed to the   */
  618. X/*       backend (i.e., argv[]) by lp spooler.                              */
  619. X/*                                                                          */
  620. X/*   how invoked - parse_LP(argc, argv)                                     */
  621. X/*                 int  argc;                                               */
  622. X/*                 char *argv[];                                            */
  623. X/*                                                                          */
  624. X/*   inputs - none                                                          */
  625. X/*                                                                          */
  626. X/*   outputs - none                                                         */
  627. X/*                                                                          */
  628. X/*   subroutines (in addition to standard C) - none                         */
  629. X/*                                                                          */
  630. X/*                                                                          */
  631. X/*                                                                          */
  632. X/*                                                                          */
  633. X/*                                                                          */
  634. X/****************************************************************************/
  635. X
  636. Xparse_LP(argc, argv)
  637. Xint  argc;
  638. Xchar *argv[];
  639. X
  640. X{
  641. X
  642. X
  643. X
  644. X        /*
  645. X        the number of arguments is: argc
  646. X        the 0th   argument is: exec path to this file
  647. X        the 1st   argument is: spool member name passed by ispintrfce program
  648. X        the 2nd   argument is: request id returned by lp
  649. X        the 3rd   argument is: logname of user who made request
  650. X        the 4th   argument is: title, if specified by user
  651. X        the 5th   argument is: number of copies requested by user
  652. X        the 6th   argument is: optional string specified by user on
  653. X                                   the command line as the argument to
  654. X                                   the "-o" flag
  655. X        the 7th thru nth of arguments is: full path name of file to print
  656. X        */
  657. X
  658. X        /* dest is used as the search key for table lookup.          */
  659. X        /* It is the queue member's (printer's) name                 */
  660. X
  661. X
  662. X        dest = &argv[1][0];
  663. X
  664. X        from = &argv[3][0];
  665. X
  666. X        title = &argv[4][0];
  667. X
  668. X
  669. X        if(strlen(title) > 0)
  670. X        {
  671. X          /* if user bothers to specify title, assume he wants a banner */
  672. X          banner = 1;
  673. X        }
  674. X
  675. X
  676. X        prtimes = atoi(argv[5]);
  677. X
  678. X
  679. X        usr_strng = &argv[6][0];
  680. X
  681. X        if(strlen(usr_strng) > 0)
  682. X        {
  683. X          /* if user bothers to specify arg to "-o" flag */
  684. X          ++usr_addr;
  685. X        }
  686. X
  687. X
  688. X        fyles = &argv[7];
  689. X
  690. X
  691. X
  692. X        /* how many args for file names to print ? */
  693. X        num_ofile = numfiles = argc - 7;
  694. X
  695. X
  696. X
  697. X       /* Since we're sending all of our messages to LOGFILE, */
  698. X       /* close the standard error file we were given.        */
  699. X       fclose(stderr);
  700. X
  701. X
  702. X  
  703. X       /* LP gives us stdin assigned to /dev/null. We'll just */
  704. X       /* close it in the interest of conservation.           */
  705. X       fclose(stdin);
  706. X
  707. X
  708. X
  709. X       /* Since we're choosing our own output file from specs   */
  710. X       /* given in rtab, also close the stdout LP gave us.      */
  711. X       /* See installation notes and notes on control terminal. */
  712. X       fclose(stdout);
  713. X  
  714. X
  715. X
  716. X       /* We'll assign our generic output output file pointer */
  717. X       /* after the daemon tells us where we're going. */
  718. X
  719. X
  720. X
  721. X}
  722. X#endif
  723. X
  724. X
  725. X/****************************************************************************/
  726. X/* pid = read_tbl             author = lbartz                      22nov88  */
  727. X/****************************************************************************/
  728. X/*                                                                          */
  729. X/*   subroutine to read and parse the table of remote printer info          */
  730. X/*                                                                          */
  731. X/****************************************************************************/
  732. X/*                                                                          */
  733. X/*   description -                                                          */
  734. X/*       This subroutine is invoked to collect info necessary to make       */
  735. X/*       contact with the remote printer.                                   */
  736. X/*                                                                          */
  737. X/*   how invoked - read_tbl()                                               */
  738. X/*                                                                          */
  739. X/*   inputs - none                                                          */
  740. X/*                                                                          */
  741. X/*   outputs - none                                                         */
  742. X/*                                                                          */
  743. X/*   subroutines (in addition to standard C) - none                         */
  744. X/*                                                                          */
  745. X/*   comments -  The success of this subroutine depends on the existence    */
  746. X/*               of the external file which is #defined as RTAB:        */
  747. X
  748. Xread_tbl()
  749. X{
  750. X  ushort not_yet = 1;     /* we haven't found the entry we're looking for yet */
  751. X
  752. X  int buf_ctr = 0;
  753. X
  754. X  int c;
  755. X
  756. X
  757. X
  758. X   if((rtab = fopen(RTAB,"r")) == NULL)
  759. X    {
  760. X          /* format an error message */
  761. X          time(&tloc);
  762. X          nowtime = (struct tm *)localtime(&tloc);
  763. X          time_str = asctime(nowtime);
  764. X
  765. X          sprintf(errmsg,"ISPIN: printer %s: open %s: %s.\n",dest,RTAB,sys_errlist[errno]);
  766. X          sprintf(errmsg2,"    USER: %s\n",from);
  767. X          strcat(errmsg,errmsg2);
  768. X          if(usr_addr)
  769. X          {
  770. X            sprintf(errmsg2,"    ADDR: %s\n",usr_strng);
  771. X            strcat(errmsg,errmsg2);
  772. X          }
  773. X#ifdef NQ
  774. X          sprintf(errmsg2,"    FILE: %s\n",fyle);
  775. X#else
  776. X          sprintf(errmsg2,"    FILE: %s\n",fyles[0]);
  777. X#endif
  778. X          strcat(errmsg,errmsg2);
  779. X          sprintf(errmsg2,"    TIME: %s\n",time_str);
  780. X          strcat(errmsg,errmsg2);
  781. X
  782. X         /* call the error routine, never come back */
  783. X         my_error(SYSERR);
  784. X
  785. X    }
  786. X
  787. X
  788. X
  789. X   while(not_yet)
  790. X    {
  791. X      while(((c = getc(rtab)) == ' ') || (c == '\t')); /* ignore spaces */
  792. X  
  793. X      while((c != EOF) && (not_yet))
  794. X       {
  795. X         buf_ctr = 0;
  796. X         switch(c)
  797. X          {
  798. X            case '#':
  799. X              ignore_line();        /* if line begins with a # */
  800. X              break;
  801. X            default:
  802. X              line_buf[buf_ctr] = c;
  803. X              ++buf_ctr;
  804. X              while(((c = getc(rtab)) != '\n') && (c != EOF))
  805. X              {
  806. X                line_buf[buf_ctr] = c;
  807. X                ++buf_ctr;
  808. X              }
  809. X              line_buf[buf_ctr] = '\0';
  810. X              /* check here to see if we got the correct line */
  811. X              status = 0;
  812. X              status = parse_tokens();
  813. X
  814. X
  815. X              if(status == 0)
  816. X              {
  817. X                /* we found what we were looking for */
  818. X                not_yet = 0;
  819. X                return(0);
  820. X              }
  821. X              break;
  822. X           }
  823. X          if((c != EOF)&&(not_yet))
  824. X            while(((c = getc(rtab)) == ' ') || (c == '\t'));
  825. X       }
  826. X       if((c == EOF)&&(not_yet))
  827. X       {
  828. X         /* we got all the way through the file but didn't find the printer */
  829. X         return(1);
  830. X       }
  831. X    }
  832. X    return(0);
  833. X}
  834. X
  835. X
  836. Xignore_line()
  837. X{
  838. X   int c;
  839. X
  840. X   /* ignore everything after # char as a comment */
  841. X   while(((c = getc(rtab)) != '\n') && (c != EOF));
  842. X}
  843. X
  844. X
  845. X
  846. X
  847. X
  848. Xparse_tokens()
  849. X{
  850. X  char *tokptr, *movptr, *lastptr ;
  851. X  char *strptr = line_buf;
  852. X  int ctr1 = 0;       /* a counter, which token is this? */
  853. X  int toggle = 0;       /* a toggle switch for EXPECT/SEND */
  854. X  int n = 0;
  855. X
  856. X
  857. X
  858. X  if((tokptr = strtok(strptr, ";")) != NULLCHARPTR)
  859. X  {
  860. X
  861. X
  862. X    strptr = NULLCHARPTR;          /* so we can proceed if we want to */
  863. X    if(strcmp(tokptr,dest) == 0)
  864. X    {
  865. X      /* This is the line from RTAB we are looking for. */
  866. X
  867. X
  868. X
  869. X      /* First, set up the heads of our lists.              */
  870. X
  871. X      busy_head = (struct busy_list *) calloc(1,sizeof(struct busy_list));
  872. X      busy_head->next = NULL;
  873. X      busy_list = busy_curr = busy_head;
  874. X
  875. X      dead_head = (struct dead_list *) calloc(1,sizeof(struct dead_list));
  876. X      dead_head->next = NULL;
  877. X      dead_list = dead_curr = dead_head;
  878. X
  879. X      quit_head = (struct quit_list *) calloc(1,sizeof(struct quit_list));
  880. X      quit_head->next = NULL;
  881. X      quit_list = quit_curr = quit_head;
  882. X
  883. X      disc_head = (struct disc_list *) calloc(1,sizeof(struct disc_list));
  884. X      disc_head->next = NULL;
  885. X      disc_list = disc_curr = disc_head;
  886. X
  887. X      expt_head = (struct expt_list *) calloc(1,sizeof(struct expt_list));
  888. X      expt_head->prev = NULL;
  889. X      expt_head->next = NULL;
  890. X      expt_list = expt_curr = expt_head;
  891. X
  892. X      send_head = (struct send_list *) calloc(1,sizeof(struct send_list));
  893. X      send_head->prev = NULL;
  894. X      send_head->next = NULL;
  895. X      send_list = send_curr = send_head;
  896. X
  897. X      /* Now we'll get the info we need to make the connection. */
  898. X
  899. X      while((tokptr = strtok(strptr, ";")) != NULLCHARPTR)
  900. X      {
  901. X        strptr = NULLCHARPTR;          /* so we can proceed if we want to */
  902. X        ++ctr1;
  903. X
  904. X
  905. X        switch(ctr1)
  906. X        {
  907. X          case 1:
  908. X            /* strtok can only parse one string at a time,*/
  909. X            /* so we have to process the DEVICES field    */
  910. X            /* ourselves.                                 */
  911. X            /* PROCESS DEVICES FIELD HERE */
  912. X            /**********************************************/
  913. X            if((movptr = strchr(tokptr,',')) != NULLCHARPTR)
  914. X            {
  915. X              /* we have more than one device */
  916. X
  917. X              /* save current position */
  918. X          ++movptr;
  919. X          lastptr = movptr;
  920. X
  921. X              /* get the first one */
  922. X              /* how many characters before the first comma ? */
  923. X              n = strcspn(tokptr,",");
  924. X              strncpy(dev_ray[0].name,tokptr,n);
  925. X              dev_ray[0].name[n] = '\0';
  926. X
  927. X              ret_val = 0;
  928. X
  929. X              while((movptr = strchr(lastptr,',')) != NULLCHARPTR)
  930. X          {
  931. X        ++ret_val;
  932. X        if(ret_val <= 10)
  933. X        {
  934. X                  /* get the next one */
  935. X                  /* how many characters before the next comma ? */
  936. X                  n = strcspn(lastptr,",");
  937. X                  strncpy(dev_ray[ret_val].name,lastptr,n);
  938. X                  dev_ray[ret_val].name[n] = '\0';
  939. X        }
  940. X              ++movptr;
  941. X              lastptr = movptr;
  942. X          }
  943. X
  944. X              /* get the last one */
  945. X              /* how many characters before the end ? */
  946. X              n = strlen(lastptr);
  947. X          ++ret_val;
  948. X          if(ret_val <= 10)
  949. X          {
  950. X                strcpy(dev_ray[ret_val].name,lastptr);
  951. X          }
  952. X
  953. X          for(++ret_val; ret_val <= 10; ++ret_val)
  954. X          {
  955. X                strcpy(dev_ray[ret_val].name,"NONE");
  956. X          }
  957. X            }
  958. X            else
  959. X            {
  960. X              /* only one device has been specified */
  961. X              strcpy(dev_ray[0].name,tokptr);
  962. X
  963. X
  964. X          for(ret_val = 1; ret_val <= 10; ++ret_val)
  965. X          {
  966. X                strcpy(dev_ray[ret_val].name,"NONE");
  967. X          }
  968. X            }
  969. X            /**********************************************/
  970. X            break;
  971. X          case 2:
  972. X            speed = atoi(tokptr);
  973. X            break;
  974. X          default:
  975. X            switch(tokptr[0])
  976. X            {
  977. X              case '-':
  978. X                switch(tokptr[1])
  979. X                {
  980. X                  case 'B':
  981. X                    /* BUSY */
  982. X                    while(busy_curr->next != NULL) /* until end o'list */
  983. X                    {
  984. X                      /* walk down the list */
  985. X                      busy_curr = busy_curr->next;
  986. X                    }
  987. X
  988. X                    /* don't really use the head for data storage */
  989. X                    /* allocate a new one */
  990. X                    busy_list = (struct busy_list *) calloc(1,sizeof(struct busy_list));
  991. X
  992. X                    /* link it */
  993. X                    busy_curr->next = busy_list;
  994. X
  995. X                    /* make the new list member the current list member */
  996. X                    busy_curr = busy_list;
  997. X
  998. X                    /* Put our new-found data in the newly allocated storage */
  999. X                    /* after first aiming the pointer at more new storage.   */
  1000. X                    /* string begins at tokptr[2] */
  1001. X                    busy_curr->busy_strg = (char *) calloc(1, ((strlen(&tokptr[2]))+1));
  1002. X                    strcpy(busy_curr->busy_strg,&tokptr[2]);
  1003. X
  1004. X
  1005. X
  1006. X
  1007. X
  1008. X                    /* terminate the list */
  1009. X                    busy_curr->next = NULL;
  1010. X                    break;
  1011. X                  case 'I':
  1012. X                    /* DEAD */
  1013. X                    while(dead_curr->next != NULL) /* until end o'list */
  1014. X                    {
  1015. X                      /* walk down the list */
  1016. X                      dead_curr = dead_curr->next;
  1017. X                    }
  1018. X
  1019. X                    /* don't really use the head for data storage */
  1020. X                    /* allocate a new one */
  1021. X                    dead_list = (struct dead_list *) calloc(1,sizeof(struct dead_list));
  1022. X
  1023. X                    /* link it */
  1024. X                    dead_curr->next = dead_list;
  1025. X
  1026. X                    /* make the new list member the current list member */
  1027. X                    dead_curr = dead_list;
  1028. END_OF_FILE
  1029. if test 38857 -ne `wc -c <'ISPIN/src/ISPIN.c.aa'`; then
  1030.     echo shar: \"'ISPIN/src/ISPIN.c.aa'\" unpacked with wrong size!
  1031. fi
  1032. # end of 'ISPIN/src/ISPIN.c.aa'
  1033. fi
  1034. if test -f 'ISPIN/doc/TECH.doc' -a "${1}" != "-c" ; then 
  1035.   echo shar: Will not clobber existing file \"'ISPIN/doc/TECH.doc'\"
  1036. else
  1037. echo shar: Extracting \"'ISPIN/doc/TECH.doc'\" \(7256 characters\)
  1038. sed "s/^X//" >'ISPIN/doc/TECH.doc' <<'END_OF_FILE'
  1039. X
  1040. X
  1041. X        Indianapolis Standard Printer Interface for Networked printers
  1042. X
  1043. X                                  ISPIN
  1044. X
  1045. X  ISPIN was developed by the Internal Revenue Service at Indianapolis. It
  1046. X  supports printing to networked printers through the native print spooler.
  1047. X  The author has secured permission through appropriate channels to release
  1048. X  ISPIN into the public domain.
  1049. X
  1050. X
  1051. X        /* WHY? */
  1052. X
  1053. X        Why would you want to use ISPIN?
  1054. X
  1055. X        - You've got more printers than you like hardwired to your cpu(s) 
  1056. X          already and your users want more. You'd like to be able to
  1057. X          support more printers while using fewer ttys than you do now.
  1058. X
  1059. X        - You've got users at far-flung remote sites. Their printers are
  1060. X          "slaved" to a few terminals. This limits the access of those 
  1061. X          printers to those users who are using those particular terminals.
  1062. X          Everybody has their own "personal" printer - wasteful.
  1063. X
  1064. X        - You have several cpus at your site, each with their own hardwired
  1065. X          printers. This limits your flexibility in balancing workload
  1066. X          across multiple systems. If you move an application to another
  1067. X          system, you've got to make sure the printers go with it.
  1068. X
  1069. X        - You're bored. You need a new software toy.
  1070. X
  1071. X        - If all users on all of your systems could access all of your
  1072. X          printers through all of your applications, life would be so
  1073. X          sweet. You'd do a lot less wiring/re-wiring and spend much
  1074. X          less time adding/deleting queue members and maintaining printer
  1075. X          selection menus.
  1076. X
  1077. X        - You have already tried uux'ing print jobs from one system to
  1078. X          another to overcome the limitations imposed by hardwired printers.
  1079. X          But your users gripe about the delays, and you are sick of the
  1080. X          maintenance.
  1081. X
  1082. X        - Your system(s) support(s) System V's lp/lpsched or 
  1083. X          (the old, Old, OLD) Zilog ZEUS 3.21 nq/xq/dqueuer.
  1084. X          (ISPIN does not, at present, support the Berzerkeley lpr.)
  1085. X
  1086. X        - You're bored. You need a new software toy. Not just something
  1087. X          to diddle around with and clear the screen when the boss walks
  1088. X          by. Something that will save money, increase productivity, and
  1089. X          make you a systems administration/datacomm hero in your shop
  1090. X          (or in your own mind, like me).
  1091. X
  1092. X
  1093. X        /* HOW? */
  1094. X
  1095. X        How could you implement ISPIN?
  1096. X
  1097. X        1. Disconnect all/some printers from their hardwired-to-cpu 
  1098. X           connections.
  1099. X
  1100. X        2. Connect all/some of your printers to a network, like:
  1101. X
  1102. X           - statistical switching multiplexor, such as Tellabs, Equinox,
  1103. X             David, Gandolph, Mitron, whatever. (examples, NOT ENDORSEMENT!)
  1104. X
  1105. X           or
  1106. X
  1107. X           - X.25 with asynchronous pads
  1108. X
  1109. X        3. Connect one or more ttys per cpu to the network. How many depends
  1110. X           only upon how many simultaneous print jobs you want to support.
  1111. X           In any case, it'll be far fewer ports than you use to support
  1112. X           hardwired printers.
  1113. X
  1114. X        4. Install and configure ISPIN, the easiest and least time-consuming
  1115. X           step.
  1116. X
  1117. X        5. Use your native print spooling software to add/delete, enable/
  1118. X           disable queue members. Also use native commands to issue and
  1119. X           cancel print requests.
  1120. X
  1121. X
  1122. X        /* HUH? */
  1123. X
  1124. X        How does ISPIN work?
  1125. X
  1126. X         - Your native spooler/queuer subsystem is fine for hardwired 
  1127. X           printers. It accepts enqueueing and cancellation requests, 
  1128. X           reports on its status, and allows you to add and remove queue
  1129. X           members (printers). When the spooler/queuer daemon determines
  1130. X           that it is time for a user's request to be satisfied, it
  1131. X           passes pertinent information to an executable or a shell script
  1132. X           which sends the print job out the designated tty to the printer.
  1133. X           This last process is known as the backend, or interface.
  1134. X
  1135. X         - We substitute a call to the ISPIN executable for the backend.
  1136. X
  1137. X         - The ISPIN process reads an entry for itself from a table
  1138. X           called "rtab". The rtab is intentionally similar to the uucp
  1139. X           L.sys file (or Systems file under HoneyDanBer uucp). There
  1140. X           is one rtab entry per virtual printer (any given physical printer
  1141. X           may be known or treated as several virtual printers).
  1142. X
  1143. X         - The rtab entry contains the chat data (EXPECT/SEND) necessary
  1144. X           for the ISPIN process to negotiate through the network to the
  1145. X           printer. This data may also include printer initialization and
  1146. X           configuration commands which can be passed both before and after
  1147. X           the print job.
  1148. X
  1149. X         - The rtab entry also contains a field which defines which tty(s)
  1150. X           (from one to eleven possible) this printer may be called through.
  1151. X
  1152. X         - The ISPIN process passes a formatted message to a daemon process
  1153. X           known as IQUEUER. IQUEUER determines which of the requested
  1154. X           ttys is available, and issues a message back to the ISPIN, telling
  1155. X           it to proceed, using a particular tty. IQUEUER also maintains
  1156. X           lock files, thereby avoiding conflicts with uucp, cu, uugetty,
  1157. X           etc.
  1158. X
  1159. X         - The ISPIN process, after receipt of its marching orders, sets
  1160. X           up the tty, negotiates the network, and sends the job to the
  1161. X           printer.
  1162. X
  1163. X         - The rtab entry also contains flags and arguments which indicate
  1164. X           network and printer busy and fault conditions. The ISPIN process 
  1165. X           watches for these indications to determine whether it should
  1166. X           terminate and loop or quit.
  1167. X
  1168. X         - All the while, the ISPIN process is under the complete control
  1169. X           of the native spooler/queuer. Its status (active or waiting) is
  1170. X           known to the native spooler/queuer daemon. It may be cancelled,
  1171. X           rescheduled, whatever by the native commands.
  1172. X
  1173. X         - While the ISPIN is "active" with respect to the native queuer,
  1174. X           the IQUEUER daemon is notified by the ISPIN process of its
  1175. X           current phase of execution (startup, negotiating the network,
  1176. X           printing, disconnecting, looping). The current status of all
  1177. X           currently executing ISPIN processes may be queryied via another
  1178. X           executable, known as "iq". 
  1179. X
  1180. X         - This all sounds very busy. But is is quite efficient and is
  1181. X           gratifyingly robust. If the printer is offline or busy, or
  1182. X           the network is unable to make the connection, the ISPIN will
  1183. X           loop and resubmit itself to the IQUEUER. If other jobs are
  1184. X           waiting for network access through the tty(s), the looper is
  1185. X           made to wait while other potentially successful jobs go ahead.
  1186. X           If a Greyhound takes out a telephone pole between the cpu and
  1187. X           the printer (or other mid-job disconnection), ISPIN detects
  1188. X           the fault and loops as above. Upon successful re-connection,
  1189. X           the job will be printed in its entirety.
  1190. X
  1191. X         - ISPIN is not experimental software. It has been in production
  1192. X           use since June 1989 and is currently (Nov 1991) operational at 
  1193. X           more than forty multiple-cpu sites.
  1194. END_OF_FILE
  1195. if test 7256 -ne `wc -c <'ISPIN/doc/TECH.doc'`; then
  1196.     echo shar: \"'ISPIN/doc/TECH.doc'\" unpacked with wrong size!
  1197. fi
  1198. # end of 'ISPIN/doc/TECH.doc'
  1199. fi
  1200. if test -f 'ISPIN/doc/OLD-DOCS/README.beta.1' -a "${1}" != "-c" ; then 
  1201.   echo shar: Will not clobber existing file \"'ISPIN/doc/OLD-DOCS/README.beta.1'\"
  1202. else
  1203. echo shar: Extracting \"'ISPIN/doc/OLD-DOCS/README.beta.1'\" \(3950 characters\)
  1204. sed "s/^X//" >'ISPIN/doc/OLD-DOCS/README.beta.1' <<'END_OF_FILE'
  1205. X
  1206. X
  1207. X
  1208. X        date:     February 1, 1989
  1209. X
  1210. X        to:       ISPIN Beta Test Site Volunteer
  1211. X
  1212. X        from:     Chief, Operations Branch, Information Systems Division, 35:IS
  1213. X
  1214. X        subject:  Indianapolis Standard Printer Interface (for Network printers)
  1215. X
  1216. X
  1217. X
  1218. X        Thank you for accepting my invitation to help me test ISPIN.
  1219. X        I chose you and your site for extension of my invitation because I
  1220. X        trust your judgement, your technical expertise, and your potential
  1221. X        for helping me "market" this thing, should our testing prove
  1222. X        successful. I am also counting on your impartiality to help me
  1223. X        me discover and address whatever shortcomings may become 
  1224. X        apparent during the course of testing.
  1225. X
  1226. X        This test is a test of the application, not of installation procedures,
  1227. X        nor of documentation, so please accept what is included here under
  1228. X        that premise for now. I promise to "pretty it up" for the general
  1229. X        release.
  1230. X
  1231. X        ISPIN is designed so that it may be installed anywhere on your system.
  1232. X        The decision about where files and directories will reside is made at
  1233. X        compile time. I have, however, defined default locations in the code
  1234. X        and in the install scripts. For purposes of our testing, please just
  1235. X        use the default locations.
  1236. X
  1237. X        The tape upon which I have transmitted the application was created
  1238. X        in cpio format. cd to a directory in which you want this release to
  1239. X        be written, then      cpio -iudmvB < your_nine_track_drive
  1240. X
  1241. X        The result of this cpio will be the creation of a directory named
  1242. X        ISPIN.beta. ISPIN.beta will contain two subdirectories, namely
  1243. X        ISPI and ISPIN.
  1244. X
  1245. X        ISPIN contains the source code, install documents, and install
  1246. X        scripts for the new ISPIN application. Of course, the ISPIN
  1247. X        application serves as a BACKEND for either of two native
  1248. X        queuer/spoolers, lp or dqueuer.
  1249. X
  1250. X        The ISPI directory contains the freshest version of our ISPI
  1251. X        application. ISPI is an application which serves as a FRONTEND
  1252. X        for the two queuer/spoolers. The ISPI application is fully self-
  1253. X        contained, with its own source code, documentation, etc. Use it
  1254. X        if you like, or don't use it. I sent ISPI along because we have
  1255. X        found it to be an extremely useful tool to support the native
  1256. X        queuer/spoolers.
  1257. X
  1258. X        ISPIN and ISPI are TWO SEPARATE AND DISTINCT APPLICATIONS.
  1259. X        Neither depends upon the other for functionality. You may use ISPIN
  1260. X        without ISPI. You may use ISPI without ISPIN.
  1261. X
  1262. X        The documentation of the formal type is sparse, but the code is
  1263. X        overflowing with comments. Read comments in the files common.h
  1264. X        and rtab to get a general idea of what is going on in ISPIN and
  1265. X        its related entities.
  1266. X
  1267. X        If you are installing this application under ZEUS 3.21 and its
  1268. X        nq/xq/dqueuer queuer family, read NQinstall.doc.
  1269. X
  1270. X        If you are installing this application under System V UNIX and
  1271. X        the lp spooler, read LPinstall.doc.
  1272. X
  1273. X        For now, install on Zilogs only, please. I haven't yet had an 
  1274. X        opportunity to test in any other environment. I expect, however,
  1275. X        to have the code running on a Sequent Balance B8 soon.
  1276. X
  1277. X        Here's a late news flash: ISPIN also compiles and runs just fine
  1278. X        on the AT&T UNIX PC (mine is a 3B1). I have included an install
  1279. X        script called 3B1install.csh, which is identical to LPinstall.csh
  1280. X        except for deletion of the "-f" flag from the compile lines.
  1281. X
  1282. X        I'll also say that after my testing, my confidence level is high.
  1283. X        Indianapolis is currently proceeding with full scale implementation
  1284. X        of ISPIN.
  1285. X
  1286. X        Feedback is what I need. Please communicate whatever observations
  1287. X        you may have soon and often.
  1288. X
  1289. X
  1290. X  
  1291. X                                                         Larry Bartz
  1292. X
  1293. X
  1294. END_OF_FILE
  1295. if test 3950 -ne `wc -c <'ISPIN/doc/OLD-DOCS/README.beta.1'`; then
  1296.     echo shar: \"'ISPIN/doc/OLD-DOCS/README.beta.1'\" unpacked with wrong size!
  1297. fi
  1298. # end of 'ISPIN/doc/OLD-DOCS/README.beta.1'
  1299. fi
  1300. if test -f 'ISPIN/doc/OLD-DOCS/rel_1.2.fixes' -a "${1}" != "-c" ; then 
  1301.   echo shar: Will not clobber existing file \"'ISPIN/doc/OLD-DOCS/rel_1.2.fixes'\"
  1302. else
  1303. echo shar: Extracting \"'ISPIN/doc/OLD-DOCS/rel_1.2.fixes'\" \(2255 characters\)
  1304. sed "s/^X//" >'ISPIN/doc/OLD-DOCS/rel_1.2.fixes' <<'END_OF_FILE'
  1305. X
  1306. X
  1307. X                         ISPIN RELEASE 1.2 CHANGES
  1308. X
  1309. X  ISPIN release 1.2 includes updates to correct a problem which existed
  1310. X  in release 1.1. The method by which waiting jobs are queued has
  1311. X  been modified.  Formerly, waiting print jobs were assigned to a device 
  1312. X  (port) and remained in queue for that device, even if another device which 
  1313. X  the job could use became available. Now under release 1.2, all waiting
  1314. X  jobs are put in one queue and are not assigned a device until they are 
  1315. X  actually ready to be printed. This results in more efficient scheduling 
  1316. X  of print jobs. The files which are affected by this change are iqueuer.h, 
  1317. X  IQUEUER.c, iqueuer, IQ.c, and iq.
  1318. X
  1319. X  Release 1.2 also corrects a problem with ISPIN flow control on Sequent Balance
  1320. X  systems which are connected directly to CDN.  The DYNIX SVAE Summary (Section 
  1321. X  A.2.16) states that the AT&T UNIX System V general terminal interface is 
  1322. X  not fully supported under the Sequent System V Applications Environment.
  1323. X  Since the Sequent Balance is NOT a TRUE System V machine, a portion of the
  1324. X  ISPIN application was not properly working. The program ISPIN.c has been
  1325. X  modified to correct this problem. The rtab entries on Sequent Balance machines
  1326. X  connected directly to CDN should also be modified to fix this problem. At 
  1327. X  least two disconnect arguments - "-Dpad>" and "-De" should be included in 
  1328. X  each rtab entry. Otherwise, a disconnection because of a printer being
  1329. X  turned off may not be recognized. See rtab for an example of a Sequent 
  1330. X  Balance rtab entry.
  1331. X
  1332. X  Also, the example rtab entries for "CPU to CDN to PRINTER" connections 
  1333. X  have been enhanced to add features which make printing more reliable.
  1334. X  In most cases, the old examples work fine. However, the new rtab entries
  1335. X  are more flexible in case of a failure to negotiate successfully to a
  1336. X  printer. The examples include entries to try again if no characters are
  1337. X  received from CDN. Also, the disconnect sequence has been changed to use
  1338. X  a CDN disconnect command other than the break character. The break 
  1339. X  character causes parity errors to occur on some printers (i.e. Qume 11/55).
  1340. X  For more details, see the example files in the directory 
  1341. X  "ISPIN.rel_1.2/ISPIN/install/lib_rtab/CPU_CDN_PTR".
  1342. X
  1343. END_OF_FILE
  1344. if test 2255 -ne `wc -c <'ISPIN/doc/OLD-DOCS/rel_1.2.fixes'`; then
  1345.     echo shar: \"'ISPIN/doc/OLD-DOCS/rel_1.2.fixes'\" unpacked with wrong size!
  1346. fi
  1347. # end of 'ISPIN/doc/OLD-DOCS/rel_1.2.fixes'
  1348. fi
  1349. if test -f 'ISPIN/misc/ISPIT.dr/ispit.sh' -a "${1}" != "-c" ; then 
  1350.   echo shar: Will not clobber existing file \"'ISPIN/misc/ISPIT.dr/ispit.sh'\"
  1351. else
  1352. echo shar: Extracting \"'ISPIN/misc/ISPIT.dr/ispit.sh'\" \(395 characters\)
  1353. sed "s/^X//" >'ISPIN/misc/ISPIT.dr/ispit.sh' <<'END_OF_FILE'
  1354. X#!/bin/sh
  1355. X# ispit.sh         080791    LSB
  1356. X# written to run as the user ispit's default shell (last field in passwd entry)
  1357. X# stty call is of "att" type, so must be run under att on dual universe boxes
  1358. Xecho "OUTPUT_FILE?"
  1359. Xread OF
  1360. Xecho "OK"
  1361. Xstty raw ixoff -echo hupcl brkint
  1362. Xecho "ISPIT START" >> ispit.log
  1363. Xdate >> ispit.log
  1364. Xecho $OF >> ispit.log
  1365. X./eot_trap > $OF
  1366. Xdate >> ispit.log
  1367. Xstty sane
  1368. Xexit
  1369. END_OF_FILE
  1370. if test 395 -ne `wc -c <'ISPIN/misc/ISPIT.dr/ispit.sh'`; then
  1371.     echo shar: \"'ISPIN/misc/ISPIT.dr/ispit.sh'\" unpacked with wrong size!
  1372. fi
  1373. # end of 'ISPIN/misc/ISPIT.dr/ispit.sh'
  1374. fi
  1375. echo shar: End of archive 7 \(of 15\).
  1376. cp /dev/null ark7isdone
  1377. MISSING=""
  1378. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
  1379.     if test ! -f ark${I}isdone ; then
  1380.     MISSING="${MISSING} ${I}"
  1381.     fi
  1382. done
  1383. if test "${MISSING}" = "" ; then
  1384.     echo You have unpacked all 15 archives.
  1385.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1386. else
  1387.     echo You still need to unpack the following archives:
  1388.     echo "        " ${MISSING}
  1389. fi
  1390. ##  End of shell archive.
  1391. exit 0
  1392.  
  1393.