

#include "V.h"
#include "mem.h"
global char V_pkg_date[] = "14/04/23";

/*
*   Vopt("<l><file>")
* This initializes the V package.  The Vlvl is 1 digit, 0-9. The <file> is
* optional, and defaults to standard error.  It is suggested that  you  invoke
* this routine via code like:
*   if ((p=getopt("VBSfoo")) || (p=getopt("DEBUG")))
*      Vopt(p);
* where FOO is a name for  your  application.   You  can  then  use  the  D*()
* functions  to  generate  debug  messages to the audit-trail file named.  For
* example, the csh command
*   setenv VBSslipd 5/usr/spool/slipd.log
* will set the debug level for the SLIP daemon to 5, and put its  audit  trail
* in the /usr/spool/slipd.log file.  Note that if the arg is null, we retrieve
* the saved string and re-use it.
*
* Special kludge added by jc (96/07/20): If the arg string starte with '#', we use
* it as a sprintf format to build the real string.
*/
static char m_Vo[] = "Voption";
static char m_logf[] = "\n# %s\t=== %s V%d logfile %s ===\n";
static CP   Vppath = 0;	/* Computed path kludge */

void Vopt(p)
	char *p;
{	int   c0, c1, c2, l, n;
	FILE *f;

	if (++VoptLvl > 1) {
		P2 "### Vopt(\"%s\" called while Vopt active!!!",Vtime(),N(Voption) D;
		Fail;
	}
	Vtimezone = Findenv("TZ");	/* Note timezone, for Vtime() */
	Vtime();				/* Ensure one call to initialize time stuff */
	if (p) {		/* Note debug string for possible re-use */

		MakStrM(&Voptstr, p, -1, m_Vo);

	} else
	if (Voption) {		/* Retrieve saved debug option */
		p = Voption;
	} else {

		MakStrM(&Voptstr, "1", 1, m_Vo);

		p = Voption;
	}
	if (*p == '#') {		/* Special kludge to allow computed file name */
		p++;					/* Rest of string is format */
		n = strlen(p) + strlen(pname) + 20;	/* This oughta be enough */
		if (Vppath) FRee(Vppath);	/* Get rid of any previous Vppath */
		if (!(Vppath = (CP)Malloc(n))) Fail;
		mypid = getpid();	/* Paranoia */
		Sprintf(Vppath,p,pname,mypid);		/* Feed our name and pid to format */
		p = Vppath;		/* Now use the result as the Vpath */
	}
/*
* Now we should have p==Voption.  Let's try to parse it.
*/
	for (c0=0; c0<CHARSETSIZE; c0++)
		Vflg[c0] = -1;	/* N.B.: assuming chars are signed */
	while (c0 = p[0]) {
		c2 = (c1 = p[1]) ? p[2] : 0;



		l = -1;
		if (('0'<=c0) && (c0<='9')) {	/* Only one digit for level */
			l = c0 - '0';	/* Decode the debug level digit */

		} else {
			FP stderr,"%s: Bad debug string: \"%s\"\n",pname,p P;
			p++;
			continue;
		}
		if (l < 0) l = 2;
		Switch(c2) {	/* Assorted field separators */
		  case ' ' :
		  case '-' :
		  case ',' :
		  case ':' :	/* <l><flg> */
		  case ';' :
		  case '\t':
		  case '\r':
		  case '\n':
		  case '\f':
			Vflg[c1] = l;

			p += 3;
			if (!c2) Done;	/* No file-name field */
			continue;
		  case  0:		/* <l> */
		  default:		/* <l><file> */
			Vlvl = l;		/* Global debug level */
			p++;
			for (c0=0; c0<CHARSETSIZE; c0++)
				if (Vflg[c0]<0 || Vflg[c0]>9)
					Vflg[c0] = l;		/* Hit all the undefined flags */
			if (!c1) Done;		/* No file name */
			if (Vout && (Vout != stderr)) {
				if (Vlvl>2) FP Vout,"Close log file \"%s\"\n",N(Vfile) P;
				if (Vlvl>2) FP Vout,"Open  log file \"%s\"\n",p P;
				Fclose(Vout);
			}
			if (f=Fopen(p,"a+")) {
/*
* We do our best to ensure that output to Vout will  be  unbuffered.
* Actually,  making  it buffered really doesn't hurt, but it's nice to
* know exactly what's going on.  Some systems are  quite  tricky,  and
* really  want  us  to  do  things efficiently.  Don't be surprised if
* buffering happens when you don't want it, and vice versa.  Sigh.
*/
#ifdef NOTNOW
#ifdef ULTRIX	/* Others may do it this way, too */
				setlinebuf(f);


#else
				setbuf(f,(CP)0);


#endif
#endif
				if (stdiofl && Vout && (Vlvl > 6))
					FP Vout,m_logf,Vtimp,progname,Vlvl,p P;
				Vout = f;
				if (Fileno(f) < 2) {	/* Make sure it's at least file 2 */
					Dup2(Fileno(f),3);
					Close(Fileno(f));
					Filefd(Vout) = 3;
				}
				Vfile = FileName(Fileno(Vout));
				P3 "%s\tDebug level %d file %d=\"%s\"",
					Vtime(),Vlvl,Fileno(Vout),p D;
			} else {
				if (stdiofl) {
					fprintf(stderr,m_access,pname,"write","debug file",
						p,Errinfo);	/* Try to inform the user somehow */
					fputc('\n',stderr);
					fflush(stderr);
				}
			}
			if (Vlvl>1 && Vout) fprintf(Vout,
				"%s\t+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ V=%d.\n",
				Vtimp,Vlvl);
			Done;	/* File name must be last field */
		}
	}
	for (c0=0; c0<CHARSETSIZE; c0++)
		if (Vflg[c0] < 0)
			Vflg[c0] = Vlvl;
done:

	if (Vout == 0) {
		Vout = stderr;
		if (Vlvl>3) FP stderr,"Vout=stderr\n" P;
	}
	if (openfilemax < Fileno(Vout))
		openfilemax = Fileno(Vout);


	if (Vlvl>2)
		FP Vout,"%s\t%s\t%s\n",Vtimy,VBSID,V_pkg_date P;
	if (Vlvl>2)
		FP Vout,"%s\tVlvl=%d\tverbose output file=\"%s\" opt=\"%s\"\n",Vtimy,Vlvl,N(Vfile),N(Voption) P;
	if ((realVlvl = Vlvl) > 1)
		dfltVlvl = 2;	/* Kludge for filtering V output based clients */
fail:
	--VoptLvl;
}
