Filewatcher File Search
FTP Search
  
Directory 
  
Content Search 
   
pkg://hwtools_0.8.orig.tar.gz:245593/hwtools-0.8/irqtune/src/irqtune.c  downloads

/* irqtune -- load IRQ tuning module */

#pragma member irqtune.h
#include <irqtune.h>

#include <lib/cmd.c>
#include <lib/file.c>
#include <lib/opt.c>
#include <lib/xstr.c>
#include <lib/sys.c>
#include <lib/zprt.c>
#include <lib/zprtx.c>

/* main -- main program */
void
main(int argc,char **argv)
{
	char *cp;
	int idx;
	int val;

	pgmname = *argv;
	--argc;
	++argv;

	proc_ints = "/proc/interrupts";
	setbuf(stderr,NULL);
	sprintf(tmpf,"/tmp/irqtune.%d",getpid());

	/* insure we got "/sbin/irqtune" and not just "irqtune" */
	cp = strchr(pgmname,'/');
	if (cp != NULL)
		dynstat |= DYN_FULL_PATH;

	/* locate the top directory */
	strcpy(dirtop,pgmname);
	filehead(dirtop);

	/* decode options */
	for (;  argc > 0;  --argc, ++argv) {
		cp = *argv;
		if (*cp != '-')
			break;
		if (! optget(opthelp,cp + 1))
			usage();
	}

	/* do install and stop */
	if (mstopt & OPTINSTALL)
		install(argc,argv);

	/* do version and stop */
	if (mstopt & (OPTVERSION | OPTERR)) {
		zprtx("irqtune: version is %s\n",IRQTUNE_VERSION);
		if (mstopt & OPTVERSION)
			exit(0);
	}

	/* display help and stop */
	if (mstopt & OPTHELP) {
		_usage();
		exit(0);
	}

	/* get IRQ priority arguments */
	idx = 0;
	for (;  argc > 0;  --argc, ++argv) {
		cp = *argv;
		if (! RNGE(*cp,'0','9'))
			break;

		if (idx >= sizeof(irqhigh_list))
			usage();

		val = atoi(cp);
		if (! RNGE(val,0,15))
			usage();
		irqhigh_list[idx++] = val & 0x0F;
	}

	/* set bad defaults */
	if (mstopt & OPTRESET) {
		irqhigh_list[0] = IRQHIGH_MST_BAD;
		irqhigh_list[1] = IRQHIGH_SLV_BAD;
	}

	/* check the sanity */
	cp = irqhigh_insane(irqhigh_list[0],irqhigh_list[1]);
	if (cp != NULL)
		sysfault("irqtune: unable to use values %u/%u -- %s\n",
			irqhigh_list[0],irqhigh_list[1],cp);

	/* fake it */
	irqhigh_set(0,irqhigh_list[0],irqhigh_list[1]);

	/* probe the configuration and find any trouble */
	probectl();

	/* load the module by whatever means necessary */
	loader();

	/* send the table */
	if ((mstopt & OPTSORT) || (mstopt & OPTNOGO))
		mstopt &= ~OPTQUIET;
	if (bigcode)
		mstopt |= OPTQUIET;
	if (! (mstopt & OPTQUIET)) {
		tblinit();
		tblread(1,proc_ints);
		tblshow();
	}

	/* do final exit */
	sysexit(bigcode);
}

/* install -- install program */
void
install(int argc,char **argv)
{
	char **modtail;
	int idx;
	int err;
	int ok;
	int unit;
	FILE *xf;
	char srcfile[1024];
	char dstfile[1024];

	bigcode = 1;
	xf = NULL;
	unit = -1;
	do {
		/* insure we're invoked by full path */
		if (! (dynstat & DYN_FULL_PATH)) {
			zprtx("install: must be invoked via full path\n");
			break;
		}

		/* check number of arguments */
		if (argc != 3) {
			zprtx("install: wrong number of arguments\n");
			break;
		}

		/* get SBIN directory */
		strcpy(pathtmp,argv[1]);

		/* do simple installation */
		if (strcmp(argv[0],"simple") == 0) {
			zprtx("irqtune: simple installation ...\n");

			/* copy over self */
			err = -1;
			for (idx = 0;  idx <= 1;  ++idx) {
				err = filecpy(idx,pathtmp,dirtop,"irqtune");
				if (err < 0)
					break;
			}
			if (err < 0)
				break;

			/* copy over our modules */
			err = -1;
			ok = 0;
			for (modtail = modnames;  *modtail != NULL;  ++modtail) {
				for (idx = 0;  idx <= 1;  ++idx) {
					sprintf(srcfile,"%s.o",*modtail);
					err = filecpy(idx,pathtmp,dirtop,srcfile);
					if (err < 0)
						continue;
					ok = 1;
				}
			}
			if (! ok) {
				zprtx("install: no modules found\n");
				break;
			}

			bigcode = 0;
			break;
		}

		/* do stub installation */
		if (strcmp(argv[0],"sh") == 0) {
			zprtx("install: stub installation ...\n");

			/* open/create the stub file */
			unit = filecpy(1,pathtmp,NULL,"irqtune");
			if (unit < 0)
				break;

			/* attach a stream */
			xf = fdopen(unit,"a");
			if (xf == NULL) {
				zprtx("install: unable to fdopen -- %s\n",
					strerror(errno));
				break;
			}
			unit = -1;

			fprintf(xf,"#!/bin/sh -\n");
			fprintf(xf,"IRQTUNE_HOME='%s'\n",argv[2]);
			fprintf(xf,"exec $IRQTUNE_HOME/sbin/irqtune $*\n");
			fclose(xf);
			xf = NULL;

			/* remove .o files */
			for (modtail = modnames;  *modtail != NULL;  ++modtail) {
				sprintf(dstfile,"%s/%s.o",pathtmp,*modtail);
				err = unlink(dstfile);
				if (err >= 0)
					zprtx("install: removing %s ...\n",dstfile);
			}

			bigcode = 0;
			break;
		}

		zprtx("install: unknown installation mode  -- '%s'\n",
			argv[0]);
	} while (0);

	if (xf != NULL)
		fclose(xf);
	if (unit >= 0)
		close(unit);

	sysexit(bigcode);
}

/* loader -- load module */
void
loader(void)
{
	char *cp;
	int err;
	int ldcode;
	int rmcode;
	char **modtail;
	int modcnt;
	char *logf;
	struct stat mystat;

	bigcode = 1;

	/* force unloading if requested (do this silently as it's likely to */
	/* fail in the normal case) we will unload anything (even stuff loaded */
	/* manually without the "-o" option) */
	rmcode = 0;
	for (modtail = modnames;  *modtail != NULL;  ++modtail) {
		if (mstopt & OPTNOGO)
			break;
		if (! (mstopt & OPTUNLOAD))
			break;
		sprintf(bigbf,"%s %s",rmmod_file,*modtail);
		rmcode = vsystem(0,"pre-unloading",*modtail,NULL,bigbf);
	} while (0);

	/* load the module (fallback to simpler versions to insure it loads) */
	modcnt = 0;

	/* don't try something that is likely to fail (unless forced) */
	modtail = modnames;
	if (! (mstopt & OPTFORCE)) {
		if (dynstat & DYN_NPRONLY)
			++modtail;
	}

	for (;  *modtail != NULL;  ++modtail) {
		sprintf(modcur,"%s/%s.o",dirtop,*modtail);

		/* check for module existence -- don't spew unless full errors as */
		/* known useless modules may be removed to speed things up */
		err = stat(modcur,&mystat);
		if (err < 0) {
			if (mstopt & OPTERR)
				zprtx("irqtune: module %s not found -- skipping\n",
					modcur);
			continue;
		}
		++modcnt;

		/* NOTE: we are version independent */
		/* insmod complains even with the force option */
		logf = "/dev/null";

		cp = bigbf;

		cp += sprintf(cp,"%s -x -o %s -f %s",
			insmod_file,modtag,modcur);

		/* tell insmod to do verbose output */
#ifdef NEVERWAS
		if (mstopt & OPTERR)
			cp += sprintf(cp," -v");
#endif /*NEVERWAS*/

		/* add the desired priority */
		cp += sprintf(cp," priority=%d,%d",irqhigh_list[0],irqhigh_list[1]);

		/* we don't need to check system log (we really should to be sure) */
		zprtx("irqtune: %s %u/%u\n",
			(mstopt & OPTNOGO) ? "simulating IRQ priority of" : "setting system IRQ priority to",
			irqhigh_list[0],irqhigh_list[1]);
		fflush(stderr);

		/* perform module load */
		ldcode = 0;
		do {
			if (mstopt & OPTNOGO)
				break;

			/* sync the disks, just in case */
			sync();

			/* install it */
			ldcode = vsystem(mstopt & OPTERR,"loading",
				modcur,modtag,bigbf);
		} while (0);

		/* check for errors -- the normal presumption is if insmod failed, */
		/* there is no module to unload */
		if (ldcode) {
			if (! (mstopt & OPTUNLOAD))
				continue;
		}

		/* the mere act of installing does the job so uninstall immediately */
		rmcode = 0;
		do {
			if (mstopt & OPTNOGO)
				break;
			sprintf(bigbf,"%s %s",rmmod_file,modtag);
			rmcode = vsystem(1,"unloading",modcur,modtag,bigbf);
		} while (0);

		/*
		// normally, failure to unload is bad because it's so simple.
		// if we're forcing unload, we may attempt to unload a module that
		// never got loaded.  this isn't an immediate killer, it will be
		// detected in the final sweep (e.g. bigcode will stay set).
		// it could also be some nasty, genuine failure of rmmod to unload.
		// we can't tell the difference without some arcane version dependent
		// digesting of rmmod stderr output, so we'll just go on and hope for
		// the best.
		*/
		if (rmcode) {
			if (! (mstopt & OPTUNLOAD))
				break;
		}

		/* stop loading if we found one that works */
		if ((ldcode == 0) && (rmcode == 0)) {
			bigcode = 0;
			break;
		}
	}

	/* complain about no modules found whatsoever */
	do {
		if (mstopt & OPTNOGO)
			break;
		if (modcnt <= 0) {
			zprtx("irqtune: no irqtune modules found\n");
			bigcode = 1;
		}
	} while (0);
}

/* probechk -- check dynamic configuration */
void
probechk(mskof_t actmsk,const char *fmt,...)
{
	int ok;
	int errflg;
	mskof_t errmsk;
	const char *tag;
	va_list ap;

	/* decide if we're missing something required */
	ok = BOOL(dynstat & actmsk);
	if (actmsk & DYN_NEG)
		ok = ! ok;

	/* decide on fatal error */
	errmsk = DYN_FATAL;
	if (mstopt & OPTWARN)
		errmsk |= DYN_WARN;
	errflg = 0;
	if (actmsk & errmsk)
		errflg = (! ok);

	if ((mstopt & OPTERR) || errflg) {
		zprtx("probe: ");

		va_start(ap,fmt);
		zprtvx(0,fmt,ap);
		va_end(ap);

		do {
			if (actmsk & DYN_FATAL) {
				tag = ok ? "OK" : "ERROR";
				break;
			}
			if (actmsk & DYN_WARN) {
				tag = ok ? "OK" : "WARNING";
				break;
			}
			tag = ok ? "YES" : "NO";
		} while (0);
		zprtx(" -- %s\n",tag);
	}

	/* mark fatal error */
	if (errflg)
		dynerr |= actmsk;
}

/* probectl -- probe control (to probe 1) */
void
probectl(void)
{

	/* do the probes */
	probeknl();
	probeksyms();
	probeins();
	tblread(0,proc_ints);

	/* check for insmod conflicts against kernel */
	do {
		/* check for the first nicely working version */
		dynstat &= ~DYN_INSMOD_STRONG;
		if (insmod_version >= INSMOD_VERGOOD) {
			dynstat |= DYN_INSMOD_STRONG;
			break;
		}

		/* both insmod and kernel are 2.0.X */
		if ((insmod_version < VERMK(2,1,0)) &&
			(kvers_dynamic < VERMK(2,1,0)))
			break;

		/* the killer a bad 2.1.X insmod on a 2.0.X kernel */
		if (RNGEM1(insmod_version,VERMK(2,1,0),INSMOD_VERGOOD) &&
			(kvers_dynamic < VERMK(2,1,0))) {
			dynstat |= DYN_INSMOD_CRASH;
			break;
		}
	} while (0);

	/* avert possible insmod crash */
	if ((dynstat & DYN_INSMOD_CRASH) &&
		(dynstat & (DYN_KSYMS_USING | DYN_KSYMS_CSUM)))
		dynstat |= DYN_NPRONLY;

	/* mention a 1.X insmod on a 2.X kernel */
	if (kvers_dynamic >= VERMK(2,0,0)) {
		if (VERMAJ(kvers_dynamic) > VERMAJ(insmod_version))
			dynstat |= DYN_INSMOD_OLD;
	}

	/* detect and show errors */
	probectl2();

	/* abort on detected errors */
	if (dynerr) {
		zprtx("irqtune: probe detected errors\n");

		if (mstopt & OPTFORCE)
			zprtx("irqtune: loading forced\n");

		else
			sysfault("irqtune: loading not performed (may be overriden by -f)\n");
	}
}

/* probectl2 -- probe control (to probe 2) */
void
probectl2(void)
{

	probechk(DYN_FATAL | DYN_FULL_PATH,
		"irqtune must be invoked via the full path");

	/* show basic insmod operation */
	probechk(DYN_SBIN_PATH,"/sbin in $PATH");
	probechk(DYN_FATAL | DYN_INSMOD_PATH,"insmod found in $PATH (%s)",
		insmod_dir);
	probechk(DYN_FATAL | DYN_INSMOD_EXEC,"insmod simple execution");
	probechk(DYN_INSMOD_VERSION,"insmod has version (" VERFMT ")",
		VERPRT(insmod_version));
	probechk(DYN_FATAL | DYN_RMMOD_PATH,"rmmod found in insmod directory");

	/* show an unusable insmod (it accepts no dash options) */
	/* FIXME -- we could support this at some cost, but really this is likely */
	/* some early beta copy of insmod.  sanity beats flexibility here */
	probechk(DYN_FATAL | DYN_NEG | DYN_INSMOD_ANCIENT,
		"insmod version supports command line options");

	/* show a downrev insmod */
	probechk(DYN_FATAL | DYN_NEG | DYN_INSMOD_OLD,
		"insmod version (" VERFMT ") compatible with kernel version (" VERFMT ")",
		VERPRT(insmod_version),VERPRT(kvers_dynamic));

	/* show a no-problems insmod */
	probechk(DYN_WARN | DYN_INSMOD_STRONG,
		"insmod version should be " VERFMT " (or better)",
		VERPRT(INSMOD_VERGOOD));

	/* show possible insmod crash (we can compensate) */
	probechk(DYN_WARN | DYN_NEG | DYN_INSMOD_CRASH,
		"insmod and kernel compatible with CONFIG_MODVERSIONS");

	/* show that we're doing crash compensation */
	probechk(DYN_WARN | DYN_NEG | DYN_NPRONLY,"%s loading will be tried",
		modnames[0]);

	probechk(DYN_KNL_CPLDIFF | DYN_NEG,
		"kernel version irqtune built under (" VERFMT ") matches current system",
		VERPRT(kvers_compile));

	/* complain about kernels where IRQ handling renders us ineffective */
	probechk(DYN_FATAL | DYN_KNL_VEROK,"kernel IRQ handling is compatible");

	/* show kernels built without modules support */
	probechk(DYN_FATAL | DYN_KNL_GSYM,"kernel has module support (CONFIG_MODULES)");
	probechk(DYN_FATAL | DYN_KSYMS_FOUND,"kernel has symbols");

	/* show modversions information */
	probechk(DYN_KSYMS_USING,"kernel is using versions (CONFIG_MODVERSIONS)");
	probechk(DYN_KSYMS_CSUM,"kernel symbols are checksummed (CONFIG_MODVERSIONS)");

	/* require /proc/interrupts */
	probechk(DYN_FATAL | DYN_PROC_INTS,"kernel has /proc/interrupts");
}

/* probeins -- probe for insmod */
void
probeins(void)
{
	char *cp;
	int nextflg;
	int err;
	struct cmdblk *cmd;
	char **av;
	char *argv[10];
	char bf[1024];

	/* add most probable place for insmod */
	cp = pathdir("/sbin");
	if (cp != NULL)
		dynstat |= DYN_SBIN_PATH;

	cmd = NULL;
	do {
		strcpy(insmod_file,"insmod");
		strcpy(rmmod_file,"rmmod");

		/* probe for insmod in $PATH */
		cp = pathlook("insmod",insmod_path);
		if (cp == NULL) {
			sprintf(insmod_dir,"???");
			break;
		}

		/* directory where insmod was found */
		dynstat |= DYN_INSMOD_PATH;
		strcpy(insmod_dir,cp);
		if (insmod_path != NULL)
			sprintf(insmod_file,"%s/insmod",insmod_dir);

		/* NOTE: we require that rmmod be in the same directory as insmod */
		/* flexibility is one thing, but probable sanity is more important */
		cp = pathlook("rmmod",insmod_dir);
		if (cp != NULL) {
			dynstat |= DYN_RMMOD_PATH;
			if (insmod_path != NULL)
				sprintf(rmmod_file,"%s/rmmod",insmod_dir);
		}

		/* capture output of simple insmod execution (and get version) */
		/* WARNING: don't change this without change to ANCIENT string below */
		sprintf(bf,"%s -V",insmod_file);
		cmd = cmdopen(bf);
		if (cmd == NULL)
			break;
		dynstat |= DYN_INSMOD_EXEC;

		/* find the version */
		while (1) {
			/* read next line */
			err = cmdread(cmd,bigbf,sizeof(bigbf));
			if (err < 0)
				break;

			/* look for ancient insmod that supports no command line options */
			if (strcmp(bigbf,"Cannot open -V") == 0)
				dynstat |= DYN_INSMOD_ANCIENT;

			/* look for "x.y.z" */
			xstrargv(argv,Cntof(argv),bigbf);
			nextflg = 0;
			for (av = argv;  *av != NULL;  ++av) {
				cp = *av;

				if (strcasecmp(cp,"version") == 0)
					nextflg = 1;

				/* bug out if we've found a version number */
				insmod_version = verdcd(cp);
				if (insmod_version)
					break;
			}
			if (insmod_version)
				break;
		}

		/* insure that we got a version */
		if (insmod_version != 0)
			dynstat |= DYN_INSMOD_VERSION;
	} while (0);

	/* remove temp file */
	cmdclose(cmd);
}

/* probeknl -- probe the kernel */
void
probeknl(void)
{
	int err;

	/* decide what kernel we were compiled under */
	kvers_compile = verdcd(kernel_version);

	/* decide what kernel we're running under */
	uname(&uts);
	kvers_dynamic = verdcd(uts.release);
	if (mstopt & OPTERR)
		zprtx("irqtune: kernel version " VERFMT "\n",
			VERPRT(kvers_dynamic));

	/* show the version discrepancy (it _should_ not matter because of -f) */
	if (kvers_compile != kvers_dynamic)
		dynstat |= DYN_KNL_CPLDIFF;

	/* check for incompatible kernel IRQ handling */
	if (! RNGE(kvers_dynamic,KNL_VERBADLO,KNL_VERBADHI))
		dynstat |= DYN_KNL_VEROK;

	/* check for module support compiled into kernel (if kernel has */
	/* CONFIG_MODULES off, this will return ENOSYS).  since we're only using */
	/* this to probe, it should still work even with 2.1.18 or later */
	err = get_kernel_syms(NULL);
	if (err >= 0)
		dynstat |= DYN_KNL_GSYM;
}

/* probeksyms -- probe /proc/ksyms */
void
probeksyms(void)
{
	char *cp;
	FILE *xf;
	int argc;
	int len;
	char *argv[10];

	dynstat &= ~DYN_KSYMS_FOUND;
	do {
		xf = fopen("/proc/ksyms","r");
		if (xf == NULL)
			break;

		/* scan the symbols */
		while (1) {
			cp = fgets(bigbf,sizeof(bigbf),xf);
			if (cp == NULL)
				break;

			/* clean the line */
			cp = strrchr(bigbf,'\n');
			if (cp != NULL)
				*cp = 0;

			argc = xstrargv(argv,Cntof(argv),bigbf);
			if (argc < 2)
				continue;

			/* look for <value> <symbol> */
			dynstat |= DYN_KSYMS_FOUND;
			cp = argv[1];

			/* decide if version numbers are being used */
			if (! (dynstat & DYN_KSYMS_USING)) {
				if (strcmp(cp,"Using_Versions") == 0)
					dynstat |= DYN_KSYMS_USING;
			}

			/* decide if symbol has been checksummed */
			len = strlen(cp);
			if (len > 10) {
				if ((cp[len - 10] == '_') && (cp[len - 9] == 'R')) {
					dynstat |= DYN_KSYMS_CSUM;
					len -= 10;
				}
			}
		}

		fclose(xf);
	} while (0);
}

/* verdcd -- decode version number */
/* RETURNS: decoded version number */
u_long
verdcd(char *bf)
{
	char *bp;
	u_long valmaj;
	u_long valmin;
	u_long valsub;

	valmaj = 0;
	valmin = 0;
	valsub = 0;
	do {
		for (bp = bf;  *bp != 0;  ++bp) {
			if (RNGE(*bp,'0','9'))
				continue;
			if (*bp != '.')
				break;
		}
		if (*bp != 0)
			break;

		bp = bf;

		valmaj = strtol(bp,&bp,10);

		++bp;
		valmin = strtol(bp,&bp,10);

		++bp;
		valsub = strtol(bp,&bp,10);
	} while (0);

	valmaj = VERMK(valmaj,valmin,valsub);

	return valmaj;
}

/* tblfind -- find table entry */
/* RETURNS: pointer to /proc/interrupts table entry */
struct tblblk *
tblfind(u_char irq_no)
{
	struct tblblk *tbl;

	/* NOTE: we can do a sort cheaply by indexing here by priority */
	if (mstopt & OPTSORT)
		irq_no = irq_prior_list[irq_no];

	tbl = &tblbase[irq_no];

	return tbl;
}

/* tblinit -- initialize to default */
void
tblinit(void)
{
	u_char irq_no;
	struct tblblk *tbl;

	/* calculate priorities */
	irqhigh_calc();

	/* initialize the table (and calculate priorities) */
	for (irq_no = 0;  irq_no < IRQHIGH_MAX;  ++irq_no) {
		tbl = tblfind(irq_no);
		tbl->tbl_irq = irq_no;
		tbl->tbl_prior = irq_prior_list[irq_no];
		tbl->tbl_bias = irq_prior_bias[irq_no];
		strcpy(tbl->tbl_bf,"        0 ? Inactive");
	}
}

/* tblread -- read in /proc/interrupts table */
void
tblread(int goflg,char *file)
{
	FILE *xf;
	int err;
	char *cp;
	u_long irq_no;
	struct tblblk *tbl;
	char bf[80];

	xf = fopen(file,"r");

	while (xf != NULL) {
		/* read a line */
		cp = fgets(bf,sizeof(bf),xf);
		if (cp == NULL)
			break;

		/* clean the line */
		cp = strchr(bf,'\n');
		if (cp != NULL)
			*cp = 0;

		/* get the irq number */
		irq_no = strtol(bf,&cp,10);

		/* do a modest syntax check */
		err = 1;
		do {
			if (*cp != ':')
				break;
			++cp;

			if (irq_no > IRQHIGH_SLV_HI)
				break;

			err = 0;
		} while (0);

		/* skip entry on error */
		if (err) {
			zprtx("tblread: SYNTAX '%s'\n",bf);
			continue;
		}
		dynstat |= DYN_PROC_INTS;

		if (! goflg)
			break;

		/* copy into table */
		tbl = tblfind(irq_no);
		strcpy(tbl->tbl_bf,cp);
		tbl->tbl_active = 1;
	}

	if (xf != NULL)
		fclose(xf);
}

/* tblshow -- show table */
void
tblshow(void)
{
	u_char irq_no;
	struct tblblk *tbl;

	/* NOTE: do _not_ use tblfind here (and this completes the sort) */
	for (irq_no = 0;  irq_no < IRQHIGH_MAX;  ++irq_no) {
		tbl = &tblbase[irq_no];
		if ((mstopt & OPTALL) || tbl->tbl_active)
			zprtx("I%2.2u/P%2.2u: %s\n",
				tbl->tbl_irq,tbl->tbl_prior - tbl->tbl_bias,tbl->tbl_bf);
	}
}

/* _usage -- show program usage */
void
_usage(void)
{

	zprtx("usage: irqtune [options] [master] [slave]\n");

	zprtx("version: %s\n",IRQTUNE_VERSION);

	zprtx("arguments:\n");
	zprtx("  master -- high priority IRQ on PIC master (DEFAULT: %d)\n",
		IRQHIGH_MST_DFT);
	zprtx("  slave -- high priority IRQ on PIC slave (DEFAULT: %d)\n",
		IRQHIGH_SLV_DFT);

	optusage(opthelp);
}

/* usage -- show program usage and exit */
void
usage(void)
{

	_usage();
	sysexit(1);
}
Results 1 - 1
Help - FTP Sites List - Software Dir.
Searching half a billion files worldwide
© 1997-2009 MARUHN Internet Solutions