
From:	RHEA::DECWRL::"decvax!minow"   19-DEC-1984 22:13  
To:	decwrl!rhea!rex!minow

Received: from DECWRL by DEC-RHEA with SMTP; Wed, 19 Dec 84 19:06-PST
Received: by decwrl.ARPA (4.22.01/4.7.34)
	id AA19144; Wed, 19 Dec 84 19:08:25 pst
Received: by decvax.UUCP (4.12/1.0)
	id AA06288; Wed, 19 Dec 84 21:35:52 est
Date: Wed, 19 Dec 84 21:35:52 est
Return-Path: <decvax!minow>
Message-Id: <8412200235.AA06288@decvax.UUCP>

From seismo!cmcl2!hipl!tony Thu Sep 20 13:04:13 1984
Received: by decvax.UUCP (4.12/1.0)
	id AA12419; Thu, 20 Sep 84 13:03:10 edt
Received: from cmcl2.UUCP by seismo.ARPA with UUCP; Thu, 20 Sep 84 12:21:56 EDT
Received: by NYU-CMCL2.ARPA; Thu, 20 Sep 84 12:08:11 edt
Received: by hipl.UUCP (4.12/4.7)
	id AA04456; Thu, 20 Sep 84 11:54:15 edt
Date: Thu, 20 Sep 84 11:54:15 edt
From: seismo!cmcl2!hipl!tony (Tony Movshon)
Message-Id: <8409201554.AA04456@hipl.UUCP>
To: minow@decvax
Status: R

Martin:

Some more Decus C stuff. (If you want me to stop sending you this kind of
thing, say so). This file is a nested archive containing:

	Two things for your miscellany: a rudimentary mail system for
	  TSX-Plus and a build program (alternative to BUILD).
	A bug-fix for comm.c, in the form of the function equals().

Cut at the end of this message, extract with archx, then inspect the results.

				Tony Movshon

PS: Thanks for ASCR50.MAC ...

PPS: I have minor adaptations of archx and archc that run under MSDOS using
the Lattice compiler. Any interest?



-h- mail.arc	Thu Sep 20 11:46:09 1984	mail.arc
A simple mail system for TSX-Plus, for Decus C
------------------------Cut here and extract with archx----------------------
--h- mail.c	Thu Sep 20 11:30:29 1984	mail.c
/*
 * mail.c
 *
 * Mail service for TSX-Plus.
 * 
 * Syntax:	mail		Reads mail
 *		mail 0		Checks for the existence of mail
 *		mail uid	Sends mail where uid is a project-programmer
 *				number or a user-name
 *
 */
/* Dox not in Runoff format ... */
#ifdef	DOCUMENTATION


		   MAIL utility for TSX-Plus

MAIL is a C program that provides an inter-user mail service for users
of the TSX-Plus operating system, version 4 or later. The MAIL program
has three functions -- to send mail to a user, to read mail, and to
check for the existence of mail.

1. To send mail to another user, type "MAIL name", where name is the
addressee's user name; you may also use the project,programmer number
instead of the user name. The mail program will then accept a typed
message and append it to any other existing messages waiting for that
user. The mail program automatically heads your message with your
identity and with the date and time. To terminate the message, type
control-Z. You may of course send mail to yourself. You may also use the
contents of a file in place of the typed message by typing

		mail henry <file.txt

2. To read your own mail, type "MAIL". The mail program will type out
your message file message by message, and then ask you whether you wish
to preserve it or delete it. If you do not have any mail, the program
types "No mail".

3. To check for mail, type "MAIL 0". The program will type "You have
mail" if you do, and nothing if you do not. This mode of using the
program is designed for inclusion in each user's startup command file.

			* * * * *

To use the mail system, the system manager must ensure the following:

1. Each user's startup command file must assign the logical name MSG: to
some permanently-resident disk in the system; all users must have full
access to MSG:. A subdevice of 100 - 200 blocks is usually suitable.

2. For addressees to be searched by user name, MSG: must contain a file
called USR.LST which lists the project-programmer number and user name
for each user. The format of each line of the file is ppn<tab>username,
e.g.
		1,2	BOB
		1,4	HENRY
		99,99	SYSOPS

3. Each user's startup command file should include a "MAIL 0" command.

4. The program MAIL.SAV should be present on SY:.

			* * * * *

Note that the mail system may only be used with project and programmer
numbers in the range 1 - 999. Note also that it is possible to send mail
to a project-programmer number that is not assigned to any user on the
system, although user names are checked against "msg:usr.lst". The MAIL
program works by creating files on device MSG: for each user to whom
mail is sent. The files are unique to each user, and are of the form
MSG:MAIm.n (expanded with leading zeroes, e.g. MSG:MAI003.012 is the
file for user 3,12). Users may edit their message files, delete them or
whatever. It is not good practice to leave old mail in the file, since
the startup message "You have mail" means only that your mail file
exists, not that someone has added to it since you last looked at it.

			* * * * *

J. Anthony Movshon, Psychology Dept., NYU, New York, NY 10003
10 January 1983, revised 7 June 1984.


#endif


#include	<stdio.h>
#include	<time.h>
#define EOS	0

FILE			*fi,*fo;
char			fname[16];
char			myname[13];
int			proj,prog;
int			j = -10;
int			k = -12;
int			hatc;
int			type;
int			old = 0;
int			skip = 0;
int			out = 0;
long			timval;
char			*timetext;
extern char		*ctime();
extern long		time();
extern int		call();
extern int		ispy();
extern int		scca();
char			*$$prmt = "mail> ";
char			*namefile = "msg:usr.lst";

main(argc, argv)
int argc;
char **argv;
{
	register c,d;

	proj = call(ispy,1,&j);
	prog = call(ispy,1,&k);
	call(scca,1,&hatc);
	type = sctype();

	if (argc == 1) {
		typemail();
		exit();
	}

	argv++;
	if (**argv == '0') {
		chkmail();
		exit();
	}

	if (**argv == '+') {
		skip = atoi(*argv);
		typemail();
		exit();
	}

	if (isalpha(**argv))
		lookup(*argv);
	else {
		if(sscanf(*argv,"%d,%d",&proj,&prog) != 2) {
			fprintf(stderr,
			"mail: don't grok \"%s\"\n",*argv);
			exit();
		}
	}

	maknam();
	if ((fo = fopen(fname,"w")) == NULL) {
		fprintf (stderr, "mail: can't create output %s\n", fname);
		exit();
	}

	if ((fi = fopen(fname,"r")) != NULL) {
		old++;
		while ((c = getc(fi)) != EOF)
			putc(c,fo);
	}

	header();
	if (isatty(fileno(stdin))) {
		printf ("Type your message, then control-Z\n");
		if (freopen("tt:","run",stdin) == NULL) {
			fprintf(stderr,"mail: erk! can't reopen stdin\n");
			exit();
		}
	}
	while ((c = getchar()) != EOF) {
		if(isprint(c) || isspace(c) && c != '\r')
			putc((d=c),fo);
	}
	if (d != '\n')
		putc('\n',fo);
	if (ferror(fo) == NULL)
		fclose(fo);
	else
		fprintf (stderr,
		"mail: fatal error writing message file\n");
}

maknam()
{
	register	i;

	sprintf(fname,"msg:mai%3d.%3d",proj,prog);
	for(i=0; fname[i] != EOS; i++) {
		if(fname[i] == ' ')
			fname[i] = '0';
	}
}

lookup(name)
char	*name;
{
	int		prj,prg,found;
	char		uname[20];

	if ((fi = fopen(namefile,"r")) == NULL) {
		fprintf (stderr,
		"mail: can't locate system namelist %s\n",namefile);
		exit();
	}
	found = 0;
	while (fscanf(fi,"%d,%d%s",&prj,&prg,uname) == 3) {
		lowers(name);
		lowers(uname);
		if (strcmp(name,uname) == NULL) {
			found++;
			proj=prj, prog=prg;
			fclose(fi);
			break;
		}
	}
	if (found == 0) {
		fprintf (stderr,
		"mail: can't locate user \"%s\"\n",name);
		exit();
	}
}

header()
{
	register	i;

	proj = call(ispy,1,&j);
	prog = call(ispy,1,&k);
	getuname(myname);
	lowers(myname);
	if(old)
		putc('\f',fo);
	time(&timval);
	timetext = ctime(&timval);
	timetext[24] = '\0';
	fprintf(fo,
	"--- Mail from %s (%d,%d), %s ---\n", myname, proj, prog, timetext);
}

chkmail()
{
	maknam();
	if ((fi = fopen(fname,"r")) != NULL)
		printf("You have mail\n");
}

typemail()
{
	register c;

	maknam();
	if ((fi = fopen(fname,"r")) == NULL) {
		printf("No mail\n");
		exit();
	}
	while (skip) {
		if ((c = getc(fi)) == EOF)
			exit();
		if (c == '\f') 
			skip--;
	}
	if (type > 1)
		scerpg(1,1);
	while ((c = getc(fi)) != EOF) {
		if (c == '\f') {
			printf("\nType <return> for more messages");
			while (getchar() != '\n');
			if (type > 1)
				scerpg(1,1);
		}
		else
			putchar(c);
	}
	printf("\nDelete? ");
	if(tolower(getchar()) == 'y') {
		delete(fname);
		printf("Mail file deleted\n");
	}
}

lowers(string)
char string[];
{
	register int i;

	for (i=0 ; string[i] != NULL ; i++ ) {
		if (string[i] >= 'A' && string[i] <= 'Z')
			string[i] |= 040;
	}
}
--h- getuna.mac	Thu Sep 20 11:30:29 1984	getuna.mac
;---	tsx-plus routine to get user name
;
;	getuname(string);
;	char	*string
;
	.globl	getuna,csv$,cret$
	.psect	.prog.
	space=	40

getuna:	jsr	r5,csv$		;cstuff
	mov	4(5),r4		;point to string
	clrb	(4)		;prepare it
	mov	#1$,r0		;emt argument
	emt	375		;do the emt
	mov	#2$,r3		;point to the string
3$:	movb	(3)+,r2		;get a byte
	cmpb	r2,#space	;is it a space?
	beq	4$		;yes - done
	movb	r2,(4)+		;no - copy a byte
	br	3$		;get more
4$:	clrb	(4)		;zero the trailing byte
	clr	r0		;return zero
	jmp	cret$		;return

1$:	.byte	0,147
	.word	2$
2$:	.blkb	12.
.end
--h- from.c	Thu Sep 20 11:30:29 1984	from.c
/*
 * from.c
 *
 * Who is my mail from? (See mail.c for description of "mail")
 * 
 */

#include	<stdio.h>
#define EOS	0

FILE			*fi;
char			fname[16];
int			proj,prog;
int			j = -10;
int			k = -12;
int			$$narg = 1;
extern int		call();
extern int		ispy();

main()
{
	register c;

	proj = call(ispy,1,&j);
	prog = call(ispy,1,&k);

	maknam();

	if ((fi = fopen(fname,"r")) == NULL)
		exit();
	for (;;) {
		while ((c = getc(fi)) != EOF && c != '\n')
				putchar(c);
		putchar ('\n');
		if (c == EOF)
			exit();
		while ((c = getc(fi)) != EOF && c != '\f');
		if (c == EOF)
			exit();
	}
}

maknam()
{
	register	i;

	sprintf(fname,"msg:mai%3d.%3d",proj,prog);
	for(i=0; fname[i] != EOS; i++) {
		if(fname[i] == ' ')
			fname[i] = '0';
	}
}
-h- cbld.arc	Thu Sep 20 11:46:09 1984	cbld.arc
An alternative to "BUILD" for compiling and linking C programs under Decus C
-----------------------Cut here and extract with archx-----------------------
--h- cbld.c	Thu Sep 20 11:37:31 1984	cbld.c
/*
 *	cbld.c
 *	Command file processor for DECUS C compiler
 *	J Anthony Movshon, Dept. of Psychology, NYU
 *	v 1.0	16-Jan-84
 *	v 1.1	6-Jun-84
 *
 *	usage:
 *		cbld [-baddr][-k][-m][-n][-p] src_list [-l obj_list]
 *
 *	Generates command file that compiles and links the files in src_list,
 *	 and optionally links them with the files in obj_list.
 *
 *	-baddr	use "addr" as base address for link (default 2000)
 *
 *	-k	keep .m, .s, .obj files
 *
 *	-l	link the following named object files
 *
 *	-m	generate load map
 *
 *	-n	compile only, do not link
 *
 *	-p	invoke the macro preprocessor mp for each compilation
 *
 *	-x	do not chain to created command file (xcc.com)
 */
/* Dox in format suitable for inclusion in RT-11HELP */
#ifdef	DOCUMENTATION

.MACRO	CBLD
CBLD		Compile and link C programs

  SYNTAX
	cbld [-baddr][-k][-m][-n][-p][-x] src_list [-l obj_list]

  SEMANTICS
	Cbld generates and runs a command file that compiles and links
	a C program. Src_list is a list of C program filenames, given
	without the extension (which MUST be ".c"). The first file
	should include main(), and will be used to name the resulting
	.sav file. Obj_list is an optional list of object files that
	may be included in the link. By default, cbld links to the
	file "c:suport.obj", and the libraries "c:culib.obj" and
	"c:clib.obj".

  OPTIONS
   -baddr
	Pass "addr" to linker as base address (default 2000)
   -k
	Do not delete intermediate files after compilation
   -l
	Include the following object files in the link
   -m
	Produce a load map from the link
   -n
	Compile the named files only, do not link them
   -p
	Invoke the macro preprocessor mp for each compilation; this
	is needed only if your programs have #define statements with
	arguments or nested #include statements.
   -x
	Create the command file "dk:xcc.com" but do not chain to it

  EXAMPLES
	cbld prog
	cbld -n file1 file2 file3
	cbld -b10000 -k -m -p prog -l mylib forlib
.ENDM

#endif

#include <stdio.h>

int	mp = 0;		/*invoke mp*/
int	link = 1;	/*link after compilation*/
int	linkobj = 0;	/*include obj_list in link*/
int	keep = 0;	/*do not delete intermediate files*/
int	map = 0;	/*generate load map*/
int	chainx = 1;	/*chain to xcc.com*/
char	fn[20];		/*filename buffer*/
char	base[] = "002000"; /*link base address*/
char	ln[10][20];	/*list of filenames for link*/
char	dn[20][20];	/*list of filenames for deletion*/
char	dln[10][20];	/*list of filenames for deletion if link*/
char	*version = "!cbld v1.1 7-Jun-84\n";	/* version id */
char	*$$prmt = "cbld> ";			/* prompt if RUN */
int	i = 0;		/*counters*/
int	j = 0;
int	k = 0;
int	l = 0;
int	m = 0;

main(argc, argv)
int	argc;
char	*argv[];
{
	FILE	*fp,*fopen();

	if ((fp = fopen("xcc.com","w")) == NULL) {
		fprintf(stderr,"cbld: can't create command file");
		exit(0);
	}
	fprintf(fp,"%s",version);
	argc--, argv++;
	for (i = 0 ; argc ; argc--, argv++) {
		if (i > 9)
			usage();
		if (argv[0][0] == '-') {
			switch (argv[0][1]) {
			case 'b':
				strcpy(base,argv[0]+2);
				break;
			case 'k':
				keep++;
				break;
			case 'l':
				linkobj = 1;
				goto linkit;
				break;
			case 'm':
				map++;
				break;
			case 'n':
				link = 0;
				break;
			case 'p':
				mp++;
				break;
			case 'x':
				chainx = 0;
				break;
			default:
				usage();
				break;
			}
		}
		else {
			strcpy(fn,*argv);
			if (mp) {
				fprintf(fp,"ru c:mp %s.c\n",fn,fn);
				fprintf(fp,"ru c:cc %s.mpc\n",fn,fn);
				sprintf(dn[k++],"%s.mpc",fn);
			}
			else
				fprintf(fp,"ru c:cc %s\n",fn,fn);
			sprintf(dn[k++],"%s.s",fn);
			fprintf(fp,"ru c:as %s\n",fn,fn);
			sprintf(dln[l++],"%s.obj",fn);
			strcpy(ln[i++],fn);
		}
	}
linkit:
	if (linkobj) {
		argc--, argv++;
		for (; argc ; argc--, argv++)
			strcpy(ln[i++],*argv);
	}
	if (link || linkobj) {
		fprintf(fp,"link/prompt/bot:%s",base);
		if (map)
			fprintf(fp,"/map:%s",ln[0]);
		fprintf(fp," %s\n",ln[0]);
		for (j = 1 ; j < i ; j++)
			fprintf(fp,"%s\n",ln[j]);
		fprintf(fp,"c:suport,culib,clib//\n");
	}
	fprintf(fp,"pip\n");
	if (!keep) {
		for (m = 0 ; m < k ; m++)
			fprintf(fp,"%s/d\n",dn[m]);
		if (link) {
			for (m = 0 ; m < l ; m++)
				fprintf(fp,"%s/d\n",dln[m]);
		}
	}
	fprintf(fp,"xcc.com/d\n\03\n");
	fclose(fp);
	if (chainx)
		chain("@xcc");
}
usage()
{
	fprintf(stderr,
	"Usage: cbld [-baddr][-k][-m][-n][-p][-x] src_list [-l obj_list]\n");
	exit();
}
--h- chain.mac	Thu Sep 20 11:37:31 1984	chain.mac
;
;---	c exit routine to pass chain command string to monitor
;
	.globl	chain,csv$
	.mcall	.exit
	jsw=	44
	$chain=	4000
	.psect	.prog.

chain:	jsr	r5,csv$		;cstuff
	mov	4(5),r4		;point to string
	mov	#1000,sp	;reset stack
	mov	#512,r1		;store string here
1$:	movb	(4)+,r0		;pass character
	beq	3$		;null ends string
	cmpb	r0,#12		;linefeed ends line
	bne	2$		;anything else goes
	clrb	r0		;(to make .asciz format)
2$:	movb	r0,(1)+		;put string out
	br	1$		;get more
3$:	clrb	(1)+		;zero final byte
	sub	#512,r1		;compute string length
	mov	r1,@#510	;store it
	bis	#$chain,@#jsw	;inform system of chain
	clr	r0		;make a *hard* exit
	.exit			;go to it
.end
-h- equals.c	Thu Sep 20 11:46:09 1984	equals.c
/*
 * function from comm.c with bug-fix 
 * the error was in the "return" statement, which omitted the "*"s
 */
equals(str1, str2)
char		*str1;		/* Strings				*/
char		*str2;		/* to compare				*/
{
	register char	*p1;
	register char	*p2;

	p1 = str1 - 1;
	p2 = str2 - 1;
	while (*++p1 == *++p2) {
		if (*p1 == 0)
			return(0);
	}
	return((*p1 < *p2) ? 1 : 2);
}



