home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume11 / 3bnet / part01 next >
Text File  |  1987-08-27  |  35KB  |  1,270 lines

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v11i025:  3Bnet utilities and printer spooler, Part01/02
  5. Message-ID: <1249@uunet.UU.NET>
  6. Date: 28 Aug 87 13:21:45 GMT
  7. Sender: Unknown@uunet.UU.NET
  8. Organization: UUNET Communications Services, Arlington, VA
  9. Lines: 1258
  10. Approved: rs@uunet.UU.NET
  11.  
  12. Submitted-by: hayes%wizard@sdcsvax.ucsd.edu (James Hayes)
  13. Posting-number: Volume 11, Issue 25
  14. Archive-name: 3bnet/Part01
  15.  
  16. This package provides a set of tools, documentation on security, and a
  17. network printer spooler for a set of machines running 3Bnet.
  18. These have only been tested on a 3b2/310 running SVR2.0x and I don't make
  19. any guarantees otherwise.  (Besides the guarantee that it is really bad
  20. code... Commented, but bad.)
  21.  
  22. As usual, complain if something doesn't work... I'll try to help as much
  23. as possible, but I can't circumvent acts of god.
  24.  
  25. Jim Hayes, University of California at San Diego.
  26.  
  27. BITNET: hayes%sdcsvax@WISCVM.BITNET
  28. ARPA:    hayes@sdcsvax.ucsd.edu
  29. UUCP:   {pick one close to berkeley}!sdcsvax!hayes
  30.  
  31. ------------------SNIPPITY-------------------
  32. # This is a shell archive.  Remove anything before this line,
  33. # then unpack it by saving it in a file and typing "sh file".
  34.  
  35. echo x - Makefile
  36. sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
  37. #
  38. #
  39. CFLAGS = -g
  40. #
  41. all:    spool 
  42.  
  43. spool:    spool.o spool.defs
  44.     cc spool.o -o spool
  45.  
  46. clean:    
  47.     rm *.o core
  48. @//E*O*F Makefile//
  49. chmod u=rw,g=r,o=r Makefile
  50.  
  51. echo x - spool.c
  52. sed 's/^@//' > "spool.c" <<'@//E*O*F spool.c//'
  53. #include <stdio.h>
  54. #include <sys/utsname.h>          /* System naming fetching library */
  55. #include <string.h>            /* Until Jim can learn strings... */
  56. #include <signal.h>
  57. #include "spool.h"            /* spool.c #defines. */
  58.  
  59. /* **************************************************************
  60. print:
  61.   spool -pprinter_name -b[banner] {files}
  62.  
  63. query:
  64.   spool -pprinter_name -q {<--query.}
  65.  
  66. list available printer:
  67.   spool -l
  68.  
  69. (A -d may be added to turn debugging on.)
  70.  
  71. Author:  James Hayes.  (hayes@sdcsvax.ucsd.edu)
  72. Log: 
  73.         Version 1.5 (Added option for banner.)        13-Feb-86 
  74.     Version 1.6 (Fixed things/cleaned up the code.)    19-Feb-86
  75.     Version 2.0 (Frozen Revision)            03-Mar-86
  76.  
  77. **************************************************************** */
  78.  
  79.    char *printer_name[20],    /* The printer name known to eecs70 students.*/
  80.         *printer_node[20],    /* The node name of the receiving printer. */
  81.     *restriction[2];    /* The restriction flag. */
  82.  
  83.     int validate_printer(),     /* Verify printer exists. */
  84.     list_printers(),    /* List available printers */
  85.     printer_status(),    /* Request remote printer status */
  86.     timeout(),        /* Wait for file to arrive. */
  87.     student,        /* Non-zero if "student" logged in */
  88.     debug;            /* Non-zero if debugging enabled. */
  89.  
  90. /* ********************************************************************** */ 
  91.  
  92. main(argc,argv)
  93. int argc;
  94. char *argv[];
  95.  
  96. {
  97.    FILE *infd, *outfd, *fopen();
  98.  
  99.    extern int errno,        /* What else? */
  100.       optind,            /* For use with getopt (2) */
  101.     opterr,            /* Ditto */
  102.     debug,            /* debug flag */
  103.         student,        /* Non zero if student running program. */
  104.     list_printers(),
  105.     validate_printer();
  106.  
  107.  
  108.    extern char *optarg,        /* Getopt option target string */
  109.     *printer_name[20],    /* The printer name known to ee70 students.*/  
  110.         *printer_node[20],    /* The node name of the receiving printer. */
  111.     *restriction[2];    /* The restriction flag. */
  112.  
  113.    char *mktemp(),        /* MaKe a TeMPorary unique file name */
  114.     *outname,        /* The temporary name itself. */
  115.     *template[150],        /* The template used to create the temp name.*/
  116.     *remote_command[255],   /* The remote command holder to the remote machine */
  117.     *requested_printer,     /* The printer requested by the student.*/
  118.     *banner,        /* The truncated (10chars) banner name. */
  119.     *login_name[20];    /* Login name of calling user. */
  120.        
  121.    int in_char,            /* Current stream input character */
  122.        current_opt,        /* Pointer the next argv[] option. getopt(2) */
  123.        error,            /* Non zero if command line errors found.*/
  124.        prflag,            /* Non zero if a printer was specified */
  125.        list_available,        /* Non zero if a printer list was asked for */
  126.        query,            /* Non zero if printer status requested    */
  127.        banflag,            /* Non zero if a banner was specified */
  128.        exec_status,        /* Exit status of the system call 'system()' */
  129.        i; 
  130.  
  131.    struct utsname name;        /* Structure for the uname() system call */
  132.  
  133.    list_available=        /* Initialize everything. */
  134.    debug=
  135.    query=
  136.    error=
  137.    prflag=
  138.    student=
  139.    banflag=0;   
  140.  
  141.    uname(&name);                    /* Get the system name. */
  142.    sprintf(template,DEFAULT_DIR,name.sysname);        /* Make the temporary file templaye. */
  143.  
  144.    cuserid(login_name);                    /* Get the login name of the user */
  145.    if ( (strcmp(login_name,"student"))==0 ) student++;  /* If student, set the student flag */
  146.  
  147.    if ( (strcmp(argv[3],"@"))==0 ) return_state(argv[1],argv[2]);   /* Invoke the return mode of spool ? */
  148.  
  149.    /* Loop through all possible options and set flags according to what
  150.       is chosen.  If an erronious command line option is choosen, then
  151.       error is set to non-zero and the spooling stops.   */
  152.  
  153.    while  ((current_opt=getopt(argc,argv,"p:b:sld")) !=EOF)
  154.          switch (current_opt)
  155.           {
  156.            case 'p':        /* Printer? */
  157.             prflag++;
  158.             requested_printer=optarg;
  159.             break;
  160.             case 'b':        /* Banner name? */
  161.             banflag++;
  162.             banner=optarg;
  163.             break;
  164.            case 's':         /* Query printer? */
  165.             query++;
  166.             break;
  167.            case 'd':        /* Debug flag? */
  168.             debug++;
  169.             break;
  170.            case 'l':        /* List printers? */
  171.             list_available++;
  172.             break;
  173.            case '?':        /* Bad option? */
  174.             error++;
  175.             break;
  176.           }
  177.  
  178.  
  179. DEBUG Template for making files %s\n",template);
  180. DEBUG Student UID=%d, student flag=%d\n",getuid(),student);
  181.  
  182.       if ( (query) && (prflag))                        /* Got -s and a printer name? */
  183.       if ( (validate_printer(requested_printer))==0 )          /* Valid name? */
  184.         {
  185.           fprintf(stderr,"spool: printer %s does not exist.\n", requested_printer);
  186.           fprintf(stderr, "       To see supported printers, use: spool -l\n"); 
  187.               exit(1);
  188.         }
  189.       else                                /* Everything O.K... Do query. */
  190.         {
  191.           query_request(printer_node);
  192.           exit(0);
  193.          }
  194.  
  195.       if (query)    /*Since -s is a strange option, be polite. */
  196.     {
  197.       fprintf(stderr,"spool: Please request a printer\n");
  198.       exit(2);
  199.     }
  200.  
  201.       if (list_available)         /* List available printers?  */
  202.     {
  203.       DEBUG Listing printers: \n");
  204.       list_printers();
  205.       exit(0);
  206.         }
  207.  
  208.       /********************************************************************
  209.        * Bad flag combinations, ie. Banner and no printer, printer and no
  210.        * banner, no banner and printer, are not allowed.
  211.        ********************************************************************
  212.        */
  213.  
  214.       if ((prflag==NULL) && (banflag)) error++;
  215.       if ((banflag==NULL) && (prflag)) error++;
  216.       if ((banflag==NULL) && (prflag==NULL)) error++;
  217.  
  218.       if (error==0)            /* No errors? Check printer name. */
  219.  
  220.       if ( (validate_printer(requested_printer))==0 )
  221.         {
  222.          fprintf(stderr, "spool: Incorrect printer choice\n");
  223.          error++;
  224.         }
  225.       if (error)
  226.        {
  227.      fprintf(stderr,USAGE);        /* If there was an error, print the */
  228.      list_printers();        /* command usage, and list the */
  229.      exit(3);            /* Available printers. */
  230.        }
  231.  
  232. DEBUG Your printer: node: %s Res: %s Name: %s\n\n", printer_node,restriction, printer_name);
  233.  
  234.        i=optind;              /* Save pointer to beginning of file names in the argv. */
  235.  
  236. /*******************************************************************************************************
  237.  * Scan through each name specified to see if it is readable...  (As usual, complain if not, and exit.)
  238.  *******************************************************************************************************
  239.  */
  240.  
  241.      for (;optind<argc;optind++)
  242.        if (access(argv[i],4) !=NULL)               /* Check for read permissions */
  243.          {
  244.            fprintf(stderr,"spool: error opening %s for transmission.\n", argv[optind]);
  245.            exit(4);
  246.          }
  247.  
  248.     infd=stdin;            /* Default input is stdin. */
  249.     outname=mktemp(template);      /* Form unique filename. */
  250.       outfd=fopen(outname,"w");     /* Open it for writing. */
  251.     if (outfd==NULL)        /* Error? */
  252.        {
  253.         fprintf(stderr,"spool: panic: error opening tempfile %s\n",outname);
  254.         exit(5);    
  255.       }
  256.  
  257.     optind=i;    /* Restore saved argv pointer */
  258.  
  259.     do           /* Copy each file into the transmission file. */
  260.       {
  261.           if (optind < argc)
  262.            {
  263.              infd=fopen(argv[i],"r");   /* Open for reading */
  264.              if (infd==NULL)
  265.               {
  266.             fprintf(stderr,"spool: File %s was deleted, spool attempt aborted.\n",argv[i]);
  267.             exit(6);
  268.               }
  269.            }
  270.            while ( (in_char=getc(infd)) !=EOF) putc(in_char,outfd); 
  271.            if (infd!=stdin) fclose(infd);                /* Don't try and close stdin. */
  272.       } while (++i < argc);                         /* Until all files are done. */
  273.  
  274.       fclose(outfd);                             /* Ready to transmit. */
  275.  
  276.       errno=0;  /* Just in case... */
  277.  
  278.       sprintf(banner,"%.10s",banner);               /* Truncate the banner. */
  279.  
  280.       if ( (strcmp(name.sysname,printer_node))==0)        /* Are we on the same node we are trying to send to? */
  281.         sprintf(remote_command,LOCAL_LP,LOCAL_LP_ARGS);         /* If so, use the local command. */
  282.       else 
  283.         sprintf(remote_command,COMMAND,ARGUMENTS);          /* Otherwise, use the network command. */
  284.  
  285.       DEBUG Remote command:\n%s\n",remote_command);
  286.  
  287.       if (debug==0)
  288.       {
  289.         exec_status=system(remote_command);             /* Execute the command. */
  290.  
  291.         if (exec_status == ERR)                 /* Was there a problem? */
  292.       {
  293.        fprintf(stderr,"spool: can't execute transmit program, spool attempt aborted with\n");
  294.        fprintf(stderr,"       system() erorr %d.\n",errno);
  295.        unlink(outname);
  296.        exit(7);
  297.       }
  298.        }
  299.  
  300. DEBUG Unlinking work file %s.\n",outname);
  301.  
  302.     if (unlink(outname) != NULL)
  303.       {
  304.         fprintf(stderr,"panic: spool could not delete the temporary workfile %s. File(s) did transmit.\n",outname);
  305.         exit(8);
  306.       }
  307.  
  308.   if ( (strcmp(name.sysname,printer_node))!=0)
  309.   list_response(name.sysname);                        /* Wait for status file to come back. & printit. */
  310.  
  311. DEBUG EXIT.\n");
  312. }
  313.  
  314. /****************************************************************************
  315.  * validate (requested_printer);
  316.  *
  317.  *        return code:  0=not found.
  318.  *            non-zero, found.
  319.  *
  320.  *       If found, the node_name of the printer is returned in printer_node,
  321.  *     along with it's restriction in restriction.
  322.  ****************************************************************************
  323.  */
  324.  
  325. validate_printer(requested_printer)
  326. char *requested_printer;
  327. {
  328.   FILE *infd;
  329.  
  330. extern char *printer_name[20],    /* The printer name known to ee70 students.*/  
  331.         *printer_node[20],    /* The node name of the receiving printer. */
  332.     *restriction[2];    /* The restriction flag. */
  333.  
  334. extern int student;
  335.  
  336.   int    in_char,        /* Current stream input char. */
  337.     found,            /* found requested printer in SYS_PRINTERS file if non-zero. */
  338.     scan_OK;        /* Result of fscanf. -1=EOF. */
  339.     
  340.   found=0;
  341.   if ((infd=fopen(SYS_PRINTERS,"r"))==NULL)
  342.   {
  343.     printf(stderr,"spool: Network printer database could not be located.\n");
  344.     exit(10);
  345.   }
  346.   else
  347.   {
  348.    scan_OK=0;
  349.    do
  350.    {
  351.      in_char=getc(infd);            /* Get first character */
  352.      if (in_char==EOL)                 /* Blank line? */
  353.       {
  354.        do in_char=getc(infd) ;          /* Skip any extra newlines. */
  355.        while (in_char==EOL);
  356.       }
  357.      if (in_char==SCRATCH)              /* Was it a beginning of a comment? */
  358.      do in_char=getc(infd) ;
  359.      while ( (in_char!=EOL) && (in_char!=EOF) ) ;
  360.              
  361.      if (in_char==EOF) scan_OK=-1;          /* End of file? God forbid! */
  362.  
  363.      if ((scan_OK==-1) || (in_char==SCRATCH) || (in_char==EOL)) ;
  364.      else
  365.        {
  366.     ungetc(in_char,infd);    /* Put the first character back. */
  367.     scan_OK=fscanf(infd,"%s%s%s",printer_name,restriction, printer_node);
  368.  
  369.        if ( (strcmp(printer_name,requested_printer))==0 ) /* Found? */
  370.          {
  371.              scan_OK=EOF;               /* Found? YES!, so artificially end the file. */
  372.          found++;
  373.          DEBUG Found printer name %s, restriction=%s.\n",printer_name, restriction);
  374.          DEBUG Student flag=%d\n",student);
  375.  
  376.              if ( ((strcmp(restriction,"R"))==0)  && (student>0) )
  377.                {
  378.              fprintf(stderr, "spool: You are not allowed to use printer %s.\n", requested_printer);
  379.              exit(13);
  380.                }
  381.          }
  382.        }
  383.    } while (scan_OK!=EOF);        /* Keep going until EOF */
  384.      fclose(infd);
  385.   }
  386.    return found;
  387. }
  388.  
  389. /****************************************************************************
  390.  * List available printers from SYS_PRINTERS.
  391.  * (and print them out of course!)
  392.  ****************************************************************************
  393.  */
  394.  
  395. list_printers()
  396. {
  397.   FILE *infd;
  398.  
  399. extern char *printer_name[20],    /* The printer name known to ee70 students.*/  
  400.         *printer_node[20],    /* The node name of the receiving printer. */
  401.     *restriction[2];    /* The restriction flag. */
  402.  
  403. extern int debug;
  404.  
  405. int     in_char,
  406.     scan_OK;
  407.  
  408.   if ((infd=fopen(SYS_PRINTERS,"r"))==NULL)
  409.   {
  410.     printf(stderr,"spool: Network printer database could not be located.\n");
  411.     exit(10);
  412.   }
  413.   else
  414.   {
  415.     fprintf(stdout,"\n   %-15s| %-30s\n","Printer Name:", "Restriction: (A=Anyone, R=Restricted)");
  416.     fprintf(stdout,"   ---------------+--------------------------------------\n");
  417.     scan_OK=0;
  418.     do
  419.      {
  420.        in_char=getc(infd);  /* See above for the comments for this mess. */
  421.        if (in_char==EOL) 
  422.           do in_char=getc(infd); while (in_char==EOL);
  423.  
  424.        if (in_char==SCRATCH)
  425.      do in_char=getc(infd); while ( (in_char!=EOL) && (in_char!=EOF) );
  426.              
  427.        if (in_char==EOF) scan_OK=-1;
  428.        if ((scan_OK==-1) || (in_char==SCRATCH) || (in_char==EOL)) ;
  429.        else
  430.         {
  431.       ungetc(in_char,infd);
  432.       scan_OK=fscanf(infd,"%s%s%s",printer_name,restriction, printer_node);
  433.       fprintf(stdout,"   %-15s|%2s\n",printer_name,restriction);
  434.         }
  435.    } while (scan_OK!=EOF) ;
  436.   }
  437.    fclose(infd);
  438.    fprintf(stdout,"\n");
  439.    return;
  440. }
  441.  
  442. /****************************************************************************
  443.  * List response sent by remote system.  If it hasn't arrived yet, wait
  444.  * until it does.  (Up to 40 seconds.)
  445.  ****************************************************************************
  446.  */
  447. list_response(system_name)            /* Name of this system. (Used to build correct file name.) */
  448. char *system_name;
  449. {
  450.    FILE *infd;
  451.    int in_char;
  452.    char *filename[30];
  453.  
  454.    sprintf(filename,STATUS_TEMPLATE,system_name);
  455.    wait_file(TIMEOUT,filename);            /* Wait for TIMEOUT seconds for file 'filename' to arrive. */
  456.  
  457.    if ( (infd=fopen(filename,"r"))==NULL )
  458.       {
  459.     fprintf(stderr,"spool: Status file \'%s\' is missing. Hmm.\n", system_name);
  460.     exit(11);
  461.       }
  462.     else
  463.       {
  464.     fprintf(stdout,"\n");
  465.         while ( (in_char=getc(infd)) !=EOF) putc(in_char,stdout);     /* List the file. */
  466.     fprintf(stdout,"\n");
  467.     close(infd);
  468.     if ( (unlink(filename)) !=NULL )
  469.         fprintf(stderr,"Can't remove status file %s. Tell proctor.\n", filename);
  470.     exit(8);
  471.       }
  472. }
  473.  
  474. /****************************************************************************
  475.  * query_request(printer_node);
  476.  * Line printer query request for printer 'printer_node'.
  477.  ****************************************************************************
  478.  */
  479.  
  480. query_request(printer_node)
  481. char *printer_node;
  482. {
  483.    extern int errno,
  484.     debug;
  485.  
  486.    int exec_status,
  487.        in_char; 
  488.  
  489.    char *mktemp(),
  490.     *outname,
  491.     *template[150],
  492.     *remote_command[255];  
  493.  
  494.    struct utsname name;        /* System name fetching structure */
  495.  
  496.    uname(&name);         /* Fetch our system name. */
  497.  
  498.    errno=0;
  499.  
  500.    if ( (strcmp(name.sysname,printer_node))==0)       /* Requesting from same machine as printer? */
  501.      sprintf(remote_command,LOCAL_LPSTAT);          /* Issue local lpstat command. */
  502.    else
  503.      sprintf(remote_command,QUERY_COMMAND,QUERY_ARGUMENTS);   /* Otherwise, use remote command. */
  504.  
  505.    DEBUG Remote command: %s\n",remote_command);
  506.  
  507.   if (debug==0)
  508.    {
  509.    exec_status=system(remote_command);
  510.  
  511.       if (exec_status == ERR)
  512.       {
  513.        fprintf(stderr,"spool: Can't execute request program, request attempt aborted with\n");
  514.        fprintf(stderr,"       system() error %d.\n",errno);
  515.        exit(9);
  516.       }
  517.    }
  518.    if ( (strcmp(name.sysname,printer_node))!=0)        /* If requesting from remote machine, wait for results. */
  519.    list_response(name.sysname);
  520. }
  521.  
  522. /****************************************************************************
  523.  * wait_file(seconds,filename);
  524.  * wait 'seconds' for file 'filename'
  525.  * NOTE:  THE FILE BEING WAITED FOR IS UNLINKED, JUST IN CASE AN OLDER 
  526.  *        VERSION OF IT MIGHT BE AROUND.    YOU HAVE BEEN WARNED....
  527.  * 
  528.  * If no file arrives after 'seconds', print error and exit(12) 
  529.  ****************************************************************************
  530.  */
  531. wait_file(seconds,filename)
  532. int seconds;
  533. char *filename;
  534. {
  535.    DEBUG Filename: %s\n",filename);
  536.    unlink(filename);            /* Just in case a leftover exists. */
  537.  
  538.    signal(SIGALRM,timeout);         /* Set the alarm to point to the time out routine. */
  539.    alarm(seconds);            /* Allow seconds timeout. */
  540.    fprintf(stdout,"One moment please, your request is being processed.");
  541.    fflush(stdout);
  542.    
  543.    do 
  544.      {
  545.        fprintf(stdout,".");        /* Print little dots every few seconds to let the user know what's goin on. */
  546.        fflush(stdout);
  547.        sleep(2);
  548.      }
  549.       while ((access(filename,4))!=NULL );    /* Keep doing it until the time runs out, or the file arrives. */
  550.  
  551.   signal(SIGALRM, SIG_IGN);
  552. }
  553.  
  554. timeout()
  555. {
  556.   signal(SIGALRM, SIG_IGN);
  557.   printf("\nSorry, the remote machine is not answering. Please make sure the\n");
  558.   printf("printer/remote machine is operating properly.\n");
  559.   exit(12);
  560. }
  561.  
  562. /****************************************************************************
  563.  * This is the return server for the spool program. It is invoked with
  564.  * spool machine_making_request request_type @
  565.  ****************************************************************************
  566.  */
  567. return_state(sysname,command)
  568. char *sysname,
  569.      *command;
  570. {
  571.  int exec_status; 
  572.  char *remote_command[255];
  573.  
  574.  printf("Command: %s, Sysname: %s\n",command,sysname);
  575.  
  576.   if (strcmp(command,"S")==0)                    /* Status request */
  577.     sprintf(remote_command,STAT_COMMAND,STAT_ARGUMENTS);
  578.  
  579.   if (strcmp(command,"R")==0)                    /* Return lp command status */
  580.     sprintf(remote_command,LP_COMMAND,LP_ARGUMENTS);
  581.  
  582.   printf("Remote command: %s\n",remote_command);
  583.  
  584.   exec_status=system(remote_command);
  585.  
  586.   exit(0);
  587. }
  588.  
  589. @//E*O*F spool.c//
  590. chmod u=rw,g=r,o=r spool.c
  591.  
  592. echo x - spool.doc.ms
  593. sed 's/^@//' > "spool.doc.ms" <<'@//E*O*F spool.doc.ms//'
  594. @.ST
  595. @.nr VS 18
  596. @.ds LH "EECS 70
  597. @.ds RH %
  598. @.ds CH "Project Report
  599. @.ds CF
  600. @.sp 2i
  601. @.LG
  602. @.ce
  603. \fBReport of activities\fI
  604. @.sp
  605. @.ce
  606. \fBPrinter Spooling Over 3bnet\fR
  607. @.sp 2
  608. @.ce
  609. @.SM
  610. @.nr VS 15
  611. James A. Hayes
  612. @.br
  613. @.ce
  614. University of California,
  615. @.br
  616. @.ce
  617. San Diego
  618. @.br
  619. @.sp 3
  620. @.ce
  621. @.LG
  622. @.I ABSTRACT
  623. @.sp
  624. @.QP
  625. @.LG
  626. @.nr VS 18
  627. The goal of the
  628. @.I spool
  629. implementation is to allow students to send information to printers
  630. not physically
  631. connected to their machine.  This design replaces the current method of
  632. having to physically login to the printer's host.  This document
  633. will provide an outline of the 
  634. @.I spool
  635. implementation.
  636. @.sp 3
  637. @.nr VS 14
  638. @.LP
  639. March, 1986
  640. @.br
  641. @.nr PS 12
  642. @.bp
  643. @.SH
  644. Introduction
  645. @.PP
  646. While the concept of a remote printer spooling system is easy to
  647. understand, the actual implementation is at best, complicated.  If you have
  648. not already done so, please read the
  649. @.I spool
  650. manual page which will explain the \fIspool\fR command syntax.
  651. This document will try to explain the
  652. @.I spool
  653. implementation in three stages.  An explanation of network
  654. security, a description of the
  655. @.I nisend
  656. command,  and finally,
  657. a nuts-and-bolts description of the spooling software.
  658. @.sp
  659. @.SH
  660. 1. Network Security
  661. @.PP
  662. The AT&T 3B2 computer is capable of running an Ethernet network 
  663. communications
  664. system.  While the software provided with the Ethernet hardware is complete, 
  665. a major problem arises when trying to use it in an educational environment.
  666. The network commands are not protected from subversive
  667. application.  That is
  668. to say, it is dangerous when
  669. @.I anyone
  670. is given permission to use the network
  671. commands.  This means that a student on machine A can
  672. @.I copy
  673. or knowingly
  674. @.I damage
  675. homework files from a student on machine B.
  676. @.PP
  677. The means for securing
  678. the crucial network command (\fInisend\fR)
  679. is borne from built-in UNIX\(dg
  680. @.FS
  681. \(dg.
  682. UNIX is a trademark of AT&T Bell Laboratories.
  683. @.FE
  684. execution privileges.
  685. @.PP
  686. The network command
  687. @.I nisend
  688. is owned by
  689. @.B bin
  690. and is a member of the newly
  691. created group
  692. \fBnisecure\fR.  It has  only the owner and group execute
  693. permissions set.  This will not allow anyone but
  694. @.B root
  695. or a member of the
  696. group
  697. @.B nisecure
  698. to execute the
  699. @.I nisend
  700. program.  The print spooler (\fIspool\fR) is
  701. also a member of the group
  702. @.B nisecure
  703. and sets its group identification (sgid) on
  704. execution.  The execute permissions for
  705. @.I spool
  706. allow it to be run by anyone.
  707. @.PP
  708. Since the group ID of
  709. @.I spool
  710. is the same as \fInisend\fR,
  711. @.I spool
  712. is allowed to call
  713. \fInisend\fR.  So far, 
  714. @.I spool
  715. is the only program that is allowed to call \fInisend\fR.
  716. @.PP
  717. The access permissions (as seen by \fIls\fR)
  718. look like this:
  719. @.KS
  720. @.sp
  721. @.ce
  722. /usr/bin/nisend /usr/bin/spool
  723. @.TS
  724. center;
  725. l l l l l l.
  726. -rwxr-s---    bin    nisecure    xx/xx/86    12:00    nisend
  727. -rwxr-xr-x    root    nisecure    xx/xx/86    12:00    spool
  728. @.TE
  729. @.KE
  730. @.sp
  731. @.SH
  732. 2. The `nisend' Program
  733. @.PP
  734. The
  735. @.I nisend
  736. program is provided by AT&T as a front-end file transfer and
  737. remote command execution system to be used by programs at the
  738. shell and applications
  739. level.  It is complete, but does have a few problems that are worth
  740. mentioning.
  741. @.PP
  742. @.I Nisend
  743. sends mail to its users after every request, transfer, command
  744. execution, error and hiccup.  The default file access mode is set to 
  745. 600 (owner read/write).  The directory where the file will be saved (once
  746. transmitted) is not the same directory it was taken from.  The default
  747. receiving directory is ~/rje/\fIname\fR.  The
  748. local file to be transmitted must
  749. be the last item on the command line.  The one line \*Q3bnet job xxxxyyy
  750. submitted\*U is always printed.
  751. @.PP
  752. The  above problems may be circumvented by command line options.  To
  753. stop mail, use the
  754. @.I undocumented
  755. -e option.  To set
  756. the access permissions of
  757. the remote files, use the -a\fImode\fR option.  To specify
  758. what directory the
  759. file is to be saved in, use the -f\fIpath\fR option.  The
  760. \*Q3bnet...\*U message may be silenced by the -s option.
  761. @.PP
  762. The spool program uses a standard form of the
  763. @.I nisend
  764. command that avoids all the above problems. It looks like this:
  765. @.LP
  766. @.in +.5i
  767. @.ti -.5i
  768. @.na
  769. nisend -s -e -d\fIremote_machine\fR -a0666
  770. -f/usr/tmp/\fIremote_name\fR
  771. -!\*Q\fIremote_command\fR\*U /usr/tmp/\fIlocal_file\fR
  772. @.ad b
  773. @.in -.5i
  774. @.sp
  775. @.SH
  776. 3. The `spool' Program, an Overview
  777. @.PP
  778. The
  779. @.I spool
  780. program is not a server, although it performs the function of
  781. a server because it is executed on the sending machine as well
  782. as the receiving machine when a request is submitted.
  783. @.PP
  784. The sending machine is responsible for collecting the files, sending
  785. them, submitting them for printing, and waiting for confirmation from the
  786. @.I spool
  787. program on the receiving end.  The 
  788. @.I spool
  789. program on the receiving end
  790. takes the confirmation from
  791. @.I lp
  792. or status from
  793. @.I lpstat
  794. and returns it to the
  795. waiting machine on the sending end.
  796. @.sp
  797. @.SH
  798. 3.1. Spooling a File for Remote Printing
  799. @.sp
  800. \fRCOMMAND: spool -p room10 -bJones foo.c
  801. @.sp
  802. ACTIONS:
  803. @.PP
  804. Validate the command options and verify that the specified file(s) and
  805. printer (via \fI/etc/sysprint\fR) exist.
  806. Read the file(s) (via stdin or file name(s)
  807. on command line), concatenate them, and put them in a temporary file
  808. /usr/tmp/sp.\fInode\fR.\fIXXXXX\fR, where
  809. @.I node
  810. is the
  811. @.B 3bnet
  812. node name of the user's
  813. machine making the request, and
  814. @.I XXXXX
  815. is the process ID of the
  816. @.I spool
  817. program.  The above actions insure that the temporary file will have a
  818. unique name on the remote machine when it is arrives there.
  819. @.PP
  820. Send the file to the remote system, execute
  821. @.I lp
  822. on the
  823. remote system, store the standard output and standard error of
  824. @.I lp
  825. in another temporary file /usr/tmp/\fInode\fR.stat,
  826. send it back to the user, display it
  827. and exit.
  828. @.KS
  829. @.LP
  830. For example: (See also \fIFigure 1\fR)
  831. @.IP \fBUSER:\fR 10
  832. $ pr *.s | spool -pX -bSharon  (executed on machine A, for printer X
  833. on machine B, with PID=5427.)
  834. @.sp
  835. @.KE
  836. @.LP
  837. @.B SPOOL:
  838. (SENDING END)
  839. @.IP 1.
  840. Collect standard input (or specified files) and save in
  841. /usr/tmp/sp.A.a5427
  842. @.IP 2.
  843. Execute
  844. @.I nisend
  845. (via the
  846. @.I system()
  847. call).
  848. @.QP
  849. @.na
  850. /usr/bin/nisend -s -e -dB -a0666 -f/usr/tmp/sp.A.a5427 -!\*Q\fBSee
  851. remote command below\fR\*U /usr/tmp/sp.A.a5427
  852. @.ad b
  853. @.IP 3.
  854. Remove /usr/tmp/sp.A.a5427
  855. @.IP 4.
  856. Wait for the response /usr/tmp/A.stat to arrive, (contains the output
  857. of the
  858. @.I lp
  859. command.) give it 40 seconds to show up, and if it doesn't
  860. arrive after that, give up and tell the user what happened. If it
  861. does arrive in the allotted time, print it out.
  862. @.IP 5.
  863. Remove /usr/tmp/A.stat (If it arrived from the remote machine.)
  864. @.sp
  865. @.LP
  866. \fBRemotely executed command (broken down into steps):\fR
  867. [Please note that the
  868. @.I lp
  869. command is executed on the printing system by
  870. @.I spool
  871. on the requesting system and not by
  872. @.I spool
  873. on the printing system.  This saves about 3 seconds that would
  874. normally be wasted waiting for
  875. @.I spool
  876. to fork() and exec(), then waiting for
  877. @.I lp
  878. to echo the request ID.  Now, the result of
  879. @.I lp
  880. can be sent back the moment it is available.  This is quirk of the
  881. @.I nisend
  882. command.]
  883. @.sp
  884. @.in +.5i
  885. @.IP A.
  886. submit the job to lp and capture its output:
  887. @.QP
  888. @.na
  889. usr/bin/lp -tSharon -c /usr/tmp/sp.A.a5427 > /usr/tmp/A.stat 2>&1
  890. @.ad b
  891. @.IP B.
  892. Remove the temporary file:
  893. rm /usr/tmp/sp.A.a5427
  894. @.IP C.
  895. Return the captured output of
  896. @.I lp
  897. to the calling spool by executing
  898. spool on the receiving end:
  899. @.in +.5i
  900. /usr/bin/spool A R @  (A=Name to send back to, R=\fIlp\fR report,
  901. @@=Receiver mode.)
  902. @.in -.5i
  903. @.IP D.
  904. Remove the captured output of lp and return.
  905. @.QP
  906. rm /usr/tmp/A.stat
  907. @.in -.5i
  908. @.sp 1
  909. @.SH
  910. 3.2. Requesting a Status Report on the Remote Printer
  911. @.sp
  912. \fRCOMMAND: spool -s -p room10
  913. @.sp
  914. ACTIONS:
  915. @.PP
  916. Validate the command options and verify that the specified printer (via
  917. \fI/etc/sysprint\fR) exists.
  918. @.PP
  919. Execute the
  920. @.I lpstat
  921. program on the remote system, store the standard output
  922. and standard error of
  923. @.I lpstat
  924. in a temporary file /usr/tmp/\fInode\fR.stat, send it back to
  925. the user, display it and exit. (\fINode\fR is the requesting
  926. @.B 3bnet
  927. node name.)
  928. @.KS
  929. @.LP
  930. For example: (see also \fIFigure 2\fR)
  931. @.IP \fBUSER:\fR 10
  932. $ spool -s -pX (executed on machine A, for printer X on machine B)
  933. @.br
  934. @.KE
  935. @.LP
  936. @.B SPOOL:
  937. (SENDING END)
  938. @.IP 1.
  939. Execute
  940. @.I nisend
  941. (via the
  942. @.I system()
  943. call):
  944. @.QP
  945. @.na
  946. /usr/bin/nisend -s -e -dB -a0666
  947. -!\*Q\fBSee remote command below\fR\*U
  948. @.ad b
  949. @.IP 2.
  950. Wait for the response /usr/tmp/A.stat to arrive, (contains the output of
  951. the
  952. @.I lpstat
  953. command.) give it 40 seconds to show up, and if it
  954. doesn't arrive after that, give up and tell the user what
  955. happened. If it does arrive in the allotted time, print it out.
  956. @.IP 3.
  957. Remove /usr/tmp/A.stat (If it arrived from the remote machine.)
  958. @.sp
  959. @.LP
  960. \fBRemotely executed command (broken down into steps):\fR
  961. @.in +.5i
  962. @.IP A.
  963. Fire-up
  964. @.I spool
  965. on the receiving end. There it will execute
  966. @.I lpstat
  967. and return the output back to the user:
  968. @.in +.5i
  969. /usr/bin/spool A S @  (A=Machine name to send back to, S=lp status
  970. report, @=Receiver mode.)
  971. @.in -.5i
  972. @.IP B.
  973. Remove the captured output of
  974. @.I lpstat
  975. and exit.
  976. @.in +.5i
  977. rm /usr/tmp/A.stat
  978. @.in -1i
  979. @.sp 2
  980. @.SH
  981. Conclusion/Comments
  982. @.PP
  983. It is not the most efficient, but it works.  Possible future
  984. improvements might involve an actual spool daemon.  This would make
  985. handshaking more reliable, instead of using 
  986. @.I nisend
  987. which is very slow and very sensitive to system load.
  988. @.sp
  989. @//E*O*F spool.doc.ms//
  990. chmod u=rwx,g=r,o= spool.doc.ms
  991.  
  992. echo x - spool.h
  993. sed 's/^@//' > "spool.h" <<'@//E*O*F spool.h//'
  994. #define SYS_PRINTERS "/etc/sysprint"    /* Location of printer info. */
  995. #define DEFAULT_DIR "/usr/tmp/%sXXXXXX"      /* Place for temp files,
  996.     where %s and XXXXXX will be replaced by the machine name and
  997.     process I.D. */
  998. #define TIMEOUT 50            /* Seconds to wait for response */
  999. /* ***************************************************************************
  1000. COMMAND is what is sent to the remote system.  Various arguments in the
  1001. command (%s strings) are specified in the ARGUMENTS portion.  The arguments
  1002. are declared in the order they appear in the command.
  1003. ************************************************************************** */
  1004.  
  1005. #define COMMAND "/usr/bin/nisend -e -d%s -a0666 -s -c -f%s -!\042\
  1006. /usr/bin/lp -c -t%s %s>/usr/tmp/%s.stat 2>&1; rm %s;\
  1007. /usr/local/spool %s R @; rm /usr/tmp/%s.stat\042 %s"
  1008.  
  1009.  
  1010. #define ARGUMENTS printer_node,outname,banner,outname,name.sysname,outname,\
  1011.     name.sysname,name.sysname,outname
  1012.  
  1013. /* **************************************************************************
  1014. QUERY_COMMAND is what gets sent to the remote printer to get its status
  1015. sent back. QUERY_ARGUEMENTS are stuffed into the QUERY_COMMAND.
  1016. ************************************************************************** */
  1017. #define QUERY_COMMAND "/usr/bin/nisend -e -s -d%s -!\
  1018. \042/usr/local/spool %s S @; rm /usr/tmp/%s.stat\042"
  1019.  
  1020. #define QUERY_ARGUMENTS printer_node,name.sysname,name.sysname
  1021.  
  1022. #define USAGE "print:  spool -p {printer} -b {banner}\n\
  1023. status: spool -p {printer} -s\n\
  1024. list supported network printers: spool -l\n"
  1025.  
  1026. #define STAT_COMMAND "lpstat -a -r -u -p>/usr/tmp/%s.stat;\
  1027. /usr/bin/nisend -c -e -d%s -a0666 -f/usr/tmp/%s.stat \
  1028. /usr/tmp/%s.stat"
  1029.  
  1030. #define STAT_ARGUMENTS sysname,sysname,sysname,sysname
  1031.  
  1032. #define LP_COMMAND "/usr/bin/nisend -s -e -c -d%s -a0666 -f /usr/tmp/%s.stat \
  1033. /usr/tmp/%s.stat"
  1034.  
  1035. #define LP_ARGUMENTS sysname,sysname,sysname 
  1036.  
  1037. /* We use these commands in the case that the person spooling to a remote
  1038.     printer, isn't.  (Meaning: When they are on the same machine as
  1039.     the printer, and no network activity needs to take place.
  1040. /*
  1041. #define LOCAL_LP "/usr/bin/lp -c -t%s %s"
  1042. #define LOCAL_LP_ARGS banner,outname
  1043.  
  1044. #define LOCAL_LPSTAT "/usr/bin/lpstat -a -r -u -p"
  1045. #define STATUS_TEMPLATE "/usr/tmp/%s.stat"
  1046.  
  1047. #define ERR -1
  1048. #define DEBUG if (debug) fprintf(stderr,"Debug>
  1049. #define EOL 10
  1050. #define SCRATCH 35
  1051.  
  1052. @//E*O*F spool.h//
  1053. chmod u=rw,g=r,o=r spool.h
  1054.  
  1055. echo x - spool.man
  1056. sed 's/^@//' > "spool.man" <<'@//E*O*F spool.man//'
  1057. @.TH SPOOL 1 Local
  1058. @.AT 5 2.0
  1059. @.SH NAME
  1060. spool - spool files to remote printer.
  1061. @.sp
  1062. @.SH SYNOPSIS
  1063. @.PP
  1064. spool -s 
  1065. @.RI -p printer
  1066. @.br
  1067. spool
  1068. @.RI -p printer
  1069. @.RI -b banner
  1070. [files]
  1071. @.br
  1072. spool -l
  1073. @.br
  1074. spool
  1075. @.I node_name
  1076. R|S @
  1077. @.B (see below)
  1078. @.sp
  1079. @.SH DESCRIPTION
  1080. @.PP
  1081. @.I Spool
  1082. allows the printing of files on a remote machine.
  1083. After sending the request,
  1084. @.I spool
  1085. waits for (and displays) confirmation of the printing or status request.
  1086. @.PP            
  1087. The command line options:
  1088. @.TP
  1089. @.B -p
  1090. This option is used to specify the remote
  1091. printer name for the printing or status request. (Required)
  1092. @.TP
  1093. @.B -s
  1094. Requests a queue and status report from the remote printer.
  1095. This must be used in conjunction with the
  1096. @.B -p
  1097. flag.
  1098. (See above.)
  1099. @.TP
  1100. @.B -l
  1101. Lists the printers that can be reached from the network, along with
  1102. information regarding restricted use.
  1103. @.TP
  1104. @.B -b
  1105. The
  1106. @.BI -b banner
  1107. option is required for all printing
  1108. requests.
  1109. @.I Banner
  1110. will appear on the printout in large letters 
  1111. below the login name of the requestor.
  1112. There is a ten character maximum, with no spaces.
  1113. @.TP
  1114. @.B -d
  1115. Turns on a myriad of sometimes useful debugging
  1116. information, but does not actually execute the
  1117. remote commands.
  1118. @.PP
  1119. The last
  1120. @.I spool
  1121. command invokes the ``return'' mode of the
  1122. @.I spool
  1123. program.  When a
  1124. @.I spool
  1125. request is submitted, the
  1126. @.I spool
  1127. program on the remote printer is invoked with the
  1128. name of the calling machine, an R for ``return 
  1129. @.I spool
  1130. request
  1131. number'' or an S for ``return
  1132. @.I lp
  1133. queue status'' and then an
  1134. @@ sign.  The @ sign is introduced to make it very unlikely
  1135. for a user to type ``spool Mach7 R @'' from the console. (See
  1136. reference below.)
  1137. @.br
  1138. @.sp
  1139. @.SH EXAMPLES
  1140. pr foo.s | spool -pgumby -bJohn
  1141. @.br
  1142. @.PP
  1143. @.in +.5i
  1144. Formats the file foo.s and feeds it to
  1145. @.I spool
  1146. for printing on the remote printer
  1147. @.B gumby.
  1148. The name on the printout will be John.
  1149. @.in -.5i
  1150. @.br
  1151. @.sp
  1152. spool -ppokey -bJones hexdump.c
  1153. @.PP
  1154. @.in +.5i
  1155. Prints the file hexdump.c on the remote printer 
  1156. @.B pokey
  1157. with the name Jones on the printout.
  1158. @.in -.5i
  1159. @.br
  1160. @.sp
  1161. spool -s -psluggo
  1162. @.PP
  1163. @.in +.5i
  1164. Requests status information about printer \fBsluggo\fR.  This
  1165. command will list the printer status, pending and
  1166. currently printing files, and other tidbits of
  1167. knowledge.
  1168. @.in -.5i
  1169. @.br
  1170. @.sp
  1171. spool -l
  1172. @.PP
  1173. @.in +.5i
  1174. Lists the reachable printers physically connected to
  1175. the network.  This list is taken from 
  1176. @.B ``etc/sysprint.''
  1177. [See \fBsysprint(7)\fR]
  1178. @.in -.5i
  1179. @.br
  1180. @.sp
  1181. @.SH NOTES
  1182. @.PP
  1183. The '-' options may be specified in any order.
  1184. Options may be combined, and spaces between options
  1185. and arguments are allowed.  For example:
  1186. \fIspool -s -p room10\fR is the same as \fIspool -sproom10\fR.
  1187. [See \fBgetopt(3C)\fR]
  1188. @.PP
  1189. Restricted use of printers is determined by login name through
  1190. \fIcuserid\fR. Currently, the
  1191. `student' login is not allowed to use restricted printers.
  1192. @.br
  1193. @.SH FILES
  1194. @.br
  1195. @.B /etc/sysprint
  1196. @.SH DIAGNOSTICS
  1197. @.br
  1198. Exit codes and messages:
  1199. @.sp
  1200. @.TP
  1201. 1
  1202. Printer xxxx does not exist
  1203. @.TP
  1204. 2
  1205. Please request a printer
  1206. @.TP
  1207. 3
  1208. General usage error
  1209. @.TP
  1210. 4
  1211. Error opening xxxx for transmission
  1212. @.TP
  1213. 5
  1214. Panic: Error opening temporary file
  1215. @.TP
  1216. 6
  1217. File disappeared
  1218. @.TP
  1219. 7
  1220. Can't execute transmit program. (Nisend failed)
  1221. @.TP
  1222. 8
  1223. Panic: Could not delete temporary file
  1224. @.TP
  1225. 9
  1226. Can't execute request program. (Nisend failed)
  1227. @.TP
  1228. 10
  1229. Network printer database is missing.
  1230. @.TP
  1231. 11
  1232. Status file is missing. Hmm.
  1233. @.TP
  1234. 12
  1235. Sorry, remote machine is not answering...
  1236. @.TP
  1237. 13
  1238. Not allowed to use printer xxxx
  1239. @.br
  1240. @.sp
  1241. @.SH REFERENCE
  1242. @.LP
  1243. ``\fBProject Report: Printer Spooling Over 3bnet\fR'' by James A.
  1244. Hayes, March, 1986.
  1245. @.SH SEE ALSO
  1246. @.LP
  1247. \fIsysprint(7)\fR, \fIgetopt(3C)\fR, \fIcuserid(2)\fR.
  1248. @.br
  1249. @//E*O*F spool.man//
  1250. chmod u=rwx,g=r,o= spool.man
  1251.  
  1252. echo x - sysprint
  1253. sed 's/^@//' > "sysprint" <<'@//E*O*F sysprint//'
  1254. # system printer database.
  1255. #
  1256. #  Name   Restriction   Node   
  1257.     5414    A    3bp5414
  1258.     5426    A    3bp5426
  1259. #
  1260. # done
  1261. #
  1262. @//E*O*F sysprint//
  1263. chmod u=rw,g=r,o= sysprint
  1264.  
  1265. -- 
  1266.  
  1267. Rich $alz
  1268. Cronus Project, BBN Labs            rsalz@bbn.com
  1269. Moderator, comp.sources.unix            sources@uunet.uu.net
  1270.