
#include	<stdio.h>
#include	<descrip.h>
#include	<prvdef.h>
#include	<ssdef.h>
#define	then

FILE *infile ;

struct dsc {
		long int len ;
		char *addr ;
	   } ;

extern char *strcpy(),*strcat(),*tmpnam(),*getenv(),tolower(),*upcase() ;
extern char *malloc(),*lowcase(),*tranlog() ;


char *bitnet_link  = "UOFT01" ;
char *printer_link = "UOFT03" ;
char *my_bitnet_node  = "BITNET_NODE" ;
char *printer_node = "NAS_PRINTER_NODE" ;
char *printer_node_xlate ;

main(argc,argv)
int argc ;
char *argv[] ;

{
/*
	User interface to the NAS (ibm) system without having
	to grant JNET access to all users.

	29-MAR-1985 15:35  Brian Nelson				
								
	edits:							
								
	29-MAR-1985 15:40 BDN	Creation			
	 8-APR-1985 14:23 BDN	Added code for remote printing	
	29-AUG-1985 12:32 BDN	Remove macro-32 subs. Mods for	
				ACXPM on the NAS		
	31-MAR-1986 08:31 BDN	Jnet version 2 mods
								
								
								
	send a file to vs2 for a batch job on uoft01		
	send a file to system for a print job on uoft01		
								
 1.	HSP filename [printername]				
 2. 	HSP filename [nodename] [username] (or user@node)
 3.	HSP filename						
	NASPRINT filename [printername]				
								
	Option (1) runs the job and routes it to the specified printer
	Option (2) runs the job and routes the output to the specified
	user at node.  Currently this is restricted to the originator.					
	Option (3) runs it and prints results on system print	
								
	Job 'card' format					

	//VAXnnnn JOB <JOB,uuuuuu,ssssss, vaxuserid

	Where:	(1) uuuuuu is a printer name on the NAS system
		(2) uuuuuu is a username and ssssss is a nodename

								
	The NASPRINT command sends a file  to  either  SYSTEM,  RSCS
	or  ACXPM  for  routing  to  the  specifed  printer. Printer
	names and  their  owner  processes  are  defined  in  system
	logical name table called LNM_NASPRINT, as in		 

	$ create/name/attr=supersede/par=lnm$system_directory lnm_nasprint
	$ define/sys/tran=term/tab=lnm_nasprint occ1   acxpm
	$ define/sys/tran=term/tab=lnm_nasprint occ2   acxpm_restricted
	$ define/sys/tran=term/tab=lnm_nasprint xlrc   rscs
	$ define/sys/tran=term/tab=lnm_nasprint xocc   rscs
	def/sys/tra=term bitnet_node uoft02				
	def/sys/tra=term/sys nas_printer_node uoft03

	If Uoft03 hangs, repeat the previous command but use UOFT01
								
	creation:						
								
	cc sendvs2						
	link/notrace sendvs2+jan_sys:bitlib/lib			
	cop sendvs2.exe sys$utility:/prot=w:re
	cop sendvs2.exe sys$utility:nas_print.exe/prot=w:re
	hsp :== $sys$utility:sendvs2
	nas*print :== $sys$utility:nas_print
	mc install
	install>sys$utility:sendvs2/priv=(exquota,sysprv,world)
	install>sys$utility:nas_print/priv=(exquota,sysprv,world)
	
								
*/
 
	static char nmsg[] = "NASPRINT file[,file,file...] [printername]" ;
	static char hmsg[] = "HSP file[,file,...] [printername]" ;
	char *s ;
	char junk[20] ;
	char fixargv2[100], *cp_node, *cp_user ;

	if ( *(printer_node_xlate = tranlog(printer_node)) == 0 )
	  printer_node_xlate = printer_link ;
	if ( argc == 0 )
	  then	{
		printf("Please define a foreign command\n") ;
		return ;
		} ;
	for ( s=argv[0]+strlen(argv[0]); *s != ']' && s != argv[0]; s--) ;
	switch (*(++s)) {
	  case 'n':
	  case 'N': switch( argc ) {
		 	case 2: nasprint(argv[1],"") ;
				break ;
			case 3: nasprint(argv[1],argv[2]) ;
				break ;
			default:printf("?Usage: %s\n",nmsg) ;
				break ;
			} ;
		    break ;
	  case 's':
	  case 'S':
	  case 'h':
	  case 'H': switch (argc) {
			case 2: sendvs2(argv[1],"","") ;
				break ;
			case 3: cp_node = strcpy(fixargv2,argv[2]) ;
				while (*cp_node && *cp_node != '@') cp_node++;
				if ( *cp_node )
				  then	{
					cp_user = fixargv2 ;
					*cp_node++ = 0 ;
					sendvs2(argv[1],cp_user,cp_node) ;
					} 
				  else sendvs2(argv[1],argv[2],"") ;
				break ;
			case 4: sendvs2(argv[1],argv[3],argv[2]) ;
				break ;
			default:printf("?Usage: %s\n",hmsg) ;
				break ;
			} ;
		    break ;
	  default:  printf("?Unknown command\n") ;
		    break ;
		} ;
							
}




sendvs2(filename,printer,node)
char *filename,*printer,*node ;
{
	int i,status ;
	char *d,*s,sequence[5],buffer[160],tempname[81],firstfile[81] ;
	char printer_owner[20],*my_rscs_node ;

	s = filename ;
	d = firstfile ;
	while ( *s != 0 && *s != ',' ) *d++ = *s++ ;
	*d = 0 ;
	droppriv() ;
	if ( (infile = fopen(firstfile,"r")) == NULL )
	  then	{
		printf("Can not access %s\n",filename) ;
		return(0) ;
		}
	getpriv() ;
	if ( ((status = incr_seq(sequence)) & 1) == 0 )
	  then	{
		printf("Access to system name table failed %x\n",status) ;
		return(0) ;
		}
	if ( fgets(buffer,80,infile) == NULL )
	  then	{
		printf("Null input file\n") ;
		fclose(infile) ;
		return(0) ;
		}
	  else	fclose(infile) ;

	s = buffer ;
	while ( *s != 0 ) *s++ = toupper(*s) ;
	if (  instr(buffer,strlen(buffer),"JOB (UT",6)
	   || instr(buffer,strlen(buffer),"JOB <UT",6) )
	  then	{
		printf("Please remove the JOB card from your file\n") ;
		return(0) ;
		}

	strcpy(buffer,"//VAXA") ;
	strcat(buffer,sequence) ;
	strcat(buffer," JOB <UT,") ;

	my_rscs_node = tranlog(my_bitnet_node) ;
	if ( *printer == 0 )
	  then	strcat(buffer,",, ") ;
	  else	if ( *node )
	    then {
		strcat(buffer,printer) ;
		strcat(buffer,",") ;
		strcat(buffer,node) ;
		strcat(buffer,", ") ;
		strcpy( (s = malloc(strlen(node)+1)),node) ;
		if ( strcmp(my_rscs_node,upcase(s)) )
		  then	{
			printf("Please route output to %s\n",my_rscs_node) ;
			return(0) ;
			}
		  else ;
		} 
	    else {
		trnprinter(printer_owner,printer) ;
		if (*printer_owner == 0 || printer_access(printer_owner) == 0)
		  then	{
			printf("Unknown printer %s on NAS system\n",printer);
			return(0) ;
			}
		  else	{
			strcat(buffer,printer) ;
			strcat(buffer,",, ") ;
			} ;
		} ;

	strcat(buffer,my_rscs_node) ;
	for ( i=72-strlen(buffer); i > 0; i-- ) strcat(buffer," ") ;
	strcat(buffer,getenv("USER")) ;
	buffer[80] = 0 ;
	upcase( buffer ) ;

	tmpnam(tempname) ;
	if ( ( infile = fopen(tempname,"w") ) == NULL )
	  then	{
		printf("Could not create tempfile\n") ;
		return(0) ;
		}
	fputs(buffer,infile) ;
	fclose(infile) ;
	sprintf(buffer,"SEND %s,%s /CONCAT/PUN/CLAS=A VS2@%s",
		tempname,filename,printer_node_xlate) ;
	status = sendfile( buffer ) ;
	printf("Your job number is VAXA%s\n",sequence) ;
	delete( tempname ) ;
	return( status ) ;
}





nasprint(filename,printer)
char *filename,*printer ;
{
	int i,status ;
	char *d,*s,buffer[160],firstfile[81],printer_owner[20],*dst ;
	struct dsc sendcommand ;
	char user[20] ;

	s = filename ;
	d = firstfile ;
	while ( *s != 0 && *s != ',' ) *d++ = *s++ ;
	*d = 0 ;
	droppriv() ;
	if ( findfile(firstfile) == 0 )
	  then	{
		printf("Can not access %s\n",filename) ;
		return(0) ;
		}
	getpriv() ;

	strcpy(buffer,"SEND ") ;
	strcat(buffer,filename) ;
	strcat(buffer," ") ;
	if ( *printer == 0 )
	  then	strcpy(printer_owner,"system") ;
	  else	{
		trnprinter(printer_owner,printer) ;
		if (*printer_owner == 0 || printer_access(printer_owner) == 0)
		  then	{
			printf("NAS printer %s is unknown\n",printer) ;
			return(0) ;
			} ;
		} ;
	dst = printer_node_xlate ;
	switch( tolower(*printer_owner) ) {
	  case 'r': strcpy(user,"RSCS") ;
		    strcat(buffer,"/CLASS=A/PRINT/DIST=") ;
		    strcat(buffer,printer) ;
		    dst = "UOFT01" ;
		    break ;
	  case 'a': strcpy(user,"ACXPM") ;
		    strcat(buffer,"/CLASS=A/PRINT/DIST=") ;
		    strcat(buffer,printer) ;
		    break ;
	  case 's': strcpy(user,"SYSTEM") ;
		    strcat(buffer,"/CLASS=M/PRINT/DIST=") ;
		    strcat(buffer,getenv("USER")) ;
		    break ;
	  case 't': strcpy(user,"SYSTEM") ;
		    strcat(buffer,"/CLASS=N/PRINT/DIST=") ;
		    strcat(buffer,getenv("USER")) ;
		    break ;
		} ;
	sprintf(buffer,"%s %s@%s",buffer,user,dst);
	upcase( buffer ) ;
	return( sendfile(buffer) ) ;
}






instr(src,len1,pat,len2)
char *src,*pat;
int  len1 ;
register int len2 ;

{
	register char *s1,*s2 ;
	char *s1save,*s2save ;
	int i,size,len2save ;

	s1 = src ;
	s2 = pat ;
	if ((len1==0) || (len2==0)) then return(0);
	size = len1 - len2 ;
	i = 0 ;
	while ( i <= size ) {
	  if ( *s1 == *s2 )
	   then {
		s1save = s1 ;
		s2save = s2 ;
		len2save = len2 ;
		if ( --len2 <= 0 ) then return( i+1 ) ;
		s1++ ; s2++ ;
		while ( len2 != 0 ) {
		  if ( *s1++ != *s2++ ) then break ;
		  len2-- ;
		  }
		if (len2 == 0) then return (i+1) ;
		len2 = len2save ;
		s2   = s2save ;
		s1   = s1save ;
		}
	  i++ ;
	  s1++ ;
	}
	return( 0 ) ;
}
		





#ifndef	LNM$_STRING
#define	LNM$_STRING	2
#define	LNM$_ATTRIBUTES	3
#define	LNM$M_TERMINAL	512
#define	LNM$M_CASE_BLIND 33554432
#endif

union  pointer	{
		int  *intbuf ;
		char *charbuf ;
		} ;

struct itmlst	{
		unsigned short int bufferlength ;
		unsigned short int item_code ;
		union pointer  addr ;
		int  *retlength ;
		} ;

struct itmlst crelist[3], trnlist[2] ;
char defseq[] = "1000" ;

incr_seq(s)
char *s ;
{
	$DESCRIPTOR(seqdesc,"NAS_BATCH_JOB_SEQ") ;
	$DESCRIPTOR(jobdesc,"LNM$JOB") ;
	$DESCRIPTOR(tabdesc,"LNM$SYSTEM_TABLE") ;
	int seqattr,seqlen,seqnum,status ;
	char seqchar[10] ;
	int attr_arg ;

	attr_arg = LNM$M_CASE_BLIND ;
	seqattr = LNM$M_TERMINAL ;
	crelist[0].bufferlength = 4 ;
	crelist[0].item_code	= LNM$_ATTRIBUTES ;
	crelist[0].addr.intbuf	= &seqattr ;
	crelist[0].retlength	= 0 ;
	crelist[1].bufferlength = 4 ;
	crelist[1].item_code	= LNM$_STRING ;
	crelist[1].addr.charbuf	= &seqchar ;
	crelist[1].retlength	= 0 ;
	crelist[2].bufferlength	= 0 ;
	crelist[2].item_code	= 0 ;

	trnlist[0].bufferlength	= 4 ;
	trnlist[0].item_code	= LNM$_STRING ;
	trnlist[0].addr.charbuf	= &seqchar ;
	trnlist[0].retlength	= &seqlen ;
	trnlist[1].bufferlength	= 0 ;
	trnlist[1].item_code	= 0 ;


	status = sys$trnlnm(&attr_arg,&tabdesc,&seqdesc,0,&trnlist) ;
	if ( status == SS$_NOLOGNAM )
	  then	{
		strcpy(seqchar,defseq) ;
		status = sys$crelnm(0,&tabdesc,&seqdesc,0,&crelist) ;
		} ;
	if ( ( status & 1 ) == 0 ) then return( status ) ;
	seqchar[4] = 0 ;
	sscanf(seqchar,"%d",&seqnum) ;
	if ( ++seqnum > 9999 ) then seqnum = 1000 ;
	sprintf(seqchar,"%d",seqnum) ;
	status = sys$crelnm(0,&tabdesc,&seqdesc,0,&crelist) ;
	strcpy(s,seqchar) ;
	return( status ) ;
}





char *tranlog(s)
char *s ;
{
	$DESCRIPTOR(tabdesc,"LNM$SYSTEM_TABLE") ;
	struct dsc name ;
	char *cp ;
	int loglen,status ;
	int attr_arg ;

	cp = malloc( 256 ) ;
	name.addr = s ;
	name.len  = strlen(s) ;
	attr_arg = LNM$M_CASE_BLIND ;
	trnlist[0].bufferlength	= 100 ;
	trnlist[0].item_code	= LNM$_STRING ;
	trnlist[0].addr.charbuf	= cp ;
	trnlist[0].retlength	= &loglen ;
	trnlist[1].bufferlength	= 0 ;
	trnlist[1].item_code	= 0 ;
	status = sys$trnlnm(&attr_arg,&tabdesc,&name,0,&trnlist) ;
	if ( status == SS$_NOLOGNAM || ( status & 1 ) == 0 ) loglen = 0 ;
	*(cp + (loglen&255)) = 0 ;
	return(cp) ;
}




/*	Look up a specifed NAS printer name in the logical name
	table LNM_nasPRINT so we can find out what process owns
	the printer, which will be ACXPM, RSCS or SYSTEM on the
	U of Toledo NAS system (bitnet node UOFT01)
*/

trnprinter(owner,name)
char *owner,*name ;
{
	$DESCRIPTOR(tabdesc,"LNM_NASPRINT") ;
	char lognam[20], *cp, *dp ;
	int loglen,status ;
	struct dsc lname ;
	int attr_arg,i ;

	attr_arg = LNM$M_CASE_BLIND ;
	lname.addr = name ;
	lname.len  = strlen( name ) ;
	trnlist[0].bufferlength	= 20 ;
	trnlist[0].item_code	= LNM$_STRING ;
	trnlist[0].addr.charbuf	= &lognam ;
	trnlist[0].retlength	= &loglen ;
	trnlist[1].bufferlength	= 0 ;
	trnlist[1].item_code	= 0 ;
	status = sys$trnlnm(&attr_arg,&tabdesc,&lname,0,&trnlist) ;
	*owner = 0 ;
	if ( ! ( status == SS$_NOLOGNAM || ( status & 1 ) == 0 )) {
	  for (i=0,dp=owner,cp=lognam; i < (loglen&255); i++) *dp++ = *cp++ ;
	  *dp = 0 ;
	} ;
	return( status ) ;
}
	

/*
	If the printer owner name has '_restricted' in it then disallow
	access by student, whose usernames always start with 'STX'.  We
	really should use a rights identifier.
*/

printer_access(s)
char *s;
{
	char temp[20] ;
	return(!( strncmp("STX",getenv("USER"),3) == 0 &&
	          instr(lowcase(strcpy(temp,s)),strlen(s),"_restrict",9) )) ;
}
	  
	


static long int privmask[2] ;

getpriv()
{
	privmask[0] = (2<<(PRV$V_EXQUOTA-1))
		    + (2<<(PRV$V_SYSPRV-1))
		    + (2<<(PRV$V_WORLD-1)) ;
	privmask[1] = 0 ;
	return( sys$setprv(1,&privmask,0,0) ) ;
}

droppriv()
{
	privmask[0] = (2<<(PRV$V_EXQUOTA-1))
		    + (2<<(PRV$V_SYSPRV-1))
		    + (2<<(PRV$V_WORLD-1)) ;
	privmask[1] = 0 ;
	return( sys$setprv(0,&privmask,0,0) ) ;
}


sendfile(s)
char *s ;
{
	struct dsc {
			long int len ;
			char *addr ;
		   } ;
	struct dsc sendcommand ;

	sendcommand.len = strlen(s) ;
	sendcommand.addr = s ;
	return( send_rscs(&sendcommand) ) ;
}


char *upcase(s)
char *s ;
{
	char *cp ;
	cp = s ;
	while ( *cp ) { *cp = toupper(*cp) ; cp++ ; } ;
	return(s) ;
}

char *lowcase(s)
char *s ;
{
	char *cp ;
	cp = s ;
	while ( *cp ) { *cp = tolower(*cp) ; cp++ ; } ;
	return(s) ;
}


findfile(s)
char *s ;
{

/*	Verify that at least one file will match the filename passed	*/
/*	so that we can have some assurance that the batch job we submit	*/
/*	to do the actual send will succeed.				*/

	char fname[256] ;
	struct dsc$descriptor_s srcbuf ;
	struct dsc$descriptor_d resbuf ;
	int context,status ;

	$DESCRIPTOR(def_spec,"") ;

	context = 0 ;
	srcbuf.dsc$w_length = strlen( s ) ;
	srcbuf.dsc$b_class  = DSC$K_CLASS_S ;
	srcbuf.dsc$b_dtype  = DSC$K_DTYPE_T ;
	srcbuf.dsc$a_pointer = s ;

	resbuf.dsc$w_length = 0 ;
	resbuf.dsc$b_class  = DSC$K_CLASS_S ;
	resbuf.dsc$b_dtype  = DSC$K_DTYPE_D ;
	resbuf.dsc$a_pointer = 0 ;
	
	status = lib$find_file(&srcbuf,&resbuf,&context,&def_spec) ;
	lib$find_file_end(&context) ;
	return( status & 1 ) ;
	
}


