:i	static char Vinit_sccs_id[] = "%W% %G%";
:1#include "V.h"
#include "sys_stat.h"
/*
* Some standard processing of the command-line args and the environment.   The
* main  things  we  do  here  are set up progname to be the full pathname from
* av[0], pname to be the last field of the progname, and Venvar* to  be  the
* debug  environment  variables "D_" or "V_" followed by pname.  We then look
* for these environment variables, and pass whichever is found to Vopt.   We
* return the number of args, though most callers currently ignore this.
*
* We also scan av[] for a debug arg, starting with Vflgchr, a 'd' or 'D',
* and if we find it, we cut it out of the list, and use its value as the
* debug option string.  The return value will then be ac-1, and the rest of
* the args in av[] will be shifted down by one.
*
* If ac == 0, we will ignore av[].
*/
extern char** environ;	/* C's environment vector */
extern char* ttyname();	/* Gets name of serial-port files */
global TIMV  Vtim0 = {0};	/* When the V package was last initialized */
global TIMZ  Vtimz = {0};	/* The time zone that the kernel thinks it's in */
global V_f  Vfctroot = {"?",0};
global char  m_badnull[] = "### Null <%s> pointer.\n";	/* [works on SunOS] */
global char* m_nullptr   = "### Null <%s> pointer.\n";	/* [doesn't work on SunOS] */
global char  m_empty[] = "### Empty %s.\n";
static char  m_Venvvar[] = "\"%s\"";
static char  m_ofnm[] ="openfile.name";
char m_EOK[] = "OK";
char m_EAGAIN[] = "Try again later";
char m_ENODEV[] = "Device can't do this operation";
char m_Vinit[] = "Vinit";
char m_Voption[] = "Voption";

/*ARGSUSED*/
Vinit(ac,av)
    int   ac;
    char**av;
{	int   r=ac;	/* Return value is number of args left */
    char**ev=environ;	/* Used to be arg; now we use environ[] */
	int   a, f, i;
	char *p=0;
	STat  st;	/* Dummy for fstat() */
	File *fp;
/*
* Don't call Fenter here; it screws up the stack!
*/
	if (!Vout) Vout = stderr;	/* Some systems can't do this at compile time */
	if (!Vtim0.tv_sec)
		Gettimeofday(&Vtim0,&Vtimz);
	ev = environ;
:9	printf("Vinit(%d,%08X,%08X) Vlvl=%d.\n",ac,av,ev,Vlvl);
:8	Vshowfiles();
:i	Vshowdefs();
/*
* We slightly POSIXify the sys_errlist[] vector.
:9	printf("Modify sys_errlist[] ...\n");
	sys_errlist[0] = m_EOK;
	sys_errlist[EAGAIN] = m_EAGAIN;
	sys_errlist[ENODEV] = m_ENODEV;
:9	printf("Modified sys_errlist[].\n");
*/
/*
* Parse the path in av[0] into progname (full) and pname (last field).
*/
	if (ac && av) {
:9		printf("av=%08X\n",av);
:9		printf("av=%08X av[0]=%08X\n",av,av[0]);
:9		printf("av=%08X av[0]=%08X \"%s\"\n",av,av[0],av[0]);
		progname = av[0];
:9		printf("progname=\"%s\"\n",progname);
		pname = lastfld('/',progname);
:9		printf("pname=\"%s\"\n",pname);
		Vfctroot.name = pname;	/* Push function name onto stack */
	}
	if (!Vfcts) {			/* Is function stack empty? */
		Vfcts = &Vfctroot;
:9		printf("Vfcts=%08X name=\"%s\"\n",Vfcts,NulC(Vfcts->name));
		Vf.name = Vfcts->name;
:9	} else {
:9		printf("Vfcts=%08X, pname not stacked.\n",Vfcts);
	}
:9	printf("Vfctroot.name=%08X=\"%s\"\n",Vfctroot.name,Vfctroot.name);
/*
* Check for an environment variable whose name is "D_" or "V_" plus the  name
* of this program. If we find it, it overrides the default debug string, which
* in turn may be overridden by a command-line debug arg.  Note that we  prefer
* the D_$pname environment variable if it exists; else V_$pname is used.
*/
	i = Strlen(pname);
	if (!(Venvar1 || (Venvar1 = (CP)MallocM(3+i,"Venvar1"))))
			Fail;
	if (!(Venvar2 || (Venvar2 = (CP)MallocM(3+i,"Venvar2"))))
			Fail;
	sprintf(Venvar1,"D_%s",pname);
	sprintf(Venvar2,"V_%s" ,pname);
:9	printf("Venvar1=\"%s\"\n",Venvar1);
:9	printf("Venvar2=\"%s\"\n",Venvar2);
	if (p = Findenv(Venvar1)) {
:8		if (Vlvl>6) dmpstr(&Voptstr,"Voptstr-if");
		MakStrM(&Voptstr,p,-1,m_Voption);
:8		if (Vlvl>6) dmpstr(&Voptstr,"Voptstr-if");
		Venvvar = Venvar1;
:7		if (Vlvl>=7) FP Vout,m_Venvvar,Venvar1 P;
	} else if (p = Findenv(Venvar2)) {
:8		if (Vlvl>6) dmpstr(&Voptstr,"Voptstr-else");
		MakStrM(&Voptstr,p,-1,m_Voption);
:8		if (Vlvl>6) dmpstr(&Voptstr,"Voptstr-else");
		Venvvar = Venvar2;
:7		if (Vlvl>=7) FP Vout,m_Venvvar,Venvar2 P;
	}
:3	if (Venvvar) if (Vlvl>=3) FP Vout,m_Venvvar,Venvvar P;
/*
* See if there is a V-file size limit in the environment.
*/
	if (p = Findenv("VBS_SIZE")) {
		i = sscanf(p,"%u",&Vsizlim);
:2		if (i < 1) if (Vlvl>=2) FP Vout,"VBS_SIZE=\"%s\" not numeric; ignored.",p P;
:6		if (Vlvl>=6) FP Vout,"File size limit=%lu.",Vsizlim P;
	}
/*
* See if we should be doing global locking.
*/
	if (p = Findenv("VBS_GLOBAL_LOCK")) {
		i = sscanf(p,"%u",&V_locking);
:2		if (i < 1) if (Vlvl>=2) FP Vout,"VBS_GLOBAL_LOCK=\"%s\" not numeric; ignored.",p P;
:6		if (Vlvl>=6) FP Vout,"V_locking=%u.",V_locking P;
	}
/*
* See if there are values for hexdump() in the environment:
*/
	if (p = Findenv("HEX_FMT")) {
		hex_fmt = *p;
:7		if (Vlvl>=8) V9 "hex_fmt=%02X='%c'",B8(hex_fmt),Dsp(hex_fmt) D;
	}
	if (p = Findenv("HEX_WORD")) {
		sscanf(p,"%d",&hex_word);
:7		if (Vlvl>=8) V9 "hex_word=%d",hex_word D;
	}
/*
* Now to run thru the command-line args passed to us,  looking  for  a
* debug  option.  If we find it, we will process it, and cut it out of
* the vector. Note that we then return a revised arg count that is one
* less than what was passed to us.
*/
:1	for (a=r=1; a<ac; a++) {
:1		if (av[a][0] == Vflgchr) {
:1			Switch(av[a][1]) {
:1			  case 'D':		/* Debug option */
:1			  case 'd':
:1			  case 'V':		/* Verbose option */
:1			  case 'v':
:1				if (av[a][2]) {
:8					if (Vlvl>6) dmpstr(&Voptstr,"Voptstr-case-if");
:1					MakStrM(&Voptstr,av[a]+2,-1,m_Voption);
:8					if (Vlvl>6) dmpstr(&Voptstr,"Voptstr-case-if");
:1				} else {
:8					if (Vlvl>6) dmpstr(&Voptstr,"Voptstr-case-else");
:1					MakStrM(&Voptstr,"2",1,m_Voption);
:8					if (Vlvl>6) dmpstr(&Voptstr,"Voptstr-case-else");
:1				}
:9				if (Vlvl>8) printf("Voption=\"%s\"\n",Voption);
:1				break;
:1			  default : av[r++] = av[a];
:1			}
:1		} else {
:1			av[r++] = av[a];
:1		}
:1	}
:1	Vtime();
	if (Voption && *Voption) Vopt(Voption);
fail:
	for (i=r; i<ac; i++)	/* Wipe out all the trailing av[] slots */
		av[i++] = 0;		/* (in case a caller ignores our return value) */
/*
* We now try to learn what we can about open  files.   This  might  be
* expanded  somewhat  as  we learn how to determine more about an open
* file. It would be really useful if we could always learn the name of
* each  file, but that's a FAQ whose answer on Unix, unfortunately, is
* "Tough luck, sucker!"  We do what we can ...
*/
	for (f=0; f<3; f++) {
:6		V8 "File %d check ...",f D;
		if (Fstat(f,&st) == 0) {
:6			V8 "File %d is open.",f D;
			if (fp = d_openfile(f)) {	/* Fetch the openfile descriptor */
				fp->flgs |= File_OPEN;	/* Note that it's open */
				if (isatty(f) && (p = ttyname(f))) {
					MakStrM(&fp->name,p,-1,m_ofnm);
					fp->flgs |= File_TERM;
:6				} else {
:6					V8 "File %d is not a tty.",f D;
					Switch(f) {
					case  0:MakStrM(&fp->name,"STDIN",5,m_ofnm); break;
					case  1:MakStrM(&fp->name,"STDOUT",6,m_ofnm); break;
					case  2:MakStrM(&fp->name,"STDERR",6,m_ofnm); break;
					default:MakStrM(&fp->name,m_unknown,-1,m_ofnm); break;
					}
:6					if (Vlvl>6)
:6						FP Vout,"%s/Vinit: +++ Can't get ttyname of file %d.\n",pname,f P;
				}
				if (!fp->name.v)	/* Ensure a printable name */
					MakStrM(&fp->name,m_unknown,-1,m_ofnm);
:6			} else {
:6				V8 "File %d not in openfile list.",f D;
			}
:6		} else {
:6			V8 "File %d is not open.",f D;
		}
	}
	if (r > ac) r = ac;
	return r;
}
dmpstr(sp,dp)
	Str* sp;
	CP   dp;
{
:5		V1 "Str %s=[%08X,%d,%d,%X]",dp,sp->v,sp->l,sp->m,sp->p D;
}
