SRI-NOSC/ncpp/tel-u/mkcharset.c

Compare this file to the similar file:
Show the results in this format:

#
#include "mapping.h"


/*


/* integer decs */

int nchars 0;			/* number of characters read from tty */
int savetty [3];
int temptty [3];

/* char decs */

char netbuf[128];		/* buffer to fiddle with characters */
char *commarr[]
{
	"end",			/* end this program */
	"bye",
	"help",			/* prints help file */
	"define",			/* enter character mapping */
	"save",			/* save the current char set */
	"load",			/* load a character set */
	"prt",			/* print character set */
	  0
};

/* associated parameter array for the above commands */
char *nextparam 0;
char *netbufp;
char *params[20];
char char_set_name[40];		/* holds current character set name */
char bitmask[]			/* returns two to the power of the index */
{
	01,02,04,010,020,040,0100,0200
};

/* structure decs */


/**/
main(argc,argv)
char *argv[];
{

	register char *charp;
	register char *endp;
	register int  i;
	extern bye();

	/* synthesize home directory and possible char set file */
	endp = colon( charp = gethomedir( netbuf ) );
	*--endp = 0;		/* make a null termed string */
	/* now that we got the home dir bring on the troops */
	strmove( "/character_set",strmove( charp,char_set_name )+1 );
	/* load it if it is there */
	load_char_set();

	/* main loop */
	write (1, "* ", 2);			/* let him know we are here */
	gtty (0,savetty);
	gtty (0,temptty);
	temptty [2] =| RAW;
	stty (0,temptty);
	while (1) {
		netbufp = netbuf;
		nchars = 0;
		if (!buffer_full_line()) continue;
		command_processor();
		write (1, "* ",2);
		}
}

/*
	C O M M A N D _ P R O C E S S O R	--  init nexparam for getoken
						    call indicated command thru
						    decode_command

*/

command_processor()
{

	register index;
	extern (*decode_command[])();

	if( *(nextparam=netbuf) == flagchar) ++nextparam;
	if ((index = getcomm (getoken ())) >= 0)
	(*decode_command [index]) ();

}

/*

	G E T C O M M		-- Scans command array for match between
				   command user typed and available commands.
				   Returns index into commarr if match found
				   otherwise 0
*/

getcomm(strpp)
char *strpp;
{

	register char *comp;	/* pointer to commarr */
	register char *strp;	/* holds strpp for speed */
	register index;		/* keeping track of index into commarr */
	int	length;		/* length of token */
	int	candidate;	/* candidate index */

	/* init some things */
	strp = strpp;
	index = 0;
	candidate = 0;
	length = 0;

	if (strp == 0) return (-1);
	while (*strp++) ++length;		/* length of token */
	strp = strpp;				/* reset it */

	while( comp = commarr[ index++ ] )
		if( compar( comp,strp,length ) == 0 )
			if (candidate) {
				printf ("Command string not unique.\r\n");
				return (-1);
				}
			else candidate = index;
	return (candidate);
}

/*
	G E T O K E N	--  looks at the command string in netbuf, and starting
			    from nextparam( global ) will scan until finds member
			    of terminators, once found, makes the string null 
			    terminated, and returns the beginning of the string
			    if the first char found was a terminator returns 0
*/

char *getoken()
{

	register char *inp;
	register char *startp;

	startp = inp = nextparam;	/* point to the beginning of the string */

	while( *inp == ' ' ) ++inp;	/* scan off leading blanks */
	startp = inp;			/* point at beginning of token */
	while( !setmember( *inp," \r\n") ) ++inp;	/* while not in set bump inp */

	/* if we found something update things and return starting pointer */
	if( inp != startp )
	{
		*inp++ = NULL;		/* make a null string */
		nextparam = inp;	/* update for next time */
		return( startp );	/* return beginning of string */
	}
	else
		return( 0 );		/* nothing found return zero */
}

/*
	E X E C U T E 		--  user typed a command so try to start
				    up a unix file by that name. First look
				    in users directory then in /bin then in
				    /usr/bin.  If not there at all
				    just exit.  The parent waits for the off-
				    spring to exit.

*/

execute()
{

	int status;			/* status of child process */
	register int startid;		/* id of forked process */

	printf("%c\r\n",flagchar);

	startid = fork();

	if( startid < 0 )
	{
		printf("%c\n",flagchar);
		return;
	}

	if( startid == 0 )
	{
		/* here for offspring */
		/* if first char is flag char ignore it */
		if( *(netbufp = netbuf) == flagchar )
			netbufp++;

		/* unparse first command so shell can use glob */
		*--nextparam = ' ';
		*++nextparam = 0;
		execl("/bin/sh","sh","-c",netbufp,0);
		exit(0);
	}
	else	/* here for parent */
	{
		while (wait(&status) != startid);
		printf("%c\n",flagchar);
	}
}


/*
	B Y E	--   Called to exit the program 
		     resets the ttybits 
		     call exit
*/

bye()
{

	stty (0,savetty);
	exit();
}

/*

	L O A D _ C H A R _ S E T		load the current character
						set
*/
load_char_set()
{
	int fid;

	if( (fid=open( char_set_name,0 )) >= 0 )
	{
		read( fid,maptab,SVESIZE );
		printf("%s\r\n",char_set_name);
	}
}

/*



	S A V E _ C H A R _ S E T	save the current character set 
*/
save_char_set()
{

	int fid;

	if( (fid=creat( char_set_name,0600 )) >= 0 )
	{
		/* read everything in the character pool see tty section */
		write( fid,maptab,SVESIZE );
		printf("%s\r\n",char_set_name);
	}
}
/* 

	P R T _ C H A R _ S E T			print any mapped characters
*/
prt_char_set()
{
	register char *cp;
	register char *str;
	register char *c;

	printf("Mapped characters are:\r\n");
	cp = maptab;
	while( cp < &maptab[ 128 ] )
	{
		if( *cp < 0 )		/* this mapped */
		{
			str = &stringtab[ definetab[ (*cp&0177) ]];
			c = cp - &maptab[0];
			if( c < ' ' )		/* this control char */
				printf("^%c      ",c | 0100);	/* make it ^<char>*/
			else
				printf(" %c      ",c);	/* normal */
			write( 1,str,strlen( str ));
			printf("\r\n");
		}
		++cp;
	}
	printf("All Others are un-mapped\r\n");
}
/*
	G E T C		--   returns a character from the buffered structure
			     'input'.  
				if doing define expansion(single level for now)
					return define expansion char 
				if no chars buffered then buffer some
					if read error return -1
				decrement num of chars in queue
				return char incrementing pointer
*/

getc()
{
	register int no_slash;
	char c;

	no_slash = 1;
	/* count zero? */
	loop: while (input.cnt == 0)
	{
		if( (input.cnt=read(0,input.nextc = &input.data[0],80)) < 0 )
			return( -1 );		/* done return error */
	}
	--input.cnt;			/* say one less around */
	c = *input.nextc++;
	if (no_slash && c == '\\') {
		no_slash = 0;
		goto loop;
		}

	++nchars;
	*netbufp++ = c;
	return (c);
}

/* 






	B U F F E R _ F U L L _ L I N E		--  keep getting characters
						    until endchar found
*/
buffer_full_line()
{

	register char c;
	while ((c = getc()) != endline)
	{
		if( c == backsp )
		{
				netbufp =- 2;
				nchars =- 2;
		}
		if( c == linedel  | nchars <= 0 )
		{
			netbufp = netbuf;
			nchars = 0;
			if (c == linedel) printf ("\r\n");
			return (0);
		}
	}
	return (nchars);
}

/*

	E N T E R _ D E F I N E _ T A B	--  change the mapping for the char
					    requested to the string requested
*/

enter_define_tab()
{

	register length;	/* length of str */
	register char c;	/* character to be mapped */
	register char *str;	/* pointer to mapped string */
	char echochar;		/* to decide if char is to be echoed */

	/* get the character to be mapped ( dont run it thru transaltion ) */
	printf("Character to be mapped: ");
	if( (c = getc()) < ' ' )
		printf("^%c\r\n",0100|c);
	else
		printf("%c\r\n",c);
	/* should echo bit be set ?? */
	printf ("Should the string be echoed? ");
	echochar = getc();

	/* build the translation string */
	printf("Enter String (end with cntrl c)\r\n");
	restart:
		str = netbuf;		/* use global netbuf to hold string */
		while( (*str = getc()) != 003 )
		{
			if( *str == 010 )	/* backspace */
				str =- 2;
			else
			if( *str == 0100 ) 	/* line delete @ */
				goto restart;
			++str;			/* bump to next char pos */
		}
	printf("\r\n");
	*str++ = 0;				/* make a null termed string */
	str = netbuf;				/* reinit str pointer */

	/* single character case */
	if( (length = strlen( str )) == 2 )	/* strlen includes the null */
	{
		maptab[c] = (*str & 0177);	/* then just store in maptab */
		return;
	}

	/* see if we have room to store the string and define pointer */
	if( nxtdefentry < NDEFINESIZE && curstrp+length <  NSTRINGS  )
	{
		/* yes have room make define entry */
		definetab[ nxtdefentry ] = curstrp;	/* store pointer to first char */
		str = strmove( str,&stringtab[curstrp] ) + 1;	/* move and update current free location */
		*str++ = 0;				/* make null str */
		curstrp = str - stringtab;		/* update to next free index */
		maptab[ c ] = 0200 | nxtdefentry;	/* make maptab knowledgeable */
		++nxtdefentry;				/* update next free entry */
		if (echochar = 'y') set_bit (c,echomask);
	}
	else
		printf(" Out of Define Space \r\n");
}


/*
	C O M P A R		Compares strings s1 to s2 for either nchars or
				either string contains a null.  If s1 != s2
				returns pointer to char in s1 at which point
				compare failed.  If s1 == s2 returns 0

*/


compar( s1,s2,n )
char *s1;
char *s2;
int n;
{

	register char c1,c2;

	while( (c1 = *s1++) == (c2 = *s2++) && (n-- > 0) )
		if( n == 0 || c1 == 0 || c2 == 0 )
			return( 0 );
	return( --s1 );
}
/*

	S T R M O V E		Copies str1 to str2 until str1 contains a null

*/

char *strmove( str1,str2 )
char *str1;
char *str2;
{

	register char *src;
	register char *dest;

	src = str1;
	dest = str2;

	while( *dest++ = *src++ );

	return( dest-2 );
}

/*





	S T R L E N	--   return the number of characters in the null
			     terminated string passed.  The count returned
			     includes the null character at the end of the
			     string
*/

strlen( str )
char *str;
{

	register char *strp;	/* for speed */
	register  int cnt;	/* for the number of chars */

	strp = str;
	cnt = 0;

	while( *strp++ ) ++cnt;
	return( ++cnt );
}
/*
	P R T F I L E		Prints the file whose name is passed

*/
prtfile()
{
	register char *charp;
	register int  cnt;
	char buf[80];		/* somewhere to put the data */
	int fid;		/* file id of opened file */

	printf("\r\n\r\n");	/* space out a bit */

	if( (fid = open("/etc/mapper_help",0 )) >= 0 )
	{
		while(cnt=read(fid,buf,80))
			write (1,buf,cnt);
		close(fid);
	}
	else
		printf ("Can not open help file.\n");

	printf("\r\n\r\n");
}

/*
	S E T M E M B E R	--  looks in the set passed for the member
				    if found will return the member else
				    zero

*/

char setmember( member,set )
char member;
char *set;
{

	register char mem;	/* holds member for speed */
	register char *setp;	/* holds set for speed */

	setp = set;
	mem = member;

	/* while there are members of set - null cant be a member */
	while( *setp )
		/* member this one? */
		if( mem == *setp++ )
			return( mem );

	/* no matches return 0 */
	return( 0 );
}

/*

	B I T _ O N			takes care of checkin whether a bit is on
					bit bitnum in map bitstr
*/

bit_on( bitnum,bitstr )
int bitnum;
char *bitstr;
{
	return( bitmask[ bitnum&07 ] & bitstr[ bitnum>>3 ] );
}

/*


	S E T _ B I T			sets bit bitnum in map bitstr

*/

set_bit( bitnum,bitstr )
int bitnum;
char *bitstr;
{

	bitstr[ bitnum>>3 ] =| bitmask[ bitnum&07 ];
}



/*


	R E S E T _ B I T		reset bit bitnum in map bitstr

*/

reset_bit( bitnum,bitstr )
int  bitnum;
char *bitstr;
{
	bitstr[ bitnum>>3 ] =& ~bitmask[ bitnum&07 ];
}

/*

	C O L O N			scans from ptr passed to a colon
					returns next char passed colon

*/
char *colon( buf )
char *buf;
{

	register char *bufp;

	bufp = buf;
	while( *bufp++ != ':' );
	return( bufp );
}
/*

	G E T H O M E D I R		based on the current UID, searches the
					password file for a match, returns a
					pointer into the buf passed which
					is the start of the home directory
					for the user.  Used to build a path-
					name for the character set file
*/

char *gethomedir( buf )
char *buf;
{

	extern fin;
	register char *bufp;
	register int  uid;
	register char c;
	int     curuid;

	/* open the password file */
	if( (fin = open( "/etc/passwd",0 )) < 0 )
		return( 0 );

	curuid = (getuid())&0377;	/* get hard user id */
	while( 1 )
	{
		bufp = buf;		/* point to beginning of area */
		/* get a full line */
		while( (c=getchar()) != '\n' )
		{
			/* get EOF ? */
			if( c <= 0 )
				return( 0 );	/* return failure */
			*bufp++ = c;
		}
		/* space over to uid part of password entry */
		bufp = colon( colon( buf ) );
		/* turn ascii uid into binary */
		uid = 0;
		while( *bufp != ':' )
			uid = uid*10 + *bufp++ - '0';
		/* match current uid ? */
		if( uid == curuid )
			/* a winnah */
			return( colon( colon( ++bufp )));
	}
}
/*
* command array for procedure addresses to be called in response to the
   above command strings
*/
int (*decode_command[]) ()
{
	&execute,			/* the default - exec unix command */
	&bye,				/* exit this program restoring tty */
	&bye,
	&prtfile,			/* print the help file */
	&enter_define_tab,		/* make a define mapping */
	&save_char_set,			/* save the current char set */
	&load_char_set,			/* load the character set */
	&prt_char_set,			/* print character set */
	     0
};