Patch #: 194 Type: operational change Priority: none Modification: add option to steal DDP dynamic ports from experimental range Modification: add option to process lwsrv jobs with no PostScript parsing Modification: add option to send various papif messages to syslog() Modification: misc changes for papif printing under Solaris 2.N Submitted: Andy Polyakov Submitted: Rakesh Patel Submitted: David Hornsby Archived: munnari.OZ.AU mac/cap.patches/cap60.patch194 Application: 'cd cap60; patch -p < cap60.patches/cap60.patch194' WARNING: The CAP STEAL_PORTS option requires UAR 1.0 at patch level 11 File: Configure File: CAP60.README File: netat/appletalk.h File: lib/cap/abkas.c File: lib/cap/abkip.c File: support/ethertalk/abelap.c File: samples/ash.c File: samples/atlook.c File: samples/papstatus.c File: samples/getzones.c File: applications/aufs/afpos.c File: applications/lwsrv/lwsrv.c File: applications/lwsrv/simple.c File: applications/papif/papif.c File: applications/papif/add_at_printer File: applications/papif/papif.interface.template *** Configure.orig Mon Oct 10 18:54:20 1994 --- Configure Mon Oct 24 16:41:45 1994 *************** *** 1,7 **** #!/bin/sh ! # $Author: djh $ $Date: 1994/10/10 08:54:05 $ ! # $Header: /mac/src/cap60/RCS/Configure,v 2.73 1994/10/10 08:54:05 djh Rel djh $ ! # $Revision: 2.73 $ # CAP configuration shell script. This ain't perfect, but it's a start. # Execute with /bin/sh Configure if your system won't run it (ksh is okay too) # --- 1,7 ---- #!/bin/sh ! # $Author: djh $ $Date: 1994/10/24 06:41:28 $ ! # $Header: /mac/src/cap60/RCS/Configure,v 2.74 1994/10/24 06:41:28 djh Rel djh $ ! # $Revision: 2.74 $ # CAP configuration shell script. This ain't perfect, but it's a start. # Execute with /bin/sh Configure if your system won't run it (ksh is okay too) # *************** *** 913,918 **** --- 913,928 ---- # + DENYREADWRITE implement AUFS read/write access and deny modes # define(`specialcflags',concat(specialcflags,` -DDENYREADWRITE')) # + # + STEAL_PORTS extends DDP dynamic skts down into experimental range 64-128 + # (WARNING!!: Requires uar.1.0.patch11 or uar.1.1.patch09 for use with UAR) + # define(`specialcflags',concat(specialcflags,` -DSTEAL_PORTS')) + # + # + USESYSLOG sends PAPIF Information, Warning & Debug messages to syslog() + # define(`specialcflags',concat(specialcflags,` -DUSESYSLOG')) + # + # + NOCAPDOTPRINTERS uses /etc/lp/printers//comment instead of cap.printers + # (Note: intended for use with Solaris 2.N only) + # define(`specialcflags',concat(specialcflags,` -DNOCAPDOTPRINTERS')) # # # AUFS definable options (previously required editing m4.setup) *** CAP60.README.orig Wed Nov 24 01:06:24 1993 --- CAP60.README Mon Oct 24 16:41:46 1994 *************** *** 233,238 **** --- 233,246 ---- with no Adobe pre-processing. This is useful for spoolers providing service for PCs. Gavin Longmuir + DONT_PARSE + If defined for LWSRV, print jobs will be passed through + with no Adobe pre-processing at all. This is useful for + spoolers which require an unaltered file, as the PASS_THRU + option does not disable some Adobe handling. The crtolf + option will continue to work if it is enabled with this + option. + Rakesh Patel LPRARGS Allows LWSRV -L command line arguments to be passed directly to lpr. For example, printing via TransScript without *************** *** 258,263 **** --- 266,288 ---- ULT42PFBUG Workaround for ULTRIX 4.2 packet filter problem (see Gotchas) David Hornsby + STEAL_PORTS + Extend DDP Dynamic Socket range down into the experimental + AppleTalk socket range 64 - 128. Adds another 64 possible + sockets for server use. + Rakesh Patel + David Hornsby + NOCAPDOTPRINTERS + If defined, PAPIF will not use /etc/cap.printers, instead + the first line of the file /etc/lp/printers/lw/comment (for + printer "lw") is expected to contain a fully qualified + AppleTalk NBP name for the printer, ie: lw:LaserWriter@Zone + This option is intended for use on Solaris 2.N hosts only. + Andy Polyakov + USESYSLOG + If defined, PAPIF will send Information, Warning and Debug + messages to syslog(). + Andy Polyakov The following were originally to be defined in m4.setup, they have been moved to m4.features for convenience. *** netat/appletalk.h.orig Tue Sep 28 18:25:08 1993 --- netat/appletalk.h Mon Oct 24 16:42:17 1994 *************** *** 1,7 **** /* ! * $Author: djh $ $Date: 1993/09/28 08:24:19 $ ! * $Header: /mac/src/cap60/netat/RCS/appletalk.h,v 2.7 1993/09/28 08:24:19 djh Rel djh $ ! * $Revision: 2.7 $ */ /* --- 1,7 ---- /* ! * $Author: djh $ $Date: 1994/10/24 06:42:08 $ ! * $Header: /mac/src/cap60/netat/RCS/appletalk.h,v 2.8 1994/10/24 06:42:08 djh Rel djh $ ! * $Revision: 2.8 $ */ /* *************** *** 162,167 **** --- 162,168 ---- #define ddpSize 13 /* size of DDP header */ #define ddpSSize 5 #define ddpWKS 128 /* boundary of DDP well known sockets */ + #define ddpEWKS 64 /* start of experimental socket range */ #define ddpRTMP 1 /* RTMP type */ #define ddpNBP 2 /* NBP type */ #define ddpATP 3 /* ATP type */ *** lib/cap/abkas.c.orig Sat Mar 7 21:04:58 1992 --- lib/cap/abkas.c Mon Oct 24 16:42:43 1994 *************** *** 1,7 **** /* ! * $Author: djh $ $Date: 1992/03/07 11:04:41 $ ! * $Header: /mac/src/cap60/lib/cap/RCS/abkas.c,v 2.1 1992/03/07 11:04:41 djh Rel djh $ ! * $Revision: 2.1 $ */ /* --- 1,7 ---- /* ! * $Author: djh $ $Date: 1994/10/24 06:42:34 $ ! * $Header: /mac/src/cap60/lib/cap/RCS/abkas.c,v 2.2 1994/10/24 06:42:34 djh Rel djh $ ! * $Revision: 2.2 $ */ /* *************** *** 595,600 **** --- 595,605 ---- if (ddpskt & ddpWKS) /* 128+x means non-wks */ return(ddpskt + ddpNWKSUnix); + + #ifdef STEAL_PORTS + if (ddpskt >= ddpEWKS) /* 64-128 experimental */ + return(ddpskt + ddpNWKSUnix); + #endif STEAL_PORTS if (ddpskt2udpport[ddpskt] < 0) { for (wksp = wks; wksp->name != NULL; wksp++) *** lib/cap/abkip.c.orig Thu May 6 00:06:58 1993 --- lib/cap/abkip.c Mon Oct 24 16:42:44 1994 *************** *** 1,8 **** /* ! * $Author: djh $ $Date: 1993/05/05 14:06:38 $ ! * $Header: /mac/src/cap60/lib/cap/RCS/abkip.c,v 2.4 1993/05/05 14:06:38 djh Rel djh $ ! * $Revision: 2.4 $ ! */ /* * abkip.c - KIP (UDP encapsulated DDP packets) network module, this --- 1,9 ---- /* ! * $Author: djh $ $Date: 1994/10/24 06:42:34 $ ! * $Header: /mac/src/cap60/lib/cap/RCS/abkip.c,v 2.5 1994/10/24 06:42:34 djh Rel djh $ ! * $Revision: 2.5 $ ! * ! */ /* * abkip.c - KIP (UDP encapsulated DDP packets) network module, this *************** *** 29,36 **** * */ - /* PATCH: Moy@Berkeley/abkip.c.diff, djh@munnari.OZ.AU, 17/11/90 */ - /* * The following list of exported routines is provided so you'll know what * have to be done to do another interface type (ethertalk, etc) --- 30,35 ---- *************** *** 58,64 **** * normally would decide where to send and then send via lap, with KIP * decides where and sends via UDP. * ! */ /* * Define the following if you have problems with arriving data being lost. --- 57,63 ---- * normally would decide where to send and then send via lap, with KIP * decides where and sends via UDP. * ! */ /* * Define the following if you have problems with arriving data being lost. *************** *** 217,224 **** --- 216,230 ---- if (ddpskt < 0 || ddpskt > ddpMaxSkt) return(0); + if (ddpskt & ddpWKS) /* 128+x means non-wks */ return(ddpskt + ddpNWKSUnix); + + #ifdef STEAL_PORTS + if (ddpskt >= ddpEWKS) /* 64-128 experimental */ + return(ddpskt + ddpNWKSUnix); + #endif STEAL_PORTS + if (ddpskt2udpport[ddpskt] < 0) { for (wksp = wks; wksp->name != NULL; wksp++) if (wksp->ddpport == ddpskt) { *************** *** 241,246 **** --- 247,256 ---- ddp2ipskt(skt) word skt; { + #ifdef STEAL_PORTS + if (skt >= ddpEWKS) + return(skt+ddpNWKSUnix); + #endif STEAL_PORTS return((skt&0x80) ? (skt+ddpNWKSUnix) : (skt+portrange)); } #endif UAB_MKIP *************** *** 318,324 **** * iov should be an array of type "struct iov" of length at least * IOV_LAP_SIZE+1. Levels after IOV_LAP_LVL are assume to filled. * ! */ int abOpen(skt,rskt, iov, iovlen) int *skt; int rskt; --- 328,335 ---- * iov should be an array of type "struct iov" of length at least * IOV_LAP_SIZE+1. Levels after IOV_LAP_LVL are assume to filled. * ! */ ! int abOpen(skt,rskt, iov, iovlen) int *skt; int rskt; *************** *** 326,331 **** --- 337,343 ---- int iovlen; { int i,fd,err; + int sktlimit = 128; word ipskt, ddp2ipskt(); /* good enough for now */ *************** *** 348,358 **** lsin.sin_family = AF_INET; lsin.sin_addr.s_addr = INADDR_ANY; *skt = (rskt == 0 ? ddpWKS : rskt); /* zero rskt is free choice */ ipskt = ddp2ipskt(*skt); /* translate into ip socket number */ if (ipskt == 0) /* bad socket? */ return(ddpSktErr); ! for (i=0; i < 128; i++,ipskt++,(*skt)++) { lsin.sin_port = htons(ipskt); if ((err = bind(fd, (struct sockaddr *)&lsin, sizeof(lsin))) == 0) break; --- 360,375 ---- lsin.sin_family = AF_INET; lsin.sin_addr.s_addr = INADDR_ANY; + #ifdef STEAL_PORTS + *skt = (rskt == 0 ? ddpEWKS : rskt); /* zero rskt is free choice */ + sktlimit += 64; + #else STEAL_PORTS *skt = (rskt == 0 ? ddpWKS : rskt); /* zero rskt is free choice */ + #endif STEAL_PORTS ipskt = ddp2ipskt(*skt); /* translate into ip socket number */ if (ipskt == 0) /* bad socket? */ return(ddpSktErr); ! for (i=0; i < sktlimit; i++,ipskt++,(*skt)++) { lsin.sin_port = htons(ipskt); if ((err = bind(fd, (struct sockaddr *)&lsin, sizeof(lsin))) == 0) break; *************** *** 359,365 **** if (rskt != 0) /* bind failed and wanted exact? */ return(err); /* yes... */ } ! if (err == 0 && i < 128) { iov[IOV_LAP_LVL].iov_base = (caddr_t)&laph; /* remember this */ iov[IOV_LAP_LVL].iov_len = lapSize; /* and this */ fdlistener(fd, kip_get, iov, iovlen); /* remember for later */ --- 376,382 ---- if (rskt != 0) /* bind failed and wanted exact? */ return(err); /* yes... */ } ! if (err == 0 && i < sktlimit) { iov[IOV_LAP_LVL].iov_base = (caddr_t)&laph; /* remember this */ iov[IOV_LAP_LVL].iov_len = lapSize; /* and this */ fdlistener(fd, kip_get, iov, iovlen); /* remember for later */ *** support/ethertalk/abelap.c.orig Mon Nov 22 20:54:35 1993 --- support/ethertalk/abelap.c Mon Oct 24 16:43:08 1994 *************** *** 1,7 **** /* ! * $Author: djh $ $Date: 1993/11/22 09:54:27 $ ! * $Header: /mac/src/cap60/support/ethertalk/RCS/abelap.c,v 2.9 1993/11/22 09:54:27 djh Rel djh $ ! * $Revision: 2.9 $ */ /* --- 1,7 ---- /* ! * $Author: djh $ $Date: 1994/10/24 06:43:01 $ ! * $Header: /mac/src/cap60/support/ethertalk/RCS/abelap.c,v 2.10 1994/10/24 06:43:01 djh Rel djh $ ! * $Revision: 2.10 $ */ /* *************** *** 213,219 **** /* * Translate ddp socket to UDP port: returns 0 if no mapping * ! */ ddp2ipskt(ddpskt) int ddpskt; { --- 213,220 ---- /* * Translate ddp socket to UDP port: returns 0 if no mapping * ! */ ! ddp2ipskt(ddpskt) int ddpskt; { *************** *** 222,229 **** --- 223,237 ---- if (ddpskt < 0 || ddpskt > ddpMaxSkt) return(0); + if (ddpskt & ddpWKS) /* 128+x means non-wks */ return(ddpskt + ddpNWKSUnix); + + #ifdef STEAL_PORTS + if (ddpskt >= ddpEWKS) /* 64-128 experimental */ + return(ddpskt + ddpNWKSUnix); + #endif STEAL_PORTS + if (ddpskt2udpport[ddpskt] < 0) { for (wksp = wks; wksp->name != NULL; wksp++) if (wksp->ddpport == ddpskt) { *************** *** 348,353 **** --- 356,362 ---- word ipskt; int etph = -1; byte this_intfno; + int sktlimit = 128; char *ep, *cp, this_intf[50]; /* good enough for now */ *************** *** 361,371 **** lsin.sin_family = AF_INET; lsin.sin_addr.s_addr = INADDR_ANY; *skt = (rskt == 0 ? ddpWKS : rskt); /* zero rskt is free choice */ ipskt = ddp2ipskt(*skt); /* translate into ip socket number */ if (ipskt == 0) /* bad socket? */ return(ddpSktErr); ! for (i=0; i < 128; i++,ipskt++,(*skt)++) { lsin.sin_port = htons(ipskt); if ((err = bind(fd, (struct sockaddr *)&lsin, sizeof(lsin))) == 0) break; --- 370,385 ---- lsin.sin_family = AF_INET; lsin.sin_addr.s_addr = INADDR_ANY; + #ifdef STEAL_PORTS + *skt = (rskt == 0 ? ddpEWKS : rskt); /* zero rskt is free choice */ + sktlimit += 64; + #else STEAL_PORTS *skt = (rskt == 0 ? ddpWKS : rskt); /* zero rskt is free choice */ + #endif STEAL_PORTS ipskt = ddp2ipskt(*skt); /* translate into ip socket number */ if (ipskt == 0) /* bad socket? */ return(ddpSktErr); ! for (i=0; i < sktlimit; i++,ipskt++,(*skt)++) { lsin.sin_port = htons(ipskt); if ((err = bind(fd, (struct sockaddr *)&lsin, sizeof(lsin))) == 0) break; *************** *** 372,378 **** if (rskt != 0) /* bind failed and wanted exact? */ return(err); /* yes... */ } ! if (err == 0 && i < 128) { iov[IOV_LAP_LVL].iov_base = (caddr_t)&laph; /* remember this */ iov[IOV_LAP_LVL].iov_len = lapSize; /* and this */ --- 386,392 ---- if (rskt != 0) /* bind failed and wanted exact? */ return(err); /* yes... */ } ! if (err == 0 && i < sktlimit) { iov[IOV_LAP_LVL].iov_base = (caddr_t)&laph; /* remember this */ iov[IOV_LAP_LVL].iov_len = lapSize; /* and this */ *** samples/ash.c.orig Fri Jan 15 00:04:17 1993 --- samples/ash.c Mon Oct 24 16:43:45 1994 *************** *** 1,7 **** /* ! * $Author: djh $ $Date: 1993/01/14 13:04:10 $ ! * $Header: /mac/src/cap60/samples/RCS/ash.c,v 2.3 1993/01/14 13:04:10 djh Rel djh $ ! * $Revision: 2.3 $ */ /* --- 1,7 ---- /* ! * $Author: djh $ $Date: 1994/10/24 06:43:36 $ ! * $Header: /mac/src/cap60/samples/RCS/ash.c,v 2.4 1994/10/24 06:43:36 djh Rel djh $ ! * $Revision: 2.4 $ */ /* *************** *** 118,123 **** --- 118,129 ---- nbpr.nbpBufSize = sizeof(nbpt); /* size of above */ nbpr.nbpDataField = 1; /* max entries */ nbpr.nbpEntityPtr = &en; /* look this entity up */ + + #ifdef ISO_TRANSLATE + cISO2Mac(en.objStr.s); + cISO2Mac(en.typeStr.s); + cISO2Mac(en.zoneStr.s); + #endif ISO_TRANSLATE printf("Looking for %s:%s@%s ...\n",en.objStr.s,en.typeStr.s,en.zoneStr.s); *** samples/atlook.c.orig Tue Dec 7 21:33:20 1993 --- samples/atlook.c Mon Oct 24 16:43:46 1994 *************** *** 1,6 **** ! static char rcsid[] = "$Author: djh $ $Date: 1993/12/07 10:32:56 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/samples/RCS/atlook.c,v 2.11 1993/12/07 10:32:56 djh Rel djh $"; ! static char revision[] = "$Revision: 2.11 $"; /* * atlook - UNIX AppleTalk test program: lookup entities --- 1,6 ---- ! static char rcsid[] = "$Author: djh $ $Date: 1994/10/24 06:43:36 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/samples/RCS/atlook.c,v 2.12 1994/10/24 06:43:36 djh Rel djh $"; ! static char revision[] = "$Revision: 2.12 $"; /* * atlook - UNIX AppleTalk test program: lookup entities *************** *** 431,436 **** --- 431,441 ---- */ for (i = 1; i <= (int)nbpr.nbpDataField; i++) { NBPExtract(nbpt,nbpr.nbpDataField,i,en,&addr); + #ifdef ISO_TRANSLATE + cMac2ISO(en->objStr.s); + cMac2ISO(en->typeStr.s); + cMac2ISO(en->zoneStr.s); + #endif ISO_TRANSLATE len = dumptostr(name, en->objStr.s); name[len++] = ':'; len += dumptostr(name+len, en->typeStr.s); *************** *** 473,480 **** --- 478,493 ---- nbpProto nbpr; /* NBP protocol record */ int err; + #ifdef ISO_TRANSLATE + cISO2Mac(en->objStr.s); + cISO2Mac(en->typeStr.s); + cISO2Mac(en->zoneStr.s); + #endif ISO_TRANSLATE sprintf(namebuf, "%s:%s@%s", en->objStr.s, en->typeStr.s, en->zoneStr.s); PAPStatus(namebuf, &statusbuf, addr); + #ifdef ISO_TRANSLATE + pMac2ISO(&statusbuf.StatusStr[0]); + #endif ISO_TRANSLATE printf("---"); dumpstatus(&statusbuf); putchar('\n'); *** samples/papstatus.c.orig Tue Sep 14 13:16:35 1993 --- samples/papstatus.c Mon Oct 24 16:43:47 1994 *************** *** 1,6 **** ! static char rcsid[] = "$Author: djh $ $Date: 1993/09/14 03:16:08 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/samples/RCS/papstatus.c,v 2.3 1993/09/14 03:16:08 djh Rel djh $"; ! static char revision[] = "$Revision: 2.3 $"; /* * papstatus - UNIX AppleTalk program: simple status display --- 1,6 ---- ! static char rcsid[] = "$Author: djh $ $Date: 1994/10/24 06:43:36 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/samples/RCS/papstatus.c,v 2.4 1994/10/24 06:43:36 djh Rel djh $"; ! static char revision[] = "$Revision: 2.4 $"; /* * papstatus - UNIX AppleTalk program: simple status display *************** *** 193,199 **** * output status message to stdout. * Note: input string is a pascal string * ! */ pstatus(s) char *s; { --- 193,200 ---- * output status message to stdout. * Note: input string is a pascal string * ! */ ! pstatus(s) char *s; { *************** *** 203,208 **** --- 204,212 ---- status_all () { + #ifdef NOCAPDOTPRINTERS + fprintf(stderr, "Sorry, CAP was configured without cap.printers support\n"); + #else NOCAPDOTPRINTERS FILE *fd; static char buf[1024]; char *ep; *************** *** 227,237 **** getstatus (lwname); } while (1); fclose(fd); } /* * get the laserwriter name of the unix spooled printer * ! */ char * getlwname(printer) char *printer; --- 231,244 ---- getstatus (lwname); } while (1); fclose(fd); + #endif NOCAPDOTPRINTERS } + /* * get the laserwriter name of the unix spooled printer * ! */ ! char * getlwname(printer) char *printer; *************** *** 240,246 **** static char buf[1024]; char *ep; ! if ((fd = fopen(capprinters,"r")) == NULL) { perror(capprinters); return(NULL); --- 247,263 ---- static char buf[1024]; char *ep; ! #ifdef NOCAPDOTPRINTERS ! sprintf(buf, "/etc/lp/printers/%s/comment", printer); ! if ((fd = fopen(buf, "r")) == NULL) { ! perror(buf); ! return(NULL); ! } ! if (fgets(buf, sizeof(buf), fd) == NULL) ! return(NULL); ! buf[strlen(buf)-1] = '\0'; /* get rid of the lf */ ! return(buf); ! #else NOCAPDOTPRINTERS if ((fd = fopen(capprinters,"r")) == NULL) { perror(capprinters); return(NULL); *************** *** 263,268 **** --- 280,286 ---- } while (1); fclose(fd); return(NULL); + #endif NOCAPDOTPRINTERS } *** samples/getzones.c.orig Mon Aug 9 00:08:36 1993 --- samples/getzones.c Mon Oct 24 16:43:48 1994 *************** *** 1,6 **** ! static char rcsid[] = "$Author: djh $ $Date: 1993/08/08 14:08:26 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/samples/RCS/getzones.c,v 2.6 1993/08/08 14:08:26 djh Rel djh $"; ! static char revision[] = "$Revision: 2.6 $"; /* * getzones - retrieves the zone list from our bridge --- 1,6 ---- ! static char rcsid[] = "$Author: djh $ $Date: 1994/10/24 06:43:36 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/samples/RCS/getzones.c,v 2.7 1994/10/24 06:43:36 djh Rel djh $"; ! static char revision[] = "$Revision: 2.7 $"; /* * getzones - retrieves the zone list from our bridge *************** *** 73,78 **** --- 73,82 ---- myzone = GetMyZone(); + #ifdef ISO_TRANSLATE + cMac2ISO(myzone); + #endif ISO_TRANSLATE + if (mzone) { printf("%s\n", (char *)myzone); exit(0); *************** *** 93,98 **** --- 97,105 ---- printf("Count is %d\n", cnt); for (i = 0; i < cnt ; i++) { + #ifdef ISO_TRANSLATE + cMac2ISO(zones[i]); + #endif ISO_TRANSLATE if (verbose) printf("ZONE %s", zones[i]); else *** applications/aufs/afpos.c.orig Mon Oct 10 19:02:22 1994 --- applications/aufs/afpos.c Mon Oct 24 16:45:20 1994 *************** *** 1,7 **** /* ! * $Author: djh $ $Date: 1994/10/10 09:02:04 $ ! * $Header: /mac/src/cap60/applications/aufs/RCS/afpos.c,v 2.51 1994/10/10 09:02:04 djh Rel djh $ ! * $Revision: 2.51 $ * */ --- 1,7 ---- /* ! * $Author: djh $ $Date: 1994/10/24 06:45:08 $ ! * $Header: /mac/src/cap60/applications/aufs/RCS/afpos.c,v 2.52 1994/10/24 06:45:08 djh Rel djh $ ! * $Revision: 2.52 $ * */ *************** *** 3480,3485 **** --- 3480,3488 ---- struct spwd *sp; int pw_check; #endif SHADOW_PASSWD + #ifdef RUTGERS + extern char *ru_crypt(); + #endif RUTGERS extern int nousrvol; safedebug = (DBOSI || (getuid() != 0 && geteuid() != 0)); *************** *** 3591,3604 **** crypted_password = ultrix_crypt(pwd, p); if (strcmp(crypted_password, p->pw_passwd) != 0) { #else ULTRIX_SECURITY ! #ifndef SHADOW_PASSWD if (strcmp(crypt(pwd,p->pw_passwd),p->pw_passwd) != 0) { ! #else SHADOW_PASSWD pw_check = (shadow_flag) ? strcmp(crypt(pwd,sp->sp_pwdp),sp->sp_pwdp) : strcmp(crypt(pwd,p->pw_passwd),p->pw_passwd); if (pw_check) { ! #endif SHADOW_PASSWD #endif ULTRIX_SECURITY logit(0, "Login: Incorrect password for user %s", nam); if (!safedebug) --- 3594,3617 ---- crypted_password = ultrix_crypt(pwd, p); if (strcmp(crypted_password, p->pw_passwd) != 0) { #else ULTRIX_SECURITY ! # ifndef SHADOW_PASSWD ! # ifdef RUTGERS ! if (strcmp(ru_crypt(pwd,p->pw_passwd,p->pw_uid,p->pw_name), ! p->pw_passwd) != 0) { ! # else RUTGERS if (strcmp(crypt(pwd,p->pw_passwd),p->pw_passwd) != 0) { ! # endif RUTGERS ! # else SHADOW_PASSWD pw_check = (shadow_flag) ? + # ifdef RUTGERS + strcmp(ru_crypt(pwd,sp->sp_pwdp,p->pw_uid,p->pw_name),sp->sp_pwdp) : + strcmp(ru_crypt(pwd,p->pw_passwd,p->pw_uid,p->pw_name),p->pw_passwd); + # else RUTGERS strcmp(crypt(pwd,sp->sp_pwdp),sp->sp_pwdp) : strcmp(crypt(pwd,p->pw_passwd),p->pw_passwd); + # endif RUTGERS if (pw_check) { ! # endif SHADOW_PASSWD #endif ULTRIX_SECURITY logit(0, "Login: Incorrect password for user %s", nam); if (!safedebug) *************** *** 3657,3663 **** --- 3670,3680 ---- logit(0,"Login: setgid failed for %s because %s",nam,syserr()); return(aeUserNotAuth); } + #ifdef RUTGERS + if ((getuid() == 0 || geteuid() == 0) && ru_initgroups(usrnam, usrgid) < 0) + #else RUTGERS if ((getuid() == 0 || geteuid() == 0) && initgroups(usrnam, usrgid) < 0) + #endif RUTGERS logit(0,"OSLogin: initgroups failed for %s!: reason: %s",syserr(),usrnam); if ((ngroups = dogetgroups()) < 0) { logit(0,"OSLogin: getgroups failed for %s!: reason: %s",syserr(), usrnam); *** applications/lwsrv/lwsrv.c.orig Mon Oct 10 19:01:20 1994 --- applications/lwsrv/lwsrv.c Mon Oct 24 16:45:49 1994 *************** *** 1,6 **** ! static char rcsid[] = "$Author: djh $ $Date: 1994/10/10 09:01:11 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/lwsrv.c,v 2.33 1994/10/10 09:01:11 djh Rel djh $"; ! static char revision[] = "$Revision: 2.33 $"; /* * lwsrv - UNIX AppleTalk spooling program: act as a laserwriter --- 1,6 ---- ! static char rcsid[] = "$Author: djh $ $Date: 1994/10/24 06:45:41 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/lwsrv.c,v 2.34 1994/10/24 06:45:41 djh Rel djh $"; ! static char revision[] = "$Revision: 2.34 $"; /* * lwsrv - UNIX AppleTalk spooling program: act as a laserwriter *************** *** 128,133 **** --- 128,137 ---- char *nextdpi = NULL; /* NeXT printer resolution */ #endif NeXT + #ifdef DONT_PARSE + export int dont_parse = FALSE; + #endif DONT_PARSE + #ifdef USESYSVLP # ifndef LPRCMD # define LPRCMD "/usr/bin/lp" *************** *** 203,208 **** --- 207,215 ---- #ifdef NeXT fprintf(stderr,"\t-R Specify resolution for NeXT printer\n"); #endif NeXT + #ifdef DONT_PARSE + fprintf(stderr,"\t-D don't parse any of the file, but allow crtolf if set\n"); + #endif DONT_PARSE 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"); *************** *** 263,268 **** --- 270,278 ---- #ifdef NeXT strcat(optlist, "R:"); #endif NeXT + #ifdef DONT_PARSE + strcat(optlist, "D"); + #endif DONT_PARSE nprt = 0; prtp = prtlist; *************** *** 349,354 **** --- 359,369 ---- nextdpi = optarg; break; #endif NeXT + #ifdef DONT_PARSE + case 'D': + dont_parse = TRUE; + break; + #endif DONT_PARSE case 'N': capture = FALSE; break; *** applications/lwsrv/simple.c.orig Sun Jul 26 00:45:14 1992 --- applications/lwsrv/simple.c Mon Oct 24 16:45:50 1994 *************** *** 1,6 **** ! static char rcsid[] = "$Author: djh $ $Date: 1992/07/25 14:44:46 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/simple.c,v 2.8 1992/07/25 14:44:46 djh Rel djh $"; ! static char revision[] = "$Revision: 2.8 $"; /* * lwsrv - UNIX AppleTalk spooling program: act as a laserwriter --- 1,6 ---- ! static char rcsid[] = "$Author: djh $ $Date: 1994/10/24 06:45:41 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/simple.c,v 2.9 1994/10/24 06:45:41 djh Rel djh $"; ! static char revision[] = "$Revision: 2.9 $"; /* * lwsrv - UNIX AppleTalk spooling program: act as a laserwriter *************** *** 22,30 **** * */ - /* PATCH: XENIX/file.3, djh@munnari.OZ.AU, 20/11/90 */ - /* PATCH: simple.c.comments, djh@munnari.OZ.AU, 04/02/91 */ - #include #include #include --- 22,27 ---- *************** *** 31,45 **** #ifndef _TYPES /* assume included by param.h */ # include ! #endif #include #include #include #ifdef USESTRINGDOTH # include ! #else # include ! #endif #include "spmisc.h" #include "procset.h" #include "fontlist.h" --- 28,42 ---- #ifndef _TYPES /* assume included by param.h */ # include ! #endif _TYPES #include #include #include #ifdef USESTRINGDOTH # include ! #else USESTRINGDOTH # include ! #endif USESTRINGDOTH #include "spmisc.h" #include "procset.h" #include "fontlist.h" *************** *** 151,156 **** --- 148,157 ---- private int simple_pass_thru = FALSE; #endif PASS_THRU + #ifdef DONT_PARSE + import int dont_parse; + #endif DONT_PARSE + export int is_simple_dsc(); export int simple_dsc_option(); export int simple_TranscriptOption(); *************** *** 423,428 **** --- 424,433 ---- while ((c = p_getc(pf)) != EOF) { if (c == '%' && atstart) maybetoken = TRUE; + #ifdef DONT_PARSE + if (dont_parse) + maybetoken = FALSE; + #endif DONT_PARSE atstart = (c == '\r' || c == '\n') ? TRUE : FALSE; if (maybetoken) { if (atstart) { /* last char is cr or lf */ *** applications/papif/papif.c.orig Mon Oct 10 19:00:52 1994 --- applications/papif/papif.c Mon Oct 24 16:46:10 1994 *************** *** 1,6 **** ! static char rcsid[] = "$Author: djh $ $Date: 1994/10/10 09:00:44 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/applications/papif/RCS/papif.c,v 2.17 1994/10/10 09:00:44 djh Rel djh $"; ! static char revision[] = "$Revision: 2.17 $"; /* * papif - UNIX AppleTalk test program: simple line printer input filter --- 1,6 ---- ! static char rcsid[] = "$Author: djh $ $Date: 1994/10/24 06:46:02 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/applications/papif/RCS/papif.c,v 2.18 1994/10/24 06:46:02 djh Rel djh $"; ! static char revision[] = "$Revision: 2.18 $"; /* * papif - UNIX AppleTalk test program: simple line printer input filter *************** *** 219,230 **** /* string value if not null, "none" o.w. */ #define strval(str) (((str) == NULL) ? "none" : (str)) /* logging levels */ ! #define log_i dolog /* information */ ! #define log_w dolog /* warning */ #define log_e dolog /* error */ #define log_r dolog /* return from remote */ - #define log_d dolog /* log debugging */ /* * LPD Error tokens - what to return from exit --- 219,235 ---- /* string value if not null, "none" o.w. */ #define strval(str) (((str) == NULL) ? "none" : (str)) + #ifdef USESYSLOG + # include + #else USESYSLOG /* logging levels */ ! # define log_i dolog /* information */ ! # define log_w dolog /* warning */ ! # define log_d dolog /* log debugging */ ! #endif USESYSLOG ! #define log_e dolog /* error */ #define log_r dolog /* return from remote */ /* * LPD Error tokens - what to return from exit *************** *** 233,238 **** --- 238,263 ---- #define lpd_REPRINT 1 /* forces a reprint */ #define lpd_ERRORS 2 /* printed with errors */ + #ifdef USESYSLOG + log_i(fmt, a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,af) + char *fmt; + { + return(syslog(LOG_INFO, fmt, a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,af)); + } + + log_w(fmt, a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,af) + char *fmt; + { + return(syslog(LOG_WARNING,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,af)); + } + + log_d(fmt, a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,af) + char *fmt; + { + return(syslog(LOG_DEBUG, fmt, a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,af)); + } + #endif USESYSLOG + /* quit gets called when we've been killed by lprm via SIGINT */ void quit() *************** *** 592,597 **** --- 617,626 ---- cno = -1; pid = getpid(); /* mark as not there for now */ + #ifdef USESYSLOG + openlog("papif", LOG_PID, LOG_LPR); + #endif USESYSLOG + getargs(argc, argv, printer, user, host, &acctfile); initenv(); /* Transcript compatibility */ *************** *** 663,668 **** --- 692,700 ---- doaccounting(spc, epc, acctfile, user, host); #endif RUTGERS log_i("papif: Finished job at %s\n", ptime ()); + #ifdef USESYSLOG + closelog(); + #endif USESYSLOG exit(lpd_OK); /* exit okay */ } *************** *** 1426,1431 **** --- 1458,1474 ---- } } + #ifdef NOCAPDOTPRINTERS + sprintf(buf, "/etc/lp/printers/%s/comment", printer); + if ((fd = fopen(buf, "r")) == NULL) { + perror(buf); + return(NULL); + } + if (fgets(buf, sizeof(buf), fd) == NULL) + return(NULL); + buf[strlen(buf)-1] = '\0'; /* get rid of the lf */ + return(buf); + #else NOCAPDOTPRINTERS if ((fd = fopen(capprinters,"r")) == NULL) { perror(capprinters); return((u_char *)NULL); *************** *** 1448,1453 **** --- 1491,1497 ---- } while (1); fclose(fd); return((u_char *)NULL); + #endif NOCAPDOTPRINTERS } /* MODULE: statuswatch EXPORTS(statuswatch) IMPORTS(lwname, pstatus) */ *** applications/papif/add_at_printer.orig Thu Oct 20 16:04:41 1994 --- applications/papif/add_at_printer Mon Oct 24 16:53:19 1994 *************** *** 0 **** --- 1,189 ---- + #!/bin/sh + # + # Copyright (C) September 1993 appro@fy.chalmers.se + # + # Script to add an AppleTalk printer on a Solaris 2.N host + # + + MYHOME=`dirname $0`; [ "$MYHOME" = "." ] && MYHOME=`pwd` + case $MYHOME in .*) + echo "Use absolute pathname for $0." + exit 1 + ;; + esac + + PAPIFHOME=${CAPHOME:-$MYHOME}${CAPHOME:+/bin}; export PAPIFHOME + if [ ! -x $PAPIFHOME/papif ]; then + echo "FATAL: can't find $PAPIFHOME/papif," + echo " make sure that $0 resides in the same directory as papif" + echo " or set CAPHOME variable properly." + exit + fi + + SUFFIX=`basename $0`.$$; export SUFFIX + trap 'rm /tmp/*.$SUFFIX > /dev/null 2>&1' 0 + trap 'exit' 1 2 3 + + echo "" + echo "Enter AppleTalk zone [*] > \c"; read ZONE + [ "$ZONE" ] || ZONE="*" + + echo "" + echo "Looking for =:LaserWriter@$ZONE ..." + $CAPHOME/bin/atlook -n "=:LaserWriter@$ZONE" | egrep -e '\[Net:[0-9]*' + + echo "" + echo "Enter AppleTalk printer name > \c"; read ATPRINTER + [ "$ATPRINTER" ] || exit + [ "`echo "$ATPRINTER" | awk -F@ '{ print $2 }'`" ] || + ATPRINTER="$ATPRINTER@$ZONE" + [ "`echo "$ATPRINTER" | awk -F: '{ print $2 }'`" ] || + ATPRINTER="`echo "$ATPRINTER" | awk -F@ '{ printf "%s:LaserWriter@%s",$1,$2; }'`" + + TEMP=`echo "$ATPRINTER" | awk -F: '{ print $1 }' | awk '{ for(i=1;i<=NF;i++) printf "%s",$i; }'` + echo "Enter Unix printer name [$TEMP] > \c"; read UXPRINTER + [ "$UXPRINTER" ] || UXPRINTER=$TEMP + + if lpstat -p $UXPRINTER >/dev/null 2>&1; then + echo "\07" + echo "WARNING: $UXPRINTER already exists," + echo " destination is \"`cat /etc/lp/printers/$UXPRINTER/comment`\"." + echo "Continue [Y/n]?\c"; read OK + case $OK in [Nn]*) exit; ;; + *) ;; + esac + disable -c -r "Redefining to $ATPRINTER" $UXPRINTER + reject $UXPRINTER + else + echo "\07" + echo "Defining \"$ATPRINTER\" AppleTalk printer as $UXPRINTER ..." + echo "Continue [Y/n]?\c"; read OK + case $OK in [Nn]*) exit; ;; + *) ;; + esac + fi + echo "" + + if [ ! -r /etc/lp/filter.table ]; then + echo "Initializing of default printer filters..." + for f in `ls /etc/lp/fd | sed 's/.fd$//'`; do + lpfilter -f $f -F/etc/lp/fd/$f.fd + done + fi + + if lpfilter -f atalkio -l > /dev/null 2>&1; then + echo "AppleTalk printer filter is already defined." + else + echo "Defining AppleTalk printer filter ..." + cat > /etc/lp/fd/atalkio.fd << EOF + #ident "@(#)atalkio.fd 1.0 (C) July 1993 appro@fy.chalmers.se" + + Input types: postscript + Output types: PS + Printer types: AppleTalk + Printers: any + Filter type: fast + Command: \$PAPIFHOME/papif 2>>\$ERRFILE + EOF + lpfilter -f atalkio -F /etc/lp/fd/atalkio.fd + fi + + if [ ! -f /usr/share/lib/terminfo/A/AppleTalk ]; then + echo "Defining terminfo for AppleTalk printers ..." + cat > /tmp/terminfo.$SUFFIX << EOF + AppleTalk, + cols#80, lines#66, + cpi=null, csnm=^D, lpi=null, scs=^D, slines=^D, u9=^D, + EOF + tic /tmp/terminfo.$SUFFIX + fi + + LOCKSDIR=/var/spool/lp/tmp/AppleTalk + if [ ! -d $LOCKSDIR ]; then + mkdir -m 0771 $LOCKSDIR + chown lp $LOCKSDIR + chgrp lp $LOCKSDIR + fi + PSEUDODEVICE=$LOCKSDIR/$UXPRINTER + touch $PSEUDODEVICE + chown lp $PSEUDODEVICE + chgrp lp $PSEUDODEVICE + chmod 0600 $PSEUDODEVICE + + echo $PAPIFHOME | sed -e 's/\//\\\//g' > /tmp/sed.$SUFFIX + sed -e "s/PAPIFHOMEMAGICTOKEN/`cat /tmp/sed.$SUFFIX`/g" \ + $MYHOME/papif.interface.template > /etc/lp/interfaces/$UXPRINTER + chown lp /etc/lp/interfaces/$UXPRINTER + chgrp lp /etc/lp/interfaces/$UXPRINTER + chmod 0775 /etc/lp/interfaces/$UXPRINTER + + echo "(Re)defining $UXPRINTER ..." + ( lpadmin -p $UXPRINTER -D "$ATPRINTER" \ + -T AppleTalk \ + -v $PSEUDODEVICE \ + -I PS \ + -i /etc/lp/interfaces/$UXPRINTER \ + -A none && \ + accept $UXPRINTER && \ + enable $UXPRINTER \ + ) || exit + + echo "\07" + echo "Do you want to make it available to network [Y/n]?\c"; read OK + case $OK in [Nn]*) exit; ;; + *) ;; + esac + + echo "" + if sacadm -l -p tcp > /dev/null; then + echo "tcp listener is already defined." + else + echo "Defining tcp listener ..." + sacadm -a -p tcp -t listen \ + -c "/usr/lib/saf/listen tcp" \ + -v `nlsadmin -V` \ + -n 9999 + fi + + ADDR_LPD="\\x`lpsystem -A`"; export ADDR_LPD + ADDR_0=`echo $ADDR_LPD | sed -e 's/\\x00020203/\\x00020ACE/g'`; export ADDR_0 + + if pmadm -l -p tcp -s 0 > /dev/null; then + echo "<0> service is already defined." + else + echo "Defining <0>/tcp service ..." + pmadm -a -p tcp -s 0 -i root \ + -m `nlsadmin -c /usr/lib/saf/nlps_server -A $ADDR_0` \ + -v `nlsadmin -V` + fi + + if pmadm -l -p tcp -s lp > /dev/null; then + echo " service is already defined." + else + echo "Defining /tcp service ..." + pmadm -a -p tcp -s lp -i root \ + -m `nlsadmin -o /var/spool/lp/fifos/listenS5` \ + -v `nlsadmin -V` + fi + + if pmadm -l -p tcp -s lpd > /dev/null; then + echo " service is already defined." + else + echo "Defining /tcp service ..." + pmadm -a -p tcp -s lpd -i root \ + -m `nlsadmin -o /var/spool/lp/fifos/listenBSD -A $ADDR_LPD` \ + -v `nlsadmin -V` + fi + + if nistest printers.org_dir; then + if nistest "[printer_name=$UXPRINTER]printers.org_dir"; then + nistbladm -m printer_host=`uname -n` \ + description="$ATPRINTER" \ + "[printer_name=$UXPRINTER]printers.org_dir" + else + nistbladm -a printer_name=$UXPRINTER \ + printer_host=`uname -n` \ + description="$ATPRINTER" \ + printers.org_dir + fi + fi *** applications/papif/papif.interface.template.orig Thu Oct 20 16:04:49 1994 --- applications/papif/papif.interface.template Mon Oct 24 16:53:19 1994 *************** *** 0 **** --- 1,1046 ---- + #ident "@(#)papif.interface 1.1 93/09/06 appro@fy.chalmers.se" /* CAP6.0 */ + + ########### + ## + ## AppleTalk printer interface program. + ## + ## For use with the Solaris 2.N print system, refer to the "Setting up + ## Printers" manual. Used in conjunction with the add_at_printer script + ## + ########### + + ##### + # + # Until we get to the point below where the printer port + # and physical printer are initialized, we can't do much + # except exit if the Spooler/Scheduler cancels us. + ##### + trap 'exit' 15 + + ##### + # + # We can be clever about getting a hangup or interrupt, though, at least + # until the filter runs. Do this early, even though $LPTELL + # isn't defined, so that we're covered. + ##### + catch_hangup () { + if [ -n "${LPTELL}" ] + then + echo \ + "The connection to the printer dropped; perhaps the printer went off-line?" \ + | ${LPTELL} ${printer} + fi + return 0 + } + catch_interrupt () { + if [ -n "${LPTELL}" ] + then + echo \ + "Received an interrupt from the printer. The reason is unknown, + although a common cause is that the baud rate is too high." \ + | ${LPTELL} ${printer} + fi + return 0 + } + trap 'catch_hangup; exit_code=129 exit 129' 1 + trap 'catch_interrupt; exit_code=129 exit 129' 2 3 + + ##### + # + # Most of the time we don't want the standard error to be captured + # by the Spooler, mainly to avoid "Terminated" messages that the + # shell puts out when we get a SIGTERM. We'll save the standard + # error channel under another number, so we can use it when it + # should be captured. + # + # Open another channel to the printer port, for use when the + # regular standard output won't be directed there, such as in + # command substitution (`cmd`). + ##### + exec 5>&2 2>/dev/null 3>&1 + + ##### + # + # Set some globally used variables and functions. + ##### + + : ${TMPDIR:=/tmp} + : ${SPOOLDIR:=/usr/spool/lp} + : ${TERMINFO:=/usr/lib/terminfo} + : ${CHARSETDIR:=/usr/lib/charsets} + + : ${LOCALPATH:=${SPOOLDIR}/bin} + PATH="/bin:/usr/bin:${LOCALPATH}" + + MAX_COLS_SMALL_BANNER=40 + + #this ----vvvvvvvvvvvvvvvvvvv---- is changed by add_at_printer + PAPIFHOME=PAPIFHOMEMAGICTOKEN; export PAPIFHOME + + ##### + # + # On the 3.2 release of the 386unix product, the parallel port does + # not support any ioctl calls. As a result, we cannot set the opost + # and onlcr attributes to have 's expanded to . This + # "filter" gets the job done for us. + ##### + : ${FIX386BD:=${LOCALPATH}/386parallel} + if [ -n "${FIX386BD}" -a -x "${FIX386BD}" ] + then + FIX386BD="| ${FIX386BD}" + else + FIX386BD="" + fi + + ##### + # Use ${TMPPREFIX} as the prefix for all temporary files, so + # that cleanup is easy. The prefix may be up to 13 characters + # long, so you only have space for one more character to make + # a file name. If necessary, make a directory using this prefix + # for better management of unique temporary file names. + ##### + TMPPREFIX=${TMPDIR}/`uname -n`$$ + + ##### + # Before exiting, set ${exit_code} to the value with which to exit. + # Otherwise, the exit from this script will be 0. + ##### + trap 'rm -fr ${TMPPREFIX}*; exit ${exit_code}' 0 + + ##### + # ${LPTELL} is the name of a program that will send its + # standard input to the Spooler. It is used to forward + # the description of a printer fault to the Spooler, + # which uses it in an alert to the administrator. + ##### + if [ ! -x "${LPTELL:=${LOCALPATH}/lp.tell}" ] + then + fake_lptell () { + header="no" + while read line + do + if [ "no" = "${header}" ] + then + errmsg ERROR ${E_IP_UNKNOWN} \ + "unknown printer/interface failure" \ + "consult your system administrator; + reasons for failure (if any) follow:" + header=yes + fi + echo "${line}" >&2 + done + return 1 + } + LPTELL=fake_lptell + fi + + ##### + # ${DRAIN} is the name of a program that will wait + # long enough for data sent to the printer to print. + ##### + if [ -x "${LOCALPATH}/drain.output" ] + then + DRAIN="${LOCALPATH}/drain.output 5" # wait only five seconds + else + DRAIN= + fi + + ##### + # ${LPCAT} is the name of a program to use as a default + # filter. Minimally it should copy its standard input to + # the standard output, but it should also trap printer + # faults. The current LPCAT traps hangups (DCD dropping, SIGHUP), + # interrupts (SIGINT, SIGQUIT), broken pipe (SIGPIPE), and + # excess delays in sending data to the printer, interpreting all + # as printer faults. + ##### + if [ ! -x "${LPCAT:=${LOCALPATH}/lp.cat}" ] + then + LPCAT="cat" + fi + + ##### + # ${LPSET} is the name of a program that will set the + # character pitch, line pitch, page width, page length, + # and character set. It helps to have this in a single + # binary program so that (1) it's faster than calls + # to "tput"; and (2) it can access the new Terminfo + # capabilities for printers (on pre SVR3.2 machines, tput can't). + ##### + if [ ! -x "${LPSET:=${LOCALPATH}/lp.set}" ] + then + fake_lpset () { + echo H V W L S >&2 + false + } + LPSET=fake_lpset + fi + + internal_lpset () { + ##### + # + # The funny business with the "2>&1 1>&3" is to let us capture + # the standard ERROR, not the standard OUTPUT as is the usual case + # with foo=`cmd`. The standard output will go to the printer. + ##### + [ -n "${stty1}" ] && stty ${stty1} 0<&1 + chk=`${LPSET} "$1" "$2" "$3" "$4" "$5" 2>&1 1>&3` + [ -n "${stty2}" ] && stty ${stty2} 0<&1 + + ##### + # + # The standard error of the delivered ${LPSET} program + # is a string of letters, H, V, W, L, S, which correspond + # to cpi, lpi, width, length, and character set. A letter + # is present only if the corresponding attribute could not + # be set. + ##### + for err in ${chk} + do + case ${err} in + H ) + errmsg WARNING ${E_IP_BADCPI} \ + "can't select the character pitch \"${cpi}\"" \ + "check the valid pitches for the printer, + or consult your system administrator; + printing continues" + ;; + V ) + errmsg WARNING ${E_IP_BADLPI} \ + "can't select the line pitch \"${lpi}\"" \ + "check the valid pitches for the printer, + or consult your system administrator; + printing continues" + ;; + W ) + width=${cols} + errmsg WARNING ${E_IP_BADWIDTH} \ + "can't select the page width \"${width}\"" \ + "check the valid widths for the printer, + or consult your system administrator; + printing continues" + ;; + L ) + length=${lines} + errmsg WARNING ${E_IP_BADLENGTH} \ + "can't select the page length \"${length}\"" \ + "check the valid lengths for the printer, + or consult your system administrator; + printing continues" + ;; + S ) + errmsg WARNING ${E_IP_BADCHARSET} \ + "can't select the character set \"${CHARSET}\"" \ + "check the name given in the -S option, + or consult your system administrator; + printing continues" + ;; + esac + done + } + + + ##### + # ${TPUT} is "tput" IF it works. We'll disable it if we get an + # ugly error message the first time we use it. See the TERM variable + # later in the script. + # + # NOTE: The check we use to see if "tput" works is to use an OLD + # Terminfo capability, like "lines". If it works with that it may + # still fail with some of the newer capabilities like "init" (SVR3.0) + # or "swidm" (SVR3.2), because the version of "tput" we have on your + # machine is older. Thus, on some of the code where ${TPUT} is used + # you'll see "2>/dev/null" being used to avoid ugly error messages. + ##### + TPUT=tput + + ##### + # Error message formatter: + # + # Invoke as + # + # errmsg severity message-number problem help + # + # where severity is "ERROR" or "WARNING", message-number is + # a unique identifier, problem is a short description of the + # problem, and help is a short suggestion for fixing the problem. + ##### + + LP_ERR_LABEL="UX:lp" + + E_IP_ARGS=1 + E_IP_OPTS=2 + #E_IP_FILTER=3 + E_IP_STTY=4 + E_IP_UNKNOWN=5 + E_IP_BADFILE=6 + E_IP_BADCHARSET=7 + E_IP_BADCPI=8 + E_IP_BADLPI=9 + E_IP_BADWIDTH=10 + E_IP_BADLENGTH=11 + E_IP_ERRORS=12 # (in slow.filter) + + errmsg () { + case $1 in + ERROR ) + sev=" ERROR"; + ;; + WARNING ) + sev="WARNING"; + ;; + esac + # tag=`expr "${LP_ERR_LABEL}" : "\(.*\):"``expr "${LP_ERR_LABEL}" : ".*:\(.*\)"` + echo "${LP_ERR_LABEL}: ${sev}: $3 + TO FIX: $4" >&5 + } + + + ########### + ## + ## Check arguments + ########### + + parse () { + echo "`expr \"$1\" : \"^[^=]*=\(.*\)\"`" + } + + ##### + # + # This program is invoked as + # + # ${SPOOLDIR}/.../printer request-id user title copies options files... + # + # The first three arguments are simply reprinted on the banner page, + # the fourth (copies) is used to control the number of copies to print, + # the fifth (options) is a blank separated list (in a single argument) + # of user or Spooler supplied options (without the -o prefix), + # and the last arguments are the files to print. + ##### + + if [ $# -lt 5 ] + then + errmsg ERROR ${E_IP_ARGS} \ + "wrong number of arguments to interface program" \ + "consult your system administrator" + exit 1 + fi + + printer=`basename $0` + request_id=$1 + user_name=$2 + title=$3 + copies=$4 + option_list=$5 + + shift 5 + files="$*" + + nobanner="yes" # enable banners here (set it to "no") + nofilebreak="no" + stty= + + inlist= + for i in ${option_list} + do + case "${inlist}${i}" in + + + nobanner ) + nobanner="yes" + ;; + + nofilebreak ) + nofilebreak="yes" + ;; + + ##### + # + # If you want to add simple options (e.g. -o simple) + # identify them here. + ##### + # simple ) + # simple="yes" + # ;; + + + cpi=pica ) + cpi=10 + ;; + cpi=elite ) + cpi=12 + ;; + cpi=* ) + cpi=`parse ${i}` + ;; + + lpi=* ) + lpi=`parse ${i}` + ;; + + length=* ) + length=`parse ${i}` + ;; + + width=* ) + width=`parse ${i}` + ;; + + ##### + # + # If you want to add simple-value options (e.g. -o value=a) + # identify them here. + ##### + # value=* ) + # value=`parse ${i}` + # ;; + + + ##### + # + # If you want to add options that, like "stty", + # take a list (e.g. -o lopt='a b c'), identify + # them here and below (look for LOPT). + ##### + stty=* | flist=* | lpd=* ) + #LOPT stty=* | flist=* | lpd=* | lopt=* ) + + inlist=`expr "${inlist}${i}" : "^\([^=]*=\)"` + case "${i}" in + ${inlist}\'*\' ) + item=`expr "${i}" : "^[^=]*='*\(.*\)'\$"` + ;; + ${inlist}\' ) + continue + ;; + ${inlist}\'* ) + item=`expr "${i}" : "^[^=]*='*\(.*\)\$"` + ;; + ${inlist}* ) + item=`expr "${i}" : "^[^=]*=\(.*\)\$"` + ;; + *\' ) + item=`expr "${i}" : "^\(.*\)'\$"` + ;; + * ) + item="${i}" + ;; + esac + + ##### + # + # We don't dare use "eval" because a clever user could + # put something in an option value that we'd end up + # exec'ing. + ##### + case "${inlist}" in + stty= ) + stty="${stty} ${item}" + ;; + flist= ) + flist="${flist} ${item}" + ;; + lpd= ) + lpd="${lpd} ${item}" + ;; + #LOPT lopt= ) + #LOPT lopt="${lopt} ${item}" + #LOPT ;; + esac + + case "${i}" in + ${inlist}\'*\' ) + inlist= + ;; + ${inlist}\'* ) + ;; + *\' | ${inlist}* ) + inlist= + ;; + esac + ;; + + * ) + errmsg WARNING ${E_IP_OPTS} \ + "unrecognized \"-o ${i}\" option" \ + "check the option, resubmit if necessary + printing continues" + ;; + esac + done + + ##### + # + # Additional ``parameters'' are passed via Shell environment + # variables: + # + # TERM The printer type (used for Terminfo access) + # CHARSET The character set to choose + # FILTER The filter to run + ##### + + ##### + # Set defaults for unset variables. + ##### + + : ${TERM:=unknown} + tput lines 1>/dev/null 2>&1 || TPUT=: + + : ${CHARSET:=cs0} + + if [ -z "${FILTER}" ] + then + ##### + # + # If no filter is being used, we have a little routine that + # will push the data to the printer. It traps hangups (loss + # of carrier) and checks for excessive delays in sending the + # data to the printer. The lesser of the print rate of the printer + # (obtained from Terminfo) or the baud rate is used to compute + # the expected delay. If neither of these is correct, you + # may be experiencing false alarms. If so, give the correct + # rate, in characters per second, as a single argument. + # An argument of 0 means don't check for delays. + # Give an -r option to get a printout of actual delays. + # (QUOTES ARE IMPORTANT!) + ##### + # FILTER="${LPCAT} 120" # e.g. 120 CPS + FILTER="${LPCAT} 0" # allow infinite delays + # FILTER="${LPCAT} -r 0 2>/tmp/delays" # check actual delays + # FILTER=${LPCAT} + fi + + ########### + ## + ## Initialize the printer port + ########### + + ##### + # + # SERIAL PORTS: + # Initialize everything. + # + # PARALLEL PORTS: + # Don't initialize baud rate. + # + # It's not obvious how to tell if a port is parallel or serial. + # However, by splitting the initialization into two steps and letting + # the serial-only part fail nicely, it'll work. + # + # Another point: The output must be a ``tty'' device. If not, don't + # bother with any of this. + ##### + stty1= stty2= + tty 0<&1 1>/dev/null 2>&1 && { + + ##### + # + # First set the default parameters, + # then the requested parameters. + ##### + + stty \ + 9600 \ + 0<&1 2>/dev/null 1>&2 + stty \ + cs8 -cstopb -parenb -parodd \ + ixon -ixany \ + opost -olcuc onlcr -ocrnl -onocr -onlret -ofill \ + nl0 cr0 tab0 bs0 vt0 ff0 \ + 0<&1 2>/dev/null 1>&2 + + if [ -n "${stty}" ] + then + if stty ${stty} 0<&1 1>/dev/null 2>&5 + then + : + else + errmsg ERROR ${E_IP_STTY} \ + "stty option list failed" \ + "check the \"-o stty\" option you used, + or consult your system administrator" + exit 1 + fi + fi + + ##### + # + # Here you may want to add other port initialization code. + # Some examples: + # + # estty # for printer needing hardware flow control (3B2/EPORTS) + # fctty # for printer needing hardware flow control (3B15,3B20) + ##### + #estty 0<&1 + #fctty 0<&1 + + + ########## + # + # Find out if we have to turn off opost before initializing the + # printer and on after. Likewise, check clocal. + # + # Turning OFF opost (output postprocessing) keeps the UNIX system + # from changing what we try to send to the printer. Turning ON + # clocal keeps the UNIX system from dropping what we are trying to + # send if the printer drops DTR. An example of the former is the + # AT&T 479, which wants to send a linefeed (ASCII 10) when a page + # width of 10 is set; with opost on, this COULD BE turned into a + # carriage-return/linefeed pair. An example of the latter is the + # AT&T 455, which momentarily drops DTR when it gets the + # initialization string, is2; with clocal off, the UNIX system + # stops sending the rest of the initialization sequence at that + # point. + # + # THIS CODE MUST FOLLOW THE REST OF THE PORT INITIALIZATION CODE. + ########## + cur_stty=`stty -a 0<&3` + expr "${cur_stty}" : '.*-opost' 1>/dev/null 2>&1 \ + || stty1="${stty1} -opost" stty2="${stty2} opost" + expr "${cur_stty}" : '.*-clocal' 1>/dev/null 2>&1 \ + && stty1="${stty1} clocal" stty2="${stty2} -clocal" + expr "${cur_stty}" : '.* opost.*' 1>/dev/null 2>&1 \ + || banner_filter=${FIX386BD} + + } + + + ########### + ## + ## Initialize the physical printer (Part I). + ## Here we bring the printer to a sane state and set the page size. + ########### + + ########## + # + # WARNING! The "echo" command will catch backslashes (\) and + # try to interpret the characters following it. Thus, using + # "echo" to print string values obtained from "tput" is dangerous. + ########## + + ##### + # We're confident that most printers don't have backslashes + # in the control sequences for carriage return and form-feed. + # We're also confident that these don't contain newlines. + # We're also confident that most printers have a linefeed + # in the control sequence for doing a newline (move to beginning + # of next line), but we can't capture it like we do the + # carriage return or form-feed. Thus we set it unconditionally. + # We don't set form-feed if it isn't defined, however, because + # maybe the printer doesn't have a formfeed. If not set, we're + # out of luck. + ##### + + CR=`${TPUT} cr` + [ -z "${CR}" ] && CR="\r" + + FF=`${TPUT} ff` + + NL="${CR}\n" + + lines=`${TPUT} lines` + [ -z "${lines}" -o 0 -ge "${lines}" ] && lines=66 + + cols=`${TPUT} cols` + [ -z "${cols}" -o 0 -ge "${cols}" ] && cols=132 + + ##### + # + # Basic initialization. The ``else'' clause is equivalent, + # but covers cases where old Terminal Information Utilities are present. + ##### + [ -n "${stty1}" ] && stty ${stty1} 0<&1 + if ${TPUT} init 2>/dev/null + then + : + else + pgm=`${TPUT} iprog` + if [ -x "${pgm}" ] + then + eval ${pgm} + fi + + ${TPUT} is1 + ${TPUT} is2 + + tabset= + if [ "8" != "`${TPUT} it`" ] + then + stty tab3 0<&1 1>/dev/null 2>&1 + + elif `${TPUT} ht >/dev/null` + then + tabset="/usr/lib/tabset/${TERM}" + if [ -r ${tabset} ] + then + cat -s ${tabset} + fi + stty tab3 0<&1 1>/dev/null 2>&1 + fi + + file=`${TPUT} if` + if [ "${tabset}" != "${file}" -a -r "${file}" ] + then + cat -s "${file}" + fi + + ${TPUT} is3 + echo "${CR}\c" + fi + [ -n "${stty2}" ] && stty ${stty2} 0<&1 + + ##### + # + # Set the page size and print spacing, but not the character set. + # We will be doing the character set later (after the header). + ##### + internal_lpset "${cpi}" "${lpi}" "${width}" "${length}" "" + + ##### + # + # The banner page (and cancellation page) will + # use double width characters if they're available. + ##### + WIDE_CS=`${TPUT} swidm 2>/dev/null` && NORM_CS=`${TPUT} rwidm 2>/dev/null` + PAD="#####${NL}" + + ##### + # + # Some printers need to have the banner page filtered. + ##### + case "${TERM}" in + + PS | PSR ) + banner_filter="/usr/lib/lp/postscript/postprint | /usr/lib/lp/postscript/postio" + ;; + + AppleTalk ) + banner_filter="$PAPIFHOME/papof" + ;; + + esac + if [ -n "${banner_filter}" ] + then + banner_filter="| ${banner_filter}" + fi + + ##### + # + # Now that the printer is ready for printing, we're able + # to record on paper a cancellation. + ##### + + cancel_banner () { + echo "${PAD}${PAD}\c" + echo "#####${WIDE_CS} Job ${request_id}${NORM_CS}${NL}\c" + echo "#####${WIDE_CS} suspended or canceled${NORM_CS}${NL}\c" + echo "${PAD}${PAD}\c" + } + + canceled () { + ${TPUT} scs 0 2>/dev/null + echo "${CR}\c" + if [ "${width:-${cols}}" -lt "${MAX_COLS_SMALL_BANNER}" ] + then + WIDE_CS= NORM_CS= + fi + cancel_banner + if [ -n "${FF}" ] + then + echo "${CR}${FF}\c" + fi + } + + ##### doesn't supported yet + #trap 'eval canceled ${banner_filter}; exit_code=0 exit' 15 + trap 'exit_code=0 exit' 15 + + + ########### + ## + ## Print the banner page + ########### + + BANNER="/tmp/banner.$$"; export BANNER + BANNERFIRST="yes"; export BANNERFIRST + #BANNERLAST="yes"; export BANNERLAST + + ##### + # + # You may want to change the following code to get a custom banner. + ##### + + regular_banner () { + echo "${CR}\c" + echo "${PAD}${PAD}${PAD}${PAD}${PAD}\c" + echo "#####${WIDE_CS} User: ${user_name}${NORM_CS}${NL}\c" + if [ -n "$ALIAS_USERNAME" ] + then + echo "${PAD}\c" + echo "#####${WIDE_CS} Alias: ${ALIAS_USERNAME}${NORM_CS}${NL}\c" + fi + if [ -n "${title}" ] + then + echo "${PAD}\c" + echo "#####${WIDE_CS} Title: ${title}${NORM_CS}${NL}\c" + fi + echo "${PAD}\c" + echo "#####${WIDE_CS} Printed: `date '+%a %H:%M %h %d, 19%y'`${NORM_CS}${NL}\c" + echo "${PAD}\c" + echo "#####${WIDE_CS} Job number: ${request_id}${NORM_CS}${NL}\c" + echo "${PAD}${PAD}${PAD}${PAD}${PAD}\c" + if [ -n "${FF}" ] + then + echo "${CR}${FF}\c" + fi + } + + small_banner () { + echo "${CR}\c" + echo "${PAD}\c" + echo "##### User: ${user_name}${NL}\c" + if [ -n "${title}" ] + then + echo "##### Title: ${title}${NL}\c" + fi + echo "##### Date: `date '+%a %H:%M %h %d, 19%y'`${NL}\c" + echo "##### Job: ${request_id}${NL}\c" + echo "${PAD}\c" + if [ -n "${FF}" ] + then + echo "${CR}${FF}\c" + fi + } + + if [ "${width:-${cols}}" -lt "${MAX_COLS_SMALL_BANNER}" ] + then + banner=small_banner + else + banner=regular_banner + fi + + if [ "no" = "${nobanner}" -a "${TERM}" != "PSR" ] + then + eval "${banner} ${banner_filter}" + fi + + + ########### + ## + ## Initialize the physical printer (Part II) + ## Here we select the character set. + ## One could argue that this should be done before the banner is printed, + ## but we don't, to keep the banner page looking consistent for the + ## operator. You can move this code before the banner code if you + ## disagree. If you do, combine it with the other call to "internal_lpset" + ## to do everything in one shot. + ########### + internal_lpset "" "" "" "" "${CHARSET}" + + ########### + ## + ## Print some copies of the file(s) + ########### + + ##### + # + # The protocol between the interface program and the Spooler + # is fairly simple: + # + # All standard error output is assumed to indicate a + # fault WITH THE REQUEST. The output is mailed to the + # user who submitted the print request and the print + # request is finished. + # + # If the interface program sets a zero exit code, + # it is assumed that the file printed correctly. + # If the interface program sets a non-zero exit code + # less than 128, it is assumed that the file did not + # print correctly, and the user will be notified. + # In either case the print request is finished. + # + # If the interface program sets an exit code greater + # than 128, it is assumed that the file did not print + # because of a printer fault. If an alert isn't already + # active (see below) one will be activated. (Exit code + # 128 should not be used at all. The shell, which executes + # this program, turns SIGTERM, used to kill this program + # for a cancellation or disabling, into exit 128. The + # Spooler thus interpretes 128 as SIGTERM.) + # + # A message sent to the standard input of the ${LPTELL} + # program is assumed to describe a fault WITH THE PRINTER. + # The output is used in an alert (if alerts are defined). + # If the fault recovery is "wait" or "begin", the printer + # is disabled (killing the interface program if need be), + # and the print request is left on the queue. + # If the fault recovery is "continue", the interface program + # is allowed to wait for the printer fault to be cleared so + # it can resume printing. + # + # This interface program relies on filters to detect printer faults. + # In absence of a filter provided by the customer, it uses a simple + # filter (${LPCAT}) to detect the class of faults that cause DCD + # (``carrier'') drop. The protocol between the interface program and + # the filter: + # + # The filter should exit with zero if printing was + # successful and non-zero if printing failed because + # of a printer fault. This interface program turns a + # non-zero exit of the filter into an "exit 129" from + # itself, thus telling the Spooler that a printer fault + # (still) exists. + # + # The filter should report printer faults via a message + # to its standard error. This interface program takes all + # standard error output from the filter and feeds it as + # standard input to the ${LPTELL} program. + # + # The filter should wait for a printer fault to clear, + # and should resume printing when the fault clears. + # Preferably it should resume at the top of the page + # that was being printed when the fault occurred. + # If it waits and finishes printing, it should exit + # with a 0 exit code. If it can't wait, it should exit + # with a non-zero exit code. + # + # The interface program expects that ANY message on the + # standard error from the filter indicates a printer fault. + # Therefore, a filter should not put user (input) error + # messages on the standard error, but on the standard output + # (where the user can read them when he or she examines + # the print-out). + # + ##### + + ##### build papif command options + FILTER="${FILTER} -P $printer -U $user_name" + ##### + + badfileyet= + i=1 + while [ $i -le $copies ] + do + for file in ${files} + do + if [ -r "${file}" ] + then + ##### + # + # Here's where we set up the $LPTELL program to + # capture fault messages, and... + # + # Here's where we print the file. + # + # We set up a pipeline to $LPTELL, but play a trick + # to get the filter's standard ERROR piped instead of + # its standard OUTPUT: Divert the standard error (#2) to + # the standard output (#1) IN THE PIPELINE. The shell + # will have changed #1 to be the pipe, not the + # printer, so diverting #2 connects it to the pipe. + # We then change the filter's #1 to a copy of the real + # standard output (the printer port) made earlier, + # so that is connected back to the printer again. + # + # We do all this inside a parenthesized expression + # so that we can get the exit code; this is necessary + # because the exit code of a pipeline is the exit + # code of the right-most command, which isn't the + # filter. + # + # These two tricks could be avoided by using a named + # pipe to connect the standard error to $LPTELL. In + # fact an early prototype of this script did just + # that; however, the named pipe introduced a timing + # problem. The processes that open a named pipe hang + # until both ends of the pipe are opened. Cancelling + # a request or disabling the printer often killed one + # of the processes, causing the other process to hang + # forever waiting for the other end of the pipe to + # be opened. + ##### + EXIT_CODE=${TMPPREFIX}e + trap '' 1 # Let the filter handle a hangup + trap '' 2 3 # and interrupts + ( + ##### + # Put the 0<${file} before the "eval" to keep + # clever users from giving a file name that + # evaluates as something to execute. + ##### + 0<${file} eval ${FILTER} 2>&1 1>&3 + echo $? >${EXIT_CODE} + ) | ${LPTELL} ${printer} + trap 'catch_hangup; exit_code=129 exit 129' 1 + trap 'catch_interrupt; exit_code=129 exit 129' 2 3 + exit_code=`cat ${EXIT_CODE}` + + if [ -n "${exit_code}" -a 0 -ne "${exit_code}" ] + then + trap '' 15 # Avoid dying from disable + sleep 4 # Give $LPTELL a chance to tell + exit_code=129 exit 129 + fi + + if [ -n "${FF}" -a "no" = "${nofilebreak}" ] + then + echo "${CR}${FF}\c" + fi + + else + + ##### + # + # Don't complain about not being able to read + # a file on second and subsequent copies, unless + # we've not complained yet. This removes repeated + # messages about the same file yet reduces the + # chance that the user can remove a file and not + # know that we had trouble finding it. + ##### + if [ "${i}" -le 1 -o -z "${badfileyet}" ] + then + errmsg WARNING ${E_IP_BADFILE} \ + "cannot read file \"${file}\"" \ + "see if the file still exists and is readable, + or consult your system administrator; + printing continues" + badfileyet=yes + fi + + fi + + done + i=`expr $i + 1` + + done + + ######## banner is already handled + #if [ "no" = "${nobanner}" -a "${TERM}" = "PSR" ] + #then + # eval "${banner} ${banner_filter}" + #fi + ######## + + if [ -n "${exit_code}" -a 0 -ne "${exit_code}" ] + then + exit ${exit_code} + fi + + ##### + # + # Always ensure the complete job ends with a ``formfeed'', to + # let the next job start on a new page. (If someone wants to + # concatenate files, they can give them in one job.) + # So, if we haven't been putting out a ``formfeed'' between files, + # it means we haven't followed the last file with a formfeed, + # so we do it here. + ##### + if [ -n "${FF}" -a "yes" = "${nofilebreak}" ] + then + echo "${CR}${FF}\c" + fi + + ${DRAIN} + + exit_code=0 exit 0 *** README.orig Mon Oct 10 18:54:16 1994 --- README Mon Oct 24 16:41:43 1994 *************** *** 2,8 **** CAP - Columbia AppleTalk Package for UNIX o RELEASE NOTES ! o CAP Distribution 6.0, Patch Level 193, October 1994 Notice ------ --- 2,8 ---- CAP - Columbia AppleTalk Package for UNIX o RELEASE NOTES ! o CAP Distribution 6.0, Patch Level 194, October 1994 Notice ------