ftp.nice.ch/pub/next/unix/network/system/cap.5.0.s.tar.gz#/cap_5.0/applications/lwsrv/lwsrv.c

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.