home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume22 / byte-benchmarks / part05 / dbmscli.c
C/C++ Source or Header  |  1990-06-07  |  20KB  |  827 lines

  1.  
  2. /*******************************************************************************
  3.  *  The BYTE UNIX Benchmarks - Release 2
  4.  *          Module: dbmscli.c   SID: 2.4 4/17/90 16:45:36
  5.  *          
  6.  *******************************************************************************
  7.  * Bug reports, patches, comments, suggestions should be sent to:
  8.  *
  9.  *    Ben Smith or Rick Grehan at BYTE Magazine
  10.  *    bensmith@bixpb.UUCP    rick_g@bixpb.UUCP
  11.  *
  12.  *****************************************************************************
  13.  *  Modification Log:
  14.  *
  15.  *    7/6/89 - Reworked messaging system so the semaphores were no
  16.  *    longer used in all cases.  Semaphores now only control the append
  17.  *    operation.  Messages contain caller's pid in type field.
  18.  *    The semaphore also serves to indicate the presence of the server. RG
  19.  *     
  20.  *    7/6/89 - added some debugging output to VERBOSE
  21.  *    7/9/89 - ifdef code that starts server from client - problems. BSS
  22.  *    7/11/89 - Added semaphore to set.  One semaphore controls the queue,
  23.  *    the other controls the append operation. RG
  24.  *      New command line format: dbmserv <filename> <queue size>
  25.  *****************************************************************************/
  26. /*
  27.  * Multi-user DBMS simulation.
  28.  * Clients
  29.  * Database has the form:
  30.  * IIIINNNNNNNNNNNNNNNNNNNNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPPPPPPPPPP
  31.  * Where IIII is the 4-digit id number (0-padded)
  32.  *       NN... is the 20-character name
  33.  *       AA... is the 40-character address
  34.  *       PP... is the 10-character phone number
  35.  * Records are accessed by ID number (1 is the 0th record, 2 is 1st..etc.)
  36.  *
  37.  * This is the client system, which you execute with:
  38.  *      dbmscli n t i
  39.  * where:
  40.  *      n = the number of tasks to fork
  41.  *      t = is the sleep time in seconds each task waits between requests
  42.  *      i = is the number of test iterations
  43.  *
  44.  * NOTE: This version assumes Unix V compatibility.
  45.  */
  46. char id[] = "@(#) @(#)dbmscli.c:1.5 -- 7/10/89 18:54:57";
  47.  
  48. #include <stdio.h>
  49. #include <ctype.h>
  50. #include <errno.h>
  51. #include <sys/types.h>
  52. #include <sys/signal.h>
  53. #include <sys/ipc.h>
  54. #include <sys/sem.h>
  55. #include <sys/msg.h>
  56. #include <sys/param.h>
  57.  
  58. #ifdef VERBOSE
  59. #include <sys/times.h>
  60. #define DEBUG    /* remove this after debugging */
  61. #endif
  62.  
  63. #define ERROR    (-1)
  64. /*
  65. ** Record definitions.
  66. */
  67.  
  68. #define IDLEN 4
  69. #define NAMELEN 20
  70. #define ADDRLEN 40
  71. #define PHONLEN 10
  72. #define RECLEN  74    /* Sum of the above. */
  73.  
  74. /*
  75. ** Queue and semaphore names.
  76. */
  77. #define    RQUEUE    "READ"        /* Read queue */
  78. #define WQUEUE    "WRIT"        /* Write queue */
  79. #define SEMA    "SEMA"        /* Semaphore name */
  80.  
  81. /*
  82. ** Message types.
  83. */
  84. #define READREQ    1        /* Read a record */
  85. #define WRITEREQ 2        /* Write a record */
  86. #define ADDREQ 3        /* Add a new record */
  87. #define GETLREQ 4        /* Get largest record number */
  88. #define RESULTREQ 10        /* Record contains results figures */
  89.                 /* Results are stored as:
  90.                 *  nnnnnnnnnnbmmmmmmmmmmb
  91.                 *   n = total time
  92.                 *   m = number of errors
  93.                 *   b = blank
  94.                 */
  95. #define DIEREQ 99        /* Orders server to terminate. */
  96.  
  97.  
  98. /*
  99. ** Return codes from the server.
  100. */
  101. #define AOK 1            /* Request met ok */
  102. #define DERR_RNF 2        /* Record not found */
  103. #define DERR_RAE 3        /* Record already exists */
  104. #define DERR_WRD 4        /* Unexplainable error */
  105. #define DERR_UNK 9        /* Unknown request type */
  106.  
  107. /*
  108. ** Error codes.
  109. */
  110. #define QERR 1            /* Queue error */
  111. #define SEMERR 2        /* Semaphore error */
  112.  
  113. /*
  114. ** Structures.
  115. */
  116.  
  117. typedef struct {
  118.     char id[IDLEN];
  119.     char name[NAMELEN];
  120.     char address[ADDRLEN];
  121.     char phone[PHONLEN];
  122. } dbrec;
  123.  
  124. typedef struct {
  125.     int request;        /* Request type and response code */
  126.     char recdat[RECLEN];    /* DBMS record data */
  127. } msgdata;
  128.  
  129. typedef struct {
  130.     long type;        /* Hold's caller's pid */
  131.     msgdata data;        /* Pointer to request and data */
  132. } amess;
  133.  
  134. struct ticker { unsigned long real,
  135.                system,
  136.                cpu; };
  137.  
  138. /******************************************************************
  139.       ####   #        ####   #####     ##    #        ####
  140.      #    #  #       #    #  #    #   #  #   #       #
  141.      #       #       #    #  #####   #    #  #        ####
  142.      #  ###  #       #    #  #    #  ######  #            #
  143.      #    #  #       #    #  #    #  #    #  #       #    #
  144.       ####   ######   ####   #####   #    #  ######   ####
  145. *******************************************************************/
  146. /*
  147. ** Structure instances.
  148. */
  149. dbrec myrec;        /* Data record */
  150. amess myreq;        /* Client request */
  151. amess hisresp;        /* Response from server */
  152.  
  153. struct sembuf unlockq = { 0 , 1 , SEM_UNDO };
  154. struct sembuf lockq = { 0 , -1 , SEM_UNDO };
  155. struct sembuf unlocka = { 0, 1, SEM_UNDO };
  156. struct sembuf locka = { 0, -1, SEM_UNDO };
  157.  
  158. #ifdef VERBOSE
  159. struct tms tbuff;    /* For times system call */
  160. struct ticker stopwatch = {0L, 0L, 0L};
  161. struct ticker tottime = {0L, 0L, 0L};
  162. #endif
  163.  
  164. int ntasks = 1;            /* Number of tasks */
  165. int sleeptime = 0;        /* Time to sleep */
  166. int iters = 1000;        /* iterations */
  167. int readq;            /* ID of read queue */
  168. int writeq;            /* ID of write queue */
  169. int qsema;            /* ID of semaphore for append */
  170. unsigned long errcnt;        /* Error count */
  171. int waitval;            /* Status return location for wait() */
  172. int rid;            /* ID chosen at random */
  173. int need_server;             /* flag for server */
  174. key_t sema_key;
  175.  
  176. /*
  177. **  Externs and function defs.
  178. */
  179. long randnum(), randwc();
  180. key_t makey();
  181.  
  182. /**************************************************************************
  183.          #    #    ##       #    #    #
  184.          ##  ##   #  #      #    ##   #
  185.          # ## #  #    #     #    # #  #
  186.          #    #  ######     #    #  # #
  187.          #    #  #    #     #    #   ##
  188.          #    #  #    #     #    #    #
  189. ****************************************************************************/
  190. main(argc,argv,envp)
  191. int argc;
  192. char *argv[];
  193. char **envp;
  194. {
  195.  
  196.     int i,j,cerr;        /* Loop variables */
  197.  
  198.     /*
  199.     * Make sure we have proper input.
  200.     */
  201.     if(argc<2)
  202.     {
  203.     fprintf(stderr,
  204.       "usage: %s datafile [ntasks] [sleeptime] [iter]\n",argv[0]);
  205.     exit(1);
  206.     }
  207.  
  208.     /************* process command line parameters ************/
  209.     /*
  210.     * Get number of tasks and sleeptime.
  211.     */
  212.     if(argc==5)
  213.         {
  214.         if((iters=atoi(argv[4]))<=0)
  215.  
  216.             {
  217.             fprintf(stderr,"**Illegal iter\n");
  218.             exit(1);
  219.             }
  220.         }
  221.  
  222.     if(argc >=4)
  223.     {
  224.         if((sleeptime=atoi(argv[3]))<0)
  225.             {
  226.             fprintf(stderr,"**Illegal sleep time\n");
  227.             exit(1);
  228.             }
  229.     }
  230.  
  231.     if(argc >=3)
  232.         {
  233.         if((ntasks=atoi(argv[2]))<=0)
  234.             {
  235.             fprintf(stderr,"**Illegal ntasks\n");
  236.             exit(1);
  237.             }
  238.         }
  239.     
  240.     /* argv[1] is the data file name */
  241.  
  242.     /*
  243.     * Make sure the server is active.
  244.     */
  245.  
  246.         sema_key=makey(SEMA);
  247.     /* test to see if the server is already running */
  248.     if((qsema=semget(sema_key,2,0))==ERROR)
  249.         {
  250.         int bad_news();
  251.  
  252.         /* fork off for an exec to the server */
  253.         if(!(j=fork())) /* this is the child aspiring to be */
  254.             {    /* a server */
  255. #ifdef DEBUG
  256.             printf("I am the child (%d) aspiring to be a server\nn",
  257.                getpid());
  258. #endif
  259.             argv[0]="dbmserv";
  260.             execvp(argv[0],argv);
  261.             /* if it gets this far, exec must have failed */
  262.             perror("exec of dbmserv failed");
  263.             exit(1);
  264.             }
  265.         /* better not do anything until the server
  266.          * is running. Just wait for the server,
  267.          * in this case a child process, gives us
  268.          * signal to proceed.
  269.          */
  270.         signal(SIGALRM,bad_news);
  271.         alarm(30); /* give the server 30 seconds to get it going */
  272.         while ((qsema=semget(sema_key,1,0))==ERROR)
  273.             {
  274. #ifdef DEBUG
  275.             printf("waiting for server\n");
  276. #endif
  277.             sleep(1);
  278.             }
  279.  
  280.                 }    
  281.  
  282.     /* get the message queue ids */
  283.     if((readq=msgget(makey(RQUEUE),0))==ERROR)
  284.         {
  285.         qerror("Client getting read queue id");
  286.         exit(1);
  287.         }
  288. #ifdef DEBUG
  289.     else
  290.         printf("read queue id is %d\n",readq);
  291. #endif
  292.     if((writeq=msgget(makey(WQUEUE),0))==ERROR)
  293.         {
  294.         qerror("Client getting write queue id");
  295.         exit(1);
  296.         }
  297. #ifdef DEBUG
  298.     else
  299.         printf("write queue id is %d\n",readq);
  300. #endif
  301.     /*
  302.     * Now fork off a bunch of processes, giving each
  303.     * one a different starting seed.
  304.     * (if fork() returns zero, this is already the child.
  305.     */
  306.     i=ntasks;
  307.     do {
  308.         j=fork();
  309.     } while((j!=0)&&(--i!=0));
  310.  
  311.     /*
  312.     * Am I a child or a father?
  313.     */
  314.     if( j==0)
  315.     {
  316. #ifdef DEBUG
  317.     printf("I am child client %d\n",getpid());
  318. #endif
  319.         /* ***Child process*** */
  320.         if((cerr=dotests(i,iters))!=0)
  321.         {
  322.         fprintf(stderr,"**Child error:\n");
  323.         switch(cerr)
  324.            {
  325.            case(QERR):
  326.             qerror("    Error is");
  327.             break;
  328.            case(SEMERR):
  329.             serror("    Error is");
  330.             break;
  331.            default:
  332.             perror("    Error is");
  333.             break;
  334.            }
  335.         exit(1);    /* If any error - just die. */
  336.         }
  337.         else
  338.         {
  339.         clearrec(myreq.data.recdat);
  340. #ifdef VERBOSE
  341.         /*
  342.         ** Log net elapsed time.
  343.         */
  344.            sprintf(myreq.data.recdat,"%#010ld %#010ld %#010ld %#010d ",
  345.             tottime.cpu,tottime.system,tottime.real,errcnt);
  346. #else
  347.            sprintf(myreq.data.recdat,"%#010d ", errcnt);
  348. #endif
  349.            myreq.type=RESULTREQ;
  350.            if(semop(qsema,&lockq,1) == ERROR) exit(0);
  351.            if(msgsnd(writeq,&myreq,RECLEN,0)<0)
  352.             exit(0);
  353.            if(semop(qsema,&unlockq,1) == ERROR) exit(0);
  354.  
  355.         exit(0);
  356.         }
  357.     }
  358.     else
  359.     {
  360. #ifdef DEBUG
  361.     printf("I am parent client %d\n",getpid());
  362. #endif
  363.         /* ***Father process*** */
  364.         /*
  365.         ** Wait for the children to complete.
  366.         */
  367.         i=ntasks;
  368.         while(i--) wait(&waitval);
  369.  
  370.         /*
  371.         ** Now tell the server to go away.
  372.         ** Note that if we have trouble (for some reason)
  373.         ** getting the semaphore...we just barrel on through.
  374.         */
  375.         myreq.data.request=DIEREQ;
  376.         myreq.type=1L; /* Pid not needed */
  377.         if(msgsnd(writeq,&myreq,RECLEN,0)<0)
  378.             qerror("**Message queue error during termination\n");
  379.         exit(0);
  380.     }
  381. }
  382.  
  383. /********************************* dotests *************************
  384. ** Execute tests.
  385. ** Input number acts as seed for random number generator.
  386. ** Returns -1 if failure.
  387. ********************************************************************/
  388. int
  389. dotests(sseed,iter)
  390. int sseed;
  391. int iter;            /* Number of iterations */
  392. {
  393.  
  394.     int i,j;        /* Loop variables */
  395.     int maxid;        /* Max ID currently in database */
  396.     long mypid;        /* Get my process id */
  397.  
  398.     /*
  399.     ** Initialize the random number seed.
  400.     */
  401.     randnum((unsigned long)sseed);
  402.  
  403.     /*
  404.     ** Initialize error count and timer stuff.
  405.     */
  406.     errcnt=0;
  407.  
  408.     /*
  409.     ** I need to know my process id.
  410.     */
  411.     mypid = (long)getpid();
  412.  
  413.     /*
  414.     ** Find out what the maximum id in the database
  415.     ** is.
  416.     */
  417.     myreq.data.request=GETLREQ;
  418.     myreq.type=mypid;
  419. #ifdef DEBUG
  420.  printf("About to send 1st transmission\n");
  421. #endif
  422.     if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
  423.     if(msgsnd(writeq,&myreq,RECLEN,0)<0) return(QERR);
  424.     if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0) return(QERR);
  425.     if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
  426. #ifdef DEBUG
  427.  printf("maxid string  = %s\n",hisresp.data.recdat);
  428. #endif
  429.     maxid=atoi(hisresp.data.recdat);
  430. #ifdef DEBUG
  431.  printf("maxid = %d\n",maxid);
  432. #endif
  433.  
  434.     /*
  435.     ** Now loop through the tests iter times.
  436.     */
  437.     for(i=0;i<iter;i++)
  438.     {
  439. #ifdef DEBUG
  440.  printf("In outer loop of client\n");
  441. #endif
  442.         /* Do 4 reads */
  443.         for(j=0;j<4;j++)
  444.         {
  445. #ifdef DEBUG
  446.  printf("In inner loop of client\n");
  447. #endif
  448.             rid=(int)randwc(maxid)+1;
  449.             clearrec(myreq.data.recdat);
  450.             sprintf(myreq.data.recdat,"%#04d",rid);
  451.             myreq.data.request=READREQ;
  452.  
  453. #ifdef VERBOSE
  454.             /* Turn on timer */
  455.             stopwatch.real = times(&tbuff);
  456.             stopwatch.system = tbuff.tms_stime;
  457.             stopwatch.cpu = tbuff.tms_utime;
  458. #endif
  459. #ifdef DEBUG
  460.             printf("About to read\n");
  461. #endif
  462.  
  463.             if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
  464.             if(msgsnd(writeq,&myreq,RECLEN,0)<0)
  465.                 return(QERR);
  466.             if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0)
  467.                 return(QERR);
  468.             if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
  469.  
  470.  
  471. #ifdef VERBOSE
  472.             /* Turn off timer */
  473.             tottime.real += times(&tbuff)-stopwatch.real;
  474.             tottime.system += tbuff.tms_stime-stopwatch.system;
  475.             tottime.cpu += tbuff.tms_utime-stopwatch.cpu;
  476.  
  477. #endif
  478.             /* Did we get what we should? */
  479.             errcnt+=verify();
  480.         }
  481.  
  482.         /* Do 1 write */
  483.         rid=(int)randwc(maxid)+1;
  484.         clearrec(myreq.data.recdat);
  485.         sprintf(myreq.data.recdat,"%#04d",rid);
  486.         loadrec((rid-1)%10);
  487.         strncpy(myreq.data.recdat+4,myrec.name,RECLEN-4);
  488.         myreq.data.request=WRITEREQ;
  489.  
  490. #ifdef VERBOSE
  491.         /* Turn on timer */
  492.         stopwatch.real = times(&tbuff);
  493.         stopwatch.system = tbuff.tms_stime;
  494.         stopwatch.cpu = tbuff.tms_utime;
  495. #endif
  496.  
  497.         if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
  498.         if(msgsnd(writeq,&myreq,RECLEN,0)<0)
  499.             return(QERR);
  500.         if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0)
  501.             return(QERR);
  502.         if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
  503. #ifdef DEBUG
  504.         printf("Message recieved\n");
  505. #endif
  506.  
  507. #ifdef VERBOSE
  508.         /* Turn off timer */
  509.         tottime.real += times(&tbuff)-stopwatch.real;
  510.         tottime.system += tbuff.tms_stime-stopwatch.system;
  511.         tottime.cpu += tbuff.tms_utime-stopwatch.cpu;
  512. #endif
  513.  
  514.         if(hisresp.data.request!=(long)AOK) errcnt++;
  515.         /* Sleep a little */
  516.         if(sleeptime) sleep(sleeptime);
  517.  
  518.         /* Do an append every 10 times through the loop */
  519.         if((i%10)==0)
  520.         {
  521.         myreq.data.request=GETLREQ;
  522.  
  523. #ifdef VERBOSE
  524.         /* Turn on timer */
  525.         stopwatch.real = times(&tbuff);
  526.         stopwatch.system = tbuff.tms_stime;
  527.         stopwatch.cpu = tbuff.tms_utime;
  528. #endif
  529.         if(semop(qsema,&locka,1)==ERROR) return(SEMERR);
  530.         if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
  531.         if(msgsnd(writeq,&myreq,RECLEN,0)<0) return(QERR);
  532.         if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0)
  533.           return(QERR);
  534.         if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
  535.  
  536. #ifdef VERBOSE
  537.         /* Turn off timer */
  538.         tottime.real += times(&tbuff)-stopwatch.real;
  539.         tottime.system += tbuff.tms_stime-stopwatch.system;
  540.         tottime.cpu += tbuff.tms_utime-stopwatch.cpu;
  541. #endif
  542.  
  543.         maxid=atoi(hisresp.data.recdat);
  544.         rid=(maxid+=1);
  545.         clearrec(myreq.data.recdat);
  546.         sprintf(myreq.data.recdat,"%#04d",rid);
  547.         loadrec((rid-1)%10);
  548.         strncpy(myreq.data.recdat+4,myrec.name,RECLEN-4);
  549.         myreq.data.request=ADDREQ;
  550.  
  551. #ifdef VERBOSE
  552.         /* Turn on timer */
  553.         stopwatch.real = times(&tbuff);
  554.         stopwatch.system = tbuff.tms_stime;
  555.         stopwatch.cpu = tbuff.tms_utime;
  556. #endif
  557.  
  558.         if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
  559.         if(msgsnd(writeq,&myreq,RECLEN,0)<0) return(QERR);
  560.         if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0)
  561.           return(QERR);
  562.         if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
  563.         if(semop(qsema,&unlocka,1)==ERROR) return(SEMERR);
  564.  
  565. #ifdef VERBOSE
  566.         /* Turn off timer */
  567.         tottime.real += times(&tbuff)-stopwatch.real;
  568.         tottime.system += tbuff.tms_stime-stopwatch.system;
  569.         tottime.cpu += tbuff.tms_utime-stopwatch.cpu;
  570. #endif
  571.  
  572.         if(hisresp.data.request!=(long)AOK) errcnt++;
  573.  
  574.         /* Sleep a little */
  575.         if(sleeptime) sleep(sleeptime);
  576.  
  577.         }
  578.     }
  579.  
  580.     /*
  581.     ** All's well that ends well.
  582.     */
  583.     return(0);
  584. }
  585.  
  586. /*
  587. ** verify
  588. */
  589. int verify()
  590. {
  591.     char buffr[80];
  592.  
  593.     /* Is there response an error response? */
  594.     if(hisresp.data.request!=(long)AOK)
  595.      return(1);
  596.  
  597.     /* Was it the number we were looking for? */
  598.     strncpy(buffr,hisresp.data.recdat,4);
  599.     buffr[4]='\0';
  600.     if(atoi(buffr)!=rid) 
  601.     return(1);
  602.  
  603.     /* Check the record number with its contents */
  604.     loadrec((rid-1)%10);
  605.  
  606.     if(strncmp(hisresp.data.recdat+4,myrec.name,RECLEN-4)!=0)
  607.         return(1);
  608.  
  609.     /* Looks good */
  610.     return(0);
  611. }
  612.  
  613.  
  614. /*
  615. ** Clear a record
  616. */
  617. clearrec(rptr)
  618. char *rptr;
  619. {
  620.     int i;
  621.  
  622.     for(i=0;i<RECLEN;++i)
  623.         *rptr++='\0';
  624.  
  625.      return;
  626. }
  627.  
  628. /*
  629. ** Load the record up with random data.
  630. */
  631. loadrec(sel)
  632. int sel;        /* Select which fake record */
  633.  
  634. {
  635.  
  636.     char *nname;
  637.     char *naddr;
  638.     char *nphon;
  639.  
  640.     switch(sel)
  641.     {
  642.     case 0:    nname="Tom Thompson        ";
  643.         naddr="9401 Billy Willy Road                   ";
  644.         nphon="3334442222";
  645.         break;
  646.     case 1: nname="Steve Apiki         ";
  647.         naddr="50 Hawaii Way c/o Jack Lord             ";
  648.         nphon="1234443333";
  649.         break;
  650.     case 2: nname="Stan Diehl          ";
  651.         naddr="27 Hoptoad Hollow Way                   ";
  652.         nphon="3332221111";
  653.         break;
  654.     case 3: nname="Judy Grehan         ";
  655.         naddr="Suite 3, WallState Building             ";
  656.         nphon="9995556666";
  657.         break;
  658.     case 4: nname="Aaron Richards      ";
  659.         naddr="Highway 40 OverPass, Second Pylon       ";
  660.         nphon="8883339999";
  661.         break;
  662.     case 5: nname="Benjamin Davidson   ";
  663.         naddr="Under The Bridge, HeavyWater City       ";
  664.         nphon="7773229988";
  665.         break;
  666.     case 6: nname="Dayle Woolston      ";
  667.         naddr="4040 Pleasant Way, WICAT Central        ";
  668.         nphon="2228332299";
  669.         break;
  670.     case 7: nname="Jim Carls           ";
  671.         naddr="Big Oak Tree Behind Barsodie's          ";
  672.         nphon="32244566657";
  673.         break;
  674.     case 8: nname="Steve Smith         ";
  675.         naddr="7000 Aloth Cove                         ";
  676.         nphon="2118332929";
  677.         break;
  678.     case 9: 
  679.     default: nname="Blind Willy Chitlins";
  680.         naddr="Unavailable Until Further Notice        ";
  681.         nphon="3456789012";
  682.         break;
  683.     }
  684.  
  685.     /*
  686.     ** Fill the structure with fake data.
  687.     */
  688.     strncpy(myrec.name,nname,NAMELEN);
  689.     strncpy(myrec.address,naddr,ADDRLEN);
  690.     strncpy(myrec.phone,nphon,PHONLEN);
  691.  
  692.     return;
  693. }
  694.  
  695. /*
  696. ** randwc(num)
  697. ** Returns random modulo num.
  698. */
  699. long randwc(num)
  700. long num;
  701. {
  702.     return(randnum(0L)%num);
  703. }
  704.  
  705. /*
  706. ** randnum(val)
  707. ** Second order linear congruential generator.
  708. ** Constants suggested by J. G. Skellam.
  709. ** If val==0, returns next member of sequence.
  710. **    val!=0, "seeds" generator with val.
  711. */
  712. long randnum(lngval)
  713. unsigned long lngval;
  714. {
  715.     register unsigned long interm;
  716.     static unsigned long randw[2] = { 13 , 117 };
  717.  
  718.     if (lngval!=0L) randw[1]=lngval;
  719.  
  720.     interm=(randw[0]*254754L+randw[1]*529562L)%999563L;
  721.     randw[1]=randw[0];
  722.     randw[0]=interm;
  723.     return(interm);
  724. }
  725.  
  726. /************************** makey ******************************
  727. ** Following routine converts an ASCII string to a key_t value.
  728. ** This routine originally appeared in ADVANCED PROGRAMMERS GUIDE
  729. ** TO UNIX SYSTEM V by R. Thomas, PHD; L. R. Rogers, and J. L. Yates.
  730. ** Osborne McGraw Hill.
  731. *******************************************************************/
  732. key_t
  733. makey(p)
  734. char *p;
  735. {
  736.     key_t keyv;
  737.     int i;
  738.  
  739.     if(isnumber(p))
  740.         keyv = (key_t)atol(p);
  741.     else
  742.     {
  743.         keyv=(key_t)0;
  744.         for(i=0;i<sizeof(key_t) && p[i];i++)
  745.             keyv=(keyv << 8) | p[i];
  746.     }
  747.     return(keyv);
  748. }
  749.  
  750. /***************************** isnumber *************************/
  751. int isnumber(p)
  752. char *p;
  753. {
  754.     for( ; *p && isdigit(*p); p++) ;
  755.     return(*p ? 0 : 1);
  756. }
  757.  
  758. /**************************** badnews **************************/
  759. int bad_news() /* things are screwed up */
  760. {
  761. fprintf(stderr,"TIMED OUT\n");
  762. exit(1);
  763. }
  764.  
  765. /******************************** qerror **********************
  766.  ** prints out the errormessage associate with a queue
  767.  ***************************************************************/
  768. qerror(s)
  769. char *s; /* message prefix string */
  770. {
  771. extern int errno;
  772.  
  773. fprintf(stderr,"QUEUE ERROR: %s:\n     ",s);
  774. switch(errno)
  775.    {
  776.    case EACCES: fprintf(stderr,
  777.        "message queue exists, but locked out (EACCES)\n");
  778.        break;
  779.    case ENOENT: fprintf(stderr,
  780.        "message queue does not exist (ENOENT)\n");
  781.        break;
  782.    case ENOSPC: fprintf(stderr,
  783.        "too manny message queus (ENOSPC)\n");
  784.        break;
  785.    case EEXIST: fprintf(stderr,
  786.        "message queue exists, but locked out (EEXIST)\n");
  787.        break;
  788.    default: fprintf(stderr,
  789.        "unknown error (%n)",errno);
  790.        break;
  791.    }
  792. return(0);
  793. }
  794.  
  795. /******************************** serror **********************
  796.  ** prints out the errormessage associate with a semaphore
  797.  ***************************************************************/
  798. serror(s)
  799. char *s; /* message prefix string */
  800. {
  801. extern int errno;
  802.  
  803. fprintf(stderr,"SEMAPHORE ERROR: %s:\n     ",s);
  804. switch(errno)
  805.    {
  806.    case EINVAL: fprintf(stderr,
  807.        "invalid number of semaphore sets (EINVAL)\n");
  808.        break;
  809.    case EACCES: fprintf(stderr,
  810.        "semaphore exists, but invalid operation (EACCES)\n");
  811.        break;
  812.    case ENOENT: fprintf(stderr,
  813.        "semaphore does not exist (ENOENT)\n");
  814.        break;
  815.    case ENOSPC: fprintf(stderr,
  816.        "too many semaphores (ENOSPC)\n");
  817.        break;
  818.    case EEXIST: fprintf(stderr,
  819.        "semaphore exists, but locked out (EEXIST)\n");
  820.        break;
  821.    default: fprintf(stderr,
  822.        "unknown error (%n)",errno);
  823.        break;
  824.    }
  825. return(0);
  826. }
  827.