home *** CD-ROM | disk | FTP | other *** search
- From: bambi@kirk.nmg.bu.oz.au (David J. Hughes)
- Newsgroups: alt.sources
- Subject: pc-pap An intelligent Appletalk (CAP) print filter
- Message-ID: <2820@kirk.nmg.bu.oz.au>
- Date: 14 Feb 91 04:26:50 GMT
-
-
- An extract from the README file :-
-
-
- This program is a replacement PAP based lpd input filter for
- the standard CAP papif. At the simplest level, it performs
- the same function as papif (send a printjob to an appletalk
- based laserwriter). It also provides for definable language
- recognition and filtering based on the contents of the first
- line of the print job (such as a PostScript magic or #! /bin/sh
- in shell scripts). It also splits PostScript printjobs into
- individual PAP connections. This is essential if IBM PC
- based applications, such as MS-Word, print via this queue.
-
- As most PostScript PC print jobs consist of a procedure set
- followed by a document, the print job sent to the laser
- contains a ^D in the middle. An Apple Laser will see this
- and flush the job untill end of file. Unfortunately, if the
- laser is connected to appletalk, it assumes that end of file is
- when the PAP connection is dropped. This is why each
- PostScript print job is split into it's own PAP connection.
-
-
- What follows is a shar file containing the source to pc-pap, a README
- file and a sample configuration. It has been tested under Ultrix 3.1
- and 4.1 and SunOS 4.1. If you port it to any other system/OS
- combination please let me know.
-
- Please send comments and bug reports to my address listed below.
-
-
-
- +----------------------------------------------------------------------------+
- | David J. Hughes (AKA bambi) | bambi@kirk.bu.oz.au |
- | Systems Programmer | bambi@kirk.bu.oz.au@uunet.uu.net |
- | Comms Development & Operations | ..!uunet!munnari!kirk.bu.oz.au!bambi |
- | Bond University, Gold Coast | Phone : +61 75 951111 |
- | Queensland, Australia 4229 | Fax : +61 75 951456 |
- +----------------------------------------------------------------------------+
-
-
- --------------------------------- CUT HERE --------------------------------
- #!/bin/sh
- # to extract, remove the header and type "sh filename"
- # wrapped by bambi@kirk.bu.oz.au
- if `test ! -s ./Makefile`
- then
- echo "writing ./Makefile"
- cat > ./Makefile << '\End\Of\Shar\'
- #CFLAGS= -DDEBUG -g -c
- CFLAGS= -O -c
- OBJS= pc-pap.o config.o
-
- .c.o:
- cc $(CFLAGS) $*.c
-
- all: pc-pap
-
- clean:
- rm *.o pc-pap
-
- pc-pap.o : pc-pap.c Makefile
- config.o : config.c Makefile
-
- pc-pap : pc-pap.o config.o
- cc -o pc-pap $(OBJS) -lcap
-
- install:
- cp pc-pap /usr/local/lib/lpdfilters
- chmod 760 /usr/local/lib/lpdfilters/pc-pap
- \End\Of\Shar\
- else
- echo "will not over write ./Makefile"
- fi
- if `test ! -s ./README`
- then
- echo "writing ./README"
- cat > ./README << '\End\Of\Shar\'
- # @(#)README (Bond) bambi
-
-
-
- Title : PC-PAP.c
- Author : David J. Hughes bambi@kirk.bu.oz.au
- Date : 27-Jan-1991
- Dept : Communications Development and Operations
- Bond University
-
-
- This program is a replacement PAP based lpd input filter for
- the standard CAP papif. At the simplest level, it performs
- the same function as papif (send a printjob to an appletalk
- based laserwriter). It also provides for definable language
- recognition and filtering based on the contents of the first
- line of the print job (such as a PostScript magic or #! /bin/sh
- in shell scripts). It also splits PostScript printjobs into
- individual PAP connections. This is essential if IBM PC
- based applications, such as MS-Word, print via this queue.
-
- As most PostScript PC print jobs consist of a procedure set
- followed by a document, the print job sent to the laser
- contains a ^D in the middle. An Apple Laser will see this
- and flush the job untill end of file. Unfortunately, if the
- laser is connected to appletalk, it assumes that end of file is
- when the PAP connection is dropped. This is why each
- PostScript print job is split into it's own PAP connection.
-
- To configure the language recognition features edit the
- pc-pap.conf file to represent your local site. Details of the
- file format are outlined in the pc-pap.conf.example file. When
- the configuration file is completed, it shoulod be installed as
- /usr/local/lib/pc-pap.conf. To check the configuration file,
- run pc-pap from the commandline. The first task it performs is
- to parse and load the configuration from file. Any errors found
- will be reported to the terminal (including location and type
- of error).
-
- Installation of the pc-pap filter is the same as the
- installation of papif. Basically, the software uses the program
- name (argv[0]) as the name of the printer to which the data
- should be sent. To install the filter for a printer called
- admin-laser, create a sym-link to pc-pap called admin-laser.
- Set the if= field in the /etc/printcap file to point to the
- sym-link as the printers input filter.
-
- The only other file that is used by pc-pap is the
- /etc/cap.printers file. It expects it to be in the same format
- as is specified in the CAP 5.0 distribution.
-
- Testing of the filter can be performed by redirecting an input
- file into the sym-link (eg. admin-laser < test.ps). If an error
- is encountered, it will be logged via syslog.
- \End\Of\Shar\
- else
- echo "will not over write ./README"
- fi
- if `test ! -s ./config.c`
- then
- echo "writing ./config.c"
- cat > ./config.c << '\End\Of\Shar\'
- /*
- * Title : config.c
- * Author : David J. Hughes bambi@kirk.bu.oz.au
- * Date : 27-Jan-1991
- * Dept : Communications Development and Operations
- * Bond University
- *
- * Routines to parse and load the configuration file
- */
-
-
- #include <stdio.h>
- #include <syslog.h>
- #include <strings.h>
- #include <malloc.h>
- #include "pc-pap.h"
-
- char *ps_token[10]; /* List of tokens */
- token_t *magics[50];
- filter_t *filters[10];
- int magic_offset = 0,
- ps_offset = 0,
- filter_offset = 0,
- ps_found = 0,
- text_found = 0;
-
-
- /*
- ** SUBST_ASCII : Check the string for any embedded ASCII values and
- ** convert them to there actual character codes.
- **
- */
-
-
- char * subst_ascii(str)
- char *str;
- {
- static char ret_str[80];
- char *cp1,
- *cp2,
- ascii[4];
-
- strcpy(ret_str,"");
- cp1 = str;
- cp2 = ret_str;
- while(*cp1 != NULL)
- {
- if(*cp1 != '\\')
- *cp2 = *cp1;
- else
- {
- ascii[0] = *++cp1;
- ascii[1] = *++cp1;
- ascii[2] = *++cp1;
- ascii[3] = 0;
- *cp2 = (char) atoi(ascii);
- }
- cp1++;
- cp2++;
- }
- *cp2 = 0;
- return(ret_str);
- }
-
-
- /*
- ** BAD_CONFIG : Report configuration error.
- **
- */
-
- bad_config(line,error)
- int line;
- char *error;
- {
- fprintf(stderr,"\n\nPC-PAP : Error in configuration file at line %d.",
- line);
- if (error != NULL)
- fprintf(stderr,"\n %s.\n",error);
- fprintf(stderr,"\nExiting \007\n");
- syslog(LOG_DEBUG,"PC-PAP : Error in config at line %d",line);
- exit(1);
- }
-
-
- /*
- ** READ_PS : load the PostScript magic tokens
- **
- */
-
- read_ps(line,line_num)
- char *line;
- int line_num;
- {
- char *token,
- *store;
-
- if (index(line,':') == NULL)
- bad_config(line_num,"No terminator on PostScript magic token");
- token = strtok(line,":");
- if (token == NULL)
- bad_config(line_num,"No token defined");
- store = (char *) malloc(strlen(token)+1);
- strcpy(store,subst_ascii(token));
- ps_token[ps_offset++] = store;
- ps_found = 1;
- }
-
-
- /*
- ** STORE_FILTER : Write a set filter definition into the filter vector.
- **
- */
-
- store_filter(lang,line,line_num)
- char *lang,
- *line;
- int line_num;
- {
- char *token,
- error_msg[80];
- filter_t *tmp_filter;
- int token_count = 0,
- arg_num = 0;
-
- tmp_filter = (filter_t *) malloc(sizeof(filter_t));
- if(strlen(lang) >= lang_len)
- {
- free(tmp_filter);
- sprintf(error_msg,"Language id too long. Max is %d characters",
- lang_len);
- bad_config(line_num,error_msg);
- }
- strcpy(tmp_filter->lang,subst_ascii(lang));
-
- if((token = strtok(line,":")) == NULL)
- {
- free(tmp_filter);
- bad_config(line_num,"Bad filter definition (2nd Token)");
- }
- if(strlen(token) >= path_len)
- {
- free(tmp_filter);
- sprintf(error_msg,"Filter path too long. Max is %d characters",
- path_len);
- bad_config(line_num,error_msg);
- }
- strcpy(tmp_filter->path,subst_ascii(token));
-
- if((token = strtok(NULL,":")) == NULL)
- {
- free(tmp_filter);
- bad_config(line_num,"Bad text filter definition (3nd Token)");
- }
- if(strlen(token) >= name_len)
- {
- free(tmp_filter);
- sprintf(error_msg,"Filter name too long. Max is %d characters",
- name_len);
- bad_config(line_num,error_msg);
- }
- strcpy(tmp_filter->name,subst_ascii(token));
-
-
- while((token = strtok(NULL,":")) != NULL)
- {
- if(strlen(token) >= args_len)
- {
- free(tmp_filter);
- sprintf(error_msg,
- "Filter arguements too long. Max is %d characters",
- args_len);
- bad_config(line_num,error_msg);
- }
- strcpy(tmp_filter->args[arg_num++],subst_ascii(token));
- }
- while(arg_num < num_filter_args)
- tmp_filter->args[arg_num++][0] = NULL;
- filters[filter_offset++] = tmp_filter;
- }
-
-
- /*
- ** READ_TEXT : load the Text to PostScript filter details
- **
- */
-
-
- read_text(line, line_num)
- char *line;
- int line_num;
- {
- char *token;
-
- store_filter(TEXT_PS,line,line_num);
- text_found = 1;
- }
-
-
- /*
- ** READ_FILTERS : load the language filter definitions
- **
- */
-
- read_filters(line, line_num)
- char *line;
- int line_num;
- {
- char *lang,
- *rest;
-
- lang = strtok(line,":");
- rest = strtok(NULL,"\n");
- store_filter(lang,rest,line_num);
- }
-
-
- /*
- ** READ_MAGICS : load the magic tokens definitions
- **
- */
-
- read_magics(line,line_num)
- char *line;
- {
- char *token,
- error_msg[80];
- token_t *tmp_token;
- int token_count = 0;
-
- tmp_token = (token_t *) malloc(sizeof(token_t));
- if((token = strtok(line,":")) == NULL)
- bad_config(line_num,"Missing tokens");
- if(strlen(token) >= lang_len)
- {
- free(tmp_token);
- sprintf(error_msg,"Language id too long. Max is %d characters",
- lang_len);
- bad_config(line_num,error_msg);
- }
- strcpy(tmp_token->lang,subst_ascii(token));
-
- if((token = strtok(NULL,":")) != NULL)
- {
- if(strlen(token) >= magic_len)
- {
- free(tmp_token);
- sprintf(error_msg,
- "Magic token too long. Max is %d characters",
- magic_len);
- bad_config(line_num,error_msg);
- }
- strcpy(tmp_token->token, subst_ascii(token));
- }
- else
- bad_config(line_num,"No magic string supplied.");
- magics[magic_offset++] = tmp_token;
- }
-
-
- /*
- ** LOAD_CONFIG : load the configuration file into internal structures.
- **
- ** Note : The internal stat machine has the following states :-
- **
- **
- ** 0. Starting config read
- ** 1. Reading PostScript section
- ** 2. Reading Text section
- ** 3. Reading Filters section
- ** 4. Reading Magics section
- */
-
-
- load_config()
- {
- FILE *conf;
- char conf_line[100],
- conf_path[100],
- *token;
- int state = 0,
- line_num=0;
-
- sprintf(conf_path,"%s/%s",conf_dir,conf_file);
- conf = fopen(conf_path,"r");
- if (conf == NULL)
- {
- fprintf(stderr,"\007\nPC-PAP : Could not open configuration");
- fprintf(stderr," file. Aborting.\n\n");
- syslog(LOG_DEBUG,"PC-PAP : Could not open configuration file");
- exit(1);
- }
- while (!feof(conf))
- {
- fgets(conf_line,99,conf);
- conf_line[strlen(conf_line)-1] = 0;
- line_num++;
- if (!feof(conf))
- {
- switch(conf_line[0])
- {
- case '#': /* Comment */
- case '\0': /* Blank Line */
- break;
- case ' ':
- case '\t':
- bad_config(line_num,
- "Leading white space");
- break;
-
- case '+': /* State change */
- token = strtok(conf_line+1," \n");
- if (strcmp(token,"postscript") == 0)
- state = 1;
- else
- if (strcmp(token,"text") == 0)
- state = 2;
- else
- if (strcmp(token,"filters") == 0)
- state = 3;
- else
- if (strcmp(token,"magics") == 0)
- state = 4;
- else
- bad_config(line_num,
- "Unknown section header");
- break;
- default:
- switch(state)
- {
- case 0:
- bad_config(line_num,
- "Section not defined");
- break;
- case 1:
- read_ps(conf_line,
- line_num);
- break;
- case 2:
- read_text(conf_line,
- line_num);
- break;
- case 3:
- read_filters(conf_line,
- line_num);
- break;
- case 4:
- read_magics(conf_line,
- line_num);
- break;
- }
- }
- }
- }
- }
- \End\Of\Shar\
- else
- echo "will not over write ./config.c"
- fi
- if `test ! -s ./pc-pap.c`
- then
- echo "writing ./pc-pap.c"
- cat > ./pc-pap.c << '\End\Of\Shar\'
- /*
- * Title : PC-PAP.c
- * Author : David J. Hughes bambi@kirk.bu.oz.au
- * Date : 14-June-1990
- * Dept : Communications Development and Operations
- * Bond University
- *
- *--------------------------------------------------------------------------
- * Edit history
- *
- * 14-June-1990 bambi
- *
- * Initial development
- *--------------------------------------------------------------------------
- * 27-Jan-1991 bambi
- *
- * Remove the hard-coded configuration for language recognition and
- * use a config file to be read at run-time.
- *
- * Fix time-out error when Laser returns a PAP eof flag to us on a
- * read.
- *
- * Include Job details in the lpq status file so that PC users can see the
- * name and type of job being printed (only supported in certain
- * applications such as Excel, PageMaker, Word for Windows etc.)
- *
- * Fix up the handling of printer error returns such as "Out of
- * paper"
- *--------------------------------------------------------------------------
- *
- */
-
-
- #include <stdio.h>
- #include <syslog.h>
- #include <varargs.h>
- #include <strings.h>
- #include <signal.h>
- #include <limits.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/file.h>
- #include <netat/appletalk.h>
- #include <netat/compat.h>
- #include "pc-pap.h"
-
- #define BUF_SIZ QUANTUM * PAPSegSize
-
-
- /*
- ** Global variable definition section
- */
-
- char printer[20],
- username[20],
- hostname[20],
- acct_file[80],
- *atalk_name,
- r_buf[100]; /* PAPRead buffer */
-
- int sock, /* Must be global for signal handler */
- r_comp = 0, /* PAPRead completion flag */
- r_len = 0, /* PAPRead data length */
- r_err = 0,
- r_eof = 0,
- CURR_PROC = 0;
-
-
-
- /*
- ** External variable definition section
- */
-
-
- extern char *ps_token[];
- extern token_t *magics[];
- extern filter_t *filters[];
- extern int magic_offset,
- ps_offset,
- filter_offset;
-
-
- /**************************************************************************
- * Close down the PAP Connection and exit REPRINT
- */
-
- fatal(sig)
- int sig;
- {
- char sig_name[15],
- proc_name[15];
-
-
- switch (sig)
- {
- case 1: strcpy(sig_name,"SIGHUP");
- break;
- case 2: strcpy(sig_name,"SIGINT");
- break;
- case 3: strcpy(sig_name,"SIGQUIT");
- break;
- case 4: strcpy(sig_name,"SIGILL");
- break;
- case 5: strcpy(sig_name,"SIGTRAP");
- break;
- case 6: strcpy(sig_name,"SIGIOT");
- break;
- case 7: strcpy(sig_name,"SIGEMT");
- break;
- case 8: strcpy(sig_name,"SIGFPE");
- break;
- case 9: strcpy(sig_name,"SIGKILL");
- break;
- case 10: strcpy(sig_name,"SIGBUS");
- break;
- case 11: strcpy(sig_name,"SIGSEGV");
- break;
- case 12: strcpy(sig_name,"SIGSYS");
- break;
- case 13: strcpy(sig_name,"SIGPIPE");
- break;
- case 14: strcpy(sig_name,"SIGALRM");
- break;
- case 15: strcpy(sig_name,"SIGTERM");
- break;
- case 16: strcpy(sig_name,"SIGURG");
- break;
- case 17: strcpy(sig_name,"SIGSTOP");
- break;
- case 18: strcpy(sig_name,"SIGSTP");
- break;
- case 19: strcpy(sig_name,"SIGCONT");
- break;
- case 20: strcpy(sig_name,"SIGCHLD");
- break;
- }
- switch(CURR_PROC)
- {
- case PS_CHILD : strcpy(proc_name,"send_ps()");
- break;
- case FILTER_CHILD : strcpy(proc_name,"do_filter()");
- break;
- case READ_CHILD : strcpy(proc_name,"read_file()");
- break;
- default: strcpy(proc_name,"unknown proc");
- }
- abSleep(4,TRUE);
- PAPClose(sock);
- syslog(LOG_INFO,"PC-PAP : terminated by %s signal in %s",
- sig_name, proc_name);
- exit(LPD_ERROR);
- }
-
-
-
-
-
- /**************************************************************************
- * Setup our signal handlers
- */
-
- set_sigs()
- {
- int sig;
-
- for ( sig = SIGINT; sig < NSIG; sig++ )
- signal(sig, fatal);
- signal(SIGHUP, SIG_IGN);
- signal(SIGCHLD, SIG_IGN);
- }
-
-
-
-
-
- /**************************************************************************
- * Check out the arguements passed to us by LPD
- */
-
- check_args(argc,argv)
- int argc;
- char *argv[];
- {
- int loop;
- char *argp;
-
- if((argv[0][0] == '/')||(argv[0][0] == '.'))/* Just want the basename */
- {
- argp = rindex(argv[0],'/');
- strcpy(printer,++argp);
- }
- else
- strcpy(printer,argv[0]);
-
- for (loop = 1; loop < argc; loop++)
- {
- argp = argv[loop];
- if (argp[0] == '-')
- {
- switch (argp[1])
- {
- case 'n':
- strcpy(username,argv[++loop]);
- break;
-
- case 'h':
- strcpy(hostname,argv[++loop]);
- break;
- }
- }
- else
- strcpy(acct_file,argv[loop]);
- }
- }
-
-
-
-
-
-
- /**************************************************************************
- * Find the Appletalk laserwriter name from the cap.printers file
- */
-
-
- char *find_lasername(queue)
- char *queue;
- {
- static char buffer[100];
- FILE *cap_file;
- int num_bytes;
-
- cap_file = fopen(CAP_PRINTERS,"r");
- if (cap_file == NULL)
- {
- syslog(LOG_ERR,"PC-PAP : Cannot open Mapping File %s",
- CAP_PRINTERS);
- return(NULL);
- }
- while (!feof(cap_file))
- {
- fgets(buffer,100,cap_file);
- if (!feof(cap_file))
- {
- if (buffer[0] != '#')
- if (strcmp(queue,strtok(buffer,"=")) == 0)
- {
- fclose(cap_file);
- return (strtok(NULL,"\n"));
- }
- }
- }
- fclose(cap_file);
- return(NULL);
- }
-
-
-
-
-
- /**************************************************************************
- * Make a PAP connection to the LaserWriter,
- * Retries the connection 5 times then fails.
- */
-
- int connect_to_laser(laser)
- char *laser;
- {
- PAPStatusRec status;
- AddrBlock addr;
- int retry_minor = 0,
- retry_major = 0,
- sock,
- comp_stat,
- error;
- char stat_string[100];
-
- #ifdef DEBUG
- fprintf(stderr,"\nOpening connection to %s\n",laser);
- #endif DEBUG
- sprintf(stat_string,"%s : Opening connection to %s",printer,laser);
- write_status(stat_string);
- abSleep(2,TRUE);
- while((error = PAPOpen(&sock,laser,QUANTUM,&status,&comp_stat))!= noErr)
- {
- if (error != -1) /* Connection Error */
- {
- if (++retry_minor == 10)
- {
- sprintf(stat_string,"%s : Cannot connect to %s",
- printer,laser);
- write_status(stat_string);
- retry_minor = 0;
- if(++retry_major == 5)
- return(0);
- }
- }
- }
- while(comp_stat > 0) /* incomplete connection */
- {
- addr.net = 0; /* sufficient */
- abSleep(4,TRUE); /* protocol sleep for 1 second */
- if (PAPStatus(laser,&status,&addr) >= 0)
- store_status(status.StatusStr);
- }
- abSleep(4,TRUE);
- return(sock);
- }
-
-
-
-
-
-
-
- /**************************************************************************
- * Write PAP status message for the spooler to use
- */
-
- store_status(status)
- char *status;
- {
- int status_file;
- char stat_line[200],
- stat[40],
- job[40],
- *cp,
- *fp;
-
- strcpy(stat,"Unknown Status");
- strcpy(job,"Unknown Job");
- strncpy(stat_line,status + 1, *status);
- cp = stat_line;
- while(*cp != NULL)
- {
- if (strncmp(cp,"status:",7) == 0)
- {
- fp = stat;
- cp += 7;
- while((*cp != NULL) && (*cp != ';'))
- {
- *fp++ = *cp++;
- }
- *fp = NULL;
- }
- else
- if (strncmp(cp,"job:",4) == 0)
- {
- fp = job;
- cp += 5;
- while((*cp != NULL) && (*cp != ';'))
- {
- *fp++ = *cp++;
- }
- *fp = NULL;
- }
- cp++;
- }
- sprintf(stat_line,"%s : Status = %s. Job = %s.",printer,stat,job);
- unlink("new_status");
- status_file = open("new_status",O_CREAT|O_WRONLY,0644);
- if (status_file == -1)
- return;
- write(status_file,stat_line,strlen(stat_line));
- write(status_file,"\n",1);
- close(status_file);
- rename("new_status","status");
- }
-
-
- /**************************************************************************
- * Write TEXT status message for the spooler to use
- */
-
- write_status(status)
- char *status;
- {
- int status_file;
-
- unlink("status");
- status_file = open("status",O_CREAT|O_WRONLY,0644);
- if (status_file == -1)
- return;
- write(status_file,status,strlen(status));
- write(status_file,"\n",1);
- close(status_file);
- }
-
-
-
-
-
- /**************************************************************************
- * Fork and exec the appropriate filter for this data stream. Also
- * fork a copy of ourself to handle reading the stdin and writing it
- * to stdout. Filter_pipe goes from the original copy of us to the
- * filter and printer_pipe goes from the stdout of the filter back to
- * new copy of us (send_ps).
- */
-
- exec_filter(filter)
- filter_t *filter;
- {
- char *args[num_filter_args+1];
- int index=1;
-
- args[0] = filter->name;
- while(filter->args[index-1][0] != '\000')
- {
- args[index] = filter->args[index-1];
- index++;
- }
- args[index] = NULL;
- index = 0;
- #ifdef DEBUG
- fprintf(stderr,"Path = %s\n",filter->path);
- #endif DEBUG
- execv(filter->path,args);
- }
-
-
- do_filter(lang,line,sock)
- char *lang,
- *line;
- int sock;
- {
- int filter_pipe[2],
- printer_pipe[2],
- index = 0;
- char *filter_name;
- char arg_line[100];
-
-
- while((strcmp(filters[index]->lang,lang)!=0) && (index<filter_offset))
- index++;
-
- if (index == filter_offset)
- {
- syslog(LOG_ERR,"PC-PAP : Bad Language %s",lang);
- exit(LPD_ERROR);
- }
- pipe(filter_pipe);
- pipe(printer_pipe);
- if (fork() == 0) /* Child Process */
- {
- CURR_PROC = FILTER_CHILD;
- dup2(filter_pipe[0],fileno(stdin));
- dup2(printer_pipe[1],fileno(stdout));
- close(filter_pipe[0]);
- close(filter_pipe[1]);
- close(printer_pipe[0]);
- close(printer_pipe[1]);
- exec_filter(filters[index]);
- syslog(LOG_ERR,"PC-PAP : Bad exec for language %s",lang);
- exit(LPD_ERROR);
- }
- else
- {
- if (fork() == 0) /*Second Child */
- {
- CURR_PROC = PS_CHILD;
- dup2(printer_pipe[0],fileno(stdin));
- close(filter_pipe[0]);
- close(filter_pipe[1]);
- close(printer_pipe[0]);
- close(printer_pipe[1]);
- send_ps(sock,NULL,0);
- sleep(1);
- exit(0);
- }
- else
- {
- CURR_PROC = READ_CHILD;
- dup2(filter_pipe[1],fileno(stdout));
- close(printer_pipe[0]);
- close(printer_pipe[1]);
- close(filter_pipe[0]);
- close(filter_pipe[1]);
- write(fileno(stdout),line,strlen(line));
- read_file();
- wait(0);
- wait(0);
- }
- }
- }
-
-
-
-
- /**************************************************************************
- * Scan and process the incoming file (including PS interpretation)
- */
-
- process_file(sock)
- int sock;
- {
- char stat_string[80],
- line[100];
- int index,
- num_bytes;
-
-
-
- sprintf(stat_string,"%s : Sending printjob to printer.",printer);
- write_status(stat_string);
-
- num_bytes = read(fileno(stdin),line,99);
- line[num_bytes] = 0;
-
- /* Is this a PostScript File ? */
-
- for(index = 0; index < ps_offset; index++)
- {
- if(strncmp(ps_token[index],line,strlen(ps_token[index]))==0)
- {
- send_ps(sock,line,num_bytes);
- return;
- }
- }
-
- /* Can we match any other language on this file ? */
-
- for(index = 0; index < magic_offset; index++)
- {
- if(strncmp(magics[index]->token,line,
- strlen(magics[index]->token)) == 0)
- {
- do_filter(magics[index]->lang,line,sock);
- return;
- }
- }
-
- /* O.K. it must be a straight text file */
-
- do_filter(TEXT_PS,line,sock);
- }
-
-
-
-
-
- /**************************************************************************
- * Just read stdin and write it to stdout. This is easier than dup-ing
- * stdin on the filter as we cannot lose the first X chars we have
- * already read for the magic recognition.
- */
-
-
- read_file()
- {
- char buff[BUF_SIZ];
- int num_bytes;
- int w_bytes;
-
- do
- {
- num_bytes = read(fileno(stdin),buff,BUF_SIZ);
- if (num_bytes != 0)
- w_bytes = write(fileno(stdout),buff,num_bytes);
- } while (num_bytes != 0);
- close(fileno(stdout));
- sleep(2);
- }
-
-
-
- /**************************************************************************
- * Send the data pointed to by ch to the laser. Initiate a read from
- * the laser. Show any change in printer status while we are waiting
- * for the write to complete.
- */
-
-
- pap_write(sock,ch,num,eof)
- int sock;
- char *ch;
- int num,
- eof;
- {
- int paperr,
- wcomp;
- PAPStatusRec status;
- AddrBlock addr;
-
- #ifdef DEBUG
- fprintf(stderr,"In pap_write() num = %d, eof = %d\n",num,eof);
- write(1,ch,num);
- #endif DEBUG
-
- if((num > 0) || (eof > 0))
- {
- paperr = PAPWrite(sock,ch,num,eof,&wcomp);
- if (paperr < 0)
- {
- PAPClose(sock);
- exit(LPD_REPRINT);
- }
- while (wcomp > 0)
- {
- #ifdef DEBUG
- fprintf(stderr,"\nerror = %d, wcomp = %d, num = %d, eof = %d\n",
- paperr, wcomp, num, eof);
- #endif DEBUG
- pap_read(sock);
- abSleep(1,TRUE);
- addr.net = 0;
- if(PAPStatus(atalk_name,&status,&addr) >= 0)
- store_status(status.StatusStr);
- }
- }
- #ifdef DEBUG
- fprintf(stderr,"Leaving pap_write()\n");
- #endif DEBUG
- }
-
-
-
- /**************************************************************************
- * Fudge up a non-blocking read from the laser. Discard anything we
- * receive.
- */
-
- pap_read(sock)
- int sock;
- {
- if(r_eof == 1)
- return(0);
- if(r_comp > 0)
- return(0);
-
- if(r_comp == -1)
- return(-1);
-
- #ifdef DEBUG
- if(r_len > 0)
- write(1,r_buf,r_len);
- #endif DEBUG
- if(r_eof == 1)
- return(1);
- r_err = PAPRead(sock, r_buf, &r_len, &r_eof, &r_comp);
- if(r_err = 0)
- return(0);
- else
- return(-1);
- }
-
-
- /**************************************************************************
- * Read the output of the filter (stdout of the filter maps to stdin of
- * this process) and send it to the laserwriter via the PAP connection.
- */
-
- send_ps(sock,line,line_len)
- int sock;
- char *line;
- int line_len;
- {
-
- char buff[BUF_SIZ],
- *c,
- *c1;
- int paperr,
- wcomp,
- num_bytes,
- count,
- index;
-
- if (line != NULL)
- {
- c = line;
- for(index = 0; index <line_len; index++)
- if(*(c+index) == '\004')
- *(c+index) = '\n';
- pap_write(sock,line,line_len,FALSE);
- }
- do
- {
- if (r_eof == 1)
- break;
- num_bytes = read(fileno(stdin),buff,BUF_SIZ - 1);
- #ifdef DEBUG
- fprintf(stderr,"Num_Bytes in read = %d\n", num_bytes);
- #endif DEBUG
- c = buff;
- index = 0;
- count = 0;
- while(count < num_bytes)
- {
- index++;
- count++;
- if (*(c+index) == '\004')
- {
- *(c+index) = '\n';
- pap_write(sock,c,index,TRUE);
- abSleep(4,TRUE);
- c += index;
- index = 0;
- PAPClose(sock);
- sock = connect_to_laser(atalk_name);
- r_comp = 0;
- r_eof = 0;
- r_err = 0;
- }
- }
- pap_write(sock,c,index,FALSE);
- abSleep(4,TRUE);
- }while (num_bytes != 0);
- if (r_eof == 0)
- {
- pap_write(sock,c,0,TRUE);
- pap_read(sock);
- }
- abSleep(2,TRUE);
- }
-
-
-
-
-
-
-
- /**************************************************************************
- * Initialise the appletalk libraries (CAP), form the connection to the
- * LaserWriter and process the data stream. Log the job to the printer
- * log file.
- */
-
-
-
- /* ARGS USED */
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
-
- char stat_string[80];
-
- check_args(argc,argv);
- load_config();
- set_sigs();
- atalk_name = find_lasername(printer);
- if (atalk_name == NULL)
- syslog(LOG_ERR,"PC-PAP : Could not map %s to a printer name",
- printer);
- abInit(FALSE);
- nbpInit();
- PAPInit();
- ATPSetResponseTimeout(sectotick(60)); /* 1 Minutes */
- sock = connect_to_laser(atalk_name);
- process_file(sock);
- abSleep(4,TRUE);
- PAPClose(sock);
- sprintf(stat_string,"%s : No Status (No Active Jobs)",printer);
- write_status(stat_string);
- }
- \End\Of\Shar\
- else
- echo "will not over write ./pc-pap.c"
- fi
- if `test ! -s ./pc-pap.conf.example`
- then
- echo "writing ./pc-pap.conf.example"
- cat > ./pc-pap.conf.example << '\End\Of\Shar\'
- # @(#)/usr/local/lib/pc-pap.conf (Bond)
- #
- # Language configuration file for PC-PAP 31-Jan-1991 bambi@kirk.bu.oz.au
- #
- # Definitions of language recognition tokens, output filters and
- # PostScript magics.
- #
- # There are four sections to the configuration :- postscript, text,
- # filters and magics. The start of a section is defined by the
- # section name preceded by a + on a line by itself.
- #
- # In the postscript section, the only entries are character tokens
- # that define the start of a PostScript file. The tokens are terminated
- # by a colon.
- #
- # The text section contains one definition being the path, name, and
- # commandline options for a text to PostScript filter. Each field is
- # colon separated. Up to ten command line options may be defined
- # to represent argv[1] through argv[9] (argv[0] is set to the
- # filter name.
- #
- # The filters section contains a list of filters used in pc-pap to
- # convert a certain language into PostScript. The format of an entry is
- # <ID>:<Path to filter>:<Name of filter>:<Arg1>:<Arg2>:<Arg N>:
- #
- # The final section, magics, contains the token to filter matchings
- # for the language translations. The format of an entry is
- # <Filter ID>:<Magic Token>:
- #
- # NOTE: The token must appear at the start of the first line of the file
- # if it is to be recognised. The \ character is the standard
- # escape and may be followed by any 3 digit decimal ASCII
- # code (such as \004 for ^D or \058 for :).
- #
- # What appears below is a sample setup used on a host at Bond Uni.
- #
-
- +postscript
-
- %!:
- \004%!:
-
- +text
-
- /usr/local/lib/translators/t2ps:t2ps::
-
- +filters
-
- C_PS:/usr/local/lib/translators/pps:pps:c:
- sh_PS:/usr/local/lib/translators/pps:pps:sh:
- csh_PS:/usr/local/lib/translators/pps:pps:csh:
- mail_PS:/usr/local/lib/translators/mp:mp::
-
- +magics
-
- C_PS:/*:
- C_PS:#include<:
- C_PS:#include <:
- C_PS:static:
- C_PS:#ifdef:
-
- sh_PS:#!/bin/sh:
- sh_PS:#! /bin/sh:
-
- csh_PS:#!/bin/csh:
- csh_PS:#! /bin/csh:
-
- mail_PS:From :
- mail_PS:From\58:
- mail_PS:Path\58:
-
- \End\Of\Shar\
- else
- echo "will not over write ./pc-pap.conf.example"
- fi
- if `test ! -s ./pc-pap.h`
- then
- echo "writing ./pc-pap.h"
- cat > ./pc-pap.h << '\End\Of\Shar\'
- /*
- * Title : PC-PAP.h
- * Author : David J. Highes bambi@kowande.bu.oz.au
- * Date : 14-June-1990
- * Dept : Network Management Group
- * Bond University
- */
-
- #define CAP_PRINTERS "/etc/cap.printers" /* Location of CAP file */
- #define conf_dir "/usr/local/lib" /* Directory of config file */
- #define conf_file "pc-pap.conf" /* Config file name */
- #define lang_len 10 /* Max length of lang ID */
- #define path_len 80 /* Max length of filter path */
- #define name_len 10 /* Max length of filter name */
- #define args_len 20 /* Max length of filter args */
- #define magic_len 30 /* Max length of magic tokens */
- #define num_filter_args 10 /* Max number args to filter */
- #define STATUS 5 /* Check Status interval (sec)*/
- #define QUANTUM 8 /* PAP Flow Quantum */
- #define PS_CHILD 1 /* Debug */
- #define FILTER_CHILD 2 /* Procedure */
- #define READ_CHILD 3 /* Flags */
- #define TEXT_PS "text_PS"
- #define LPD_OK 0 /* LPD Good Print Exit Code */
- #define LPD_REPRINT 1 /* LPD Reprint Exit Code */
- #define LPD_ERROR 2 /* LPD Abort Job Exit Code */
-
-
- typedef struct token_s
- {
- char token[magic_len];
- char lang[lang_len];
- } token_t;
-
-
- typedef struct filter_s
- {
- char lang[lang_len];
- char path[path_len];
- char name[name_len];
- char args[10][args_len];
- } filter_t;
-
-
- \End\Of\Shar\
- else
- echo "will not over write ./pc-pap.h"
- fi
- echo "Finished archive 1 of 1"
- exit
-