source: trunk/src/seismic_processing/eqprelim/eqprelim.c @ 3162

Revision 3162, 44.9 KB checked in by dietz, 11 years ago (diff)

Added config file option "ReportCoda?" to control whether codas are
written to the output or not.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1
2/*
3 *   THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE
4 *   CHECKED IT OUT USING THE COMMAND CHECKOUT.
5 *
6 *    $Id$
7 *
8 *    Revision history:
9 *     $Log$
10 *     Revision 1.9  2007/11/30 00:03:30  dietz
11 *     Added config file option "ReportCoda" to control whether codas are
12 *     written to the output or not.
13 *
14 *     Revision 1.8  2007/02/26 19:50:03  paulf
15 *     fixed a ton of windows warnings
16 *
17 *     Revision 1.7  2007/02/26 13:44:40  paulf
18 *     fixed heartbeat sprintf() to cast time_t as long
19 *
20 *     Revision 1.6  2005/03/11 18:08:12  dietz
21 *     Modified to make pick/quake FIFO lengths configurable
22 *
23 *     Revision 1.5  2004/05/17 22:16:53  dietz
24 *     Modified to work with TYPE_PICK_SCNL and TYPE_CODA_SCNL as input
25 *     and to output TYPE_EVENT_SCNL.
26 *
27 *     Revision 1.4  2002/06/05 15:48:52  patton
28 *     Made logit changes.
29 *
30 *     Revision 1.3  2001/05/09 18:38:18  dietz
31 *     Changed to shut down gracefully if the transport flag is
32 *     set to TERMINATE or MyPID.
33 *
34 *     Revision 1.2  2000/07/24 20:38:44  lucky
35 *     Implemented global limits to module, installation, ring, and
36 *     message type strings.
37 *
38 *     Revision 1.1  2000/02/14 17:10:42  lucky
39 *     Initial revision
40 *
41 *
42 */
43
44/*
45 * eqprelim.c : Send out a preliminary event notification
46 *              after a user-set number of picks are associated
47 *              with it.
48 */
49#include <stdio.h>
50#include <stdlib.h>
51#include <string.h>
52#include <time.h>
53#include <math.h>
54#include <chron3.h>
55#include <earthworm.h>
56#include <kom.h>
57#include <rdpickcoda.h>
58#include <site.h>
59#include <tlay.h>
60#include <transport.h>
61
62#define ABS(x) (((x) >= 0.0) ? (x) : -(x))
63#define X(lon) (facLon * ((lon) - orgLon))
64#define Y(lat) (facLat * ((lat) - orgLat))
65#define hypot(x,y) (sqrt((x)*(x) + (y)*(y)))
66
67/* Functions in this source file
68 *******************************/
69void  eqprelim_config ( char * );
70void  eqprelim_lookup ( void );
71int   eqprelim_pickscnl( char * );
72int   eqprelim_codascnl( char * );
73int   eqprelim_link   ( char * );
74int   eqprelim_quake2k( char * );
75int   eqprelim_compare( const void *, const void * );
76void  eqprelim_notify ( int );
77void  eqprelim_status ( unsigned char, short, char * );
78char *eqprelim_phscard( int, char * );
79char *eqprelim_hypcard( int, char * );
80
81static SHM_INFO  Region;         /* shared memory region to use for input  */
82
83#define   MAXLOGO   8
84MSG_LOGO  GetLogo[MAXLOGO];     /* array for requesting module,type,instid */
85short     nLogo;
86
87/* Things to read from configuration file
88 ****************************************/
89static char RingName[MAX_RING_STR];       /* transport ring to read from    */
90static char MyModName[MAX_MOD_STR];      /* speak as this module name/id    */
91static int  LogSwitch;          /* 0 if no logging should be done to disk   */
92static char NextProc[150];      /* actual command to start next program     */
93static int  ReportS;            /* if 0, don't send S to next process       */
94static int  ReportCoda = 1;     /* if 0, don't send codas to next process   */
95static int  NumPickNotify;      /* send prelim eq if it has this many picks */
96static char LocalCode;          /* single char to label local picks with    */
97static long HeartbeatInt;       /* #seconds between heartbeats              */
98
99/* Things to look up in the earthworm.h tables with getutil.c functions
100 **********************************************************************/
101static long          RingKey;       /* key of ring for input         */
102static unsigned char InstId;        /* local installation id         */
103static unsigned char MyModId;       /* Module Id for this program    */
104static unsigned char TypeHeartBeat;
105static unsigned char TypeError;
106static unsigned char TypeQuake2K;
107static unsigned char TypeLink;
108static unsigned char TypePickSCNL;
109static unsigned char TypeCodaSCNL;
110static unsigned char TypeEventSCNL;
111static unsigned char TypeKill;
112
113static char  EqMsg[MAX_BYTES_PER_EQ]; /* char array to hold eq message  */
114
115/* Error messages used by eqprelim
116 *********************************/
117#define  ERR_MISSMSG            0
118#define  ERR_TOOBIG             1
119#define  ERR_NOTRACK            2
120#define  ERR_PICKREAD           3
121#define  ERR_CODAREAD           4
122#define  ERR_QUAKEREAD          5
123#define  ERR_LINKREAD           6
124#define  ERR_UNKNOWNSTA         7
125#define  ERR_TIMEDECODE         8
126
127#define  MAXSTRLEN            256
128static char  Text[MAXSTRLEN];  /* string for log/error messages */
129
130#define MAXHYP 100     /* default quake fifo length */
131typedef struct {
132        double  trpt;  /* time the event was reported */
133        double  t;
134        double  lat;
135        double  lon;
136        double  z;
137        long    id;
138        float   rms;
139        float   dmin;
140        float   ravg;
141        float   gap;
142        int     nph;
143        short   flag;    /* 0=virgin, 1=modified, 2=reported, -1=killed  */
144} RPT_HYP;
145RPT_HYP *Hyp; /* alloc to length=maxHyp */
146
147#define MAXPCK 1000   /* default pick fifo length */
148long nPck = 0;
149typedef struct {
150        double          t;
151        long            quake;
152        int             id;
153        unsigned char   src;
154        unsigned char   instid;
155        int             site;
156        char            phase;
157        char            ie;
158        char            fm;
159        char            wt;
160        long            pamp[3];
161        long            paav;
162        long            caav[6];
163        short           clen;
164        time_t          timeout;
165} RPT_PCK;
166RPT_PCK *Pck; /* alloc to length=maxPck */
167
168int nSrt;
169typedef struct {
170        double  t;
171        int     ip;
172} SRT;
173SRT *Srt; /* alloc to length=maxPck */
174
175/* Parameters
176 ************/
177double orgLat;
178double orgLon;
179double facLat;
180double facLon;
181size_t maxHyp = MAXHYP;         /* Quake FIFO length                    */
182size_t maxPck = MAXPCK;         /* Pick  FIFO length                    */
183pid_t  MyPID=0;
184
185int main( int argc, char **argv )
186{
187   char       rec[MAXSTRLEN];   /* actual retrieved message  */
188   long       recsize;          /* size of retrieved message */
189   MSG_LOGO   reclogo;          /* logo of retrieved message */
190   int        res;
191   int        iq;
192   int        is;
193   time_t     timeNow;          /* current time                */
194   time_t     timeLastBeat;     /* time of previous heartbeat  */
195
196/* Check command line arguments
197 ******************************/
198   if ( argc != 2 )
199   {
200        fprintf( stderr, "Usage: eqprelim <configfile>\n" );
201        exit( 0 );
202   }
203
204/* Initialize name of log-file & open it
205 ***************************************/
206   logit_init( argv[1], 0, MAXSTRLEN*2, 1 );
207
208/* Read the configuration file(s)
209 ********************************/
210   eqprelim_config( argv[1] );
211   logit( "" , "eqprelim: Read command file <%s>\n", argv[1] );
212
213/* Look up important info from earthworm.h tables
214 ************************************************/
215   eqprelim_lookup();
216
217/* Store my own processid
218 ************************/
219   MyPID = getpid();
220 
221/* Reinitialize logit to desired logging level
222 *********************************************/
223   logit_init( argv[1], 0, MAXSTRLEN*2, LogSwitch );
224
225/* Allocate space for Quake FIFO, Pick FIFO, sorting array
226 *********************************************************/
227   Hyp = (RPT_HYP *) calloc( maxHyp, sizeof( RPT_HYP ) );
228   if( Hyp == (RPT_HYP *) NULL ) {
229      logit( "et","eqprelim: Error allocating quake FIFO at length=%ld; "
230             "exiting!\n", maxHyp );
231      exit( -1 );
232   }
233   logit( "", "eqprelim: Allocated quake fifo (length=%ld)\n", maxHyp );
234
235   Pck = (RPT_PCK *) calloc( maxPck, sizeof( RPT_PCK ) );
236   if( Pck == (RPT_PCK *) NULL ) {
237      logit( "et","eqprelim: Error allocating pick FIFO at length=%ld; "
238             "exiting!\n", maxPck );
239      free( Hyp );
240      exit( -1 );
241   }
242   logit( "", "eqprelim: Allocated pick fifo (length=%ld)\n", maxPck );
243
244   Srt = (SRT *) calloc( maxPck, sizeof( SRT ) );
245   if( Srt == (SRT *) NULL ) {
246      logit( "et","eqprelim: Error allocating sort array at length=%ld; "
247             "exiting!\n", maxPck );
248      free( Hyp );
249      free( Pck );
250      exit( -1 );
251   }
252
253/* Initialize some variables
254 ***************************/
255   nPck   = 0;                  /* no picks have been processed    */
256   for(iq=0; iq<(int)maxHyp; iq++)   /* set all hypocenter id's to zero */
257   {
258        Hyp[iq].id  = 0;
259   }
260
261/* Attach to PICK shared memory ring & flush out all old messages
262 ****************************************************************/
263   tport_attach( &Region, RingKey );
264   logit( "", "eqprelim: Attached to public memory region %s: %d\n",
265          RingName, RingKey );
266   while( tport_getmsg( &Region, GetLogo, nLogo,
267                        &reclogo, &recsize, rec, MAXSTRLEN ) != GET_NONE );
268
269/* Start the next processing program & open pipe to it
270 *****************************************************/
271   if( pipe_init( NextProc, 0 ) < 0 ) {
272        logit( "et",
273               "eqprelim: Error opening pipe to %s; exiting!\n", NextProc);
274        tport_detach( &Region );
275        free( Hyp );
276        free( Pck );
277        free( Srt );
278        exit( -1 );
279   }
280   logit( "e", "eqprelim: piping output to <%s>\n", NextProc );
281
282/* Calculate network origin
283 **************************/
284   logit( "", "eqprelim: nSite = %d\n", nSite );
285   orgLat = 0.0;
286   orgLon = 0.0;
287   for(is=0; is<nSite; is++) {
288        orgLat += Site[is].lat;
289        orgLon += Site[is].lon;
290   }
291   orgLat /= nSite;
292   orgLon /= nSite;
293   facLat = (double)(40000.0 / 360.0);
294   facLon = facLat * cos(6.283185 * orgLat / 360.0);
295
296/* Force a heartbeat to be issued in first pass thru main loop
297 *************************************************************/
298   timeLastBeat = time(&timeNow) - HeartbeatInt - 1;
299
300/*----------------- setup done; start main loop -----------------------*/
301
302   while(1)
303   {
304     /* Send eqprelim's heartbeat
305      ***************************/
306        if ( time(&timeNow) - timeLastBeat  >=  HeartbeatInt )
307        {
308            timeLastBeat = timeNow;
309            eqprelim_status( TypeHeartBeat, 0, "" );
310        }
311
312     /* Process all new hypocenter, pick-time, pick-coda, & link messages
313      *******************************************************************/
314        do
315        {
316        /* see if a termination has been requested
317         *****************************************/
318           if ( tport_getflag( &Region ) == TERMINATE  ||
319                tport_getflag( &Region ) == MyPID )
320           {
321           /* send a kill message down the pipe */
322                pipe_put( "", TypeKill );
323                logit("e","eqprelim: sent TYPE_KILL msg to pipe.\n");
324           /* detach from shared memory */
325                tport_detach( &Region );
326           /* free allocated memory */
327                free( Hyp );
328                free( Pck );
329                free( Srt );
330           /* write a few more things to log file and close it */
331                logit( "t", "eqprelim: Termination requested; exiting!\n" );
332           /* close down communication to child */
333                pipe_close();
334                fflush( stdout );
335                return( 0 );
336           }
337
338        /* Get next message from shared memory; check return code
339         ********************************************************/
340           res = tport_getmsg( &Region, GetLogo, nLogo,
341                               &reclogo, &recsize, rec, MAXSTRLEN-1 );
342
343           if( res == GET_NONE )           /* no new messages */
344           {
345                break;
346           }
347           else if( res == GET_TOOBIG )    /* next msg too big for target; */
348           {                               /* complain & try for another   */
349                sprintf(Text,
350                        "Retrieved msg[%ld] (i%u m%u t%u) too big for rec[%d]",
351                        recsize, reclogo.instid, reclogo.mod, reclogo.type,
352                        MAXSTRLEN-1 );
353                eqprelim_status( TypeError, ERR_TOOBIG, Text );
354                continue;
355           }
356           else if( res == GET_MISS )      /* got a message, but missed some */
357           {
358                sprintf( Text,
359                        "Missed msg(s)  i%u m%u t%u  region:%ld.",
360                         reclogo.instid, reclogo.mod, reclogo.type, Region.key);
361                eqprelim_status( TypeError, ERR_MISSMSG, Text );
362           }
363           else if( res == GET_NOTRACK )   /* got a message; couldn't tell */
364           {                               /* if any were missed or not    */
365                sprintf( Text,
366                        "Msg received i%u m%u t%u; transport.h NTRACK_GET exceeded",
367                         reclogo.instid, reclogo.mod, reclogo.type );
368                eqprelim_status( TypeError, ERR_NOTRACK, Text );
369           }
370
371        /* Process the new message
372         *************************/
373           rec[recsize] = '\0';         /*null terminate the message*/
374         /*logit( "", "type:%u\n%s", reclogo.type, rec );*/   /*DEBUG*/
375
376           if( reclogo.type == TypePickSCNL )
377           {
378               eqprelim_pickscnl( rec );
379           }
380           else if( reclogo.type == TypeCodaSCNL )
381           {
382               eqprelim_codascnl( rec );
383           }
384           else if( reclogo.type == TypeQuake2K )
385           {
386               eqprelim_quake2k( rec );
387           }
388           else if( reclogo.type == TypeLink )
389           {
390               eqprelim_link( rec );
391           }
392
393        } while( res != GET_NONE );  /*end of message-processing-loop */
394
395        sleep_ew( 500 );  /* wait a bit for more messages to show up  */
396
397   }
398/*-----------------------------end of main loop-------------------------------*/
399}
400
401/******************************************************************************
402 *   eqprelim_config() processes command file(s) using kom.c functions        *
403 *                   exits if any errors are encountered                      *
404 ******************************************************************************/
405#define ncommand 10         /* # of required commands you expect to process   */
406void eqprelim_config( char *configfile )
407{
408   char     init[ncommand]; /* init flags, one byte for each required command */
409   int      nmiss;          /* number of required commands that were missed   */
410   char    *com; 
411   char    *str;
412   char     processor[64];
413   int      nfiles;
414   int      success;
415   int      i;
416
417/* Set to zero one init flag for each required command
418 *****************************************************/
419   for( i=0; i<ncommand; i++ )  init[i] = 0;
420   nLogo = 0;
421
422/* Open the main configuration file
423 **********************************/
424   nfiles = k_open( configfile );
425   if ( nfiles == 0 ) {
426        logit( "e",
427                "eqprelim: Error opening command file <%s>; exiting!\n",
428                 configfile );
429        exit( -1 );
430   }
431
432/* Process all command files
433 ***************************/
434   while(nfiles > 0)   /* While there are command files open */
435   {
436        while(k_rd())        /* Read next line from active file  */
437        {
438            com = k_str();         /* Get the first token from line */
439
440        /* Ignore blank lines & comments
441         *******************************/
442            if( !com )           continue;
443            if( com[0] == '#' )  continue;
444
445        /* Open a nested configuration file
446         **********************************/
447            if( com[0] == '@' ) {
448               success = nfiles+1;
449               nfiles  = k_open(&com[1]);
450               if ( nfiles != success ) {
451                  logit( "e",
452                          "eqprelim: Error opening command file <%s>; exiting!\n",
453                           &com[1] );
454                  exit( -1 );
455               }
456               continue;
457            }
458
459        /* Process anything else as a command
460         ************************************/
461            strcpy( processor, "eqprelim_config" );
462
463         /* Numbered commands are required
464          ********************************/
465  /*0*/     if( k_its("HeartbeatInt") ) {
466                HeartbeatInt = k_int();
467                init[0] = 1;
468            }
469  /*1*/     else if( k_its("LogFile") ) {
470                LogSwitch = k_int();
471                init[1] = 1;
472            }
473  /*2*/     else if( k_its("MyModuleId") ) {
474                str = k_str();
475                if(str) strcpy( MyModName, str );
476                init[2] = 1;
477            }
478  /*3*/     else if( k_its("RingName") ) {
479                str = k_str();
480                if(str) strcpy( RingName, str );
481                init[3] = 1;
482            }
483
484         /* Enter installation & module to get picks & codas from
485          *******************************************************/
486  /*4*/     else if( k_its("GetPicksFrom") ) {
487                if ( nLogo+1 >= MAXLOGO ) {
488                    logit( "e",
489                            "eqprelim: Too many <Get*> commands in <%s>",
490                             configfile );
491                    logit( "e", "; max=%d; exiting!\n", (int) MAXLOGO/2 );
492                    exit( -1 );
493                }
494                if( ( str=k_str() ) ) {
495                   if( GetInst( str, &GetLogo[nLogo].instid ) != 0 ) {
496                       logit( "e",
497                               "eqprelim: Invalid installation name <%s>", str );
498                       logit( "e", " in <GetPicksFrom> cmd; exiting!\n" );
499                       exit( -1 );
500                   }
501                   GetLogo[nLogo+1].instid = GetLogo[nLogo].instid;
502                }
503                if( ( str=k_str() ) ) {
504                   if( GetModId( str, &GetLogo[nLogo].mod ) != 0 ) {
505                       logit( "e",
506                               "eqprelim: Invalid module name <%s>", str );
507                       logit( "e", " in <GetPicksFrom> cmd; exiting!\n" );
508                       exit( -1 );
509                   }
510                   GetLogo[nLogo+1].mod = GetLogo[nLogo].mod;
511                }
512                if( GetType( "TYPE_PICK_SCNL", &GetLogo[nLogo].type ) != 0 ) {
513                    logit( "e",
514                               "eqprelim: Invalid message type <TYPE_PICK_SCNL>" );
515                    logit( "e", "; exiting!\n" );
516                    exit( -1 );
517                }
518                if( GetType( "TYPE_CODA_SCNL", &GetLogo[nLogo+1].type ) != 0 ) {
519                    logit( "e",
520                               "eqprelim: Invalid message type <TYPE_CODA_SCNL>" );
521                    logit( "e", "; exiting!\n" );
522                    exit( -1 );
523                }
524            /*    printf("GetLogo[%d] inst:%d module:%d type:%d\n",
525                        nLogo, (int) GetLogo[nLogo].instid,
526                               (int) GetLogo[nLogo].mod,
527                               (int) GetLogo[nLogo].type ); */  /*DEBUG*/
528            /*    printf("GetLogo[%d] inst:%d module:%d type:%d\n",
529                        nLogo+1, (int) GetLogo[nLogo+1].instid,
530                               (int) GetLogo[nLogo+1].mod,
531                               (int) GetLogo[nLogo+1].type ); */  /*DEBUG*/
532                nLogo  += 2;
533                init[4] = 1;
534            }
535         /* Enter installation & module to get associations from
536          ******************************************************/
537  /*5*/     else if( k_its("GetAssocFrom") ) {
538                if ( nLogo+1 >= MAXLOGO ) {
539                    logit( "e",
540                            "eqprelim: Too many <Get*From> commands in <%s>",
541                             configfile );
542                    logit( "e", "; max=%d; exiting!\n", (int) MAXLOGO/2 );
543                    exit( -1 );
544                }
545                if( ( str=k_str() ) ) {
546                   if( GetInst( str, &GetLogo[nLogo].instid ) != 0 ) {
547                       logit( "e",
548                               "eqprelim: Invalid installation name <%s>", str );
549                       logit( "e", " in <GetAssocFrom> cmd; exiting!\n" );
550                       exit( -1 );
551                   }
552                   GetLogo[nLogo+1].instid = GetLogo[nLogo].instid;
553                }
554                if( ( str=k_str() ) ) {
555                   if( GetModId( str, &GetLogo[nLogo].mod ) != 0 ) {
556                       logit( "e",
557                               "eqprelim: Invalid module name <%s>", str );
558                       logit( "e", " in <GetAssocFrom> cmd; exiting!\n" );
559                       exit( -1 );
560                   }
561                   GetLogo[nLogo+1].mod = GetLogo[nLogo].mod;
562                }
563                if( GetType( "TYPE_QUAKE2K", &GetLogo[nLogo].type ) != 0 ) {
564                    logit( "e",
565                               "eqprelim: Invalid message type <TYPE_QUAKE2K>" );
566                    logit( "e", "; exiting!\n" );
567                    exit( -1 );
568                }
569                if( GetType( "TYPE_LINK", &GetLogo[nLogo+1].type ) != 0 ) {
570                    logit( "e",
571                               "eqprelim: Invalid message type <TYPE_LINK>" );
572                    logit( "e", "; exiting!\n" );
573                    exit( -1 );
574                }
575            /*    printf("GetLogo[%d] inst:%d module:%d type:%d\n",
576                        nLogo, (int) GetLogo[nLogo].instid,
577                               (int) GetLogo[nLogo].mod,
578                               (int) GetLogo[nLogo].type ); */  /*DEBUG*/
579            /*    printf("GetLogo[%d] inst:%d module:%d type:%d\n",
580                        nLogo+1, (int) GetLogo[nLogo+1].instid,
581                               (int) GetLogo[nLogo+1].mod,
582                               (int) GetLogo[nLogo+1].type ); */  /*DEBUG*/
583                nLogo  += 2;
584                init[5] = 1;
585            }
586
587         /* Enter next process to hand the event to
588          *****************************************/
589   /*6*/    else if( k_its("PipeTo") ) {
590                str = k_str();
591                if(str) strcpy( NextProc, str );
592                init[6] = 1;
593            }
594
595         /* Enter rule for making prelimary notification
596          **********************************************/
597   /*7*/    else if( k_its("NumPickNotify") ) {
598                NumPickNotify = k_int();
599                init[7] = 1;
600            }
601
602         /* Single char to label locally-made picks with
603          **********************************************/
604   /*8*/    else if( k_its("LocalCode") ) {
605                if ( str=k_str() ) {
606                   LocalCode = str[0];
607                }
608                init[8] = 1;
609            }
610
611        /* Set switch for sending S-phases to next process
612          *************************************************/
613  /*9*/    else if( k_its("ReportS") ) {
614                ReportS = k_int();
615                init[9] = 1;
616            }
617
618         /* Optional commands to change default settings
619          **********************************************/
620            else if( k_its("pick_fifo_length") ) {
621                maxPck = (size_t) k_val();
622            }
623
624            else if( k_its("quake_fifo_length") ) {
625                maxHyp = (size_t) k_val();
626            }
627
628            else if( k_its("ReportCoda") ) {
629                ReportCoda = k_int();
630            }
631
632
633         /* Some commands may be processed by other functions
634          ***************************************************/
635            else if( t_com()    )  strcpy( processor, "t_com"    );
636            else if( site_com() )  strcpy( processor, "site_com" );
637            else {
638                logit( "e", "eqprelim: <%s> Unknown command in <%s>.\n",
639                         com, configfile );
640                continue;
641            }
642
643        /* See if there were any errors processing the command
644         *****************************************************/
645            if( k_err() ) {
646               logit( "e",
647                       "eqprelim: Bad <%s> command for %s() in <%s>; exiting!\n",
648                        com, processor, configfile );
649               exit( -1 );
650            }
651        }
652        nfiles = k_close();
653   }
654
655/* After all files are closed, check init flags for missed commands
656 ******************************************************************/
657   nmiss = 0;
658   for ( i=0; i<ncommand; i++ )  if( !init[i] ) nmiss++;
659   if ( nmiss ) {
660       logit( "e", "eqprelim: ERROR, no " );
661       if ( !init[0] )  logit( "e", "<HeartbeatInt> "  );
662       if ( !init[1] )  logit( "e", "<LogFile> "       );
663       if ( !init[2] )  logit( "e", "<MyModuleId> "    );
664       if ( !init[3] )  logit( "e", "<RingName> "      );
665       if ( !init[4] )  logit( "e", "<GetPicksFrom> "  );
666       if ( !init[5] )  logit( "e", "<GetAssocFrom> "  );
667       if ( !init[6] )  logit( "e", "<PipeTo> "        );
668       if ( !init[7] )  logit( "e", "<NumPickNotify> " );
669       if ( !init[8] )  logit( "e", "<LocalCode> "     );
670       if ( !init[9] )  logit( "e", "<ReportS> "       );
671       logit( "e", "command(s) in <%s>; exiting!\n", configfile );
672       exit( -1 );
673   }
674
675   return;
676}
677
678/*****************************************************************************
679 *  eqprelim_lookup( ) Look up important info from earthworm.h tables        *
680 *****************************************************************************/
681void eqprelim_lookup( void )
682{
683/* Look up keys to shared memory regions
684   *************************************/
685   if( ( RingKey = GetKey(RingName) ) == -1 ) {
686        fprintf( stderr,
687                "eqprelim:  Invalid ring name <%s>; exiting!\n", RingName);
688        exit( -1 );
689   }
690
691/* Look up installations of interest
692   *********************************/
693   if ( GetLocalInst( &InstId ) != 0 ) {
694      fprintf( stderr,
695              "eqprelim: error getting local installation id; exiting!\n" );
696      exit( -1 );
697   }
698
699/* Look up modules of interest
700   ***************************/
701   if ( GetModId( MyModName, &MyModId ) != 0 ) {
702      fprintf( stderr,
703              "eqprelim: Invalid module name <%s>; exiting!\n", MyModName );
704      exit( -1 );
705   }
706
707/* Look up message types of interest
708   *********************************/
709   if ( GetType( "TYPE_HEARTBEAT", &TypeHeartBeat ) != 0 ) {
710      fprintf( stderr,
711              "eqprelim: Invalid message type <TYPE_HEARTBEAT>; exiting!\n" );
712      exit( -1 );
713   }
714   if ( GetType( "TYPE_ERROR", &TypeError ) != 0 ) {
715      fprintf( stderr,
716              "eqprelim: Invalid message type <TYPE_ERROR>; exiting!\n" );
717      exit( -1 );
718   }
719   if ( GetType( "TYPE_QUAKE2K", &TypeQuake2K ) != 0 ) {
720      fprintf( stderr,
721              "eqprelim: Invalid message type <TYPE_QUAKE2K>; exiting!\n" );
722      exit( -1 );
723   }
724   if ( GetType( "TYPE_LINK", &TypeLink ) != 0 ) {
725      fprintf( stderr,
726              "eqprelim: Invalid message type <TYPE_LINK>; exiting!\n" );
727      exit( -1 );
728   }
729   if ( GetType( "TYPE_PICK_SCNL", &TypePickSCNL ) != 0 ) {
730      fprintf( stderr,
731              "eqprelim: Invalid message type <TYPE_PICK_SCNL>; exiting!\n" );
732      exit( -1 );
733   }
734   if ( GetType( "TYPE_CODA_SCNL", &TypeCodaSCNL ) != 0 ) {
735      fprintf( stderr,
736              "eqprelim: Invalid message type <TYPE_CODA_SCNL>; exiting!\n" );
737      exit( -1 );
738   }
739   if ( GetType( "TYPE_EVENT_SCNL", &TypeEventSCNL ) != 0 ) {
740      fprintf( stderr,
741              "eqprelim: Invalid message type <TYPE_EVENT_SCNL>; exiting!\n" );
742      exit( -1 );
743   }
744   if ( GetType( "TYPE_KILL", &TypeKill ) != 0 ) {
745      fprintf( stderr,
746              "eqprelim: Invalid message type <TYPE_KILL>; exiting!\n" );
747      exit( -1 );
748   }
749   return;
750}
751
752/****************************************************************************
753 *  eqprelim_quake2k() processes a TYPE_QUAKE2K message from binder_ew      *
754 ****************************************************************************/
755int eqprelim_quake2k( char *msg )
756{
757   char       cdate[25];
758   char       corg[25];
759   char       timestr[20];
760   double     t;
761   double     lat, lon, z;
762   float      rms, dmin, ravg, gap;
763   long       qkseq;
764   int        nph;
765   int        iq;
766   int        narg;
767
768/* Read info from ascii message
769 ******************************/
770   narg = sscanf( msg,
771                 "%*d %*d %ld %s %lf %lf %lf %f %f %f %f %d",
772                  &qkseq, timestr, &lat, &lon, &z,
773                  &rms, &dmin, &ravg, &gap, &nph );
774
775   if ( narg < 10 )
776   {
777       sprintf( Text, "eqprelim_quake2k: Error reading ascii quake msg: %s", msg );
778       eqprelim_status( TypeError, ERR_QUAKEREAD, Text );
779       return( 0 );
780   }
781
782   t = julsec17( timestr );
783   if ( t == 0. )
784   {
785       sprintf( Text, "eqprelim_quake2k: Error decoding quake time: %s", timestr );
786       eqprelim_status( TypeError, ERR_TIMEDECODE, Text );
787       return( 0 );
788   }
789
790/* Store all hypo info in eqprelim's RPT_HYP structure
791 *****************************************************/
792   iq = qkseq % maxHyp;
793
794   if( qkseq != Hyp[iq].id )        /* initialize flags the 1st  */
795   {                                /* time a new quake id#      */
796        Hyp[iq].flag  = 0;
797        Hyp[iq].id    = qkseq;
798   }
799   Hyp[iq].t    = t;
800   Hyp[iq].trpt = 0.0;
801   Hyp[iq].lat  = lat;
802   Hyp[iq].lon  = lon;
803   Hyp[iq].z    = z;
804   Hyp[iq].rms  = rms;
805   Hyp[iq].dmin = dmin;
806   Hyp[iq].ravg = ravg;
807   Hyp[iq].gap  = gap;
808   Hyp[iq].nph  = nph;
809
810   if (Hyp[iq].flag != 2)             /* don't reflag if the event */
811        Hyp[iq].flag =  1;            /* has already been reported */
812   if (Hyp[iq].nph  == 0)
813        Hyp[iq].flag = -1;            /* flag an event as killed   */
814
815/* Write out the time-stamped hypocenter to the log file
816 *******************************************************/
817   t = tnow();
818   date20( t, cdate );
819   date20( Hyp[iq].t, corg );
820   logit( "",
821         "%s:%8ld %s%9.4f%10.4f%6.2f%5.2f%5.1f%5.1f%4.0f%3d\n",
822          cdate+10, Hyp[iq].id, corg+10,
823          Hyp[iq].lat, Hyp[iq].lon, Hyp[iq].z,
824          Hyp[iq].rms, Hyp[iq].dmin, Hyp[iq].ravg,
825          Hyp[iq].gap, Hyp[iq].nph);
826
827/* Send event2k message if it passes
828 ***********************************/
829   eqprelim_notify( iq );
830
831   return( 1 );
832}
833
834/*****************************************************************************
835 *  eqprelim_link() processes a MSG_LINK                                     *
836 *****************************************************************************/
837int eqprelim_link( char *msg )
838{
839   long          lp1;
840   long          lp2;
841   long          lp;
842   int           ip, narg;
843   long          qkseq;
844   int           pkseq;
845   unsigned char pksrc;
846   unsigned char pkinstid;
847   int           isrc, iinstid, iphs;
848
849   narg  = sscanf( msg, "%ld %d %d %d %d",
850                  &qkseq, &iinstid, &isrc, &pkseq, &iphs );
851
852   if ( narg < 5 )
853   {
854       sprintf( Text, "eqprelim_link: Error reading ascii link msg: %s", msg );
855       eqprelim_status( TypeError, ERR_LINKREAD, Text );
856       return( 0 );
857   }
858   pksrc    = (unsigned char) isrc;
859   pkinstid = (unsigned char) iinstid;
860
861   lp2 = nPck;
862   lp1 = lp2 - maxPck;
863   if(lp1 < 0)
864        lp1 = 0;
865   for( lp=lp1; lp<lp2; lp++ )   /* loop from oldest to most recent */
866   {
867        ip = lp % maxPck;
868        if( pkseq    != Pck[ip].id )      continue;
869        if( pksrc    != Pck[ip].src )     continue;
870        if( pkinstid != Pck[ip].instid )  continue;
871        Pck[ip].quake = qkseq;
872        Pck[ip].phase = (char) iphs;
873        return( 1 );
874   }
875   return( 0 );
876}
877
878/*****************************************************************************
879 * eqprelim_pickscnl() decodes a TYPE_PICK_SCNL message from ascii to binary *
880 *****************************************************************************/
881int eqprelim_pickscnl( char *msg )
882{
883   EWPICK   pick;
884   time_t   t_in;
885   int      isite;
886   int      lp, lp1, lp2, ip;
887   int      i;
888
889/* Make note of current system time
890 **********************************/
891   time( &t_in );
892
893 /* Read the pick into an EWPICK struct
894 *************************************/
895   if( rd_pick_scnl( msg, strlen(msg), &pick ) != EW_SUCCESS )
896   {
897      sprintf( Text, "eqprelim_pickscnl: Error reading pick: %s", msg );
898      eqprelim_status( TypeError, ERR_PICKREAD, Text );
899      return( 0 );
900   }
901 
902/* Get site index (isite)
903 ************************/
904   isite = site_index( pick.site, pick.net, pick.comp, pick.loc );
905   if( isite < 0 )
906   {
907      sprintf( Text, "eqprelim_pickscnl: %s.%s.%s.%s - Not in station list.",
908               pick.site, pick.comp, pick.net, pick.loc );
909      eqprelim_status( TypeError, ERR_UNKNOWNSTA, Text );
910      return( 0 );
911   }
912       
913/* Try to find coda part in existing pick list
914 *********************************************/
915   lp2 = nPck;
916   lp1 = lp2 - maxPck;
917   if(lp1 < 0)
918         lp1 = 0;
919   for( lp=lp2-1; lp>=lp1; lp-- )  /* loop from most recent to oldest */
920   {
921      ip = lp % maxPck;
922      if( pick.instid != Pck[ip].instid ) continue;
923      if( pick.modid  != Pck[ip].src    ) continue;
924      if( pick.seq    != Pck[ip].id     ) continue;
925      Pck[ip].t       = pick.tpick + (double)GSEC1970; /* use gregorian time */
926      Pck[ip].site    = isite;
927      Pck[ip].phase   = 0;
928      Pck[ip].fm      = pick.fm;
929      Pck[ip].ie      = ' ';
930      Pck[ip].wt      = pick.wt;
931      Pck[ip].timeout = 0;
932      for( i=0; i<3; i++ ) {
933         Pck[ip].pamp[i] = pick.pamp[i];
934      }
935      return( 1 );
936   }
937
938/* Coda was not in list; load pick info into list
939 ************************************************/
940   ip  = nPck % maxPck;
941   Pck[ip].instid  = pick.instid;
942   Pck[ip].src     = pick.modid;
943   Pck[ip].id      = pick.seq;
944   Pck[ip].t       = pick.tpick + (double)GSEC1970; /* use gregorian time */
945   Pck[ip].site    = isite;
946   Pck[ip].phase   = 0;
947   Pck[ip].fm      = pick.fm;
948   Pck[ip].ie      = ' ';
949   Pck[ip].wt      = pick.wt;
950   for( i=0; i<3; i++ ) {
951         Pck[ip].pamp[i] = pick.pamp[i];
952   }
953   Pck[ip].quake   = 0;
954   Pck[ip].timeout = t_in + 150;
955   nPck++;
956
957/* Coda was not in list; zero-out all coda info;
958   will be filled by TYPE_CODA_SCNL later.
959 ***********************************************/
960   for( i=0; i<6; i++ ) {
961      Pck[ip].caav[i] = 0;
962   }
963   Pck[ip].clen   = 0;
964
965   return ( 1 );
966}
967
968
969/*****************************************************************************
970 *  eqprelim_codascnl() processes a TYPE_CODA_SCNL message                   *
971 *****************************************************************************/
972
973int eqprelim_codascnl( char *msg )
974{
975   EWCODA  coda;
976   long    lp, lp1, lp2;
977   int     i, ip;
978
979/* Read the coda into an EWCODA struct
980 *************************************/
981   if( rd_coda_scnl( msg, strlen(msg), &coda ) != EW_SUCCESS )
982   {
983      sprintf( Text, "eqprelim_codascnl: Error reading coda: %s", msg );
984      eqprelim_status( TypeError, ERR_CODAREAD, Text );
985      return( 0 );
986   }
987 
988/* Try to find pick part in existing pick list
989 *********************************************/
990   lp2 = nPck;
991   lp1 = lp2 - maxPck;
992   if( lp1 < 0 ) lp1 = 0;
993 
994   for( lp=lp2-1; lp>=lp1; lp-- )  /* loop from most recent to oldest */
995   {
996      ip = lp % maxPck;
997      if( coda.instid != Pck[ip].instid )  continue;
998      if( coda.modid  != Pck[ip].src )     continue;
999      if( coda.seq    != Pck[ip].id )      continue;
1000      for( i=0; i<6; i++ ) {
1001         Pck[ip].caav[i] = coda.caav[i];
1002      }
1003      Pck[ip].clen     = coda.dur;
1004      Pck[ip].timeout  = 0;
1005      return( 1 );
1006   }
1007
1008/* Pick was not in list; load coda info into list
1009 ************************************************/
1010   ip  = nPck % maxPck;
1011   Pck[ip].instid = coda.instid;
1012   Pck[ip].src    = coda.modid;
1013   Pck[ip].id     = coda.seq;
1014   for( i=0; i<6; i++ ) {
1015      Pck[ip].caav[i] = coda.caav[i];
1016   }
1017   Pck[ip].clen   = coda.dur;
1018   Pck[ip].quake  = 0;
1019   nPck++;
1020
1021/* Pick was not in list; zero-out all pick info;
1022   will be filled by TYPE_PICK_SCNL later.
1023 ***********************************************/
1024   Pck[ip].t      = 0.0;
1025   Pck[ip].site   = 0;
1026   Pck[ip].phase  = 0;
1027   Pck[ip].fm     = ' ';
1028   Pck[ip].ie     = ' ';
1029   Pck[ip].wt     = '9';
1030   for( i=0; i<3; i++ ) {
1031      Pck[ip].pamp[i] = (long) 0.;
1032   }
1033   Pck[ip].timeout  = 0;
1034   return( 1 );
1035}
1036
1037/*****************************************************************************
1038 * eqprelim_phscard() builds a char-string phase-card from RPT_PCK structure *
1039 *****************************************************************************/
1040char *eqprelim_phscard( int ip, char *phscard )
1041{
1042   char   timestr[19];
1043   int    is, iph;
1044   char   datasrc;
1045   char   imported = 'I';
1046
1047/*--------------------------------------------------------------------------
1048Sample Earthworm format phase card (variable-length whitespace delimited):
1049CMN VHZ NC -- U1 P 19950831183134.902 953 1113 968 23 201 276 289 0 0 7 W\n
1050----------------------------------------------------------------------------*/
1051 
1052/* Get a character to denote the data source
1053 *******************************************/
1054   if   ( Pck[ip].instid == InstId )  datasrc = LocalCode;
1055   else                               datasrc = imported;
1056
1057/* Convert julian seconds character string
1058 *****************************************/
1059   date18( Pck[ip].t, timestr );
1060   is  = Pck[ip].site;
1061   iph = Pck[ip].phase;
1062
1063/* Write all info to an Earthworm phase card
1064 *******************************************/
1065   if( ReportCoda ) {
1066      sprintf( phscard,
1067           "%s %s %s %s %c%c %s %s %ld %ld %ld %ld %ld %ld %ld %ld %ld %hd %c\n",
1068            Site[is].name,
1069            Site[is].comp,
1070            Site[is].net,
1071            Site[is].loc,
1072            Pck[ip].fm,
1073            Pck[ip].wt,
1074            Phs[iph],
1075            timestr,
1076            Pck[ip].pamp[0],
1077            Pck[ip].pamp[1],
1078            Pck[ip].pamp[2],
1079            Pck[ip].caav[0],
1080            Pck[ip].caav[1],
1081            Pck[ip].caav[2],
1082            Pck[ip].caav[3],
1083            Pck[ip].caav[4],
1084            Pck[ip].caav[5],
1085            Pck[ip].clen,
1086            datasrc );
1087   } else {
1088       sprintf( phscard,
1089           "%s %s %s %s %c%c %s %s %ld %ld %ld 0 0 0 0 0 0 0 %c\n",
1090            Site[is].name,
1091            Site[is].comp,
1092            Site[is].net,
1093            Site[is].loc,
1094            Pck[ip].fm,
1095            Pck[ip].wt,
1096            Phs[iph],
1097            timestr,
1098            Pck[ip].pamp[0],
1099            Pck[ip].pamp[1],
1100            Pck[ip].pamp[2],
1101            datasrc );
1102   }
1103
1104 /*logit( "", "%s", phscard );*/ /*DEBUG*/
1105   return( phscard );
1106}
1107
1108/******************************************************************************
1109 * eqprelim_hypcard() builds char-string hypocenter card from RPT_HYP struct  *
1110 ******************************************************************************/
1111char *eqprelim_hypcard( int iq, char *hypcard )
1112{
1113   char   timestr[19];
1114   char   version = '0';  /* 0=preliminary (no mag); 1=final with Md */
1115 
1116/*------------------------------------------------------------------------------------
1117Sample binder-based hypocenter as built below (whitespace delimited, variable length);
1118Event id from binder is added at end of card.
111919920429011704.653 36.346578 -120.546932 8.51 27 78 19.8 0.16 10103 1\n
1120--------------------------------------------------------------------------------------*/
1121 
1122 /* Convert julian seconds character string
1123 *****************************************/
1124   date18( Hyp[iq].t, timestr );
1125
1126/* Write all info to hypocenter card
1127 ***********************************/
1128   sprintf( hypcard,
1129           "%s %.6lf %.6lf %.2lf %d %.0f %.1f %.2f %ld %c\n",
1130            timestr,
1131            Hyp[iq].lat,
1132            Hyp[iq].lon,
1133            Hyp[iq].z,
1134            Hyp[iq].nph,
1135            Hyp[iq].gap,
1136            Hyp[iq].dmin,
1137            Hyp[iq].rms,
1138            Hyp[iq].id,
1139            version );
1140 
1141/* logit( "", "%s", hypcard );*/ /*DEBUG*/
1142   return( hypcard );
1143}
1144
1145/******************************************************************************
1146 *  eqprelim_compare() compare 2 times                                        *
1147 ******************************************************************************/
1148int eqprelim_compare( const void *p1, const void *p2 )
1149{
1150   SRT *srt1;
1151   SRT *srt2;
1152
1153   srt1 = (SRT *) p1;
1154   srt2 = (SRT *) p2;
1155   if(srt1->t < srt2->t)   return -1;
1156   if(srt1->t > srt2->t)   return  1;
1157   return 0;
1158}
1159
1160
1161/******************************************************************************
1162 * eqprelim_notify() writes message for a hypocenter that passes the          *
1163 *                   preliminary notification rule                            *
1164 ******************************************************************************/
1165void eqprelim_notify( int iq )  /* iq is the index into Hyp    */
1166{
1167   struct Greg  g;
1168   long         minute;
1169   char         cdate[40];       /* string for current time      */
1170   double       t;               /* current time                 */
1171   double       xs, ys;          /* x,y coordinates of station   */
1172   double       xq, yq, zq;      /* x,y,x coords of hypocenter   */
1173   double       r;               /* epicentral distance (km)     */
1174   double       dtdr, dtdz;      /* travel-time stuff            */
1175   double       tres;            /* travel-time residual         */
1176   long         lp, lp1, lp2;    /* indices into pick structure  */
1177   int          i, is, ip, iph;  /* working indices              */
1178   int          nphs_P;          /* number of P-phases           */
1179   int          nsend;           /* number of phases to ship out */
1180   char        *eqmsg;           /* working pointer into EqMsg   */
1181
1182/* See if this hypocenter passes the notification rule
1183 *****************************************************/
1184   if( Hyp[iq].flag == 2 )             return;   /* already reported it   */
1185   if( Hyp[iq].nph  < NumPickNotify )  return;   /* not enough phases yet */
1186
1187/* Note current system time
1188 **************************/
1189   t = tnow();
1190   date20( t, cdate );
1191
1192/* Loop thru all picks, collecting associated picks
1193 **************************************************/
1194   nSrt   = 0;
1195   nphs_P = 0;
1196   lp2    = nPck;
1197   lp1    = lp2 - maxPck;
1198   if(lp1 < 0) lp1 = 0;
1199   for(lp=lp1; lp<lp2; lp++)
1200   {
1201      ip  = lp % maxPck;
1202      if(Pck[ip].quake != Hyp[iq].id) continue;  /* not assoc w/this quake */
1203      if(Pck[ip].phase%2 == 0) {      /* It's a P-phase... */
1204         nphs_P++;                    /* ...count them     */
1205      }
1206      else {                          /* It's an S-phase... */
1207         if(ReportS == 0) continue;   /* ...see if it should be skipped */
1208      }
1209      Srt[nSrt].= Pck[ip].t;       /* load info for sorting  */
1210      Srt[nSrt].ip = ip;
1211      nSrt++;                         /* count total # phases   */
1212   }
1213
1214/* Make sure we have the minimum number of P-phases before notifying
1215 *******************************************************************/
1216   if ( nphs_P < NumPickNotify )  {
1217      logit( "",
1218            "%s:%8ld #### Report delayed: %3d P-phs; %3d picks total\n",
1219            cdate+10, Hyp[iq].id, nphs_P, Hyp[iq].nph );
1220      return;
1221   }
1222
1223/* Report this event
1224 *******************/
1225   minute = (long) (Hyp[iq].t / 60.0);
1226   grg(minute, &g);
1227   logit( "", "%s:%8ld #### Preliminary report: %04d%02d%02d%02d%02d%_%02d\n",
1228          cdate+10, Hyp[iq].id, g.year, g.month, g.day,
1229          g.hour, g.minute, (int) (Hyp[iq].id % 100) );
1230   date20( Hyp[iq].t, cdate );
1231   logit("", "%8ld %s%9.4f%10.4f%6.2f%5.2f%5.1f%5.1f%4.0f%3d\n",
1232         Hyp[iq].id, cdate,
1233         Hyp[iq].lat, Hyp[iq].lon, Hyp[iq].z,
1234         Hyp[iq].rms, Hyp[iq].dmin,
1235         Hyp[iq].ravg, Hyp[iq].gap, Hyp[iq].nph);
1236   xq = X(Hyp[iq].lon);
1237   yq = Y(Hyp[iq].lat);
1238   zq = Hyp[iq].z;
1239
1240/* Loop thru all associated picks, writing logfile output
1241 ********************************************************/
1242   for(i=0; i<nSrt; i++ )
1243   {
1244      ip  = Srt[i].ip;
1245      is  = Pck[ip].site;
1246      iph = Pck[ip].phase;
1247      date20(Pck[ip].t, cdate);
1248      xs  = X(Site[is].lon);
1249      ys  = Y(Site[is].lat);
1250      r   = hypot(xs - xq, ys - yq);
1251      tres = Pck[ip].t - Hyp[iq].t
1252             - t_phase(iph, r, zq, &dtdr, &dtdz);
1253      logit("", "%-5s %-3s %-2s %-2s %s %-2s%c%c%6.1f%7.2f\n",
1254            Site[is].name, Site[is].comp, 
1255            Site[is].net, Site[is].loc, 
1256            cdate, Phs[iph], Pck[ip].fm,
1257            Pck[ip].wt, r, tres);
1258   }
1259
1260/* Build an event message an write it to the pipe
1261 ************************************************/
1262/* write binder's hypocenter to message */
1263   eqprelim_hypcard(iq, EqMsg);
1264/* sort picks by time and add them to message */
1265   qsort(Srt, nSrt, sizeof(SRT), eqprelim_compare);
1266   nsend = nSrt;
1267   if( nsend > MAX_PHS_PER_EQ ) nsend = MAX_PHS_PER_EQ;
1268   for (i=0; i<nsend; i++) {
1269      eqmsg = EqMsg + strlen(EqMsg);
1270      eqprelim_phscard(Srt[i].ip, eqmsg);
1271   }
1272/* write event message to pipe */
1273   if ( pipe_put( EqMsg, TypeEventSCNL ) != 0 )
1274      logit("et","eqprelim_check: Error writing eq message to pipe.\n");
1275
1276/* Flag event as reported & note the time
1277 ****************************************/
1278   Hyp[iq].flag = 2;
1279   Hyp[iq].trpt = t;
1280
1281   return;
1282}
1283
1284
1285/******************************************************************************
1286 * eqprelim_status() builds a heartbeat or error msg & puts it into shared    *
1287 *                   memory                                                   *
1288 ******************************************************************************/
1289void eqprelim_status( unsigned char type, short ierr, char *note )
1290{
1291   char     msg[256];
1292   time_t   t;
1293
1294/* Build the message
1295 *******************/
1296   time( &t );
1297
1298   if( type == TypeHeartBeat )
1299   {
1300        sprintf( msg, "%ld %d\n", (long) t, (int) MyPID );
1301   }
1302   else if( type == TypeError )
1303   {
1304        sprintf( msg, "%ld %d %s\n\0", (long) t, ierr, note);
1305        logit( "et", "eqprelim:  %s\n", note );
1306   }
1307
1308/* Write the message to the pipe
1309 *******************************/
1310   if( pipe_put( msg, type ) != 0 )
1311        logit( "et", "eqprelim:  Error sending msg to pipe.\n");
1312
1313   return;
1314}
Note: See TracBrowser for help on using the repository browser.