This is lwsrv.c in view mode; [Download] [Up]
static char rcsid[] = "$Author: cck $ $Date: 88/03/20 16:49:26 $";
static char rcsident[] = "$Header: lwsrv.c,v 1.16 88/03/20 16:49:26 cck Rel $";
static char revision[] = "$Revision: 1.16 $";
/*
* lwsrv - UNIX AppleTalk spooling program: act as a laserwriter
* driver: handles setup and farms out incoming jobs
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* Feb 15, 1987 Schilit Created, based on lsrv
* Mar 17, 1987 Schilit Fixed nonprintables, added -r
* May 15, 1987 CCKim Add support for LaserPrep 4.0
* Make multifork by default (turn
* off by defining SINGLEFORK)
*
*/
char copyright[] = "Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the City of New York";
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <signal.h>
#include <sys/param.h>
#ifndef _TYPES
# include <sys/types.h> /* assume included by param.h */
#endif
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <netat/appletalk.h> /* include appletalk definitions */
#include <netat/compat.h>
#ifdef USESTRINGDOTH
# include <string.h>
#else
# include <strings.h>
#endif
#ifndef NOWAIT3
# include <sys/wait.h>
#endif
#ifdef NEEDFCNTLDOTH
# include <fcntl.h>
#endif
#include "papstream.h"
private char *tracefile = NULL;
private char *fontfile = NULL;
private char *logfile = NULL;
private char *prtname = NULL;
private char *unixpname = NULL;
private char *prttype = "LaserWriter";
private char *dictdir = "."; /* assume local dir */
private int rflag = FALSE; /* retain print file */
private int hflag = TRUE; /* default to print banner */
private int singlefork = FALSE;
export PAPStatusRec statbuff; /* status buffer */
private char username[80],jobname[80];
#ifndef TEMPFILE
# define TEMPFILE "/tmp/lwsrvXXXXXX" /* temporary file holds job */
#endif
#define RFLOWQ atpMaxNum
#define BUFMAX (PAPSegSize*RFLOWQ)+10
private void
usage(s,err)
char *s,*err;
{
if (err != NULL)
fprintf(stderr,"%s: %s\n",s,err);
fprintf(stderr,"usage: %s -n <PrinterName> -p <unix printer name>\n",s);
fprintf(stderr,"usage:\t\t-a <DictionaryDirectory> -f <FontFile>\n");
fprintf(stderr,"usage:\t\t[-l <LogFile>] [-t <TraceFile>] [-r] [-h]\n");
fprintf(stderr,"usage:\t\t[-T crtolf] [-T quote8bit]\n\n");
fprintf(stderr,"\t-p*<unix printer name> is the unix printer to print to\n");
fprintf(stderr,"\t-n*<PrinterName> specifies the name lwsrv registers.\n");
fprintf(stderr,"\t-a*<DictionaryDirectory> is the ProcSet directory.\n");
fprintf(stderr,"\t-f*<FontFile> contains an font coordination list.\n");
fprintf(stderr,"\t-t <Tracefile> stores session and appledict in\n");
fprintf(stderr,"\t <Tracefile> without printing.\n");
fprintf(stderr,"\t-l <LogFile> specifies a file to log the lwsrv session\n");
fprintf(stderr,"\t-e Allow an eexec to occur in a procset\n");
fprintf(stderr," warning: this may cause problems, use carefully\n");
fprintf(stderr,"\t-r Will retain temp print file for inspection\n");
fprintf(stderr,"\t-h means to print without a banner page\n");
if (is_simple_dsc())
fprintf(stderr,"\t-A [on*|off] means to turn on or off Adobe document\n");
else
fprintf(stderr,"\t-A [on|off*] means to turn on or off Adobe document\n");
fprintf(stderr,"\tstructuring revision 2 compatibility\n");
fprintf(stderr,"\t(this can cause problems, *'ed item is default)\n");
fprintf(stderr,"\t-S single lwsrv fork (default is multiforking)\n");
fprintf(stderr,"\t-T Transcript compatibilty options\n");
fprintf(stderr,"\t-T crtolf: translate cr to lf for Transcript filters\n");
fprintf(stderr,"\t-T quote8bit: quote 8 bit chars for Transcript\n");
fprintf(stderr,"\t-T makenondscconformant: make non DSC conformant: use\n");
fprintf(stderr,"\t if psrv only works with DSC 1.0 conventions\n");
fprintf(stderr,"\nexample: %s -n Laser -p ps -a/usr/lib/ADicts\n",s);
fprintf(stderr,"\t\t-f /usr/lib/LW+Fonts\n");
fprintf(stderr,"\t(note the starred items above are required)\n");
exit(0);
}
private void
doargs(argc,argv)
int argc;
char **argv;
{
int c;
extern char *optarg;
extern int optind;
while ((c = getopt(argc,argv,"a:f:l:p:P:t:d:n:rehT:A:S")) != EOF) {
switch (c) {
case 'a':
if (index(optarg, '/') == NULL) {
dictdir = (char *)malloc(strlen(optarg)+4);
strcpy(dictdir, "./");
strcat(dictdir, optarg);
} else
dictdir = optarg; /* remember dictionary directory */
break;
case 'd':
dbugarg(optarg);
break;
case 'f':
fontfile = optarg; /* -f fontfile */
break;
case 'l': /* -l logfile */
logfile = optarg;
break;
case 'n': /* lwsrv printer name */
prtname = optarg;
break;
case 'p': /* -p unix printer name */
case 'P':
unixpname = optarg;
break;
case 'h':
hflag = FALSE; /* do not print banner */
break;
case 'r': /* do not remove file */
rflag = TRUE;
break;
case 't': /* -t tracefile */
tracefile = optarg;
break;
case 'e':
setflag_encrypted_instream(TRUE); /* maybe "eexec" in code */
break;
case 'T':
if (simple_TranscriptOption(optarg) < 0)
usage(argv[0], NULL);
break;
case 'A':
if (simple_dsc_option(optarg) < 0)
usage(argv[0], NULL);
break;
case 'S':
singlefork = TRUE;
fprintf(stderr, "lwsrv: single fork\n");
break;
case '?': /* illegal character */
usage(argv[0],NULL); /* usage and exit */
break;
}
}
if (unixpname == NULL)
usage(argv[0],"No Unix Printer Name");
if (prtname == NULL)
usage(argv[0],"No AppleTalk Printer Name");
if (fontfile == NULL)
usage(argv[0],"No FontFile specified");
}
private
childdone()
{
#ifndef NOWAIT3
union wait status;
while (wait3(&status, WNOHANG, 0) > 0) ;
signal(SIGCHLD, childdone);
#else
int status;
(void)wait(&status);
signal(SIGCHLD, childdone);
#endif /* NOWAIT3 */
}
main(argc,argv)
int argc;
char **argv;
{
char buf[100];
int err,i,cno;
int rcomp;
int srefnum;
int childdone();
doargs(argc,argv); /* handle args */
if (!dbug.db_flgs) { /* disassociate */
if (fork())
exit(0); /* kill off parent */
for (i=0; i < 20; i++)
close(i); /* close all files */
(void) open("/dev/null",0);
#ifndef NODUP2
(void) dup2(0,1);
#else
(void)dup(0); /* for slot 1 */
#endif
if (logfile == NULL) {
#ifndef NODUP2
(void) dup2(0,2);
#else
(void) dup(0); /* for slot 2 */
#endif
} else {
if ((i = open(logfile,O_WRONLY|O_APPEND)) < 0)
i = creat(logfile,0666);
if (i != 2) {
#ifndef NODUP2
(void) dup2(i,2);
#else
close(2); /* try again */
(void) dup(0); /* for slot 2 */
#endif
(void) close(i);
}
}
#ifdef TIOCNOTTY
if ((i = open("/dev/tty",2)) > 0) {
ioctl(i, TIOCNOTTY,(char *) 0);
close(i);
}
#endif
}
/* dbug.db_pap = TRUE; */
abInit(FALSE); /* initialize appletalk driver */
nbpInit();
PAPInit(); /* init PAP printer routines */
fprintf(stderr,"lwsrv: Spooler starting for %s.%s.*\n",prtname,prttype);
if (!spool_setup(tracefile, fontfile, prtname, dictdir)) {
usage(argv[0]);
exit(1);
}
sprintf(buf,"%s:%s@*",prtname,prttype);
cpyc2pstr(statbuff.StatusStr,"status: idle");
err = SLInit(&srefnum, buf, 8, &statbuff);
if (err != noErr) {
fprintf(stderr,"lwsrv: SLInit failed: %d\n",err);
exit(1);
}
if (!singlefork)
signal(SIGCHLD, childdone);
while (TRUE) {
NewStatus("idle");
err = GetNextJob(srefnum, &cno, &rcomp);
if (err != noErr) {
fprintf(stderr,"lwsrv: GetNextJob failed: %d\n",err);
exit(1);
}
while (rcomp > 0)
abSleep(20,TRUE);
fprintf(stderr,"lwsrv: Starting print job for %s\n",prtname);
if (!singlefork) {
if (fork() != 0) {
PAPShutdown(cno); /* kill off connection */
continue;
}
SLClose(srefnum); /* close server for child */
nbpShutdown(); /* shutdown nbp for child */
} else NewStatus("busy, processing job");
/* need for multi-forking, nice for single forking */
/* handle the connection in cno */
childjob(p_opn(cno, BUFMAX));
if (!singlefork)
exit(0);
}
}
export
childjob(pf)
PFILE *pf;
{
long t;
char tname[100],status[80];
char buf[256];
FILE *outfile;
jobname[0] = username[0] = '\0';
if (tracefile != NULL) /* is this a trace? */
strcpy(tname,tracefile); /* yes... then output is tracefile */
else { /* otherwise use a temp file */
strcpy(tname,TEMPFILE);
mktemp(tname);
}
if ((outfile = fopen(tname, "w+")) == NULL) {
perror(tname);
}
if (singlefork)
NewStatus("initializing");
sprintf(status,"receiving job for %s",prtname);
scandicts(dictdir);
while (getjob(pf,outfile)) { /* while still open... */
if (singlefork)
NewStatus(status);
/* don't send out real eof - causes real problems */
/* given that we are prepending procsets */
fprintf(outfile,"%% *EOF*\n");
}
fclose(outfile);
(void) time(&t);
if (tracefile != NULL)
fprintf(stderr,"lwsrv: Tracing to file: %s; job %s; user %s; on %s\n",
tracefile,jobname,username,ctime(&t));
else {
if (rflag)
fprintf(stderr,"lwsrv: Preserving file in %s\n",tname);
fprintf(stderr,"lwsrv: Printing job: %s; user %s; on %s\n",
jobname,username,ctime(&t));
sprintf(buf,"/usr/ucb/lpr -P%s %s %s -J 'MacUser: %s' %s\n",
unixpname,rflag ? "" : "-r",hflag ? "" : "-h", username,tname);
system(buf);
}
p_cls(pf); /* close out the pap connection */
}
export void
setjobname(ts)
char *ts;
{
strcpy(username, ts);
}
setusername(ts)
char *ts;
{
strcpy(username, ts);
}
export
NewStatus(status)
char *status;
{
char tmp[255];
if (*username != '\0')
sprintf(tmp,"job: %s for %s; status: %s",
jobname,username,status);
else
sprintf(tmp,"status: %s",status);
cpyc2pstr(statbuff.StatusStr, tmp);
abSleep(0,TRUE); /* make sure protocol runs */
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.