[comp.sources.unix] v22i032: Byte Unix benchmarks, Part05/05

rsalz@uunet.uu.net (Rich Salz) (05/08/90)

Submitted-by: "Ben Smith @ BYTE" <ben@bytepb.byte.com>
Posting-number: Volume 22, Issue 32
Archive-name: byte-benchmarks/part05

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 5 (of 5)."
# Contents:  dbmscli.c
# Wrapped by rsalz@papaya.bbn.com on Tue May  8 08:55:34 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'dbmscli.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dbmscli.c'\"
else
echo shar: Extracting \"'dbmscli.c'\" \(19728 characters\)
sed "s/^X//" >'dbmscli.c' <<'END_OF_FILE'
X
X/*******************************************************************************
X *  The BYTE UNIX Benchmarks - Release 2
X *          Module: dbmscli.c   SID: 2.4 4/17/90 16:45:36
X *          
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X *	Ben Smith or Rick Grehan at BYTE Magazine
X *	bensmith@bixpb.UUCP    rick_g@bixpb.UUCP
X *
X *****************************************************************************
X *  Modification Log:
X *
X *	7/6/89 - Reworked messaging system so the semaphores were no
X *	longer used in all cases.  Semaphores now only control the append
X *	operation.  Messages contain caller's pid in type field.
X *	The semaphore also serves to indicate the presence of the server. RG
X *	 
X *	7/6/89 - added some debugging output to VERBOSE
X *	7/9/89 - ifdef code that starts server from client - problems. BSS
X *	7/11/89 - Added semaphore to set.  One semaphore controls the queue,
X *	the other controls the append operation. RG
X *      New command line format: dbmserv <filename> <queue size>
X *****************************************************************************/
X/*
X * Multi-user DBMS simulation.
X * Clients
X * Database has the form:
X * IIIINNNNNNNNNNNNNNNNNNNNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPPPPPPPPPP
X * Where IIII is the 4-digit id number (0-padded)
X *       NN... is the 20-character name
X *       AA... is the 40-character address
X *       PP... is the 10-character phone number
X * Records are accessed by ID number (1 is the 0th record, 2 is 1st..etc.)
X *
X * This is the client system, which you execute with:
X *      dbmscli n t i
X * where:
X *      n = the number of tasks to fork
X *      t = is the sleep time in seconds each task waits between requests
X *      i = is the number of test iterations
X *
X * NOTE: This version assumes Unix V compatibility.
X */
Xchar id[] = "@(#) @(#)dbmscli.c:1.5 -- 7/10/89 18:54:57";
X
X#include <stdio.h>
X#include <ctype.h>
X#include <errno.h>
X#include <sys/types.h>
X#include <sys/signal.h>
X#include <sys/ipc.h>
X#include <sys/sem.h>
X#include <sys/msg.h>
X#include <sys/param.h>
X
X#ifdef VERBOSE
X#include <sys/times.h>
X#define DEBUG	/* remove this after debugging */
X#endif
X
X#define ERROR	(-1)
X/*
X** Record definitions.
X*/
X
X#define IDLEN 4
X#define NAMELEN 20
X#define ADDRLEN 40
X#define PHONLEN 10
X#define RECLEN  74	/* Sum of the above. */
X
X/*
X** Queue and semaphore names.
X*/
X#define	RQUEUE	"READ"		/* Read queue */
X#define WQUEUE	"WRIT"		/* Write queue */
X#define SEMA	"SEMA"		/* Semaphore name */
X
X/*
X** Message types.
X*/
X#define READREQ	1		/* Read a record */
X#define WRITEREQ 2		/* Write a record */
X#define ADDREQ 3		/* Add a new record */
X#define GETLREQ 4		/* Get largest record number */
X#define RESULTREQ 10		/* Record contains results figures */
X				/* Results are stored as:
X				*  nnnnnnnnnnbmmmmmmmmmmb
X				*   n = total time
X				*   m = number of errors
X				*   b = blank
X				*/
X#define DIEREQ 99		/* Orders server to terminate. */
X
X
X/*
X** Return codes from the server.
X*/
X#define AOK 1			/* Request met ok */
X#define DERR_RNF 2		/* Record not found */
X#define DERR_RAE 3		/* Record already exists */
X#define DERR_WRD 4		/* Unexplainable error */
X#define DERR_UNK 9		/* Unknown request type */
X
X/*
X** Error codes.
X*/
X#define QERR 1			/* Queue error */
X#define SEMERR 2		/* Semaphore error */
X
X/*
X** Structures.
X*/
X
Xtypedef struct {
X	char id[IDLEN];
X	char name[NAMELEN];
X	char address[ADDRLEN];
X	char phone[PHONLEN];
X} dbrec;
X
Xtypedef struct {
X	int request;		/* Request type and response code */
X	char recdat[RECLEN];	/* DBMS record data */
X} msgdata;
X
Xtypedef struct {
X	long type;		/* Hold's caller's pid */
X	msgdata data;		/* Pointer to request and data */
X} amess;
X
Xstruct ticker { unsigned long real,
X		       system,
X		       cpu; };
X
X/******************************************************************
X	  ####   #        ####   #####     ##    #        ####
X	 #    #  #       #    #  #    #   #  #   #       #
X	 #       #       #    #  #####   #    #  #        ####
X	 #  ###  #       #    #  #    #  ######  #            #
X	 #    #  #       #    #  #    #  #    #  #       #    #
X	  ####   ######   ####   #####   #    #  ######   ####
X*******************************************************************/
X/*
X** Structure instances.
X*/
Xdbrec myrec;		/* Data record */
Xamess myreq;		/* Client request */
Xamess hisresp;		/* Response from server */
X
Xstruct sembuf unlockq = { 0 , 1 , SEM_UNDO };
Xstruct sembuf lockq = { 0 , -1 , SEM_UNDO };
Xstruct sembuf unlocka = { 0, 1, SEM_UNDO };
Xstruct sembuf locka = { 0, -1, SEM_UNDO };
X
X#ifdef VERBOSE
Xstruct tms tbuff;	/* For times system call */
Xstruct ticker stopwatch = {0L, 0L, 0L};
Xstruct ticker tottime = {0L, 0L, 0L};
X#endif
X
Xint ntasks = 1;			/* Number of tasks */
Xint sleeptime = 0;		/* Time to sleep */
Xint iters = 1000;		/* iterations */
Xint readq;			/* ID of read queue */
Xint writeq;			/* ID of write queue */
Xint qsema;			/* ID of semaphore for append */
Xunsigned long errcnt;		/* Error count */
Xint waitval;			/* Status return location for wait() */
Xint rid;			/* ID chosen at random */
Xint need_server; 			/* flag for server */
Xkey_t sema_key;
X
X/*
X**  Externs and function defs.
X*/
Xlong randnum(), randwc();
Xkey_t makey();
X
X/**************************************************************************
X		 #    #    ##       #    #    #
X		 ##  ##   #  #      #    ##   #
X		 # ## #  #    #     #    # #  #
X		 #    #  ######     #    #  # #
X		 #    #  #    #     #    #   ##
X		 #    #  #    #     #    #    #
X****************************************************************************/
Xmain(argc,argv,envp)
Xint argc;
Xchar *argv[];
Xchar **envp;
X{
X
X	int i,j,cerr;		/* Loop variables */
X
X	/*
X	* Make sure we have proper input.
X	*/
X	if(argc<2)
X	{
X	fprintf(stderr,
X	  "usage: %s datafile [ntasks] [sleeptime] [iter]\n",argv[0]);
X	exit(1);
X	}
X
X	/************* process command line parameters ************/
X	/*
X	* Get number of tasks and sleeptime.
X	*/
X	if(argc==5)
X		{
X		if((iters=atoi(argv[4]))<=0)
X
X			{
X			fprintf(stderr,"**Illegal iter\n");
X			exit(1);
X			}
X		}
X
X	if(argc >=4)
X	{
X		if((sleeptime=atoi(argv[3]))<0)
X			{
X			fprintf(stderr,"**Illegal sleep time\n");
X			exit(1);
X			}
X	}
X
X	if(argc >=3)
X		{
X		if((ntasks=atoi(argv[2]))<=0)
X			{
X			fprintf(stderr,"**Illegal ntasks\n");
X			exit(1);
X			}
X		}
X	
X	/* argv[1] is the data file name */
X
X	/*
X	* Make sure the server is active.
X	*/
X
X        sema_key=makey(SEMA);
X	/* test to see if the server is already running */
X	if((qsema=semget(sema_key,2,0))==ERROR)
X		{
X		int bad_news();
X
X		/* fork off for an exec to the server */
X		if(!(j=fork())) /* this is the child aspiring to be */
X			{	/* a server */
X#ifdef DEBUG
X			printf("I am the child (%d) aspiring to be a server\nn",
X			   getpid());
X#endif
X			argv[0]="dbmserv";
X			execvp(argv[0],argv);
X			/* if it gets this far, exec must have failed */
X			perror("exec of dbmserv failed");
X			exit(1);
X			}
X		/* better not do anything until the server
X		 * is running. Just wait for the server,
X		 * in this case a child process, gives us
X		 * signal to proceed.
X		 */
X		signal(SIGALRM,bad_news);
X		alarm(30); /* give the server 30 seconds to get it going */
X		while ((qsema=semget(sema_key,1,0))==ERROR)
X			{
X#ifdef DEBUG
X			printf("waiting for server\n");
X#endif
X			sleep(1);
X			}
X
X                }	
X
X	/* get the message queue ids */
X	if((readq=msgget(makey(RQUEUE),0))==ERROR)
X		{
X		qerror("Client getting read queue id");
X		exit(1);
X		}
X#ifdef DEBUG
X	else
X		printf("read queue id is %d\n",readq);
X#endif
X	if((writeq=msgget(makey(WQUEUE),0))==ERROR)
X		{
X		qerror("Client getting write queue id");
X		exit(1);
X		}
X#ifdef DEBUG
X	else
X		printf("write queue id is %d\n",readq);
X#endif
X	/*
X	* Now fork off a bunch of processes, giving each
X	* one a different starting seed.
X	* (if fork() returns zero, this is already the child.
X	*/
X	i=ntasks;
X	do {
X		j=fork();
X	} while((j!=0)&&(--i!=0));
X
X	/*
X	* Am I a child or a father?
X	*/
X	if( j==0)
X	{
X#ifdef DEBUG
X	printf("I am child client %d\n",getpid());
X#endif
X		/* ***Child process*** */
X		if((cerr=dotests(i,iters))!=0)
X		{
X		fprintf(stderr,"**Child error:\n");
X		switch(cerr)
X		   {
X		   case(QERR):
X			qerror("    Error is");
X			break;
X		   case(SEMERR):
X			serror("    Error is");
X			break;
X		   default:
X			perror("    Error is");
X			break;
X		   }
X		exit(1);	/* If any error - just die. */
X		}
X		else
X		{
X		clearrec(myreq.data.recdat);
X#ifdef VERBOSE
X		/*
X		** Log net elapsed time.
X		*/
X		   sprintf(myreq.data.recdat,"%#010ld %#010ld %#010ld %#010d ",
X			tottime.cpu,tottime.system,tottime.real,errcnt);
X#else
X		   sprintf(myreq.data.recdat,"%#010d ", errcnt);
X#endif
X		   myreq.type=RESULTREQ;
X		   if(semop(qsema,&lockq,1) == ERROR) exit(0);
X		   if(msgsnd(writeq,&myreq,RECLEN,0)<0)
X			exit(0);
X		   if(semop(qsema,&unlockq,1) == ERROR) exit(0);
X
X		exit(0);
X		}
X	}
X	else
X	{
X#ifdef DEBUG
X	printf("I am parent client %d\n",getpid());
X#endif
X		/* ***Father process*** */
X		/*
X		** Wait for the children to complete.
X		*/
X		i=ntasks;
X		while(i--) wait(&waitval);
X
X		/*
X		** Now tell the server to go away.
X		** Note that if we have trouble (for some reason)
X		** getting the semaphore...we just barrel on through.
X		*/
X		myreq.data.request=DIEREQ;
X		myreq.type=1L; /* Pid not needed */
X		if(msgsnd(writeq,&myreq,RECLEN,0)<0)
X			qerror("**Message queue error during termination\n");
X		exit(0);
X	}
X}
X
X/********************************* dotests *************************
X** Execute tests.
X** Input number acts as seed for random number generator.
X** Returns -1 if failure.
X********************************************************************/
Xint
Xdotests(sseed,iter)
Xint sseed;
Xint iter;			/* Number of iterations */
X{
X
X	int i,j;		/* Loop variables */
X	int maxid;		/* Max ID currently in database */
X	long mypid;		/* Get my process id */
X
X	/*
X	** Initialize the random number seed.
X	*/
X	randnum((unsigned long)sseed);
X
X	/*
X	** Initialize error count and timer stuff.
X	*/
X	errcnt=0;
X
X	/*
X	** I need to know my process id.
X	*/
X	mypid = (long)getpid();
X
X	/*
X	** Find out what the maximum id in the database
X	** is.
X	*/
X	myreq.data.request=GETLREQ;
X	myreq.type=mypid;
X#ifdef DEBUG
X printf("About to send 1st transmission\n");
X#endif
X	if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
X	if(msgsnd(writeq,&myreq,RECLEN,0)<0) return(QERR);
X	if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0) return(QERR);
X	if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
X#ifdef DEBUG
X printf("maxid string  = %s\n",hisresp.data.recdat);
X#endif
X	maxid=atoi(hisresp.data.recdat);
X#ifdef DEBUG
X printf("maxid = %d\n",maxid);
X#endif
X
X	/*
X	** Now loop through the tests iter times.
X	*/
X	for(i=0;i<iter;i++)
X	{
X#ifdef DEBUG
X printf("In outer loop of client\n");
X#endif
X		/* Do 4 reads */
X		for(j=0;j<4;j++)
X		{
X#ifdef DEBUG
X printf("In inner loop of client\n");
X#endif
X			rid=(int)randwc(maxid)+1;
X			clearrec(myreq.data.recdat);
X			sprintf(myreq.data.recdat,"%#04d",rid);
X			myreq.data.request=READREQ;
X
X#ifdef VERBOSE
X			/* Turn on timer */
X			stopwatch.real = times(&tbuff);
X			stopwatch.system = tbuff.tms_stime;
X			stopwatch.cpu = tbuff.tms_utime;
X#endif
X#ifdef DEBUG
X			printf("About to read\n");
X#endif
X
X			if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
X			if(msgsnd(writeq,&myreq,RECLEN,0)<0)
X				return(QERR);
X			if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0)
X				return(QERR);
X			if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
X
X
X#ifdef VERBOSE
X			/* Turn off timer */
X			tottime.real += times(&tbuff)-stopwatch.real;
X			tottime.system += tbuff.tms_stime-stopwatch.system;
X			tottime.cpu += tbuff.tms_utime-stopwatch.cpu;
X
X#endif
X			/* Did we get what we should? */
X			errcnt+=verify();
X		}
X
X		/* Do 1 write */
X		rid=(int)randwc(maxid)+1;
X		clearrec(myreq.data.recdat);
X		sprintf(myreq.data.recdat,"%#04d",rid);
X		loadrec((rid-1)%10);
X		strncpy(myreq.data.recdat+4,myrec.name,RECLEN-4);
X		myreq.data.request=WRITEREQ;
X
X#ifdef VERBOSE
X		/* Turn on timer */
X		stopwatch.real = times(&tbuff);
X		stopwatch.system = tbuff.tms_stime;
X		stopwatch.cpu = tbuff.tms_utime;
X#endif
X
X		if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
X		if(msgsnd(writeq,&myreq,RECLEN,0)<0)
X			return(QERR);
X		if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0)
X			return(QERR);
X		if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
X#ifdef DEBUG
X		printf("Message recieved\n");
X#endif
X
X#ifdef VERBOSE
X		/* Turn off timer */
X		tottime.real += times(&tbuff)-stopwatch.real;
X		tottime.system += tbuff.tms_stime-stopwatch.system;
X		tottime.cpu += tbuff.tms_utime-stopwatch.cpu;
X#endif
X
X		if(hisresp.data.request!=(long)AOK) errcnt++;
X		/* Sleep a little */
X		if(sleeptime) sleep(sleeptime);
X
X		/* Do an append every 10 times through the loop */
X		if((i%10)==0)
X		{
X		myreq.data.request=GETLREQ;
X
X#ifdef VERBOSE
X		/* Turn on timer */
X		stopwatch.real = times(&tbuff);
X		stopwatch.system = tbuff.tms_stime;
X		stopwatch.cpu = tbuff.tms_utime;
X#endif
X		if(semop(qsema,&locka,1)==ERROR) return(SEMERR);
X		if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
X		if(msgsnd(writeq,&myreq,RECLEN,0)<0) return(QERR);
X		if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0)
X		  return(QERR);
X		if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
X
X#ifdef VERBOSE
X		/* Turn off timer */
X		tottime.real += times(&tbuff)-stopwatch.real;
X		tottime.system += tbuff.tms_stime-stopwatch.system;
X		tottime.cpu += tbuff.tms_utime-stopwatch.cpu;
X#endif
X
X		maxid=atoi(hisresp.data.recdat);
X		rid=(maxid+=1);
X		clearrec(myreq.data.recdat);
X		sprintf(myreq.data.recdat,"%#04d",rid);
X		loadrec((rid-1)%10);
X		strncpy(myreq.data.recdat+4,myrec.name,RECLEN-4);
X		myreq.data.request=ADDREQ;
X
X#ifdef VERBOSE
X		/* Turn on timer */
X		stopwatch.real = times(&tbuff);
X		stopwatch.system = tbuff.tms_stime;
X		stopwatch.cpu = tbuff.tms_utime;
X#endif
X
X		if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
X		if(msgsnd(writeq,&myreq,RECLEN,0)<0) return(QERR);
X		if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0)
X		  return(QERR);
X		if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
X		if(semop(qsema,&unlocka,1)==ERROR) return(SEMERR);
X
X#ifdef VERBOSE
X		/* Turn off timer */
X		tottime.real += times(&tbuff)-stopwatch.real;
X		tottime.system += tbuff.tms_stime-stopwatch.system;
X		tottime.cpu += tbuff.tms_utime-stopwatch.cpu;
X#endif
X
X		if(hisresp.data.request!=(long)AOK) errcnt++;
X
X		/* Sleep a little */
X		if(sleeptime) sleep(sleeptime);
X
X		}
X	}
X
X	/*
X	** All's well that ends well.
X	*/
X	return(0);
X}
X
X/*
X** verify
X*/
Xint verify()
X{
X	char buffr[80];
X
X	/* Is there response an error response? */
X	if(hisresp.data.request!=(long)AOK)
X	 return(1);
X
X	/* Was it the number we were looking for? */
X	strncpy(buffr,hisresp.data.recdat,4);
X	buffr[4]='\0';
X	if(atoi(buffr)!=rid) 
X	return(1);
X
X	/* Check the record number with its contents */
X	loadrec((rid-1)%10);
X
X	if(strncmp(hisresp.data.recdat+4,myrec.name,RECLEN-4)!=0)
X		return(1);
X
X	/* Looks good */
X	return(0);
X}
X
X
X/*
X** Clear a record
X*/
Xclearrec(rptr)
Xchar *rptr;
X{
X	int i;
X
X	for(i=0;i<RECLEN;++i)
X		*rptr++='\0';
X
X 	return;
X}
X
X/*
X** Load the record up with random data.
X*/
Xloadrec(sel)
Xint sel;		/* Select which fake record */
X
X{
X
X	char *nname;
X	char *naddr;
X	char *nphon;
X
X	switch(sel)
X	{
X	case 0:	nname="Tom Thompson        ";
X		naddr="9401 Billy Willy Road                   ";
X		nphon="3334442222";
X		break;
X	case 1: nname="Steve Apiki         ";
X		naddr="50 Hawaii Way c/o Jack Lord             ";
X		nphon="1234443333";
X		break;
X	case 2: nname="Stan Diehl          ";
X		naddr="27 Hoptoad Hollow Way                   ";
X		nphon="3332221111";
X		break;
X	case 3: nname="Judy Grehan         ";
X		naddr="Suite 3, WallState Building             ";
X		nphon="9995556666";
X		break;
X	case 4: nname="Aaron Richards      ";
X		naddr="Highway 40 OverPass, Second Pylon       ";
X		nphon="8883339999";
X		break;
X	case 5: nname="Benjamin Davidson   ";
X		naddr="Under The Bridge, HeavyWater City       ";
X		nphon="7773229988";
X		break;
X	case 6: nname="Dayle Woolston      ";
X		naddr="4040 Pleasant Way, WICAT Central        ";
X		nphon="2228332299";
X		break;
X	case 7: nname="Jim Carls           ";
X		naddr="Big Oak Tree Behind Barsodie's          ";
X		nphon="32244566657";
X		break;
X	case 8: nname="Steve Smith         ";
X		naddr="7000 Aloth Cove                         ";
X		nphon="2118332929";
X		break;
X	case 9: 
X	default: nname="Blind Willy Chitlins";
X		naddr="Unavailable Until Further Notice        ";
X		nphon="3456789012";
X		break;
X	}
X
X	/*
X	** Fill the structure with fake data.
X	*/
X	strncpy(myrec.name,nname,NAMELEN);
X	strncpy(myrec.address,naddr,ADDRLEN);
X	strncpy(myrec.phone,nphon,PHONLEN);
X
X	return;
X}
X
X/*
X** randwc(num)
X** Returns random modulo num.
X*/
Xlong randwc(num)
Xlong num;
X{
X	return(randnum(0L)%num);
X}
X
X/*
X** randnum(val)
X** Second order linear congruential generator.
X** Constants suggested by J. G. Skellam.
X** If val==0, returns next member of sequence.
X**    val!=0, "seeds" generator with val.
X*/
Xlong randnum(lngval)
Xunsigned long lngval;
X{
X	register unsigned long interm;
X	static unsigned long randw[2] = { 13 , 117 };
X
X	if (lngval!=0L) randw[1]=lngval;
X
X	interm=(randw[0]*254754L+randw[1]*529562L)%999563L;
X	randw[1]=randw[0];
X	randw[0]=interm;
X	return(interm);
X}
X
X/************************** makey ******************************
X** Following routine converts an ASCII string to a key_t value.
X** This routine originally appeared in ADVANCED PROGRAMMERS GUIDE
X** TO UNIX SYSTEM V by R. Thomas, PHD; L. R. Rogers, and J. L. Yates.
X** Osborne McGraw Hill.
X*******************************************************************/
Xkey_t
Xmakey(p)
Xchar *p;
X{
X	key_t keyv;
X	int i;
X
X	if(isnumber(p))
X		keyv = (key_t)atol(p);
X	else
X	{
X		keyv=(key_t)0;
X		for(i=0;i<sizeof(key_t) && p[i];i++)
X			keyv=(keyv << 8) | p[i];
X	}
X	return(keyv);
X}
X
X/***************************** isnumber *************************/
Xint isnumber(p)
Xchar *p;
X{
X	for( ; *p && isdigit(*p); p++) ;
X	return(*p ? 0 : 1);
X}
X
X/**************************** badnews **************************/
Xint bad_news() /* things are screwed up */
X{
Xfprintf(stderr,"TIMED OUT\n");
Xexit(1);
X}
X
X/******************************** qerror **********************
X ** prints out the errormessage associate with a queue
X ***************************************************************/
Xqerror(s)
Xchar *s; /* message prefix string */
X{
Xextern int errno;
X
Xfprintf(stderr,"QUEUE ERROR: %s:\n     ",s);
Xswitch(errno)
X   {
X   case EACCES: fprintf(stderr,
X       "message queue exists, but locked out (EACCES)\n");
X       break;
X   case ENOENT: fprintf(stderr,
X       "message queue does not exist (ENOENT)\n");
X       break;
X   case ENOSPC: fprintf(stderr,
X       "too manny message queus (ENOSPC)\n");
X       break;
X   case EEXIST: fprintf(stderr,
X       "message queue exists, but locked out (EEXIST)\n");
X       break;
X   default: fprintf(stderr,
X       "unknown error (%n)",errno);
X       break;
X   }
Xreturn(0);
X}
X
X/******************************** serror **********************
X ** prints out the errormessage associate with a semaphore
X ***************************************************************/
Xserror(s)
Xchar *s; /* message prefix string */
X{
Xextern int errno;
X
Xfprintf(stderr,"SEMAPHORE ERROR: %s:\n     ",s);
Xswitch(errno)
X   {
X   case EINVAL: fprintf(stderr,
X       "invalid number of semaphore sets (EINVAL)\n");
X       break;
X   case EACCES: fprintf(stderr,
X       "semaphore exists, but invalid operation (EACCES)\n");
X       break;
X   case ENOENT: fprintf(stderr,
X       "semaphore does not exist (ENOENT)\n");
X       break;
X   case ENOSPC: fprintf(stderr,
X       "too many semaphores (ENOSPC)\n");
X       break;
X   case EEXIST: fprintf(stderr,
X       "semaphore exists, but locked out (EEXIST)\n");
X       break;
X   default: fprintf(stderr,
X       "unknown error (%n)",errno);
X       break;
X   }
Xreturn(0);
X}
END_OF_FILE
if test 19728 -ne `wc -c <'dbmscli.c'`; then
    echo shar: \"'dbmscli.c'\" unpacked with wrong size!
fi
chmod +x 'dbmscli.c'
# end of 'dbmscli.c'
fi
echo shar: End of archive 5 \(of 5\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.