/*
 *  MBUTIL.C -  Utility functions.
 *                                 Mar.23,1991
 */

#include "mb.h"
#include "mbexp.h"
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>

#if	SHARE				/* AY-880609 */
#include <sys/locking.h>
#endif

#if	!(XENIX|UNIX|BSD)
#include <signal.h>	/* 880326 */
#define BADSIG (int (*)())-1
#endif

extern int errno; /* AY-880326 */
extern char *strchr();	/* AY-881120 */
int	trace_tnc;		/* AY-880619 */

static char *onoff[2] = { 
	"off", "on" };

/*
 *  Sort 'em.
 */

sort(base, n, w, t)
char *base;
int   n;
int   w;
char *t;
{
	register int i;
	register int j;
	register int g;
	char *p1, *p2;

	for (g = n/2; g; g /= 2)
		for (i = g; i < n; i++)
			for (j = i - g; j >= 0; j -= g)
			{
				p1 = base + (w * j);
				p2 = base + (w * (j + g));

				if (strncmp(p1, p2, w) <= 0) break;
				memcpy(t, p1, w);   /* these three line by AY-870918 */
				memcpy(p1, p2, w);
				memcpy(p2, t, w);
                                /*      memcpy(t, p1, ln_call);
                                        memcpy(p1, p2, ln_call);
                                        memcpy(p2, t, ln_call);     */
			}
}

/*
 *  Save remote sysop command, for later execution.
 */

savecmd()
{
	strcpy(scmd, port->line);
	s_param setbit s_cmd;
	port->msg = mdone;
}

/*
 *  EP command, change port parameters.
 */

edport()
{
	register PORTS *p;
	register int i;

	if ((p = findport(*port->fld[1])) is NULL) { 
		port->msg = mnport; 
		return; 
	}

	if (p->priv & p_bbs) i = 1; 
	else i = 0;
	sprintf(tmp->scr, "BBS Only is %s, B to turn %s.\n",
	    onoff[i], onoff[1-i]);
	outstr(tmp->scr);

	if (p->priv & p_dnload) i = 1; 
	else i = 0;
	sprintf(tmp->scr, "Download allowed is %s, D to turn %s.\n",
	    onoff[i], onoff[1-i]);
	outstr(tmp->scr);

	if (p->priv & p_gate) i = 1; 
	else i = 0;
	sprintf(tmp->scr, "GateWay allowed is %s, G to turn %s.\n",
	    onoff[i], onoff[1-i]);
	outstr(tmp->scr);

	if (p->priv & p_ilcal) i = 1; 
	else i = 0;
	sprintf(tmp->scr, "Exclude Illegal call is %s, I to turn %s.\n",
	    onoff[i], onoff[1-i]);
	outstr(tmp->scr);

	if (p->priv & p_mon) i = 1; 
	else i = 0;
	sprintf(tmp->scr, "Monitoring allowed is %s, M to turn %s.\n",
	    onoff[i], onoff[1-i]);
	outstr(tmp->scr);

	if (p->priv & p_sysop) i = 1; 
	else i = 0;
	sprintf(tmp->scr, "Remote Sysop allowed is %s, R to turn %s.\n",
	    onoff[i], onoff[1-i]);
	outstr(tmp->scr);

	if (p->priv & p_upload) i = 1; 
	else i = 0;
	sprintf(tmp->scr, "Upload allowed is %s, U to turn %s.\n",
	    onoff[i], onoff[1-i]);
	outstr(tmp->scr);

	sprintf(tmp->scr, "Timeout is %d, T n to change.\n", p->ctime);
	outstr(tmp->scr);

	sprintf(tmp->scr, "%d digipeats allow on connect, C n to change.\n", p->ndigi);
	outstr(tmp->scr);

	sprintf(tmp->scr, "Forwarding time is %d, F n to change.\n", p->fwdmin);
	outstr(tmp->scr);

	sprintf(tmp->scr, "Allowed command errors are %d, E n to change.\n", p->errmax);
	outstr(tmp->scr);

	outchar('>');
	getcmd(); 
	i = atoi(port->fld[1]);
	if (port->mode & (discon | timeout)) return;
	switch(port->opt1)
	{
	case 'B' : 
		p->priv flipbit p_bbs;     
		break;
	case 'C' : 
		p->ndigi = i;              
		break;
	case 'D' : 
		p->priv flipbit p_dnload;  
		break;
	case 'E' : 
		p->errmax = i;             
		break;
	case 'F' : 
		p->fwdmin = i;             
		break;
	case 'G' : 
		p->priv flipbit p_gate;    
		break;
	case 'I' : 
		p->priv flipbit p_ilcal;   
		break;
	case 'M' : 
		p->priv flipbit p_mon;     
		break;
	case 'R' : 
		p->priv flipbit p_sysop;   
		break;
	case 'T' : 
		p->ctime = i;              
		break;
	case 'U' : 
		p->priv flipbit p_upload;  
		break;
	default  : 
		;
	}
}

/*
 *  ES command, change system parameters.
 */

chgparam()
{
	register int i;

	if (s_param & s_page) i = 1; 
	else i = 0;
    sprintf(tmp->scr, "SYSOP page bell is [%s].\nType \"B\" to turn [%s].\n",
	    onoff[i], onoff[1-i]);
	outstr(tmp->scr);

	if (s_param & s_kill) i = 1; 
	else i = 0;
    sprintf(tmp->scr, "Kill_after_forward is [%s].\nType \"K\" to turn [%s].\n",
	    onoff[i], onoff[1-i]);
	outstr(tmp->scr);

	if (s_param & s_fkill) i = 1; 
	else i = 0;
    sprintf(tmp->scr, "Kill_F_after_forward is [%s].\nType \"M\" to turn [%s].\n",
	    onoff[i], onoff[1-i]);
	outstr(tmp->scr);

	if (s_param & s_svc) i = 1; 
	else i = 0;
    sprintf(tmp->scr, "Generate_service_msg is [%s].\nType \"S\" to turn [%s].\n",
	    onoff[i], onoff[1-i]);
	outstr(tmp->scr);

	/* AY-871020 */
	outstr("\nType \"X\" for edit expanded next parameters\n");
    outstr("+--------------------------+--------------------------+\n");
	sprintf(tmp->scr, "| %-25s|%25s |\n", "Editor", edname);
	outstr(tmp->scr);
    outstr("+--------------------------+--------------------------+\n");
	sprintf(tmp->scr, "| %-25s|%25s |\n", "Trace TNC",
        (trace_tnc & 1) ? "Yes" : "No");
    outstr(tmp->scr);
	outstr("+--------------------------+--------------------------+\n");
	sprintf(tmp->scr, "| %-25s|%25s |\n", "Mean-Time is:", mean_time);
	outstr(tmp->scr);
/*
        outstr("+--------------------------+--------------------------+\n");
	sprintf(tmp->scr, "| %-25s|%25s |\n", "Shell name is", shell_name);
	outstr(tmp->scr);
*/
        outstr("+--------------------------|--------------------------+\n");
	sprintf(tmp->scr, "| %-25s|%25s |\n", "List Kanji Title Msgs",
	    (check_kanji_title & 1) ? "Yes" : "No");
	outstr(tmp->scr);
#if	(XENIX|UNIX|BSD)
        outstr("+--------------------------|--------------------------+\n");
        sprintf(tmp->scr, "| %-25s|%25s |\n", "Shell name is", shell_name);
        outstr(tmp->scr);
	outstr("+--------------------------|--------------------------+\n");
	sprintf(tmp->scr, "| %-25s|%25s |\n", "Kill after fwd to mailer",
	    (kill_after_m & 1) ? "Yes" : "No");
	outstr(tmp->scr);
#endif
	outstr("+--------------------------|--------------------------+\n");
	/* AY-871020 (end) */

        outstr("[B,K,M,S,X]Cmd?>");
	getcmd();
	if (port->mode & (discon | timeout)) return;
	switch(port->opt1)
	{
	case 'B' : 
		s_param flipbit s_page;  
		break;
	case 'K' : 
		s_param flipbit s_kill;  
		break;
	case 'M' : 
		s_param flipbit s_fkill; 
		break;
	case 'S' : 
		s_param flipbit s_svc;   
		break;
	case 'X' : 
		editenv(); 
		break;
	default  : 
		;
	}
}

/*
 *  Screen paging.
 */
char *pausemsg;
static char *pghdr = NULL;
static short lnmax;
static short lncnt;

/*
 *  If local console, pause until user types a character.
 *  Return the character.
 *  If not local console, just return a blank.
 */

static /* AY-881004 */
char pause()
{
	register char t;

        if ((port->mode is local) and isatty(1) and isatty(0) )  /* MAY5,90 */
	{
		prtx(pausemsg);
		t = inchar();
		outchar('\n');
		return toupper(t);
	}
	return ' ';
}

/*
 *  Start screen pagin.
 */

pgst(cp)
char *cp;
{
	if ((pghdr = cp) is NULL) lnmax = 23; 
	else lnmax = 22;
	lncnt = lnmax;
}

/*
 *  Pause if full screen.
 */

char pgck()
{
/*	lncnt -= (strlen(tmp->scr) / 79); /* AY-871027 */
	if (--lncnt > 0) return ' ';      /* AY-871030 */
	lncnt = lnmax;
	return pause();
}

/*
 *  Put out header if top of screen.
 */

pghd()
{
	if (lncnt is lnmax) if (pghdr isnt NULL) outstr(pghdr);
}

/*
 *  Pause if required at last line.
 */

pgdn()
{
	if (lncnt isnt lnmax) pause();
}

/*
 *  Print "no such file" message, and file name.
 */

nofile(c)
char *c;
{
	prtx(mnfile); 
	outstr(c); 
	outchar('\n');
}

/*
 *  Memory allocation problem, just plain quit.
 */

errall()
{
	outstr("Not enough memory\n");
	exit (0);
}

/*
 *  Is this a callsign?
 */

iscall(call)
char call[ln_call];
{
        register short i, ld, ls, nd, ns;
        int ch ;
        nd = ns = 0;                                    /* Dec1,89 */
        for (i = 0; (i < ln_call) and (call[i] isnt ' ') and call[i]; i++)
	{
                ch  = call[i];                  /* Nov.21,89 */
                ld  = isdigit (ch) ;
                ls  = isalpha(ch);
                if (!(ld or ls)) return false ; /* Not digit nor alpha */
                if (ls)
			ns++;
		if (ld) {
                        if (ns > 2) return false ; /* Feb11,90 */
                        nd++;
			ns = 0;
		}
	}
	return (((i > 3) and ((nd is 1) or (nd is 2)) and !ld) and (ns <= 3));
}

#if !(UTNCV_NO & MTNCV_NO & J_NO)
/*
 *  Print list of ports and port names.
 */

shports()
{
	register PORTS *p;

	sprintf(port->line, "Use %c and port ID:\n", port->opt1);
	outstr(port->line);
	for (p = porthd; p isnt NULL; p = p->next)
	{
		sprintf(port->line, "%c%c  %s\n", port->opt1, p->id, p->name);
		outstr(port->line);
	}
}
#endif

PORTS *findport(pid)
char pid;
{
	register PORTS *p;

	for (p = porthd; p isnt NULL; p = p->next) if (p->id is pid) return p;
	return NULL;
}

/*
 *  Is it?
 */

iseof(cp)
char *cp;
{
	return match(cp, "*** EOF\n");
}

/*
 *  Uppercase a string.
 */

uc(p)
char *p;
{
	for (; *p; p++) if (islower(*p)) *p = toupper(*p);
}

/*
 *  Remove new line from end of string.
 */

remnl(p)
char *p;
{
#if	(XENIX|UNIX|BSD)
	for (; *p; p++)
		if ((*p is '\n') || (*p is '\r')) { 
			*p = '\0'; 
			return; 
		}
#else
        for (; *p; p++) {
                if (*p is '\n') {
                        *p = '\0';
                        return;
                }
                if ( (*p > '\0') and (*p < ' ')) *p = ' ' ; /* Dec.5,89 */
	}
#endif
}

/*
 *  Parse trailing ssid from call.
 */

pcall(c, p)
char *c;
char *p;
{
	register short i;

	/*
 *  Blank fill the target buffer.
 */

	fill (c, ' ', ln_call);

	/*
 *  Ignore leading spaces.
 */

	while (*p and (*p is ' ')) p++;

	/*
 *  Copy the call from the string into the call buffer.
 */

	for (i = ln_call; i and *p; i--)
	{
		if (*p <= ' ') return 0;
                if (*p is '.') return 0;     /* Feb11,90 */
		if (*p is '-') return atoi(++p);
		*c++ = *p++;
	}
	if (*p++ is '-') return atoi(p); 
	else return 0;
}

/*
 *  Is the string a number?
 */

num(p)
char *p;
{
	for (; *p; p++) if (!isdigit(*p)) return false;
	return true;
}

/*
 *  "Output, no blanks".
 */

outnb(p, n)
char *p;
short n;
{
	while (n--) switch (*p)
	{
	case ' ' :
	case '\n' :
	case '\0' : 
		return;
	default: 
		outchar(*p++);
	}
}

/*
 *  Print a number right justified in a fixed width field.
 */

outnr(i, n)
int   i;  /* The number to print */
short n;  /* Field width */
{
	char num[7];

        sprintf (num, "%-6u", i); /* d -> u 5/13 */
	outnb (num, n);
}

/*
 *  For building the "Mail for:" beacon text.
 *  For now, it is hardwired.
 */

outfwd()
{
}

/*
 *  Display software version.
 */

prtver()
{
	outstr(ver); 
	outchar('\n');
}

/*
 *  Print a string, expanding the "$" fields.
 */

prtx(p)
char *p;
{
#if !DOMAIN_NO  /* AY-881125 */
extern int domainok;
extern char domain[];
#endif
	struct tm *t, *gmtime(), *localtime();
	struct stat statbuf;
        char bbuf[10] ;

	if (strchr(p, '$') == NULL) {
		outstr(p);
		return;
	}
	statbuf.st_ctime = 0;
	for (; *p; p++) {
		if (*p isnt '$') outchar(*p);

		else switch (*(++p)) {
		case 'A' : 
#if !DOMAIN_NO  /* AY-881125 */
                  /*june2,1991 change
                        if (domainok && port->mmhs->unu2 && domain[0])
				outstr(domain);
                  */
                        if (port->mmhs->unu2 && domain[0])
                                if (domainok) outstr (domain);
                                else {  pcall (bbuf,domain);
                                        outnb (bbuf, ln_call) ;
                                }
			else
				outnb(port->mmhs->bbs, ln_call); 
#else
			outnb(port->mmhs->bbs, ln_call); 
#endif
			break;
		case 'B' : 
			outchar(port->mmhs->type); 
			break;
		case 'C' : 
			outnr(mfhs->next_msg, 5); 
			break;
		case 'D' : 
			outstr(l_date); 
			break;
		case 'E' : 
			outfwd(); 
			break;
		case 'F' : 
			outstr(port->lport->name); 
			break;
		case 'G' : 
			outnb(port->mmhs->to, ln_call); 
			break;
		case 'H' : 
			p++; 
			break;
		case 'I' : 
			outnb(port->user->handle, 12); 
			break;
		case 'J' :
			if (!statbuf.st_ctime) {
                             sprintf(tmp->scr, "%s%u", msgdir, port->mmhs->number);
                             stat(tmp->scr, &statbuf);       /* CHANGED SMC %s/%u -> %s%u */
                             if (matchn(mean_time, "GMT", 3))
                                     t = gmtime(&statbuf.st_ctime);
                              else
                                     t = localtime(&statbuf.st_ctime);
			}
			sprintf(tmp->scr, "%02d%02d%02d", t->tm_year, t->tm_mon + 1, t->tm_mday);
			outnb(tmp->scr, ln_date); 
			break;
			break;
		case 'K' :
			if (!statbuf.st_ctime)
			{
                             sprintf(tmp->scr, "%s%u", msgdir, port->mmhs->number);
                             stat(tmp->scr, &statbuf);       /* CHANGED SMC %s/%u -> %s%u */
                             if (matchn(mean_time, "GMT", 3))
                                     t = gmtime(&statbuf.st_ctime);
				else
                                     t = localtime(&statbuf.st_ctime);
			}
			sprintf(tmp->scr, "%02d%02d", t->tm_hour, t->tm_min);
			outnb(tmp->scr, ln_time); 
			break;
			break;
		case 'L' : 
			outnr(mfhs->next_msg - 1, 5); 
			break;
		case 'M' : 
			outnr(port->mmhs->number, 5); 
			break;
		case 'N' : 
			outnr(mfhs->count, 4); 
			break;
		case 'O' : 
			outnb(cport->user->call, ln_call); 
			break;
		case 'P' : 
			outnb(port->mmhs->from, ln_call); 
			break;
		case 'Q' : 
			outstr(qth); 
			break;
		case 'R' : 
			outnb(port->rcall, ln_call); 
			break;
		case 'S' : 
			outnb(port->lport->user->call, ln_call); 
			break;
		case 'T' : 
			outnb(l_time, ln_time); 
			break;
		case 'U' : 
			outnb(port->user->call, ln_call); 
			break;
		case 'V' : 
			outstr(ver); 
			break;
		case 'W' : 
			outnb(port->lport->user->handle, 12); 
			break;
		case 'X' : 
			outnb(port->user->date, ln_date); 
			break;
		case 'Y' : 
			outnb(port->user->time, ln_time); 
			break;
		case 'Z' : 
			outnr(port->user->msg_number, 5); 
			break;
		case 's' : 
			outnb(port->lport->user->handle, 12); 
			break;
		default  : 
			outchar(*p);
		}
	}
}

/*
 *  Write random record.
 */
write_rec(fid, rec, buffer)
int fid;
int rec;
char buffer[];
{
long lseek();
long offs;

#if !(XENIX|UNIX|BSD)	/* AY-881011 */
#define die(n) done()
#endif

	offs = (long)rec * (long)RECSIZE;
	if (lseek(fid, offs, 0) == -1)
		{ perror("write_rec"); fprintf(stderr, "\r"); die(1); }

	if ((write(fid, buffer, RECSIZE) is RECSIZE) == -1)
		{ perror("write_rec2"); fprintf(stderr, "\r"); die(1); }
	
	return(1);
}

/*
**  Read random record.
*/

read_rec(fid, rec, buffer)
int fid;
int rec;
char buffer[];
{
	long lseek();
	long offs;

	offs = (long)rec * (long)RECSIZE;
	lseek(fid, offs, 0);
	return (read(fid, buffer, RECSIZE) is RECSIZE);
}

/*
 *  Fill buffer with characters from the current input,
 *  until CR or buffer overflow. Terminate buffer with
 *  '\0', thus making it a string.
 *  Translate \r to \n.
 *  Ignore \n.
 *  Deal with backspace and things like that.
 *  Set flags for timeout and disconnect.
 */
#if (XENIX|UNIX|BSD)	/* AY-880803 */
getdat()
{
register unsigned char *cp;
register unsigned char ch;
register unsigned rest;	/* AY-880501 */
register PORTS *p;

	p = port;

	catchalarm();
	if((p->mode & idle) and (p->dev is p_tnc))
		alarm(2);
	else
		alarm((unsigned)p->ctime);
	p->flags setbit p_dotmr;
	cp = p->line;

	while (true) {
		if (p->dev isnt p_console)
			while(!instat()) {
				ioport(cport);
				if (instat()) {
					ch = inchar();
					if (ch is achar) {
						alarm(0);
						p->mode = forced; 
						ioport(p);
						return true;
					}
					if (ch is tchar) {
						alarm(0);
						p->flags setbit p_opreq; 
						ioport(p);
						return true;
					}
				}
				ioport(p);
				if (!(rest = alarm(0))) {
					if (!(p->mode & idle))
						p->mode = timeout;
					return true;
				} else
					alarm(rest);
			}

		*cp = inchar();

/*
 *  Got a character, deal with it.
 */

		if ((cp is (p->line + linelen - 2)) or (*cp is '\r')) {
/*
 *  Got a whole line. Either buffer full, or character is CR.
 */
			alarm(0);
			if (*cp is '\r') *cp = '\n';
			cp++; 
			*cp = '\0';

			if (p->flags & p_echo) outchar('\n');

			if (isdis(p->line)) {
				if (!(p->mode & idle)) p->mode = discon;
				return true;
			}

			if (isreq(p->line)) {
				p->flags setbit p_req;
				pcall(p->rcall, p->line + 20);
				p->flags clrbit p_dotmr;
				return false;
			}
			return true;
		}

/*
 *  Not end of line.
 *  Stuff the character in the buffer.
 *  Handle some control characters. Ignore some.
 */

		switch(*cp) {
		default	: 
			if (p->flags & p_echo) outchar(*cp); 
			cp++; 
			break;
		case '\b' : 
			if (cp > p->line) { 
				cp--; 
				if (p->flags & p_echo) outstr("\b \b"); 
			} 
			break;

		case '\n' : 
			if (cp is p->line) {
				*cp = '\0';
				alarm(0);
				return false;
			}
		case '\0' :
			if (!(rest = alarm(0))) {
				if (!(p->mode & idle))
					p->mode = timeout;
				return true;
			} else
				alarm(rest);
			break;
		case ctl_c: 
		case ctl_v: 
			;   /* Ignore most ctl char */
		case 17  :
		case 19  :
			if (cp is p->line) {
				alarm(0);			/* AY-880618 */
				*cp = '\0';
				return false;
			} else {
				DBGMSG((stderr, "************************************\n\r\7"));
				DBGMSG((stderr, "*****  getdat - got CTRL-Q,S  ******\n\r\7"));
				DBGMSG((stderr, "************************************\n\r\7"));
				; /* Ignore DC1/DC3 */
			}
		}
	}
}
#else
getdat()
{
	register char *cp;
	register char ch;
	register PORTS *p;

	p = port;

	if (p->flags & p_dotmr) {
		if ((p->mode & idle) and (p->dev is p_tnc))
                        settmr(&p->itime, 3); /* 2sec -> 3 5/13 */
		else
			settmr(&p->itime, p->ctime);
	}
	p->flags setbit p_dotmr;
	cp = p->line;

	while (true) {
			while(!instat()) {
				if (p isnt cport) {
					ioport(cport);
					if (instat()) {
						ch = inchar();
						if (ch is achar) {
							p->mode = forced; 
							ioport(p);
							return true;
						}
						if (ch is tchar) {
							p->flags setbit p_opreq; 
							ioport(p);
							return true;
						}
					}
					ioport(p);
				}
				if (!chktmr(p->itime)) {
					*cp = '\0';
                                        if (!(p->mode & idle))
						p->mode = timeout;
					return true;
				}
			}

		*cp = inchar();

/*
 *  Got a character, deal with it.
 */

		if ((cp is (p->line + linelen - 2)) or (*cp is '\r')) {
/*
 *  Got a whole line. Either buffer full, or character is CR.
 */
			if (*cp is '\r') *cp = '\n';
			cp++; 
			*cp = '\0';

			if (p->flags & p_echo)
				outchar('\n');

			if (isdis(p->line)) {
				if (!(p->mode & idle))
					p->mode = discon;
				return true;
			}

			if (isreq(p->line)) {
				p->flags setbit p_req;
				pcall(p->rcall, p->line + 20);
				p->flags clrbit p_dotmr;
				return false;
			}
			return true;
		}

/*
 *  Not end of line.
 *  Stuff the character in the buffer.
 *  Handle some control characters. Ignore some.
 */

		switch(*cp) {
		default	: 
			if (p->flags & p_echo) outchar(*cp); 
			cp++; 
			break;
		case '\b' : 
			if (cp > p->line) { 
				cp--; 
				if (p->flags & p_echo) outstr("\b \b"); 
			} 
			break;

		case '\n' : 
			if (cp is p->line) {
				*cp = '\0';
				return false;
			}
		case '\0' :
                        if (isatty(0)) break ; /* changed SMC 891106   */
                        return false;          /* Ignore most ctl char */
                case ctl_c:
			;   /* Ignore most ctl char */
		case ctl_v: 
			;   /* Ignore most ctl char */
		}
	}
}
#endif

/*
 *  Parse a message header line. Written by WD6CMU
 *
 *  Input:   Line of message in port->line.
 *  Returns: Number of fields found.
 *	     Fields are placed in port->cmd.
 *	     Each field is null-terminated.
 *	     The first character of the field is the field type.
 */

parse_head ()
{
	register char *ip;
	register char *op;

	ip = port->line;
	op = port->cmd;
	port->flds = 0;

	while (*ip) {
		if (*ip is ':') {
			if (port->flds) {
				op--; 
				while (*(op - 1) is ' ') op--; 
				*op++ = '\0';
			}
			port->fld[port->flds] = op;
			*op++ = *(ip - 1); 
			ip++; 
			port->flds++;
		}
		else if (port->flds) *op++ = *ip++;
		else ip++;
	}
	if (port->flds) while (*(op - 1) is ' ') op--;
	*op++ = '\0';
}

pparse()
{
	register short bl;
        register unsigned char *in, *out;
	static char *nullst = "";

	for (port->flds = 0; port->flds < maxflds;)
		port->fld[port->flds++] = nullst;

	in  = port->line;
	out = port->cmd;
	bl  = false;
	port->flds = 0;

	while (*in and (port->flds < maxflds) and (out < (port->cmd + cmdlen - 1)))
	{
                if ( *in > 0x7f) *in = ' ' ;    /* SJIS-> SPACE Mar. 23,91 */
		if (islower(*in)) *out = toupper(*in); 
		else *out = *in;
		if (bl) { 
			if (*in <= ' ') { /* AY-880830 */
				bl = false; 
				*out = '\0'; 
			}  
			out++; 
		} else { 
			if (*in > ' ')  {
				bl = true; 
				port->fld[port->flds++] = out++; 
			}
		}
		in++;
	}
	*out = '\0';

	port->opt1 = *port->fld[0];
	port->opt2 = *(port->fld[0] + 1);
	if (!port->opt2) port->opt2 = ' ';
}

/*
 *  Bundle getdat and parse.
 */

getcmd()
{
	while(!getdat())
		;
	pparse();
}

/*
 *  Fill some memory with a character.
 */

fill(adr, ch, len)
char *adr;
char ch;
int len;
{
	while (len--) *adr++ = ch;
}

/*
 *  Copy C string to LJSF string.
 */

ljsf(to, from, size)
char *to;
char *from;
int  size;
{
	fill(to, ' ', size);
	while (size--) {
		if (*from < ' ') return;
		*to++ = *from++;
	}
}

/*
 *  Copy LJSF string to C string.
 */

unbl(to, from, size)
char *to, *from;
int size;
{
	while (size--) {
		if (*from <= ' ') { 
			*to = '\0'; 
			return; 
		}
		*to++ = *from++;
	}
	*to = '\0';
}
