ftp.nice.ch/pub/next/tools/printer/djf_for_3.0.I.bs.tar.gz#/djf_for_3.0/djf.c

This is djf.c in view mode; [Download] [Up]

/* Hacked 9/91 by D. Beatty for HP DeskJet.   */
/* Hacked 2/92 to support resolution & paper feed options.
 * Includes printer setup and pswrap from Djf--Deskjet 500 printer filter
 * Reimer Mellin & Uwe Meyer-Gruhl August 1991 with help of Christian Baur
 */
/* hacked 7/92 to support EPS (one-time reading of setup) umg */
/* djf--DeskJet line printer filter
 * from iwf--Imagewriter II line printer filter by
 * Eric P. Scott, San Francisco State University, November 1990
 * Copyright 1990, 1991 by Eric P. Scott.  All rights reserved.
 *
 * This file (and the accompanying iwwraps.psw) are freely
 * redistributable in their original, unmodified forms.  The
 * author grants you a nonexclusive, royalty-free license to use
 * this software, and modify it as needed provided that this
 * copyright notice remains, and any changes are clearly
 * indicated as such.  No part may be incorporated in products or
 * packages sold for profit without express permission of the
 * copyright holder.
 *
 * Send bug reports, enhancements, etc. to <beatty+@cs.cmu.edu>
 *
 * This software makes certain assumptions that are valid in NeXT
 * Software Release 2.0, and may not hold in future releases.
 * NO WARRANTY is expressed or implied--use at your own risk!
 *
 * It's not the best code in the world--far from it--such is the
 * price of working under time pressure...
 *
 * What it doesn't do:
 *   8-bit ASCII
 *   use RLE (ESC V nnnn b) to reduce number of characters output
 *   trap SIGINT to guarantee writing accounting record
 *
 * Revision History
 * 11/ 6/90  EPS  1.0 release
 * 11/ 7/90  EPS  1.1 release
 *                fixed "creeping pixel" bug
 *                changed ysize default from 792 to length*12
 * internal  EPS  1.2
 *                <streams/error.h> => <objc/error.h>
 *                recognize R (Resolution) argument
 *  3/28/91  EPS  2.0 release
 *                significant rewrite to use machportdevice
 *                instead of offscreen window
 *                add "sidedoor" code for no PublicWindowServer
 */
#include	<stdio.h>
#include	<string.h>
#include	<stdlib.h>
#include	<libc.h>
#include	<limits.h>
#ifdef	__ARCHITECTURE__
#include	<mach/mach_error.h>
#else
#include	<mach_error.h>
#endif
#include	<pwd.h>
#include	<signal.h>
#ifdef	__ARCHITECTURE__
#include	<mach/cthreads.h>
#else
#include	<cthreads.h>
#endif
#include	<servers/netname.h>
#include	<windowserver/printmessage.h>
#ifdef	__ARCHITECTURE__
#include	"table.h"
#else
#include	<sys/table.h>
#endif
#include	<servers/bootstrap.h>
#import		<dpsclient/dpsclient.h>
#import		<dpsclient/psops.h>
#import		<objc/error.h>


#ifndef lint
static char sccsid[]="@(#)djf.c\t1.7 (umg) 6/28/92";
#endif
int literal;
char *host;
int indent;
int length;
char *name;
int width;
int xsize, ysize;
int xbytes;
int resolution;			/* dpi */
int out_count;
int linect, pagect;
int status;		/* exit status (0=ok; 1=reprint; 2=flush) */
port_t pport;		/* port for machportdevice */
netname_name_t djfportname;	/* name for machportdevice */
NXPrintPageMessage ppm;	/* Mach messaging area */
#define KODMSGID 0xdeadbeef
mutex_t mutex1;
int seen_setup= 0;		/* flag for parsing only the first setup section we see! */

/* DeskJet setup:
 * ASCII characters
 * normal placement
 * 12 point (will change later per -l option)
 * upright characters
 * normal stroke weight
 * 66 lines on a page (will change later per -l option)
 * no top margin
 * clear margins (will set left margin later per -i option)
 * 6 lpi (will change per -l option)
 * graphics resolution 300dpi  (will change later if -R specified)
 * cancel underline
 * display off
 * perforation skip off
 * no wrap at end of line
 * add CR at LF or FF
 * enhancement not line-by-line
 * si/so not line-by-line
 * bidirectional printing
 * text scale off (will turn on later for text mode)
 * paper size US letter
 * Deliberately omitted so as to be selectable from printer front panel: 
 *	Fixed or proportional spacing, 
 *	typeface selection, 
 *	draft mode
 * Set later:
 *	Graphics compression mode
 *	text pitch (per -w option)
 * Type size limits assume original Deskjet with Prestige cartridge.
 */
static char setup[]="\
\033(0U\
\033(s0U\
\033(s12V\
\033(s0S\
\033(s0B\
\033&l6D\
\033&l72P\
\033&l0E\
\033&l71F\
\0339\
\033*t300R\
\033&d@\
\033Z\
\033&l0L\
\033&s1C\
\033&k3G\
\033&k1E\
\033&k1F\
\033&k1W\
\033&k5W\
\033&l26A";

#define UNPRINTABLE 32 /* total unprintable height on page, in points */

#ifdef A4
#define		DPGW	595
#define		DPGH	842
#else
#ifdef LETTER
#define		DPGW	612
#define		DPGH	792
#else
#error You must specify a default paperformat! Run 'make' for infos.
#endif
#endif

int match(char *pattern, char *data)
{
	int r = !strncmp(pattern,data,strlen(pattern));
#ifdef DEBUG
	if (r) fprintf(stderr,"DJF: matched %s\n", pattern);
#endif
	return r;
}

char *skip_token(char *p)	/* skip token and following spaces */
{
    while (*p && *p!=' ') p++;
    while (*p && *p==' ') p++;
    return p;
}

int main(int argc, char *argv[])
{
	extern void *malloc();	/* stupid ANSI!!! */
	extern void minit1(void);
	extern void minit2(int res, int w, int h, char *portname);
	extern int optind;
	extern char *optarg;
	void _textpl(DPSContext ctx, char *buf, unsigned long count);
	int c, l=0;
	int in_setup, res=300, pgwi=DPGW, pghi=DPGH, man=0;
	char *b;
	FILE *af;
	DPSContext pctx;
	struct passwd *pw;
	cthread_t rthread;	/* reader thread */
	static msg_header_t kod;
	char buf[8192];

	while ((c=getopt(argc, argv, "cf:h:i:l:n:p:w:x:y:R:"))!=EOF)
		switch (c) {
	case 'c':
		literal++;
		break;
	case 'f':	/* file--NeXT extension */
		break;
	case 'h':
		host=optarg;
		break;
	case 'i':
		indent=atoi(optarg);
		break;
	case 'l':
		length=atoi(optarg);
		if (length>198) length=198; /* 72pt/" * 11" / 4pt */
		break;
	case 'n':
		name=optarg;
		break;
	case 'p':	/* printer--NeXT extension */
		break;
	case 'w':
		width=atoi(optarg);
		if (width>266) width=266; /* 8" * 33.33 cpi */
		break;
	case 'x':
		xsize=atoi(optarg);
		if (xsize>2400) xsize=2400; /*  8" * 300 dpi */
		break;
	case 'y':
		ysize=atoi(optarg);
		if (ysize>3150) ysize=3150; /* 10.5" * 300dpi */
		break;
	case 'R':	/* Resolution--NeXT extension [2.0] */
		resolution = atoi(optarg);
		if (resolution <= 75) resolution = 75;
		else if (resolution <= 100) resolution = 100;
		else if (resolution <= 150) resolution = 150;
		else resolution = 300;
		break;
	default:
	usage:
		(void)fprintf(stderr, "Usage: %s [options] [acctfile]\n",
			*argv);
		(void)fputs("\t-c  don't interpret control characters\n",
			stderr);
		(void)fputs("\t-hhost  host name of job owner\n", stderr);
		(void)fputs("\t-i# indent\n", stderr);
		(void)fputs("\t-l# page length in lines\n", stderr);
		(void)fputs("\t-nname  login name of job owner\n", stderr);
		(void)fputs("\t-w# page width in characters\n", stderr);
		(void)fputs("\t-x# horizontal page size in pixels\n", stderr);
		(void)fputs("\t-y# vertical page size in pixels\n", stderr);
		(void)fputs("\t-R# resolution (pixels/inch: 75/100/150/300)\n", stderr);
		exit(2);	/* can't use <sysexits.h>!!! */
		break;
	}
	af=(FILE *)NULL;
	switch (argc-optind) {
	case 0:
		break;
	case 1:
		if (argv[optind][0]&&!(af=fopen(argv[optind], "a"))) {
			perror(argv[optind]);
			exit(2);
		}
		break;
	default:
		goto usage;
	}
	if (length<=0) length=66;
	if (width<=0) width=132;
	if (indent>=width) indent=width-1;
	if (xsize<=0) xsize=2400; /* 8" * 300dpi */
	if (ysize<=0) ysize=3150;  /* 10.5" * 300dpi */

	if (resolution<=0)
		resolution = 300; /* best */
	/* adjust bitmap size according to resolution */
	xsize *= resolution; xsize /= 300;
	ysize *= resolution; ysize /= 300;
	xbytes= (xsize+7)/8;

	/* <stdio.h> declares this as int but man page says void */
	(void)setvbuf(stdout, (char *)NULL, _IOFBF, 8192);
	(void)fwrite(setup, 1, (sizeof setup)-1, stdout);
	(void)printf("\033&a%uL\033&l%uD", (unsigned)indent, (unsigned)length/11);
	if ((c=getchar())==EOF) exit(0);
	if (c!='%') {
	normal:	/* text mode filter */
		(void)seteuid(getuid());
		printf("\033(s%uH", (unsigned)(width+7)/8); /* set pitch, over 8" line */
		printf("\033(s%uV", (unsigned)(72*11)/length); /* (point size) */
		printf("\033&k6W"); /* set deskjet text scale on */
		do {
		rerun:
			switch (c) {	/* "but it's one instr. on a VAX" */
			case '\0':
			case '\001':
			case '\002':
			case '\003':
			case '\004':
			case '\005':
			case '\006':
			case '\007':
			case '\013':
			case '\016':
			case '\017':
			case '\020':
			case '\021':
			case '\022':
			case '\023':
			case '\024':
			case '\025':
			case '\026':
			case '\027':
			case '\030':
			case '\032':
			case '\033':
			case '\034':
			case '\035':
			case '\036':
			case '\037':
				putchar(literal ? c : ' ');
				break;
			case '\031':	/* Only at Berkeley... */
				if ((c=getchar())==EOF) {
					l='\031';
					putchar(literal ? l : ' ');
					goto done;
				}
				if (c=='\001') {
					(void)fflush(stdout);
					(void)kill(getpid(), SIGSTOP);
					continue;
				}
				putchar(literal ? '\031' : ' ');
				goto rerun;
			case '\n':
				linect++;
				if (linect<length) goto anyway;
				/*FALL THROUGH*/
			case '\f':
				pagect++; linect=0;
				/*FALL THROUGH*/
			case '\b':	/* you expected intelligence? */
			case '\t': /* may be wrong for deskjet */
			case '\r':
			default:
			anyway:
				putchar(c);
				break;
			}
			l=c;
		} while ((c=getchar())!=EOF);
	done:
		switch (l) {
		default:
			putchar('\n');
			linect++; if (linect>=length) pagect++;
			/*FALL THROUGH*/
		case '\n': case '\r':
			putchar('\f');
			pagect++;
			/*FALL THROUGH*/
		case '\f':
			break;
		}
	}
	else {
		int reader(any_t arg);
      
		if ((c=getchar())==EOF) {
			(void)seteuid(getuid());
			l='%';
			putchar(l);
			goto done;
		}
		if (c!='!') {
			putchar('%'); goto normal;
		}
		/* At this point, we are committed to PostScript */
		pctx=(DPSContext)NULL;
	NX_DURING
		/* attempt to connect to Window Server using defaults */
		pctx=DPSCreateContext((void *)NULL, (void *)NULL,
			(DPSTextProc) _textpl, DPSDefaultErrorProc);
	NX_HANDLER
		if (NXLocalHandler.code!=dps_err_cantConnect)
		     NX_RERAISE();
		NX_DURING
			void sidedoor();
			sidedoor();	/* try to climb in through side door */
			pctx=DPSCreateContext((void *)NULL, (void *)NULL,
				(DPSTextProc) _textpl, DPSDefaultErrorProc);
		NX_HANDLER
			if (NXLocalHandler.code!=dps_err_cantConnect)
				NX_RERAISE();
		NX_ENDHANDLER
		if (!pctx) {
/* This is so lame.  NeXT should make _NXDpsReporter public!!! */
			(void)fputs(
"DPS client library error: Could not form connection, host ", stderr);
			(void)fputs((char *)NXLocalHandler.data2, stderr);
			putc('\n', stderr);
		}
	NX_ENDHANDLER
		if (!pctx)
		        exit(2);
		DPSSetContext(pctx); /* per postscript.321 this is unneeded */
		(void)seteuid(getuid());
		if ((c=port_allocate(task_self(), &pport))!=KERN_SUCCESS) {
			mach_error("port_allocate failed", c);
			exit(2);
		}
		(void)sprintf(djfportname, "djf-%d", getpid());
		if ((c=netname_check_in(name_server_port, djfportname,
			PORT_NULL, pport))!=KERN_SUCCESS) {
			mach_error("netname_check_in failed", c);
			exit(2);
		}
		/* printf("\033&k0W"); */	/* unidirectional printing */
		printf("\033*t%dR", resolution);
		if (pw=getpwnam(name ? name : "nobody"))
			DPSPrintf(pctx, "%d %d setjobuser\n", pw->pw_uid,
			pw->pw_gid);
		/* endpwent() ? */

		/* call function from djwraps.psw: */
#ifdef DEBUG
		fprintf(stderr, "DJF: chosen resolution: %d\n", resolution);
#endif
		minit1();
		minit2(resolution, xsize, ysize, djfportname);

		DPSWaitContext(pctx);
		/* I don't want to rewrite things to use DPSAddPort()
		 * and friends, and C Threads are probably the lesser
		 * of several evils.
		 */
		mutex1=mutex_alloc();
		rthread=cthread_fork((cthread_fn_t)reader, (any_t)0);
		mutex_lock(mutex1);

		DPSPrintf(pctx, "/-saveDJ-%d- save def\n/note {} def\n\
/envelope {} def\n%%%%BeginDocument: DJGraphic\n", getpid());
		mutex_unlock(mutex1);

	NX_DURING
		b=buf;
		*b++='%';
		*b++='!';
		l=0;	/* sick, disgusting! */
		in_setup=0;
		while ((c=getchar())!=EOF) {
			*b++=c;
			if (c=='\n'||b>&buf[sizeof buf]) {
				/* what a crock... */
			    if (buf[0]=='%') {
				if (buf[1]=='%') {
				    if (!l)
				        DPSWaitContext(pctx);
				    l=1;
				}
				/* here's where to interpret comments such as:
				 * %%BeginSetup
				 * %%PaperSize: Executive
				 * %%Feature: *ManualFeed True
				 * %%Feature: *Resolution 150
				 * %%EndSetup
				 * to set up the printer, and then call minit() again.
				 * (I think this might work.)
				 */

				if (!seen_setup && match("%%BeginSetup\n",buf)) {
				    in_setup = seen_setup = 1;
				    pgwi=DPGW; pghi=DPGH; man=0; res= 300; /* default US letter, tray, 300dpi */
				} else if (in_setup && match("%%PaperSize: ",buf)) {
				    if (match("Letter\n", buf+13)) { pgwi=612; pghi=792; }
				    else if (match("Legal\n", buf+13)) { pgwi=612; pghi=1008; }
				    else if (match("Executive\n", buf+13)) { pgwi=540; pghi= 720; }
				    else if (match("A4\n", buf+13)) { pgwi= 595; pghi= 842; }
				    else if (match("A5\n", buf+13)) { pgwi= 420; pghi= 595; }
				    else if (match("B3\n", buf+13)) { pgwi= 1032; pghi= 1460; }
				    else if (match("B4\n", buf+13)) { pgwi= 728; pghi= 1023; }
				    else if (match("B5\n", buf+13)) { pgwi= 516; pghi= 729; }
				    else if (match("B6\n", buf+13)) { pgwi= 363; pghi= 516; }
				    else if (match("B7\n", buf+13)) { pgwi= 258; pghi= 363; }
				    else if (match("B8\n", buf+13)) { pgwi= 181; pghi= 258; }
				    else if (match("B9\n", buf+13)) { pgwi= 127; pghi= 181; }
				    else if (match("B10\n", buf+13)) { pgwi= 91; pghi= 127; }
				    else /* default to US Letter */ { pgwi= DPGW; pghi= DPGH; }
				} else if (in_setup && match("%%Feature: *CustomPaperSize ", buf)) {
				    /* This shows up when you print Landscape. */
				    pgwi = atoi(buf+28); pghi = atoi(skip_token(buf+28));
				} else if (in_setup && match("%%Feature: *ManualFeed ",buf)) {
				    if (match("True\n", buf+23)) { man = 1; }
				    else if (match("False\n", buf+23)) { man = 0; }
				    else /* default to tray feed */ { man = 0; }
				} else if (in_setup && match("%%Feature: *Resolution ",buf)) {
				    if (match("300\n", buf+23)) { res = 300; }
				    else if (match("150\n", buf+23)) { res = 150; }
				    else /* default to 300 dpi */ { res = 300; }
				} else if (in_setup && match("%%EndSetup\n",buf)) {
				    in_setup= 0;
				    mutex_lock(mutex1);
				    /* size paper based on height */
				    switch (pghi) {
				      case 792: printf("\033&l2A"); break; /* letter */
				      case 1008: printf("\033&l3A"); break; /* legal */
				      case 842: printf("\033&l26A"); break; /* A4 */
				      case 297: printf("\033&l81A"); break; /* #10 envelope */
				      default: printf("\033&l26A"); break;
				    }
				    /* now try the German hack of setting height by setting lines:
				     * set page length, top margin, and text length   
				     */
				    printf("\033&%dp0e%dF", pghi/12+2, pghi/12+1);
#ifdef DEBUG
				    fprintf(stderr,"DJF: page size %d x %d pt.\n", pgwi, pghi);
#endif
				    /* select envelope or paper tray */
				    printf("\033&l%dH", man ? 3 : 1);
#ifdef DEBUG
				    fprintf(stderr,"DJF: manual feed %d\n", man);
#endif				    				   
				    /* Select resolution; use draft mode at 150dpi and below   */
				    printf("\033*t%dR", res);
				    printf("\033(s%dQ", res > 150 ? 2 : 1);
#ifdef DEBUG
				    fprintf(stderr,"DJF: resolution %d\n",
					    res);
#endif
				    mutex_unlock(mutex1);
				    /* Finally, tell PostScript about all this nonsense. */
				    /* Of course, UNPRINTABLE might really vary with paper size,
				     * but we'll assume not unless proven wrong...
				     */

				    minit2(res, (pgwi*res)/72, ((pghi-UNPRINTABLE)*res)/72, djfportname);

				    DPSWaitContext(pctx);
				}
			    } 
			    else
			        l=0;
				
			    DPSWritePostScript(pctx, buf, b-buf);
			    b=buf;
			}
		}
		if (b>buf) {
		    *b++='\n';
		    DPSWritePostScript(pctx, buf, b-buf);
		}
		DPSWaitContext(pctx);
		if (pagect==0) {	/* wrong, but expected */
		    mutex_lock(mutex1);
		    DPSPrintf(pctx, "\nshowpage\n");
		    mutex_unlock(mutex1);
		    DPSWaitContext(pctx);
		}
		mutex_lock(mutex1);
		DPSPrintf(pctx, "%%%%EndDocument\n-saveDJ-%d- restore\n",
			getpid());
		mutex_unlock(mutex1);
		DPSWaitContext(pctx);
		PSnulldevice();
		DPSWaitContext(pctx);
	NX_HANDLER
		if (NXLocalHandler.code!=dps_err_ps)
		        NX_RERAISE();
		else {
			mutex_lock(mutex1);
			DPSPrintError(stderr,
				(DPSBinObjSeq)(NXLocalHandler.data2));
			putc('\n', stderr);
			mutex_unlock(mutex1);
		}
		status=2;
	NX_ENDHANDLER
		/* fake "EOF" on port */
		kod.msg_simple=TRUE;
		kod.msg_size=sizeof kod;
		kod.msg_type=MSG_TYPE_NORMAL;
		kod.msg_local_port=PORT_NULL;
		kod.msg_remote_port=pport;
		kod.msg_id=KODMSGID;
                if ((c=msg_send(&kod, MSG_OPTION_NONE, 0))!=SEND_SUCCESS) {
			mutex_lock(mutex1);
                        mach_error("msg_send failed", c);
			mutex_unlock(mutex1);
		}
		else pagect=(int)cthread_join(rthread);
		if (*djfportname&&
			(c=netname_check_out(name_server_port, djfportname,
			PORT_NULL))!=KERN_SUCCESS) {
			mutex_lock(mutex1);
			mach_error("netname_check_out failed", c);
			mutex_unlock(mutex1);
		}
		(void)port_deallocate(task_self(), pport);
		DPSDestroySpace(DPSSpaceFromContext(pctx));
	}

	if (af) {
		if (name) {
			mutex_lock(mutex1);
			(void)fprintf(af, "%4d.00\t", pagect);
			if (host) (void)fprintf(af, "%s:", host);
			(void)fprintf(af, "%s\n", name);
			mutex_unlock(mutex1);
		}
		(void)fclose(af);
	}

	return(status);
}

/* msg_receive blocks until something happens, so this runs in
 * its own thread.  I'm trying to do a minimum amount of mutex
 * locking (set fingers=crossed).
 *
 * This code could stand a serious rethink...
 */
int reader(any_t arg) {
	register msg_return_t m;
	extern void PrintPage(void);

	for (;;) {
		ppm.msgHeader.msg_size=sizeof ppm;
		ppm.msgHeader.msg_local_port=pport;
		if ((m=msg_receive(&ppm.msgHeader, RCV_INTERRUPT|
			RCV_NO_SENDERS, 0))!=RCV_SUCCESS) {
			mutex_lock(mutex1);
			mach_error("msg_receive failed", m);
			mutex_unlock(mutex1);
			break;
		}
		if (ppm.msgHeader.msg_id==KODMSGID)
			break;
		if (ppm.msgHeader.msg_id!=NX_PRINTPAGEMSGID||
			ppm.printPageVersion!=3)
			continue;	/* munchers */
		if (*djfportname) {	/* recall send rights */
			register kern_return_t s;
			if ((s=netname_check_out(name_server_port,
				djfportname, PORT_NULL))!=KERN_SUCCESS) {
				mutex_lock(mutex1);
				mach_error("netname_check_out failed", s);
				mutex_unlock(mutex1);
			}
			*djfportname='\0';
			if (ppm.oolImageParam.msg_type_long_size!=8) {
				/* woke up in the wrong universe... */
				if (port_deallocate(task_self(), pport)==
					KERN_SUCCESS) pport=PORT_NULL;
				return(0);
			}
		}

		if (ppm.pixelsWide>xsize)
			ppm.pixelsWide=xsize;	/* uh-oh! */
		PrintPage();

		pagect++;
		/* unmap and ACK page */
		(void) vm_deallocate(task_self(),
			(vm_address_t) ppm.printerData,
			(vm_size_t) ppm.oolImageParam.msg_type_long_number);
		ppm.msgHeader.msg_simple=TRUE;
		ppm.msgHeader.msg_size=sizeof ppm.msgHeader;
		ppm.msgHeader.msg_type=MSG_TYPE_NORMAL;
		ppm.msgHeader.msg_local_port=PORT_NULL;
		ppm.msgHeader.msg_id=NX_PRINTPAGEMSGID;
		if ((m=msg_send(&ppm.msgHeader, MSG_OPTION_NONE, 0))!=
			SEND_SUCCESS) {
			mutex_lock(mutex1);
			mach_error("msg_send failed", m);
			mutex_unlock(mutex1);
			break;
		}
	}
	return(pagect);
}

/* DPSCreateContext[WithTimeoutFromZone] looks in two places for
 * a port to the Window Server:
 *
 * 1) The Bootstrap Server for "WindowServer"
 * 2) The Network Name Server for "NextStep(tm) Window Server"
 *
 * If PublicWindowServer is *not* set, then (2) won't be checked
 * in, and (1) will be checked in with a subset bootstrap port
 * and available only to descendents of loginwindow (i.e.
 * Workspace and its descendents).
 *
 * This horrible hack set us up to inherit from loginwindow, as
 * if we were a proper descendent.
 * 
 * Most is lifted straight from the 2.0 Reference.
 * table() is undocumented according to NextAnswers.
 *
 * N.B. when a user with PublicWindowServer==No logs out, the
 * subset port is destroyed and neither (1) nor (2) will work.
 * No one said life was fair.
 *
 * This code *must* run as root; djf must be set-uid root if
 * we're to be standalone (not running under control of lpd).
 * 
 */
#ifndef lint
static char sccsid_[]="@(#)sidedoor.c\t1.0 (SFSU) 3/27/91";
#endif
void sidedoor()
{
    extern table();
 
    register host_priv_t hpriv;
    register unsigned int hidx, tidx;
    processor_set_name_array_t hlist;
    unsigned int hcount;
    processor_set_t ppriv;
    task_array_t tlist;
    unsigned int tcount;
    int pid, mypid;
    port_t b;
    struct tbl_procinfo pi;

    if (!(hpriv=host_priv_self())) {	/* must run as root! */
	(void)fputs("couldn't get host privileged port\n", stderr);
	return;
    }
    /* superuser privileges are not required beyond this point */
    if (host_processor_sets(hpriv, &hlist, &hcount)!=KERN_SUCCESS)
	(void)fputs("couldn't get processor sets\n", stderr);
    else {
	mypid=getpid();
	for (hidx=0;hidx<hcount;hidx++) {
	    if (host_processor_set_priv(hpriv, hlist[hidx], &ppriv)!=
		KERN_SUCCESS) ppriv=hlist[hidx];
	    if (processor_set_tasks(ppriv, &tlist, &tcount)==KERN_SUCCESS) {
		for (tidx=0;tidx<tcount;tidx++) {
		    if (unix_pid(tlist[tidx], &pid)==KERN_SUCCESS&&pid>3) {
			if (pid==mypid) continue;
			if (table(TBL_PROCINFO, pid, (char *)&pi, 1,
			    sizeof pi)==1&&
			    pi.pi_status==PI_ACTIVE&&pi.pi_ppid==1&&
			    pi.pi_ttyd<0&&pi.pi_uid==0&&
			    !strncmp(pi.pi_comm, "loginwindow", PI_COMLEN)&&
			    task_get_bootstrap_port(tlist[tidx], &b)==
			    KERN_SUCCESS&&b!=PORT_NULL) {
			    if (task_set_bootstrap_port(task_self(), b)==
				KERN_SUCCESS) bootstrap_port=b;
			    else (void)port_deallocate(task_self(), b);
			}
		    }
		    (void)port_deallocate(task_self(), tlist[tidx]);
		}
		(void)vm_deallocate(task_self(), (vm_address_t)tlist,
		    tcount*sizeof (port_t));
	    }
	    else (void)fprintf(stderr,
		"couldn't get tasks for processor set %d\n", (int)hidx);
	    (void)port_deallocate(task_self(), ppriv);
	    if (hlist[hidx]!=ppriv)
		(void)port_deallocate(task_self(), hlist[hidx]);
	}
	(void)vm_deallocate(task_self(), (vm_address_t)hlist,
	    hcount*sizeof (processor_set_name_t));
    }
    (void)port_deallocate(task_self(), hpriv);
    /* have I deallocated everything I should? */
}

/* this shouldn't ever be called... */
void _textpl(DPSContext ctx, char *buf, unsigned long count)
{
#ifdef DEBUG
	fprintf(stderr, "_textpl says:\n");
#endif
	(void)write(2, buf, count);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.