home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-08-27 | 33.8 KB | 1,270 lines |
- Path: uunet!rs
- From: rs@uunet.UU.NET (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v11i025: 3Bnet utilities and printer spooler, Part01/02
- Message-ID: <1249@uunet.UU.NET>
- Date: 28 Aug 87 13:21:45 GMT
- Sender: Unknown@uunet.UU.NET
- Organization: UUNET Communications Services, Arlington, VA
- Lines: 1258
- Approved: rs@uunet.UU.NET
-
- Submitted-by: hayes%wizard@sdcsvax.ucsd.edu (James Hayes)
- Posting-number: Volume 11, Issue 25
- Archive-name: 3bnet/Part01
-
- This package provides a set of tools, documentation on security, and a
- network printer spooler for a set of machines running 3Bnet.
- These have only been tested on a 3b2/310 running SVR2.0x and I don't make
- any guarantees otherwise. (Besides the guarantee that it is really bad
- code... Commented, but bad.)
-
- As usual, complain if something doesn't work... I'll try to help as much
- as possible, but I can't circumvent acts of god.
-
- Jim Hayes, University of California at San Diego.
-
- BITNET: hayes%sdcsvax@WISCVM.BITNET
- ARPA: hayes@sdcsvax.ucsd.edu
- UUCP: {pick one close to berkeley}!sdcsvax!hayes
-
- ------------------SNIPPITY-------------------
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
-
- echo x - Makefile
- sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
- #
- #
- CFLAGS = -g
- #
- all: spool
-
- spool: spool.o spool.defs
- cc spool.o -o spool
-
- clean:
- rm *.o core
- @//E*O*F Makefile//
- chmod u=rw,g=r,o=r Makefile
-
- echo x - spool.c
- sed 's/^@//' > "spool.c" <<'@//E*O*F spool.c//'
- #include <stdio.h>
- #include <sys/utsname.h> /* System naming fetching library */
- #include <string.h> /* Until Jim can learn strings... */
- #include <signal.h>
- #include "spool.h" /* spool.c #defines. */
-
- /* **************************************************************
- print:
- spool -pprinter_name -b[banner] {files}
-
- query:
- spool -pprinter_name -q {<--query.}
-
- list available printer:
- spool -l
-
- (A -d may be added to turn debugging on.)
-
- Author: James Hayes. (hayes@sdcsvax.ucsd.edu)
- Log:
- Version 1.5 (Added option for banner.) 13-Feb-86
- Version 1.6 (Fixed things/cleaned up the code.) 19-Feb-86
- Version 2.0 (Frozen Revision) 03-Mar-86
-
- **************************************************************** */
-
- char *printer_name[20], /* The printer name known to eecs70 students.*/
- *printer_node[20], /* The node name of the receiving printer. */
- *restriction[2]; /* The restriction flag. */
-
- int validate_printer(), /* Verify printer exists. */
- list_printers(), /* List available printers */
- printer_status(), /* Request remote printer status */
- timeout(), /* Wait for file to arrive. */
- student, /* Non-zero if "student" logged in */
- debug; /* Non-zero if debugging enabled. */
-
- /* ********************************************************************** */
-
- main(argc,argv)
- int argc;
- char *argv[];
-
- {
- FILE *infd, *outfd, *fopen();
-
- extern int errno, /* What else? */
- optind, /* For use with getopt (2) */
- opterr, /* Ditto */
- debug, /* debug flag */
- student, /* Non zero if student running program. */
- list_printers(),
- validate_printer();
-
-
- extern char *optarg, /* Getopt option target string */
- *printer_name[20], /* The printer name known to ee70 students.*/
- *printer_node[20], /* The node name of the receiving printer. */
- *restriction[2]; /* The restriction flag. */
-
- char *mktemp(), /* MaKe a TeMPorary unique file name */
- *outname, /* The temporary name itself. */
- *template[150], /* The template used to create the temp name.*/
- *remote_command[255], /* The remote command holder to the remote machine */
- *requested_printer, /* The printer requested by the student.*/
- *banner, /* The truncated (10chars) banner name. */
- *login_name[20]; /* Login name of calling user. */
-
- int in_char, /* Current stream input character */
- current_opt, /* Pointer the next argv[] option. getopt(2) */
- error, /* Non zero if command line errors found.*/
- prflag, /* Non zero if a printer was specified */
- list_available, /* Non zero if a printer list was asked for */
- query, /* Non zero if printer status requested */
- banflag, /* Non zero if a banner was specified */
- exec_status, /* Exit status of the system call 'system()' */
- i;
-
- struct utsname name; /* Structure for the uname() system call */
-
- list_available= /* Initialize everything. */
- debug=
- query=
- error=
- prflag=
- student=
- banflag=0;
-
- uname(&name); /* Get the system name. */
- sprintf(template,DEFAULT_DIR,name.sysname); /* Make the temporary file templaye. */
-
- cuserid(login_name); /* Get the login name of the user */
- if ( (strcmp(login_name,"student"))==0 ) student++; /* If student, set the student flag */
-
- if ( (strcmp(argv[3],"@"))==0 ) return_state(argv[1],argv[2]); /* Invoke the return mode of spool ? */
-
- /* Loop through all possible options and set flags according to what
- is chosen. If an erronious command line option is choosen, then
- error is set to non-zero and the spooling stops. */
-
- while ((current_opt=getopt(argc,argv,"p:b:sld")) !=EOF)
- switch (current_opt)
- {
- case 'p': /* Printer? */
- prflag++;
- requested_printer=optarg;
- break;
- case 'b': /* Banner name? */
- banflag++;
- banner=optarg;
- break;
- case 's': /* Query printer? */
- query++;
- break;
- case 'd': /* Debug flag? */
- debug++;
- break;
- case 'l': /* List printers? */
- list_available++;
- break;
- case '?': /* Bad option? */
- error++;
- break;
- }
-
-
- DEBUG Template for making files %s\n",template);
- DEBUG Student UID=%d, student flag=%d\n",getuid(),student);
-
- if ( (query) && (prflag)) /* Got -s and a printer name? */
- if ( (validate_printer(requested_printer))==0 ) /* Valid name? */
- {
- fprintf(stderr,"spool: printer %s does not exist.\n", requested_printer);
- fprintf(stderr, " To see supported printers, use: spool -l\n");
- exit(1);
- }
- else /* Everything O.K... Do query. */
- {
- query_request(printer_node);
- exit(0);
- }
-
- if (query) /*Since -s is a strange option, be polite. */
- {
- fprintf(stderr,"spool: Please request a printer\n");
- exit(2);
- }
-
- if (list_available) /* List available printers? */
- {
- DEBUG Listing printers: \n");
- list_printers();
- exit(0);
- }
-
- /********************************************************************
- * Bad flag combinations, ie. Banner and no printer, printer and no
- * banner, no banner and printer, are not allowed.
- ********************************************************************
- */
-
- if ((prflag==NULL) && (banflag)) error++;
- if ((banflag==NULL) && (prflag)) error++;
- if ((banflag==NULL) && (prflag==NULL)) error++;
-
- if (error==0) /* No errors? Check printer name. */
-
- if ( (validate_printer(requested_printer))==0 )
- {
- fprintf(stderr, "spool: Incorrect printer choice\n");
- error++;
- }
- if (error)
- {
- fprintf(stderr,USAGE); /* If there was an error, print the */
- list_printers(); /* command usage, and list the */
- exit(3); /* Available printers. */
- }
-
- DEBUG Your printer: node: %s Res: %s Name: %s\n\n", printer_node,restriction, printer_name);
-
- i=optind; /* Save pointer to beginning of file names in the argv. */
-
- /*******************************************************************************************************
- * Scan through each name specified to see if it is readable... (As usual, complain if not, and exit.)
- *******************************************************************************************************
- */
-
- for (;optind<argc;optind++)
- if (access(argv[i],4) !=NULL) /* Check for read permissions */
- {
- fprintf(stderr,"spool: error opening %s for transmission.\n", argv[optind]);
- exit(4);
- }
-
- infd=stdin; /* Default input is stdin. */
- outname=mktemp(template); /* Form unique filename. */
- outfd=fopen(outname,"w"); /* Open it for writing. */
- if (outfd==NULL) /* Error? */
- {
- fprintf(stderr,"spool: panic: error opening tempfile %s\n",outname);
- exit(5);
- }
-
- optind=i; /* Restore saved argv pointer */
-
- do /* Copy each file into the transmission file. */
- {
- if (optind < argc)
- {
- infd=fopen(argv[i],"r"); /* Open for reading */
- if (infd==NULL)
- {
- fprintf(stderr,"spool: File %s was deleted, spool attempt aborted.\n",argv[i]);
- exit(6);
- }
- }
- while ( (in_char=getc(infd)) !=EOF) putc(in_char,outfd);
- if (infd!=stdin) fclose(infd); /* Don't try and close stdin. */
- } while (++i < argc); /* Until all files are done. */
-
- fclose(outfd); /* Ready to transmit. */
-
- errno=0; /* Just in case... */
-
- sprintf(banner,"%.10s",banner); /* Truncate the banner. */
-
- if ( (strcmp(name.sysname,printer_node))==0) /* Are we on the same node we are trying to send to? */
- sprintf(remote_command,LOCAL_LP,LOCAL_LP_ARGS); /* If so, use the local command. */
- else
- sprintf(remote_command,COMMAND,ARGUMENTS); /* Otherwise, use the network command. */
-
- DEBUG Remote command:\n%s\n",remote_command);
-
- if (debug==0)
- {
- exec_status=system(remote_command); /* Execute the command. */
-
- if (exec_status == ERR) /* Was there a problem? */
- {
- fprintf(stderr,"spool: can't execute transmit program, spool attempt aborted with\n");
- fprintf(stderr," system() erorr %d.\n",errno);
- unlink(outname);
- exit(7);
- }
- }
-
- DEBUG Unlinking work file %s.\n",outname);
-
- if (unlink(outname) != NULL)
- {
- fprintf(stderr,"panic: spool could not delete the temporary workfile %s. File(s) did transmit.\n",outname);
- exit(8);
- }
-
- if ( (strcmp(name.sysname,printer_node))!=0)
- list_response(name.sysname); /* Wait for status file to come back. & printit. */
-
- DEBUG EXIT.\n");
- }
-
- /****************************************************************************
- * validate (requested_printer);
- *
- * return code: 0=not found.
- * non-zero, found.
- *
- * If found, the node_name of the printer is returned in printer_node,
- * along with it's restriction in restriction.
- ****************************************************************************
- */
-
- validate_printer(requested_printer)
- char *requested_printer;
- {
- FILE *infd;
-
- extern char *printer_name[20], /* The printer name known to ee70 students.*/
- *printer_node[20], /* The node name of the receiving printer. */
- *restriction[2]; /* The restriction flag. */
-
- extern int student;
-
- int in_char, /* Current stream input char. */
- found, /* found requested printer in SYS_PRINTERS file if non-zero. */
- scan_OK; /* Result of fscanf. -1=EOF. */
-
- found=0;
- if ((infd=fopen(SYS_PRINTERS,"r"))==NULL)
- {
- printf(stderr,"spool: Network printer database could not be located.\n");
- exit(10);
- }
- else
- {
- scan_OK=0;
- do
- {
- in_char=getc(infd); /* Get first character */
- if (in_char==EOL) /* Blank line? */
- {
- do in_char=getc(infd) ; /* Skip any extra newlines. */
- while (in_char==EOL);
- }
- if (in_char==SCRATCH) /* Was it a beginning of a comment? */
- do in_char=getc(infd) ;
- while ( (in_char!=EOL) && (in_char!=EOF) ) ;
-
- if (in_char==EOF) scan_OK=-1; /* End of file? God forbid! */
-
- if ((scan_OK==-1) || (in_char==SCRATCH) || (in_char==EOL)) ;
- else
- {
- ungetc(in_char,infd); /* Put the first character back. */
- scan_OK=fscanf(infd,"%s%s%s",printer_name,restriction, printer_node);
-
- if ( (strcmp(printer_name,requested_printer))==0 ) /* Found? */
- {
- scan_OK=EOF; /* Found? YES!, so artificially end the file. */
- found++;
- DEBUG Found printer name %s, restriction=%s.\n",printer_name, restriction);
- DEBUG Student flag=%d\n",student);
-
- if ( ((strcmp(restriction,"R"))==0) && (student>0) )
- {
- fprintf(stderr, "spool: You are not allowed to use printer %s.\n", requested_printer);
- exit(13);
- }
- }
- }
- } while (scan_OK!=EOF); /* Keep going until EOF */
- fclose(infd);
- }
- return found;
- }
-
- /****************************************************************************
- * List available printers from SYS_PRINTERS.
- * (and print them out of course!)
- ****************************************************************************
- */
-
- list_printers()
- {
- FILE *infd;
-
- extern char *printer_name[20], /* The printer name known to ee70 students.*/
- *printer_node[20], /* The node name of the receiving printer. */
- *restriction[2]; /* The restriction flag. */
-
- extern int debug;
-
- int in_char,
- scan_OK;
-
- if ((infd=fopen(SYS_PRINTERS,"r"))==NULL)
- {
- printf(stderr,"spool: Network printer database could not be located.\n");
- exit(10);
- }
- else
- {
- fprintf(stdout,"\n %-15s| %-30s\n","Printer Name:", "Restriction: (A=Anyone, R=Restricted)");
- fprintf(stdout," ---------------+--------------------------------------\n");
- scan_OK=0;
- do
- {
- in_char=getc(infd); /* See above for the comments for this mess. */
- if (in_char==EOL)
- do in_char=getc(infd); while (in_char==EOL);
-
- if (in_char==SCRATCH)
- do in_char=getc(infd); while ( (in_char!=EOL) && (in_char!=EOF) );
-
- if (in_char==EOF) scan_OK=-1;
- if ((scan_OK==-1) || (in_char==SCRATCH) || (in_char==EOL)) ;
- else
- {
- ungetc(in_char,infd);
- scan_OK=fscanf(infd,"%s%s%s",printer_name,restriction, printer_node);
- fprintf(stdout," %-15s|%2s\n",printer_name,restriction);
- }
- } while (scan_OK!=EOF) ;
- }
- fclose(infd);
- fprintf(stdout,"\n");
- return;
- }
-
- /****************************************************************************
- * List response sent by remote system. If it hasn't arrived yet, wait
- * until it does. (Up to 40 seconds.)
- ****************************************************************************
- */
- list_response(system_name) /* Name of this system. (Used to build correct file name.) */
- char *system_name;
- {
- FILE *infd;
- int in_char;
- char *filename[30];
-
- sprintf(filename,STATUS_TEMPLATE,system_name);
- wait_file(TIMEOUT,filename); /* Wait for TIMEOUT seconds for file 'filename' to arrive. */
-
- if ( (infd=fopen(filename,"r"))==NULL )
- {
- fprintf(stderr,"spool: Status file \'%s\' is missing. Hmm.\n", system_name);
- exit(11);
- }
- else
- {
- fprintf(stdout,"\n");
- while ( (in_char=getc(infd)) !=EOF) putc(in_char,stdout); /* List the file. */
- fprintf(stdout,"\n");
- close(infd);
- if ( (unlink(filename)) !=NULL )
- fprintf(stderr,"Can't remove status file %s. Tell proctor.\n", filename);
- exit(8);
- }
- }
-
- /****************************************************************************
- * query_request(printer_node);
- * Line printer query request for printer 'printer_node'.
- ****************************************************************************
- */
-
- query_request(printer_node)
- char *printer_node;
- {
- extern int errno,
- debug;
-
- int exec_status,
- in_char;
-
- char *mktemp(),
- *outname,
- *template[150],
- *remote_command[255];
-
- struct utsname name; /* System name fetching structure */
-
- uname(&name); /* Fetch our system name. */
-
- errno=0;
-
- if ( (strcmp(name.sysname,printer_node))==0) /* Requesting from same machine as printer? */
- sprintf(remote_command,LOCAL_LPSTAT); /* Issue local lpstat command. */
- else
- sprintf(remote_command,QUERY_COMMAND,QUERY_ARGUMENTS); /* Otherwise, use remote command. */
-
- DEBUG Remote command: %s\n",remote_command);
-
- if (debug==0)
- {
- exec_status=system(remote_command);
-
- if (exec_status == ERR)
- {
- fprintf(stderr,"spool: Can't execute request program, request attempt aborted with\n");
- fprintf(stderr," system() error %d.\n",errno);
- exit(9);
- }
- }
- if ( (strcmp(name.sysname,printer_node))!=0) /* If requesting from remote machine, wait for results. */
- list_response(name.sysname);
- }
-
- /****************************************************************************
- * wait_file(seconds,filename);
- * wait 'seconds' for file 'filename'
- * NOTE: THE FILE BEING WAITED FOR IS UNLINKED, JUST IN CASE AN OLDER
- * VERSION OF IT MIGHT BE AROUND. YOU HAVE BEEN WARNED....
- *
- * If no file arrives after 'seconds', print error and exit(12)
- ****************************************************************************
- */
- wait_file(seconds,filename)
- int seconds;
- char *filename;
- {
- DEBUG Filename: %s\n",filename);
- unlink(filename); /* Just in case a leftover exists. */
-
- signal(SIGALRM,timeout); /* Set the alarm to point to the time out routine. */
- alarm(seconds); /* Allow seconds timeout. */
- fprintf(stdout,"One moment please, your request is being processed.");
- fflush(stdout);
-
- do
- {
- fprintf(stdout,"."); /* Print little dots every few seconds to let the user know what's goin on. */
- fflush(stdout);
- sleep(2);
- }
- while ((access(filename,4))!=NULL ); /* Keep doing it until the time runs out, or the file arrives. */
-
- signal(SIGALRM, SIG_IGN);
- }
-
- timeout()
- {
- signal(SIGALRM, SIG_IGN);
- printf("\nSorry, the remote machine is not answering. Please make sure the\n");
- printf("printer/remote machine is operating properly.\n");
- exit(12);
- }
-
- /****************************************************************************
- * This is the return server for the spool program. It is invoked with
- * spool machine_making_request request_type @
- ****************************************************************************
- */
- return_state(sysname,command)
- char *sysname,
- *command;
- {
- int exec_status;
- char *remote_command[255];
-
- printf("Command: %s, Sysname: %s\n",command,sysname);
-
- if (strcmp(command,"S")==0) /* Status request */
- sprintf(remote_command,STAT_COMMAND,STAT_ARGUMENTS);
-
- if (strcmp(command,"R")==0) /* Return lp command status */
- sprintf(remote_command,LP_COMMAND,LP_ARGUMENTS);
-
- printf("Remote command: %s\n",remote_command);
-
- exec_status=system(remote_command);
-
- exit(0);
- }
-
- @//E*O*F spool.c//
- chmod u=rw,g=r,o=r spool.c
-
- echo x - spool.doc.ms
- sed 's/^@//' > "spool.doc.ms" <<'@//E*O*F spool.doc.ms//'
- @.ST
- @.nr VS 18
- @.ds LH "EECS 70
- @.ds RH %
- @.ds CH "Project Report
- @.ds CF
- @.sp 2i
- @.LG
- @.ce
- \fBReport of activities\fI
- @.sp
- @.ce
- \fBPrinter Spooling Over 3bnet\fR
- @.sp 2
- @.ce
- @.SM
- @.nr VS 15
- James A. Hayes
- @.br
- @.ce
- University of California,
- @.br
- @.ce
- San Diego
- @.br
- @.sp 3
- @.ce
- @.LG
- @.I ABSTRACT
- @.sp
- @.QP
- @.LG
- @.nr VS 18
- The goal of the
- @.I spool
- implementation is to allow students to send information to printers
- not physically
- connected to their machine. This design replaces the current method of
- having to physically login to the printer's host. This document
- will provide an outline of the
- @.I spool
- implementation.
- @.sp 3
- @.nr VS 14
- @.LP
- March, 1986
- @.br
- @.nr PS 12
- @.bp
- @.SH
- Introduction
- @.PP
- While the concept of a remote printer spooling system is easy to
- understand, the actual implementation is at best, complicated. If you have
- not already done so, please read the
- @.I spool
- manual page which will explain the \fIspool\fR command syntax.
- This document will try to explain the
- @.I spool
- implementation in three stages. An explanation of network
- security, a description of the
- @.I nisend
- command, and finally,
- a nuts-and-bolts description of the spooling software.
- @.sp
- @.SH
- 1. Network Security
- @.PP
- The AT&T 3B2 computer is capable of running an Ethernet network
- communications
- system. While the software provided with the Ethernet hardware is complete,
- a major problem arises when trying to use it in an educational environment.
- The network commands are not protected from subversive
- application. That is
- to say, it is dangerous when
- @.I anyone
- is given permission to use the network
- commands. This means that a student on machine A can
- @.I copy
- or knowingly
- @.I damage
- homework files from a student on machine B.
- @.PP
- The means for securing
- the crucial network command (\fInisend\fR)
- is borne from built-in UNIX\(dg
- @.FS
- \(dg.
- UNIX is a trademark of AT&T Bell Laboratories.
- @.FE
- execution privileges.
- @.PP
- The network command
- @.I nisend
- is owned by
- @.B bin
- and is a member of the newly
- created group
- \fBnisecure\fR. It has only the owner and group execute
- permissions set. This will not allow anyone but
- @.B root
- or a member of the
- group
- @.B nisecure
- to execute the
- @.I nisend
- program. The print spooler (\fIspool\fR) is
- also a member of the group
- @.B nisecure
- and sets its group identification (sgid) on
- execution. The execute permissions for
- @.I spool
- allow it to be run by anyone.
- @.PP
- Since the group ID of
- @.I spool
- is the same as \fInisend\fR,
- @.I spool
- is allowed to call
- \fInisend\fR. So far,
- @.I spool
- is the only program that is allowed to call \fInisend\fR.
- @.PP
- The access permissions (as seen by \fIls\fR)
- look like this:
- @.KS
- @.sp
- @.ce
- /usr/bin/nisend /usr/bin/spool
- @.TS
- center;
- l l l l l l.
- -rwxr-s--- bin nisecure xx/xx/86 12:00 nisend
- -rwxr-xr-x root nisecure xx/xx/86 12:00 spool
- @.TE
- @.KE
- @.sp
- @.SH
- 2. The `nisend' Program
- @.PP
- The
- @.I nisend
- program is provided by AT&T as a front-end file transfer and
- remote command execution system to be used by programs at the
- shell and applications
- level. It is complete, but does have a few problems that are worth
- mentioning.
- @.PP
- @.I Nisend
- sends mail to its users after every request, transfer, command
- execution, error and hiccup. The default file access mode is set to
- 600 (owner read/write). The directory where the file will be saved (once
- transmitted) is not the same directory it was taken from. The default
- receiving directory is ~/rje/\fIname\fR. The
- local file to be transmitted must
- be the last item on the command line. The one line \*Q3bnet job xxxxyyy
- submitted\*U is always printed.
- @.PP
- The above problems may be circumvented by command line options. To
- stop mail, use the
- @.I undocumented
- -e option. To set
- the access permissions of
- the remote files, use the -a\fImode\fR option. To specify
- what directory the
- file is to be saved in, use the -f\fIpath\fR option. The
- \*Q3bnet...\*U message may be silenced by the -s option.
- @.PP
- The spool program uses a standard form of the
- @.I nisend
- command that avoids all the above problems. It looks like this:
- @.LP
- @.in +.5i
- @.ti -.5i
- @.na
- nisend -s -e -d\fIremote_machine\fR -a0666
- -f/usr/tmp/\fIremote_name\fR
- -!\*Q\fIremote_command\fR\*U /usr/tmp/\fIlocal_file\fR
- @.ad b
- @.in -.5i
- @.sp
- @.SH
- 3. The `spool' Program, an Overview
- @.PP
- The
- @.I spool
- program is not a server, although it performs the function of
- a server because it is executed on the sending machine as well
- as the receiving machine when a request is submitted.
- @.PP
- The sending machine is responsible for collecting the files, sending
- them, submitting them for printing, and waiting for confirmation from the
- @.I spool
- program on the receiving end. The
- @.I spool
- program on the receiving end
- takes the confirmation from
- @.I lp
- or status from
- @.I lpstat
- and returns it to the
- waiting machine on the sending end.
- @.sp
- @.SH
- 3.1. Spooling a File for Remote Printing
- @.sp
- \fRCOMMAND: spool -p room10 -bJones foo.c
- @.sp
- ACTIONS:
- @.PP
- Validate the command options and verify that the specified file(s) and
- printer (via \fI/etc/sysprint\fR) exist.
- Read the file(s) (via stdin or file name(s)
- on command line), concatenate them, and put them in a temporary file
- /usr/tmp/sp.\fInode\fR.\fIXXXXX\fR, where
- @.I node
- is the
- @.B 3bnet
- node name of the user's
- machine making the request, and
- @.I XXXXX
- is the process ID of the
- @.I spool
- program. The above actions insure that the temporary file will have a
- unique name on the remote machine when it is arrives there.
- @.PP
- Send the file to the remote system, execute
- @.I lp
- on the
- remote system, store the standard output and standard error of
- @.I lp
- in another temporary file /usr/tmp/\fInode\fR.stat,
- send it back to the user, display it
- and exit.
- @.KS
- @.LP
- For example: (See also \fIFigure 1\fR)
- @.IP \fBUSER:\fR 10
- $ pr *.s | spool -pX -bSharon (executed on machine A, for printer X
- on machine B, with PID=5427.)
- @.sp
- @.KE
- @.LP
- @.B SPOOL:
- (SENDING END)
- @.IP 1.
- Collect standard input (or specified files) and save in
- /usr/tmp/sp.A.a5427
- @.IP 2.
- Execute
- @.I nisend
- (via the
- @.I system()
- call).
- @.QP
- @.na
- /usr/bin/nisend -s -e -dB -a0666 -f/usr/tmp/sp.A.a5427 -!\*Q\fBSee
- remote command below\fR\*U /usr/tmp/sp.A.a5427
- @.ad b
- @.IP 3.
- Remove /usr/tmp/sp.A.a5427
- @.IP 4.
- Wait for the response /usr/tmp/A.stat to arrive, (contains the output
- of the
- @.I lp
- command.) give it 40 seconds to show up, and if it doesn't
- arrive after that, give up and tell the user what happened. If it
- does arrive in the allotted time, print it out.
- @.IP 5.
- Remove /usr/tmp/A.stat (If it arrived from the remote machine.)
- @.sp
- @.LP
- \fBRemotely executed command (broken down into steps):\fR
- [Please note that the
- @.I lp
- command is executed on the printing system by
- @.I spool
- on the requesting system and not by
- @.I spool
- on the printing system. This saves about 3 seconds that would
- normally be wasted waiting for
- @.I spool
- to fork() and exec(), then waiting for
- @.I lp
- to echo the request ID. Now, the result of
- @.I lp
- can be sent back the moment it is available. This is quirk of the
- @.I nisend
- command.]
- @.sp
- @.in +.5i
- @.IP A.
- submit the job to lp and capture its output:
- @.QP
- @.na
- usr/bin/lp -tSharon -c /usr/tmp/sp.A.a5427 > /usr/tmp/A.stat 2>&1
- @.ad b
- @.IP B.
- Remove the temporary file:
- rm /usr/tmp/sp.A.a5427
- @.IP C.
- Return the captured output of
- @.I lp
- to the calling spool by executing
- spool on the receiving end:
- @.in +.5i
- /usr/bin/spool A R @ (A=Name to send back to, R=\fIlp\fR report,
- @@=Receiver mode.)
- @.in -.5i
- @.IP D.
- Remove the captured output of lp and return.
- @.QP
- rm /usr/tmp/A.stat
- @.in -.5i
- @.sp 1
- @.SH
- 3.2. Requesting a Status Report on the Remote Printer
- @.sp
- \fRCOMMAND: spool -s -p room10
- @.sp
- ACTIONS:
- @.PP
- Validate the command options and verify that the specified printer (via
- \fI/etc/sysprint\fR) exists.
- @.PP
- Execute the
- @.I lpstat
- program on the remote system, store the standard output
- and standard error of
- @.I lpstat
- in a temporary file /usr/tmp/\fInode\fR.stat, send it back to
- the user, display it and exit. (\fINode\fR is the requesting
- @.B 3bnet
- node name.)
- @.KS
- @.LP
- For example: (see also \fIFigure 2\fR)
- @.IP \fBUSER:\fR 10
- $ spool -s -pX (executed on machine A, for printer X on machine B)
- @.br
- @.KE
- @.LP
- @.B SPOOL:
- (SENDING END)
- @.IP 1.
- Execute
- @.I nisend
- (via the
- @.I system()
- call):
- @.QP
- @.na
- /usr/bin/nisend -s -e -dB -a0666
- -!\*Q\fBSee remote command below\fR\*U
- @.ad b
- @.IP 2.
- Wait for the response /usr/tmp/A.stat to arrive, (contains the output of
- the
- @.I lpstat
- command.) give it 40 seconds to show up, and if it
- doesn't arrive after that, give up and tell the user what
- happened. If it does arrive in the allotted time, print it out.
- @.IP 3.
- Remove /usr/tmp/A.stat (If it arrived from the remote machine.)
- @.sp
- @.LP
- \fBRemotely executed command (broken down into steps):\fR
- @.in +.5i
- @.IP A.
- Fire-up
- @.I spool
- on the receiving end. There it will execute
- @.I lpstat
- and return the output back to the user:
- @.in +.5i
- /usr/bin/spool A S @ (A=Machine name to send back to, S=lp status
- report, @=Receiver mode.)
- @.in -.5i
- @.IP B.
- Remove the captured output of
- @.I lpstat
- and exit.
- @.in +.5i
- rm /usr/tmp/A.stat
- @.in -1i
- @.sp 2
- @.SH
- Conclusion/Comments
- @.PP
- It is not the most efficient, but it works. Possible future
- improvements might involve an actual spool daemon. This would make
- handshaking more reliable, instead of using
- @.I nisend
- which is very slow and very sensitive to system load.
- @.sp
- @//E*O*F spool.doc.ms//
- chmod u=rwx,g=r,o= spool.doc.ms
-
- echo x - spool.h
- sed 's/^@//' > "spool.h" <<'@//E*O*F spool.h//'
- #define SYS_PRINTERS "/etc/sysprint" /* Location of printer info. */
- #define DEFAULT_DIR "/usr/tmp/%sXXXXXX" /* Place for temp files,
- where %s and XXXXXX will be replaced by the machine name and
- process I.D. */
- #define TIMEOUT 50 /* Seconds to wait for response */
- /* ***************************************************************************
- COMMAND is what is sent to the remote system. Various arguments in the
- command (%s strings) are specified in the ARGUMENTS portion. The arguments
- are declared in the order they appear in the command.
- ************************************************************************** */
-
- #define COMMAND "/usr/bin/nisend -e -d%s -a0666 -s -c -f%s -!\042\
- /usr/bin/lp -c -t%s %s>/usr/tmp/%s.stat 2>&1; rm %s;\
- /usr/local/spool %s R @; rm /usr/tmp/%s.stat\042 %s"
-
-
- #define ARGUMENTS printer_node,outname,banner,outname,name.sysname,outname,\
- name.sysname,name.sysname,outname
-
- /* **************************************************************************
- QUERY_COMMAND is what gets sent to the remote printer to get its status
- sent back. QUERY_ARGUEMENTS are stuffed into the QUERY_COMMAND.
- ************************************************************************** */
- #define QUERY_COMMAND "/usr/bin/nisend -e -s -d%s -!\
- \042/usr/local/spool %s S @; rm /usr/tmp/%s.stat\042"
-
- #define QUERY_ARGUMENTS printer_node,name.sysname,name.sysname
-
- #define USAGE "print: spool -p {printer} -b {banner}\n\
- status: spool -p {printer} -s\n\
- list supported network printers: spool -l\n"
-
- #define STAT_COMMAND "lpstat -a -r -u -p>/usr/tmp/%s.stat;\
- /usr/bin/nisend -c -e -d%s -a0666 -f/usr/tmp/%s.stat \
- /usr/tmp/%s.stat"
-
- #define STAT_ARGUMENTS sysname,sysname,sysname,sysname
-
- #define LP_COMMAND "/usr/bin/nisend -s -e -c -d%s -a0666 -f /usr/tmp/%s.stat \
- /usr/tmp/%s.stat"
-
- #define LP_ARGUMENTS sysname,sysname,sysname
-
- /* We use these commands in the case that the person spooling to a remote
- printer, isn't. (Meaning: When they are on the same machine as
- the printer, and no network activity needs to take place.
- /*
- #define LOCAL_LP "/usr/bin/lp -c -t%s %s"
- #define LOCAL_LP_ARGS banner,outname
-
- #define LOCAL_LPSTAT "/usr/bin/lpstat -a -r -u -p"
- #define STATUS_TEMPLATE "/usr/tmp/%s.stat"
-
- #define ERR -1
- #define DEBUG if (debug) fprintf(stderr,"Debug>
- #define EOL 10
- #define SCRATCH 35
-
- @//E*O*F spool.h//
- chmod u=rw,g=r,o=r spool.h
-
- echo x - spool.man
- sed 's/^@//' > "spool.man" <<'@//E*O*F spool.man//'
- @.TH SPOOL 1 Local
- @.AT 5 2.0
- @.SH NAME
- spool - spool files to remote printer.
- @.sp
- @.SH SYNOPSIS
- @.PP
- spool -s
- @.RI -p printer
- @.br
- spool
- @.RI -p printer
- @.RI -b banner
- [files]
- @.br
- spool -l
- @.br
- spool
- @.I node_name
- R|S @
- @.B (see below)
- @.sp
- @.SH DESCRIPTION
- @.PP
- @.I Spool
- allows the printing of files on a remote machine.
- After sending the request,
- @.I spool
- waits for (and displays) confirmation of the printing or status request.
- @.PP
- The command line options:
- @.TP
- @.B -p
- This option is used to specify the remote
- printer name for the printing or status request. (Required)
- @.TP
- @.B -s
- Requests a queue and status report from the remote printer.
- This must be used in conjunction with the
- @.B -p
- flag.
- (See above.)
- @.TP
- @.B -l
- Lists the printers that can be reached from the network, along with
- information regarding restricted use.
- @.TP
- @.B -b
- The
- @.BI -b banner
- option is required for all printing
- requests.
- @.I Banner
- will appear on the printout in large letters
- below the login name of the requestor.
- There is a ten character maximum, with no spaces.
- @.TP
- @.B -d
- Turns on a myriad of sometimes useful debugging
- information, but does not actually execute the
- remote commands.
- @.PP
- The last
- @.I spool
- command invokes the ``return'' mode of the
- @.I spool
- program. When a
- @.I spool
- request is submitted, the
- @.I spool
- program on the remote printer is invoked with the
- name of the calling machine, an R for ``return
- @.I spool
- request
- number'' or an S for ``return
- @.I lp
- queue status'' and then an
- @@ sign. The @ sign is introduced to make it very unlikely
- for a user to type ``spool Mach7 R @'' from the console. (See
- reference below.)
- @.br
- @.sp
- @.SH EXAMPLES
- pr foo.s | spool -pgumby -bJohn
- @.br
- @.PP
- @.in +.5i
- Formats the file foo.s and feeds it to
- @.I spool
- for printing on the remote printer
- @.B gumby.
- The name on the printout will be John.
- @.in -.5i
- @.br
- @.sp
- spool -ppokey -bJones hexdump.c
- @.PP
- @.in +.5i
- Prints the file hexdump.c on the remote printer
- @.B pokey
- with the name Jones on the printout.
- @.in -.5i
- @.br
- @.sp
- spool -s -psluggo
- @.PP
- @.in +.5i
- Requests status information about printer \fBsluggo\fR. This
- command will list the printer status, pending and
- currently printing files, and other tidbits of
- knowledge.
- @.in -.5i
- @.br
- @.sp
- spool -l
- @.PP
- @.in +.5i
- Lists the reachable printers physically connected to
- the network. This list is taken from
- @.B ``etc/sysprint.''
- [See \fBsysprint(7)\fR]
- @.in -.5i
- @.br
- @.sp
- @.SH NOTES
- @.PP
- The '-' options may be specified in any order.
- Options may be combined, and spaces between options
- and arguments are allowed. For example:
- \fIspool -s -p room10\fR is the same as \fIspool -sproom10\fR.
- [See \fBgetopt(3C)\fR]
- @.PP
- Restricted use of printers is determined by login name through
- \fIcuserid\fR. Currently, the
- `student' login is not allowed to use restricted printers.
- @.br
- @.SH FILES
- @.br
- @.B /etc/sysprint
- @.SH DIAGNOSTICS
- @.br
- Exit codes and messages:
- @.sp
- @.TP
- 1
- Printer xxxx does not exist
- @.TP
- 2
- Please request a printer
- @.TP
- 3
- General usage error
- @.TP
- 4
- Error opening xxxx for transmission
- @.TP
- 5
- Panic: Error opening temporary file
- @.TP
- 6
- File disappeared
- @.TP
- 7
- Can't execute transmit program. (Nisend failed)
- @.TP
- 8
- Panic: Could not delete temporary file
- @.TP
- 9
- Can't execute request program. (Nisend failed)
- @.TP
- 10
- Network printer database is missing.
- @.TP
- 11
- Status file is missing. Hmm.
- @.TP
- 12
- Sorry, remote machine is not answering...
- @.TP
- 13
- Not allowed to use printer xxxx
- @.br
- @.sp
- @.SH REFERENCE
- @.LP
- ``\fBProject Report: Printer Spooling Over 3bnet\fR'' by James A.
- Hayes, March, 1986.
- @.SH SEE ALSO
- @.LP
- \fIsysprint(7)\fR, \fIgetopt(3C)\fR, \fIcuserid(2)\fR.
- @.br
- @//E*O*F spool.man//
- chmod u=rwx,g=r,o= spool.man
-
- echo x - sysprint
- sed 's/^@//' > "sysprint" <<'@//E*O*F sysprint//'
- # system printer database.
- #
- # Name Restriction Node
- 5414 A 3bp5414
- 5426 A 3bp5426
- #
- # done
- #
- @//E*O*F sysprint//
- chmod u=rw,g=r,o= sysprint
-
- --
-
- Rich $alz
- Cronus Project, BBN Labs rsalz@bbn.com
- Moderator, comp.sources.unix sources@uunet.uu.net
-