John Forkosh Associates ®
B a s i s   S o u r c e   L i s t i n g
Copyright © 1988-2010, John Forkosh Associates, Inc.
All rights reserved.

Click for:   homepage,   resume

Below is a sample of the source code comprising Basis
(those modules whose filenames begin with the letter b).


  CCCCCCC    OOOOOO   NN      NN TTTTTTTTTT EEEEEEEEEE NN      NN TTTTTTTTTT   SSSSSSS 
 CCCCCCCCC  OOOOOOOO  NNN     NN TTTTTTTTTT EEEEEEEEEE NNN     NN TTTTTTTTTT  SSSSSSSSS
CC      CC OO      OO NNNN    NN TT  TT  TT  EE     EE NNNN    NN TT  TT  TT SS        
CC         OO      OO NN NN   NN     TT      EEEEEE    NN NN   NN     TT      SSSSSSS  
CC         OO      OO NN   NN NN     TT      EEEEEE    NN   NN NN     TT       SSSSSSS 
CC      CC OO      OO NN    NNNN     TT      EE     EE NN    NNNN     TT             SS
 CCCCCCCCC  OOOOOOOO  NN     NNN    TTTT    EEEEEEEEEE NN     NNN    TTTT    SSSSSSSSS 
  CCCCCCC    OOOOOO   NN      NN    TTTT    EEEEEEEEEE NN      NN    TTTT     SSSSSSS  

   1: basis.c
   2: basis.h
   3: basis.hlp
   4: basis_comm.c
   5: basis_init.c
   6: basis_object.c
   7: basis_switch.c
   8: bclose.c
   9: bdump.h
  10: bdumper.c
  11: bdumper.com
  12: bdumper_run.com
  13: bglobals.h
  14: binfo.c
  15: blogoff.c
  16: blogon.c
  17: bprice.c
  18: brecalc.c
  19: breqprice.c
  20: bsclock.c
  21: bserver.c
  22: bserver.h
  23: bserver_comm.c


BBBBBBBB        AA      SSSSSSS    IIIIII     SSSSSSS               CCCCCCC 
BBBBBBBBB      AAAA    SSSSSSSSS   IIIIII    SSSSSSSSS             CCCCCCCCC
 BB     BB    AA  AA  SS             II     SS                    CC      CC
 BBBBBBBB    AA    AA  SSSSSSS       II      SSSSSSS     .        CC        
 BBBBBBBB   AAAAAAAAA   SSSSSSS      II       SSSSSSS   ...       CC        
 BB     BB AAAAAAAAAA         SS     II             SS .....      CC      CC
BBBBBBBBB  AA      AA SSSSSSSSS    IIIIII   SSSSSSSSS   ...        CCCCCCCCC
BBBBBBBB   AA      AA  SSSSSSS     IIIIII    SSSSSSS     .          CCCCCCC 

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Program:     Basis Revision 2.00
  7:  *
  8:  * Purpose:     Main entry point for Basis client/trader process.
  9:  *
 10:  * Call:        $ basis -tTRADER -pPRIVILEGES -mMSGLEVEL -hHOST
 11:  *                      -bFILENAME -nFILENAME -aFILENAME -zFILENAME -fFILENAME
 12:  *              (where $basis :== $sys$sysdevice:[]basis.exe
 13:  *              has been installed as a foreign command)
 14:  *
 15:  * Command-line Arguments:
 16:  *
 17:  *              -tTRADER        Trader/Salesperson identification
 18:  *                              (-tADMIN brings up the administrator functions,
 19:  *                               -tSALES brings up a salesperson screen).
 20:  *                              Note that multiple -t switches are permitted,
 21:  *                              and a separate trader/salesperson screen will
 22:  *                              be opened for each one, loaded with issues
 23:  *                              from the corresponding profile file.
 24:  *
 25:  *              -pPRIVILEGES    Integer privilege/superuser level.
 26:  *
 27:  *              -mMSGLEVEL      Controls level of informational/debugging
 28:  *                              output displayed during execution (0=absolutely
 29:  *                              no output, 1=serious errors only, 2=all errors,
 30:  *                              3=errors+"significant events", etc.)
 31:  *
 32:  *              -hHOST          Name of host node on which server is running
 33:  *                              (if HOST="NONE", connection not made)
 34:  *
 35:  * Notes:     o Several files are opened as follows:
 36:  *                BASIS.PRV     contains the master list of issues assigned
 37:  *                              to each trader by the administrator.
 38:  *                'TRADER'.PRF  contains the trader's context information
 39:  *                              (e.g., basis issue, settlement date, list of
 40:  *                              issues on his trader window when he logged off)
 41:  *                Q?.PRM        Universe data is usually expected in QB.PRM,
 42:  *                              QN.PRM, QA.PRM, QZ.PRM, and QF.PRM unless
 43:  *                              these defaults are overridden on the command
 44:  *                              line.
 45:  *
 46:  * Source:      BASIS.C
 47:  *
 48:  * --------------------------------------------------------------------------
 49:  * Revision History:
 50:  *
 51:  * 10/17/88     J.Forkosh       Installation.
 52:  * 02/07/89     J.Forkosh       Modifications for Version 2.00
 53:  *
 54:  ****************************************************************************/
 55: 
 56: /* -------------------------------------------------------------------------
 57: Header files required by main().  Note that all externs allocated here.
 58: -------------------------------------------------------------------------- */
 59: /* --- allocate everything in main() --- */
 60: #define BALLOCATE               /* allocate all externs in main() */
 61: /* --- Basis headers --- */
 62: #include "basis.h"
 63: #include "trader.h"
 64: #include "bglobals.h"
 65: #include "qdescrip.h"
 66: #include "screens.h"
 67: #include "reports.h"
 68: #include "menus.h"
 69: #include "keys.h"
 70: #include "timrast.h"
 71: /* ----------------------------------------------------------------------- */
 72: 
 73: /* --- main() entry point --- */
 74: main    ( argc, argv )
 75: int     argc;
 76: char    *argv[];
 77: {
 78: /* -------------------------------------------------------------------------
 79: Allocations and Declarations
 80: -------------------------------------------------------------------------- */
 81: /* --- The Basis Trader Struct is the major control block for Basis --- */
 82: BTS     bts;                            /* allocate the Basis Trader Struct */
 83: /* --- decide whether or not to declare exit handler for Basis --- */
 84: #define ISHANDLER TRUE
 85: int     basis_rundown();                /* this is our exit handler */
 86: unsigned long arglist[8];               /* and the argument list for it */
 87: /* --- other program control variables --- */
 88: char    *atoday();                      /* set logon date after init */
 89: int     status;                         /* return status from various calls */
 90: /* ----------------------------------------------------------------------- */
 91: 
 92: /* -------------------------------------------------------------------------
 93: Initialization required within main()
 94: -------------------------------------------------------------------------- */
 95: /* --- Rescale ulayout[] table from absolute address to offsets --- */
 96: int     utem;                           /* item = ulayout[utem].item */
 97: for ( utem=0; ulayout[utem].item >= 0; utem++ )
 98:         ulayout[utem].offset -= (int)(&dummy_universe);
 99: /* --- Declare exit handler --- */
100: if ( ISHANDLER )                        /* only if it's wanted */
101:     {
102:     arglist[0] = &bts; arglist[1] = &status; /* two args needed for rundown */
103:     dclexh ( basis_rundown, 2, arglist ); /* declare it */
104:     basis_rundown ( &(-99), &bts, &status ); /* dummy call to page it in */
105:     }
106: /* --- Sign on --- */
107: set_screen ( C_MAIN );                  /* ready Curses, and assign TTY chan */
108: basis_logo ( );                         /* display Basis signon logo */
109: 
110: /* -------------------------------------------------------------------------
111: Primary Basis Initialization
112: -------------------------------------------------------------------------- */
113: status = basis_init ( argc, argv, &bts, 1 ); /* primary initialization */
114: if ( status < 0 ) goto end_of_job;      /* something terrible forced exit */
115: 
116: /* -------------------------------------------------------------------------
117: Set global variables
118: -------------------------------------------------------------------------- */
119: /* --- universe data --- */
120: global_bts  = &bts;                     /* global copy of bts's address */
121: global_bus  = bts.universe;             /* global copy of 1st issue's address */
122: global_nbus = bts.nuniverse;            /* and number of issues in universe */
123: /* --- socket data --- */
124: ishostup = FALSE;                       /* server connection not established */
125: sktctl = (struct skt_control_struct *)(NULL); /* creskt() hasn't alloc-ed yet */
126: sktseqin = 0; sktseqout = 0;            /* init seq #'s for msg flow control */
127: /* --- other miscellaneous data --- */
128: timr_reqidt = (-1);                     /* no timer request id for clock yet */
129: 
130: /* -------------------------------------------------------------------------
131: Initialize Server connection and initialize relations
132: -------------------------------------------------------------------------- */
133: if ( bts.user_type != ADMIN_TYPE )      /* admin doesn't need any more init */
134:   {
135:   /* --- Initialize server connection --- */
136:   status = basis_comm ( &bts, 1 );      /* call for initialization */
137:   if ( status < 0 ) goto end_of_job;    /* something terrible forced exit */
138: 
139:   /* --- Update initial relations (and refresh all issues) --- */
140:   status = init_relations ( &bts );     /* call to initialize relations */
141:   if ( status < 0 ) goto end_of_job;    /* something terrible forced exit */
142:   } /* --- end-of-if(user_type!=ADMIN_TYPE) --- */
143: 
144: /* -------------------------------------------------------------------------
145: Main Switch
146: -------------------------------------------------------------------------- */
147: strcpy ( bts.logon_date, atoday() );    /* reset logon date at this point */
148: status = basis_switch ( &bts );         /* then turn control over to user */
149: 
150: /* -------------------------------------------------------------------------
151: End of Job
152: -------------------------------------------------------------------------- */
153: end_of_job:
154:     if ( ISHANDLER )                    /* got an exit handler */
155:         canexh ( 0 );                   /* so cancel it/them */
156:     basis_rundown ( &(1), &bts, &status ); /* run down the process ourselves */
157: 
158:     /* --- close down remainder of Basis process --- */
159:     reset_screen ( );                   /* shut down Curses */
160:     /* border ( BLACK ); */             /* not necessary on VAX (only on PC) */
161:     if ( bts.msglevel >= BUGLEVEL )     /* we have an output device */
162:         { if ( *(bts.msgbuff) != '\000' ) /* and a final unhandled error msg */
163:             printf ( "\n%s", bts.msgbuff ); /* so display error message */
164:           else printf ( "\nHave a nice day." ); } /* else just print signoff */
165:     sys$exit ( 1 );
166: } /* --- end-of-program main() for Basis process --- */
167: 
168: 
169: /****************************************************************************
170:  *
171:  * Function:    basis_rundown ( condition_value, bts, status )
172:  *
173:  * Purpose:     Basis exit handler.
174:  *
175:  * Arguments:
176:  *              condition_value (I) addr of int containing condition
177:  *                              responsible for $exit.
178:  *              bts (I)         addr of Basis Trader Struct.
179:  *              status (I)      addr of int containing Basis
180:  *                              application status
181:  *
182:  * Returns:     (int)           void
183:  *
184:  ****************************************************************************/
185: /* --- entry point --- */
186: int     basis_rundown ( condition_value, bts, status )
187: int     *condition_value;
188: BTS     *bts;
189: int     *status;
190: {
191: char    *vmsmsg();                      /* to xlate condition_value */
192: /* --- check statuses --- */
193: if ( condition_value == (int *)NULL ) return; /* dummy call */
194: if ( *condition_value < 0 ) return;     /* dummy call */
195: if ( *condition_value != 1 )            /* probably a forced exit */
196:         {
197:         sprintf( bts->msgbuff, "%s", vmsmsg(*condition_value) );
198:         strcpy ( bts->attn_buff, "EXIT" ); /* exit for INPUT trader */
199:         } /* --- end-of-if(*condition_value!=1) --- */
200: if ( *status < 0 ) bts->isabort=TRUE; /* flag an abort if something failed */
201: 
202: /* --- first log off server and disconnect channel --- */
203: if ( ishostup )
204:         {
205:         /* --- first purge any buffered prices waiting to be sent --- */
206:         sendprice ( "SEND", 0.0, 0.0, 0 ); /* last buffer sent */
207:         /* --- then call basis_comm() to close the connection --- */
208:         basis_comm ( bts, 0 );          /* send logoff msg, and shutdown */
209:         } /* --- end-of-if(ishostup) --- */
210: 
211: /* --- rewrite files (if not aborting) and close windows --- */
212: basis_init ( 0, 0, bts, 0 );            /* done for us by basis_init() */
213: } /* --- end-of-function basis_rundown() --- */
214: 
215: 
216: /****************************************************************************
217:  *
218:  * Function:    basis_logo ( )
219:  *
220:  * Purpose:     Displays the Basis logo at beginning of job.
221:  *
222:  * Arguments:
223:  *              -none
224:  *
225:  * Returns:     (int)           always TRUE
226:  *
227:  ****************************************************************************/
228: static char *blogo[] = {
229: "c+-----------------------------------------------------------------------+",
230: "c|                                                                       |",
231: "c|       +------+      BBBBBBBBBBB                                       |",
232: "c|     + |--------+    BBBBBBBBBBBB       V e r s i o n   2 . 1 0        |",
233: "c|   + | |----------+   BBB       BB                                     |",
234: "c| + | | |------------+ BBB       BB    AAAA     SSSSSS  IIIIII  SSSSSS  |",
235: "c| | | | |      | | | | BBBBBBBBBBB    AA  AA   SSS   SS   II   SSS   SS |",
236: "c| | | | |      | | | | BBBBBBBBBBB   AA    AA  SSS        II   SSS      |",
237: "c| +------------| | | + BBB       BB AAA     AA  SSSSSS    II    SSSSSS  |",
238: "c|   +----------| | +   BBB       BB AAAAAAAAAA       SS   II         SS |",
239: "c|     +--------| +    BBBBBBBBBBBB  AAA     AA SSS   SS   II   SSS   SS |",
240: "c|       +------+      BBBBBBBBBBB   AAA     AA  SSSSSS  IIIIII  SSSSSS  |",
241: "c|                                                                       |",
242: "c+ Copyright(c) 1989, John Forkosh Associates, Inc.  All rights reserved.+",
243: "  ",
244: "  ",
245: "  ",
246: "  ",
247: "  ",
248: "c...Please wait a moment while the quote sheet data is being read...",
249: "\000" } ; /* --- end-of-message (terminated by null line) --- */
250: 
251: /* --- entry point --- */
252: int     basis_logo ( )
253: {
254: /* -------------------------------------------------------------------------
255: Allocations and Declarations
256: -------------------------------------------------------------------------- */
257: int     iline, nlines;                  /* index, #lines in logo */
258: char    *msgptr;                        /* ptr to blogo[iline] */
259: int     ncols;                          /* #cols in an individual line */
260: int     row, col;                       /* where current logo line starts */
261: 
262: /* -------------------------------------------------------------------------
263: Display the logo
264: -------------------------------------------------------------------------- */
265: /* --- determine #lines in logo --- */
266: nlines = 0;                             /* no lines counted yet */
267: while ( *blogo[nlines] != '\000' )      /* logo terminated by a null line */
268:         nlines++;                       /* and we haven't found it yet */
269: 
270: /* --- print the logo a line at a time --- */
271: row = 0;                                /* start at top */
272: /* row = ((MAX_ROWS-nlines+2)/2)/2; */  /* start welcome message at this row */
273: if ( row < 0 ) row=0;                   /* as long as that's possible */
274: for ( iline=0; iline<nlines; iline++ )  /* and start printing the lines */
275:         {
276:         msgptr = blogo[iline];          /* ptr to current message line */
277:         ncols = strlen(msgptr)-1;       /* #cols on this line */
278:         switch ( *msgptr++ )            /* look for justification request */
279:                 { default: msgptr--;    /* no justification command to skip */
280:                         col = 0; break; /* just assume left-justified */
281:                   case 'c':             /* center request */
282:                         col = (MAX_COLS-ncols)/2; break;
283:                   case 'r':             /* right justified */
284:                         col = MAX_COLS-ncols; break;
285:                   case 'l':             /* left justified */
286:                         col = 0; break;
287:                 } /* --- end-of-switch --- */
288:         prts ( row, col, FG, BG, msgptr ); /* print the message line */
289:         row++;                          /* and bump the row counter */
290:         } /* --- end-of-for(ilines) --- */
291: return ( TRUE );                        /* back to caller */
292: } /* --- end-of-function basis_logo() --- */
293: /* -------------------------- END-OF-FILE BASIS.C --------------------------- */


BBBBBBBB        AA      SSSSSSS    IIIIII     SSSSSSS             HHHH  HHHH
BBBBBBBBB      AAAA    SSSSSSSSS   IIIIII    SSSSSSSSS            HHHH  HHHH
 BB     BB    AA  AA  SS             II     SS                     HH    HH 
 BBBBBBBB    AA    AA  SSSSSSS       II      SSSSSSS     .         HHHHHHHH 
 BBBBBBBB   AAAAAAAAA   SSSSSSS      II       SSSSSSS   ...        HHHHHHHH 
 BB     BB AAAAAAAAAA         SS     II             SS .....       HH    HH 
BBBBBBBBB  AA      AA SSSSSSSSS    IIIIII   SSSSSSSSS   ...       HHHH  HHHH
BBBBBBBB   AA      AA  SSSSSSS     IIIIII    SSSSSSS     .        HHHH  HHHH

  1: #ifndef _BASIS
  2: #define _BASIS
  3: /****************************************************************************
  4:  *
  5:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  6:  * --------------------------------------------------------------------------
  7:  *
  8:  * Header:      Basis
  9:  *
 10:  * Purpose:     Defines standard symbols for Basis,
 11:  *              declares a few global variables,
 12:  *              and includes default header files.
 13:  *
 14:  * Notes:     o Various routines also need to #include "bglobals.h".
 15:  *
 16:  * Source:      BASIS.H
 17:  *
 18:  * --------------------------------------------------------------------------
 19:  * Revision History:
 20:  *
 21:  * 02/03/88     J.Forkosh       Installation for Version 2
 22:  *                              (revised from/replacing globals.h).
 23:  *
 24:  ****************************************************************************/
 25: 
 26: /* -----------------------------------------------------------------------------
 27: Default header files (and a few symbols we're treating as part of the toolbox)
 28: ----------------------------------------------------------------------------- */
 29: /* --- note that tools.h includes stdio and curses --- */
 30: #include "tools.h"              /* Product Development group toolbox */
 31: #include "colors.h"             /* separate toolbox header for colors */
 32: /* --- additional toolbox-like symbols --- */
 33: #define FIRST_ROW       0       /* row numbers expressed as offset from here */
 34: #define FIRST_COL       0       /* and similarly for column numbers */
 35: #define MAX_ROWS        25      /* screen row size */
 36: #define MAX_COLS        80      /* screen column size */
 37: /* --- window color defaults --- */
 38: #define FG              WHITE   /* default foreground color */
 39: #define BG              BLACK   /* default background color */
 40: #define BOLD            CYAN    /* default "emphasized"/"bold" color */
 41: /* --- special user name for inputting data --- */
 42: #define INPUTTER        "INPUT" /* check for data entry personnel */
 43: 
 44: /* -----------------------------------------------------------------------------
 45: Data Initialization
 46: ----------------------------------------------------------------------------- */
 47: /* --- directory containing all Basis files --- */
 48: #define BPATH           "BDAT:" /* this logical should be assigned for Basis */
 49: /* --- initial recalc, i.e., all issues are passed to poy when first read --- */
 50: #define RECALC1 TRUE            /* true to force recalc of all initial data */
 51: #define INIT_CHANGE_NUM (-999)  /* initial change num to force recalc */
 52: 
 53: /* -----------------------------------------------------------------------------
 54: Message Level Cutoff Values
 55: ----------------------------------------------------------------------------- */
 56: /* --- compare msglevel in BTS against these symbols to decide to display --- */
 57: #define MSGLEVEL        5       /* default msglevel (if not on command line) */
 58: #define BUGLEVEL        1       /* internal error reporting if msglevel>=1 */
 59: #define ERRLEVEL        2       /* user errors reported if msglevel>=ERRLEVEL */
 60: #define INITLEVEL       3       /* initialization reported */
 61: /* --- special message level switches (to debug specific functions) --- */
 62: #define SRVRLEVEL       6       /* incoming/outgoing server prices reported */
 63: #define UPDLEVEL        8       /* detailed reporting of server price msgs */
 64: #define DEBLEVEL        99      /* debugging level */
 65: #define LOADLEVEL       DEBLEVEL /* dump loaded file data */
 66: #define SETUP_MSGLEVEL  99
 67: #define SCROLL_MSGLEVEL 99
 68: #define DISPLAY_MSGLEVEL 99
 69: #define OPEN_MSGLEVEL   99
 70: 
 71: /* -----------------------------------------------------------------------------
 72: Window Row Defaults (rows 22 and 23 reserved for Basis messages)
 73: ----------------------------------------------------------------------------- */
 74: #define MENU_ROW        22      /* row where menu will be displayed */
 75: #define MENU_ROW2       23      /* secondary menu row */
 76: #define MSG_ROW         23      /* informational messages */
 77: #define MSG_ROW2        22      /* secondary message row */
 78: #define ERR_ROW         22      /* error messages */
 79: #define ERR_ROW2        23      /* secondary error row */
 80: #define BUG_ROW         23      /* debugging output */
 81: #define BUG_ROW2        22      /* secondary debugging row */
 82: #define BUG_ROW3        21      /* and third debugging row */
 83: 
 84: /* -------------------------------------------------------------------------
 85: Toolbox/Curses macros for Basis video display functions
 86: --------------------------------------------------------------------------- */
 87: /* --- macros to clear row1->row1+nrows-1 (using default colors) --- */
 88: #define clrows(row1,nrows) (clearbox((short)row1,(short)0,(short)(nrows),\
 89:                                 (short)80,(short)FG,(short)BG))
 90: 
 91: /* --- macros to print a msg (using default colors) --- */
 92: #define prtmsg(row,msg) { clrows(row,1); prts(row,0,FG,BG,msg); }
 93: 
 94: /* --- macro to reverse writing colors ("permanent" mark survives scroll) --- */
 95: #define flipfgbg(x)     { short icolor; \
 96:                           icolor=ifg; ifg=ibg; ibg=icolor; \
 97:                           icolor=mfg; mfg=mbg; mbg=icolor; }
 98: 
 99: /* --- macros to "mark","unmark" row, etc (using default colors) --- */
100: #define reverse(row)    paint(row,0,row,79,BG,FG)
101: #define normal(row)     paint(row,0,row,79,FG,BG)
102: #define blink(row)      paint(row,0,row,79,LTWHITE,BG)
103: /* ---------------------------- END-OF-FILE BASIS.H ------------------------- */
104: #endif


BBBBBBBB        AA      SSSSSSS    IIIIII     SSSSSSS             HHHH  HHHH LLLLL     
BBBBBBBBB      AAAA    SSSSSSSSS   IIIIII    SSSSSSSSS            HHHH  HHHH LLLLL     
 BB     BB    AA  AA  SS             II     SS                     HH    HH   LL       
 BBBBBBBB    AA    AA  SSSSSSS       II      SSSSSSS     .         HHHHHHHH   LL       
 BBBBBBBB   AAAAAAAAA   SSSSSSS      II       SSSSSSS   ...        HHHHHHHH   LL       
 BB     BB AAAAAAAAAA         SS     II             SS .....       HH    HH   LL     LL
BBBBBBBBB  AA      AA SSSSSSSSS    IIIIII   SSSSSSSSS   ...       HHHH  HHHH LLLLLLLLLL
BBBBBBBB   AA      AA  SSSSSSS     IIIIII    SSSSSSS     .        HHHH  HHHH LLLLLLLLLL

  1: -NAVIGATION Summary of Basis Navigation and Editing Keys (see Template)
  2:    H   request this Help screen      | XX  e"X"it program immediately
  3:    0-9 data entry keys               | TAB go to next editable field
  4:    Ctrl-K  restore field to original | Ctrl-W  refresh the entire screen
  5:    ->  "down arrow" for next issue   | <-  "up arrow" for previous issue  
  6:    D   to scroll Down one screen     | U   to scroll Up one screen
  7:    ],[ go to bottom,top of screen    | >,< go to last,first issue
  8:    Q   got to a specific issue       | B   go to basis of current issue
  9:    +,- plus/lower current field      | Ctrl-P/L Plus/Lower marked issues
 10:    /   enter/leave setup menus       | \   enter/leave future issue edit
 11:    I   toggle edit mode              | M/C Mark an issue/Clear all marks
 12:    Y   returns to previous screen    | T   goes to (next) Trader Screen
 13:    P   goes to Profile Screen        | R   goes to Relation Screen
 14:    Ctrl-R  report menu               | =   menu for current screen
 15:    RETURN executes current action    | !   enter "command mode"
 16:  Press any of the above keys for additional help with its function, or
 17:  Press N (Next) for Summary of Basis Menus, or Press RETURN to exit help.
 18: -MENU_CHOICES Summary of Selections Available from Basis Menus
 19:    -------- All Screen Menus --------+--------- Setup Menus -----------
 20:    Continue    No Action Desired     | Next_Setup Go to next Setup Menu
 21:    Help        Current screen help   | (B)asis    Choose Basis issue
 22:    e(X)it      Exit Basis            | (S)elect   Search for an issue
 23:    (P)rofile   Go to Profile Screen  | (F)reeze   Stop/Start price updates
 24:    (R)elation  Go to Relation Screen | (W)indow_Sort   Sorts your screen
 25:    (T)rader    Go to Trader Screen   | Yield      Choose yield method
 26:    Detail      Go to Detail Screen   | Settlement Change settlement date
 27:    ----------- Trader Menu ----------+--------- Profile Menu ----------
 28:    Delete      All marked issues     | Copy_Marks To Trader Screen
 29:    Move        Marks above cursor    |
 30:    Close       Send closing prices   |
 31:  Press any key in parentheses for additional help with its function, or
 32:  Press L (Previous) for Main Help Screen, or Press RETURN to exit help.
 33: -ABORT Exit Basis ("Exit" from Menu, or Keypress X X)
 34:    There are two ways to exit Basis:
 35: 
 36:       o You normally leave Basis by selecting "Exit" from the Trader Menu
 37:         (or from any other menu with the "Exit" option).  When this method
 38:         is used, Basis saves your current "profile", which includes
 39:         information about any new relations you have established, any new
 40:         issues you have copied to your trader window, etc.  In this way,
 41:         the next time you log on to Basis, your screen will look exactly
 42:         as you left it (except for any prices that may have changed).
 43: 
 44:       o Basis may be "aborted" by pressing the X key twice in succession.
 45:         In this case, your profile is not saved.  This option is useful
 46:         if you have made some mistake in your relations or windows, and
 47:         want all changes made during the current session to be "forgotten".
 48: -REFRESH "Refresh" the current Basis Screen
 49:    Occasionally, communications between the computer and your terminal
 50:    are corrupted by "static" that generates incorrect or unintelligible
 51:    characters on your screen.  If you notice something that you suspect
 52:    may be such "garbage", just:
 53: 
 54:         Press Ctrl-W to erase the current screen and redraw it.
 55: 
 56:    Note: Ctrl-W means hold down the key marked CTRL (or "Control") as
 57:          though it were a Shift key.  While holding it down press the
 58:          W key, and then release them both.
 59: -RESTORE Restore a Field to its Original Value while Editing
 60:    If you're in the process of entering a number and notice you've
 61:    made a mistake (before the computer has re-calculated anything):
 62:         Press Ctrl-U to restore the field to its original values.
 63:    Thus, for instance, if you're editing a price that was originally, say,
 64:    98.23+, and you change your mind, just Press Ctrl-U.  That will
 65:    restore the original value even if you've forgotten what it was.
 66: 
 67:    Even more "powerful" than restore (Ctrl-U) is the recall feature.
 68:    At any time BEFORE you navigate away from the current issue, you
 69:    may recall the ask price/yield in effect when you navigated to it:
 70:         Press Ctrl-K to recall the original ask price/yield.
 71:    Thus, you may try several prices and still recall the original.
 72: -PLUSMINUS Automatically "Raise" or "Lower" a Value
 73:    If you are editing a price which, say, happens to currently be 98.15,
 74:    and you want to raise (or lower) it by a 32nd, just:
 75: 
 76:         Press + to automatically raise a price by a 32nd, or
 77:         Press - to autonatically lower a price by a 32nd.
 78: 
 79:         Press RETURN after pressing + or - to recalculate the issue
 80:         (or move to some other issue for an automatic recalculation).
 81: 
 82:    Note: Yields are automatically raised (or lowered) by a basis point.
 83:          Generally speaking, Basis is aware of the "natural" units
 84:          in which different kinds of data is usually expressed,
 85:          and the + and - keys usually behave in the way you'd expect.
 86: -TAB Move to the Next Field
 87:    The TAB key moves from the current field to the adjacent field
 88:    on its right-hand side (BACKTAB moves to the left).
 89: 
 90:    Note: If you change an issue's price and then TAB to its yield,
 91:          Basis will automatically do a recalculation.
 92: -ROW_UPDN Move Up or Down an Issue (Keypress Up-Arrow or Down-Arrow)
 93:    The issue currently being edited is the one with the highlighted cursor.
 94:    The Up- and Down- Arrow keys allow you to "navigate" to a (vertically)
 95:    adjacent issue.
 96: 
 97:       o To move your cursor one issue closer to the top of the screen,
 98:         press the Up-Arrow key.
 99:       o To move one issue towards the bottom of the screen,
100:         press the Down-Arrow key.
101: 
102:    If you're already at the top (or bottom) of the screen, then
103:    pressing Up- (or Down-) Arrow will "scroll" the screen one issue,
104:    with one new issue being brought into view (and one disappearing).
105: -SCR_UPDN Move Up or Down One Screen (Keypress U or D)
106:    To navigate among issues more quickly, the D and U keys move down or
107:    up an entire screen's worth of issues (about 20) with one keystroke.
108: 
109:    Note: If you're moving up or down several screens trying to find
110:         a particular issue, you'll probably find the "Select" option
111:         from the Setup Menus considerably more convenient.
112:         To view that help screen now, first press / to get the Setup
113:         Menu help screen, and then press N to get the next screen
114:         after it (which is the Select help screen).
115: -FIRSTLAST Go To the Top or Bottom of a Window (Keypress < or > )
116:    At any point, you may go to the the very first or to the very last
117:    issue on your current window.
118: 
119:       o To go to the very first issue, press <
120:       o to go to the very last  issue, press >
121: 
122:    Note that these keys take you to the VERY first (or last) issue,
123:    in contrast with [ or ] which take you to the first (or last) issue
124:    that's currently VISIBLE on your screen (Press N for help with [,]).
125: -TOPBOT Go To the Top or Bottom of a Screen (Keypress [ or ])
126:    At any point, you may go to the first or last issue currently
127:    visible on your window.
128: 
129:       o To go to the first visible issue, press [
130:       o to go to the last  visible issue, press ]
131: 
132:    Note that these keys take you to the first (or last) VISIBLE issue,
133:    in contrast with < or > which take you to the VERY first (or last)
134:    issue on your screen (Press L for help with <,>).
135: -MARKCLEAR Mark One or More Issues (Keypress M...M, Keypress C to Clear)
136:    Pressing M will mark the issue under your current cursor position.
137:    The marked issue will be highlighted to indicate that it is marked.
138:    To mark a (contiguous) block of issues, mark the first issue,
139:    then navigate to the last issue and press M again.  The entire
140:    block of issues between the first and last will be highlighted
141:    to indicate that they are all marked.
142: 
143:    Pressing C at any time will "clear" all the issues currently marked.
144: -TRADER_STATE Basis Trader Screen ("Trader" from Menu, or Keypress T)
145:    The Trader Screen is your primary work area, where prices and yields
146:    are updated, and from which information about updated issues you are
147:    trading is sent to the Server for distribution.  From here you may:
148:       o Enter prices, yields, and spreads, either for "what-if" analysis
149:         or to be sent to the Server for public distribution.
150:       o Enter the price for your "Basis issue".
151:       o Go to the Detail Screen for additional information about the
152:         issues displayed on your Trader Screen.
153:       o Go to the Relation Screen to set relations for issues on your
154:         Trader Screen.
155:       o Go to the Profile Screen to add "browse" issues to your Trader
156:         Screen.
157:       o Exercise various additional options from the Setup Menus.
158: -DETAIL_STATE Basis Detail Screen ("Detail" from Menu)
159:    The Detail Screen (usually) shows the same issues as the previous
160:    Trader Screen that you were on.  But it displays additional, detailed
161:    information about these issues that may be of interest if you're
162:    planning on a more thorough analysis.
163: -RELATION_STATE Basis Relation Screen ("Relation" from Menu, or Keypress R)
164:    The Relation Screen allows you to set a Basis or "Bellweather" issue
165:    for each issue on your Trader Screen, and the spreads from that basis.
166:       o In the "Keyed Off" field you enter the security id of the basis
167:         for the issue being traded.  This may be in the explicit form
168:         1234 (a four-digit security id number), or, say, usz9, or the
169:         word base will spread off the current Basis issue.  (You may also
170:         SET or SUB issues as described by help for "command mode".)
171:       o The "Spread" field contains the spread between the issue and the
172:         basis you chose for it, i.e., issue = basis + "spread".
173:         For the time being, all spreads are expressed as decimal values,
174:         e.g., a price spread of 0:04 (an eighth) must be entered as 0.125,
175:         and a yield spread of one basis point must be entered as 0.01.
176:       o The "Type" field must contain either P or Y or B, depending on the
177:         type of relation you want to establish between the issue and basis.
178: -PROFILE_STATE Basis Profile Screen ("Profile" from Menu, or Keypress P)
179:    The profile screen allows you to "browse" through all the issues
180:    in the "universe of issues" that comprise the Basis quote database.
181:    These should be the same issues that appear on your quote sheets.
182: 
183:    The profile screen also allows you to select issues you aren't trading
184:    for viewing on your main trader screen (and detail screen) as follows:
185:       o Find the first issue you want to view on your trader screen.
186:       o While your cursor is on this issue press "M" (for "Mark").
187:       o If there are more issues (immediately above or below this one)
188:         move your cursor to the last one and press "M" again.
189:         Basis should "mark" the entire block between the two you marked.
190:       o Press "=" to get the Profile menu.
191:       o Select the "Copy Marks" option.
192:       o Basis should return to your trader menu, with the marked issues
193:         immediately above where you left your cursor.
194: -ADMIN_STATE Administrator Screen Description
195:    The Administrator Screen allows the Basis System Administrator to
196:    assign issues to the traders who are trading them.
197: 
198:    When you change a price (or yield or spread) on your Trader Screen,
199:    then that information is sent to the Server and to all other traders
200:    IF that issue has been assigned to you.  If not, the data you've
201:    entered remains "local", and, in fact, may be wiped out if the
202:    assigned trader enters data which is then sent to you.  To avoid
203:    this, set an "Input Freeze" (Press F for help with Freeze).
204: -ATTENTION Summary of Attention Commands (Keypress !)
205:    Various free-form commands may be entered at the "Attention prompt"
206:    for special purposes as follows:
207:       o From the Trader Screen or Relation Screen you may Mark a block
208:         of issues, then press the Attention key and enter "set=1234,P"
209:         where 1234 is any Security ID and P means to spread on price,
210:         or "set=usz9,Y" (Y for yield), or "set=base,B" (B for basis).
211:         All the marked issues will be spread from the issue you set.
212:       o From the Relation Screen you may place your cursor on any issue
213:         for which a relation already exists, then press the Attention key
214:         and enter "sub=1234", etc.  Every issue spread off the issue your
215:         cursor is on will be substituted with the issue you entered.
216:       o From any screen you may enter "message=anything you want to say".
217:         This text will be displayed on the message line of every other
218:         trader currently logged on to Basis.
219: -REPORTS Hardcopy Basis Reports (Keypress Ctrl-R)
220:    Basis is capable of producing various hardcopy reports on demand:
221: 
222:       o Currently, the Input Sheet Report is the only available option.
223: 
224:    Any selected report is generated from the immediately current data,
225:    i.e., from exactly the same data currently displayed on your screens.
226:    For instance, the Input Sheet Report does not contain yesterday's
227:    closing prices, but rather the prices as they currently stand.
228: -Basis: Select Basis Issue (Keypress /  then "Next Setup" as needed)
229:    You may select a Future for the primary Basis issue from your which
230:    other issues are spread.  That is, when "BASE" is typed on the Relation
231:    Screen, the issue selected here is taken as the "Bellweather" issue.
232: 
233:    Note that this menu really consists of two "sub-menus".  Select a Basis
234:    issue as follows:
235:       o First press the left and right arrow keys until the selection
236:         you want is highlighted.
237:       o Then press either the up or down arrow key once.  This will
238:         automatically take you to the next sub-menu.
239:       o Now press the left and right arrow keys again.  This time the
240:         highlight bar will move among the contract dates on the second
241:         sub-menu.  When the one you want is highlighted, press Return.
242: -Freeze: Set Freeze Options (Keypress /  then "Next Setup" as needed)
243:    "Freezing" provides communication control with the Server as follows:
244:       o "Output" freeze prevents any changes you make from being sent to
245:         the Server (immediately).  Instead, they are saved for possible
246:         transmission to the Server when you unfreeze later.
247:       o "Input" freeze prevents any Server changes received from affecting
248:         your prices (immediately).  Instead, they are saved and will all
249:         take effect if you unfreeze befor logging off Basis.
250:       o "Both" is a simultaneous combination of "Input" and "Output".
251:       o "Unfreeze" releases any saved input and/or output changes.  Any
252:         saved input changes are immediately displayed on your trader screen,
253:         and any saved output changes are immediately sent to the Server.
254:       o "Refresh" erases any saved "Output" changes and re-establishes the
255:         prices before the last "Input" freeze (i.e., undoes any "what-ifs").
256: -Window_Sort: Window Sorting Options (Keypress /  then "Next Setup" as needed)
257:    You may choose among one of three orders in which Basis can re-display
258:    the issues on your current window:
259:       o Security_ID sorts issues strictly on their security id number,
260:         which is always displayed in the first (leftmost) column
261:         of every Basis window.
262:       o Type&Maturity sorts issues first by type (Bills are first,
263:         followed by Notes/Bonds, Agencies, Zeroes, and Futures),
264:         and within each type by maturity date (and coupon).
265:       o Maturity&Coupon sorts issues solely by maturity date, and by
266:         coupon within maturity (i.e., when several issues have the
267:         same maturity the lowest coupon will appear first).
268:    If no issues are marked then all issues in the window are sorted,
269:    but if a block of issues is marked then only those issues are
270:    sorted among themselves and the "surrounding" issues don't move.
271: -Select: Find an Issue (Keypress Q, or /  then "Next Setup" as needed)
272:    Using this option, Basis will find an issue on your current screen
273:    without requiring you to "hunt" for it "manually".
274:    There are two kinds of searches Basis will perform:
275:       o Selecting "Bills", "Notes", "Agencies", "Zeroes", or "Futures"
276:         will automatically move your window to the first Bill
277:         (or Note, etc.) that's anywhere in your current screen.
278:       o If you select "Explicit", Basis further prompts you for the
279:         security id of the issue you want to find.  Enter a four-digit
280:         id code, and Basis will move your window so that issue is on top.
281:         You may also enter a maturity date as mm/yy or a maturity and
282:         coupon as mm/yy,6.375 or an explicit three-digit line number.
283:       Note: If, for instance, you select "Bills" and there are no bills
284:         on your screen, or if you enter an Explicit id that's not on
285:         your screen, Basis simply leaves your screen unchanged.
286: -Settlement: Set Settlement Date (Keypress /  then "Next Setup" as needed)
287:    The settlement date displayed on your Basis screens usually corresponds
288:    to the settlement date on the quote sheets.  If you want price/yield
289:    calculations to be based on some other settlement date, this menu allows
290:    you to select it by any of the following methods:
291:       o Explicit will prompt you to enter a date, and further calculations
292:         will be based on whatever date you enter.  Note that dates are
293:         expected in the form mm/dd/yy, e.g., 10/11/89 is Oct 11 1989.
294:         Basis automatically skips over the positions containing /'s,
295:         so just enter 101189.
296:       o Government settlement dates are two business days from "today".
297:       o Skip Day is one business day from "today".
298:       o Corporate is five business days from "today".
299: -Yield: Set Yield Method (Keypress /  then "Next Setup" as needed)
300:    Note: The yield options on this menu are not yet implemented.
301:          Calculations are currently based on those provided by the original
302:          "poy calculator", and results from Basis are merely consistent
303:          with poy.  This corresponds to "True" yield.
304: -END_HELP end-of-help
305:  /* --- End-of-File basis.hlp --- */


BBBBBBBB        AA      SSSSSSS    IIIIII     SSSSSSS               CCCCCCC    OOOOOO  
BBBBBBBBB      AAAA    SSSSSSSSS   IIIIII    SSSSSSSSS             CCCCCCCCC  OOOOOOOO 
 BB     BB    AA  AA  SS             II     SS                    CC      CC OO      OO
 BBBBBBBB    AA    AA  SSSSSSS       II      SSSSSSS              CC         OO      OO
 BBBBBBBB   AAAAAAAAA   SSSSSSS      II       SSSSSSS             CC         OO      OO
 BB     BB AAAAAAAAAA         SS     II             SS            CC      CC OO      OO
BBBBBBBBB  AA      AA SSSSSSSSS    IIIIII   SSSSSSSSS  __________  CCCCCCCCC  OOOOOOOO 
BBBBBBBB   AA      AA  SSSSSSS     IIIIII    SSSSSSS   __________   CCCCCCC    OOOOOO  

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Function:    basis_comm ( bts, isinit )
  7:  *
  8:  * Purpose:     StartUp/ShutDown communications with the Basis server process
  9:  *              for this trader.
 10:  *
 11:  * Arguments:
 12:  *              bts (I)         addr of Basis Trader Struct.
 13:  *
 14:  *              isinit (I)      int containing 1 to start up communications,
 15:  *                              or 0 to shut them down.
 16:  *
 17:  * Returns:     ( int )         1 if successful (and host is up/down),
 18:  *                              0 if unable to establish/break communications.
 19:  *
 20:  * Notes:     o
 21:  *
 22:  * Source:      BASIS_COMM.C
 23:  *
 24:  * --------------------------------------------------------------------------
 25:  * Revision History:
 26:  *
 27:  * 02/07/89     J.Forkosh       Installation (for Version 2).
 28:  *
 29:  ****************************************************************************/
 30: 
 31: /* -------------------------------------------------------------------------
 32: Header files
 33: -------------------------------------------------------------------------- */
 34: /* --- basis headers --- */
 35: #include "basis.h"
 36: #include "trader.h"
 37: /* --- server communications headers --- */
 38: #define BSOCKET 1
 39: #include "bglobals.h"
 40: /* ----------------------------------------------------------------------- */
 41: 
 42: /* --- entry point --- */
 43: int     basis_comm ( bts, isinit )
 44: BTS     *bts;
 45: int     isinit;
 46: {
 47: /* -------------------------------------------------------------------------
 48: Allocations and Declarations
 49: -------------------------------------------------------------------------- */
 50: struct  sktmsghdr_struct *sktmsghdr;    /* msgbuf starts with formatted hdr */
 51: int     iuniverse;                      /* index to loop through issues */
 52: int     status;                         /* return status from various calls */
 53: 
 54: /* -------------------------------------------------------------------------
 55: Initialization: establish TCP/IP link with detached Basis server process
 56: -------------------------------------------------------------------------- */
 57: if ( isinit                             /* if we were called for init */
 58: &&   bts->user_type != ADMIN_TYPE       /* admin doesn't need server */
 59: &&   memcmp(hostname,"NONE",4) )        /* "NONE" means no server wanted */
 60:   {
 61:   /* --- see if we need to use default hostname --- */
 62:   if ( *hostname == '\000' )            /* no hostname from command line */
 63:         strcpy ( hostname, HOSTNAME );  /* so use default */
 64: 
 65:   /* --- initialize ioctl shell to send messages to server --- */
 66:   status = fmtskt ( &(sktmsg.ioctl), hostname, SERVER_PORT );
 67:   sktmsg.iobuff = sktmsgbuf;            /* point it to default message buffer */
 68:   sktmsg.maxmsg = SKT_MAXMSG;           /* size of default buffer */
 69: 
 70:   /* --- create socket over which we'll communicate --- */
 71:   if ( status == SS$_NORMAL )
 72:     status = creskt ( &sktctl, "", 0 ); /* open our channel to server */
 73: 
 74:   /* --- arm the ast routine to read server messages --- */
 75:   if ( status == SS$_NORMAL )
 76:     { status = recvskt ( sktctl );      /* arm first read ast to the socket */
 77:       if ( status != SS$_NORMAL )
 78:         sys$dassgn ( (short)(sktctl->chan) ); /* close creskt()'s chan */
 79:     }
 80: 
 81:   /* --- check whether everything above initialized all right --- */
 82:   if ( status == SS$_NORMAL )
 83:         ishostup = TRUE;                /* server communications established */
 84:   else  { prtmsg ( MSG_ROW, "Server initialization failed." ); }
 85: 
 86:   /* --- Log on to server if we're connected --- */
 87:   if ( ishostup )
 88:     {
 89:     /* --- format logon message --- */
 90:     sktmsghdr = (struct sktmsghdr_struct *)(sktmsgbuf); /* format buf as hdr */
 91:     strcpy ( sktmsghdr->sender, bts->trader[0] );       /* msg sender=trader */
 92:     sktmsghdr->opcode = SKT$_LOGONMSG;                  /* msg type is logon */
 93:     sktmsg.msgsz = sizeof ( struct sktmsghdr_struct );  /* only need a hdr */
 94:     /* --- and write to the network --- */
 95:     sktmsghdr->msgseqnum = ++sktseqout;                 /* use next seq# */
 96:     status = sendsktw ( sktctl, &sktmsg );              /* and send the msg */
 97:     if ( status == SS$_NORMAL )                         /* if sent ok */
 98:          { prtmsg ( MSG_ROW, "Logon message sent to server." );} /* logged on */
 99:     else { prtmsg ( MSG_ROW, "Logon attempt failed." ); /* else shut it down */
100:            sys$dassgn ( (short)(sktctl->chan) );        /* close chan */
101:            ishostup = ishostup = FALSE; }               /* reset hostup flag */
102:     } /* --- end-of-if(ishostup) --- */
103: 
104:   } /* --- end-of-if(isinit) --- */
105: 
106: /* -------------------------------------------------------------------------
107: Shutdown
108: -------------------------------------------------------------------------- */
109: if ( !isinit                            /* shutdown requested by caller */
110: &&   ishostup )                         /* and we got a link to cut */
111:     {
112:     /* --- format logoff message --- */
113:     sktmsghdr = (struct sktmsghdr_struct *)(sktmsgbuf); /* buf=hdr */
114:     strcpy ( sktmsghdr->sender, bts->trader[0] ); /* msg sender=trader */
115:     sktmsghdr->opcode = SKT$_LOGOFFMSG;         /* msg type is logoff */
116:     sktmsg.msgsz = sizeof ( struct sktmsghdr_struct );  /* only hdr */
117:     /* --- and write to the network --- */
118:     sktmsghdr->msgseqnum = ++sktseqout;         /* use next seq# */
119:     status = sendsktw ( sktctl, &sktmsg );      /* and send the msg */
120:     if ( status == SS$_NORMAL )                 /* check status */
121:           { prtmsg ( MSG_ROW, "Logged off server." ); }
122:     else  { prtmsg ( MSG_ROW, "Failed to logoff server." );}
123:     sleep ( 1 );                        /* give logoff time to be sent */
124:     sys$dassgn ( (short)(sktctl->chan) ); /* close creskt()'s chan */
125:     ishostup = FALSE;                   /* host no longer up */
126:     } /* --- end-of-if(!isinit) --- */
127: 
128: return ( 1 );                           /* back to caller */
129: } /* --- end-of-function basis_comm() --- */
130: /* ----------------------- END-OF-FILE BASIS_COMM.C ------------------------- */


BBBBBBBB        AA      SSSSSSS    IIIIII     SSSSSSS               IIIIII   NN      NN
BBBBBBBBB      AAAA    SSSSSSSSS   IIIIII    SSSSSSSSS              IIIIII   NNN     NN
 BB     BB    AA  AA  SS             II     SS                        II     NNNN    NN
 BBBBBBBB    AA    AA  SSSSSSS       II      SSSSSSS                  II     NN NN   NN
 BBBBBBBB   AAAAAAAAA   SSSSSSS      II       SSSSSSS                 II     NN   NN NN
 BB     BB AAAAAAAAAA         SS     II             SS                II     NN    NNNN
BBBBBBBBB  AA      AA SSSSSSSSS    IIIIII   SSSSSSSSS  __________   IIIIII   NN     NNN
BBBBBBBB   AA      AA  SSSSSSS     IIIIII    SSSSSSS   __________   IIIIII   NN      NN

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Function:    basis_init ( argc, argv, bts, isinit )
  7:  *
  8:  * Purpose:     Initialization:
  9:  *                interpret command-line input,
 10:  *                allocate and initialize major Basis structures,
 11:  *                read universe data files,
 12:  *                read profile and privileges files,
 13:  *                load and open windows.
 14:  *              Shutdown:
 15:  *                rewrite profile file(s),
 16:  *                rewrite universe files (if requested),
 17:  *                close all windows.
 18:  *
 19:  * Arguments:
 20:  *              argc (I)        int containing command-line argument count.
 21:  *
 22:  *              argv (I)        addr of array of char ptrs,
 23:  *                              containing the command-line arguments.
 24:  *
 25:  *              bts (I)         addr of basis trader structure (BTS),
 26:  *                              allocated in main(), and containing all
 27:  *                              major control data relevant to Basis.
 28:  *
 29:  *              isinit (I)      int containing TRUE for initialization,
 30:  *                              or FALSE for shutdown procedure.
 31:  *
 32:  * Notes:     o
 33:  *
 34:  * Source:      BASIS_INIT.C
 35:  *
 36:  * --------------------------------------------------------------------------
 37:  * Revision History:
 38:  *
 39:  * 02/04/89     J.Forkosh       Installation.
 40:  *
 41:  ****************************************************************************/
 42: 
 43: /* -------------------------------------------------------------------------
 44: Default Trader and File Names
 45: -------------------------------------------------------------------------- */
 46: #define ADMINISTRATOR   "ADMIN"         /* trader name for administrator */
 47: #define SALESPERSON     "SALES"         /* trader name for salesperson */
 48: #define READONLY        "123456789"     /* prefix to trader name for r/o */
 49: #define TRADER          SALESPERSON     /* default name for trader */
 50: #define PRIV_FILE       "BASIS.PRV"     /* default privilege file */
 51: #define TRANSFER        "BXFR:"         /* logical for Transfer directory */
 52: #define HOSTLOG         "BASIS$HOST"    /* logical that xlates to host node */
 53: #define HOLIDAY_FILE    "BDAT:DATEFILE.DAT" /* holiday file for isbusday() */
 54: #define HOLIDAY_ICAL    1               /* default calendar number */
 55: /* ----------------------------------------------------------------------- */
 56: 
 57: /* -------------------------------------------------------------------------
 58: Header files required by basis_init()
 59: -------------------------------------------------------------------------- */
 60: /* --- primary basis headers --- */
 61: #include "basis.h"                      /* standard basis headers */
 62: #include "trader.h"                     /* trader control structures */
 63: /* --- additional basis headers --- */
 64: #include "qdescrip.h"
 65: #include "screens.h"
 66: #include "menus.h"
 67: extern  char    hostname[64];           /* the only BSOCKET global we need */
 68: #define BUNIVERSE
 69: #include "bglobals.h"
 70: /* ----------------------------------------------------------------------- */
 71: 
 72: /* -------------------------------------------------------------------------
 73: Static data required globally (by qrenamer())
 74: -------------------------------------------------------------------------- */
 75: static  int  isinput   = FALSE;         /* true for data entry personnel */
 76: static  int  isrefresh = FALSE;         /* to refresh from jou or input files */
 77: static  char qext[16]  = "\000";        /* extension on dumped files */
 78: /* ----------------------------------------------------------------------- */
 79: 
 80: /* --- entry point --- */
 81: int     basis_init ( argc, argv, bts, isinit )
 82: int     argc;
 83: char    *argv[];
 84: BTS     *bts;
 85: int     isinit;
 86: {
 87: /* -------------------------------------------------------------------------
 88: Allocations and Declarations
 89: -------------------------------------------------------------------------- */
 90: /* --- universe/relation data --- */
 91: BUS     *up;                            /* ptr to calloc-ed basis universe */
 92: BRS     *rp;                            /* and to basis relation structure */
 93: char    *trader;                        /* ptr to bts->trader[ntraders] */
 94: int     iuniverse,nuniverse, nsorted;   /* index, #universe issues in memory */
 95: char    *traderlist;                    /* for admin, array[MAX_UNIVERSE][16] */
 96: int     iqtype;                         /* qtypes[] index */
 97: char    *qdate;                         /* settlement for dump */
 98: static  char qsettlements[16][16];      /* settlement dates read from qfiles */
 99: static  int  nloaded[16], ndumped[16];  /* # issues loaded for iqtype */
100: /* --- window data --- */
101: BWS     *wp;                            /* ptrs to a window */
102: BOS     *op;                            /* ptr to a window object */
103: unsigned char *create_window();         /* function to do creation/init */
104: int     iwindow, owindow, nwindows;     /* index, # of window pointers */
105: int     iobject, nobjects, max_objects; /* #, max# objects in window by type */
106: int     objlist[32];                    /* in case we need to add to window */
107: int     *x_screens;                     /* ptr to t_, s_, or a_screens[] list */
108: int     iscreen, screen;                /* index to screens[], item from it */
109: /* --- trader privilege/profile data files --- */
110: FILE    *fopen(), *tr_priv, *tr_prof;   /* trader privileges and profile */
111: int     itrader, ntraders;              /* index 0 <= itrader < bts->ntraders */
112: static  int isreadonly = FALSE;         /* true if name prefixed by r/o flag */
113: static  int isbasis = TRUE;             /* to qdump() files in Basis format */
114: int     nscanned;                       /* # lines in prof_, priv_ files */
115: int     nnewobj;                        /* #new issues auto added to window */
116: char    priv_file[64], prof_file[64];   /* privilege, profile filenames */
117: char    *priv_delims[] = { "/", 0 };    /* all privs use / for delimiter, and */
118: char    *prof_delims[] = { "/", 0 };    /* all profs use / for delimiter, too */
119: int     setpriv(), setprof(), setadmin(); /*scanfile's privilege/profile funcs*/
120: int     (*asetpriv)() = setpriv,        /* addr of setpriv passed to scanfile */
121:         (*asetprof)() = setprof,        /* addr of setprof passed to scanfile */
122:         (*asetadmin)() = setadmin;      /* addr of setprof for administrator */
123: /* --- other program control variables --- */
124: unsigned char *calloc(), *cap;          /* to alloc various MAX_xxx buffers */
125: int     iarg;                           /* counter over command-line switches */
126: char    *argptr, argfld[64], opcode;    /* ptr to argv[iarg], 1st char of arg */
127: int     status;                         /* return status from various calls */
128: int     sincemid, numsetdays=2;         /*secs since 12am, #days for inputter*/
129: char    msgbuff[132];                   /* local message buffer (not in bts) */
130: char    trdrlognam[32], trdrlogval[64]; /* trnlnm() of trader for dup check */
131: char    *delim, *strchr(), *index();    /* to search for various chars */
132: char    *strupper(), *trim(), *ltrim(); /* trim and toupper a string */
133: char    *daytime(), *atoday();          /* to print date-time stamp */
134: char    *anextbusday();                 /* entry point in isbusday.c */
135: char    *qrenamer();                    /* to determine input/output filename */
136: /* ----------------------------------------------------------------------- */
137: 
138: /* -------------------------------------------------------------------------
139: Check for initialization or shutdown request
140: -------------------------------------------------------------------------- */
141: if ( !isinit ) goto shutdown;           /* not init request, must be shutdown */
142: 
143: /* -------------------------------------------------------------------------
144: Default Initialization
145: -------------------------------------------------------------------------- */
146: /* --- reset toolbox color defaults --- */
147: cfg = mfg = efg = hbg = ibg = FG;       /* edit() won't work consistently */
148: cbg = mbg = ebg = hfg = ifg = BG;       /* unless we tell it our colors */
149: 
150: /* --- other initialized data --- */
151: strcpy ( menu_fields[EXPLICIT_DATE].str_field, "" ); /* for menu date entry */
152: strcpy ( menu_fields[EXPLICIT_SECID].str_field, "           " ); /* secid */
153: 
154: /* -------------------------------------------------------------------------
155: Basis Trader Structure Default Initialization
156: -------------------------------------------------------------------------- */
157: /* --- init the bts --- */
158: memset ( bts, '\000', sizeof(BTS) );    /* clear Basis Trader Structure */
159: 
160: /* --- allocate targets for various bts pointers --- */
161: cap = calloc ( MAX_TRADERS, sizeof(BCS) ); /* recalc_options structures */
162: if ( cap == NULL )                      /* can't calloc buffers */
163:     { sprintf ( bts->msgbuff, "Can't alloc %d recalc_options of %d bytes each",
164:           MAX_TRADERS, sizeof(BCS));    /* format error message */
165:       return ( -1 ); }                  /* error return will force exit */
166: bts->recalc_options = (BCS *)(cap);     /* store ptr to recalc_options in bts */
167: 
168: /* --- init various bts defaults --- */
169: bts->universe = (BUS *)(NULL);          /* no universe allocated yet */
170: bts->relation = (BRS *)(NULL);          /* no relations allocated yet */
171: bts->traderlist = (char *)(NULL);       /* admin needs assigned trader list */
172: bts->nuniverse = nuniverse = 0;         /* no universe issues in memory yet */
173: bts->iuniverse = (-1);                  /* cursor not on any issue yet */
174: bts->user_type = TRADER_TYPE;           /* user is usually a trader */
175: bts->ntrading = 0;                      /* no issues privileged to trade yet */
176: bts->ntraders = 0;                      /* no -t trader switches found yet */
177: bts->itrader = itrader = 0;             /* default to primary trader index */
178: bts->privileges = 0;                    /* no privileges for this user yet */
179: bts->change_num = 0;                    /* start change number counter at 0 */
180: bts->state = INIT_STATE;                /* context initialization state */
181: bts->attn_command = (-1);               /* no attention command issued yet */
182: *(bts->msgbuff) = '\000';               /* nothing in the message buffer */
183: *(bts->attn_buff) = '\000';             /* nothing in the attention buffer */
184: 
185: /* --- window inits --- */
186: bts->nwindows = 0;                      /* no windows allocated/opened yet */
187: bts->iwindow = 0;                       /* set current window to top one */
188: bts->iwsorting = 0;                     /* init to unsorted windows */
189: bts->fg = FG; bts->bg = BG; bts->bold = BOLD; /* set window "colors" */
190: bts->iwtrader[0] = bts->iwdetail = bts->iwrelation = bts->iwprofile = (-1);
191: 
192: /* --- init various bts profile defaults --- */
193: strcpy ( bts->pricing, "A" );           /* ask/offer side pricing (not bid) */
194: strcpy ( bts->yield_method, "T" );      /* true yield (not SIA or Monroe) */
195: strcpy ( bts->contract, "N" );          /* near contract (not Far or none) */
196: strcpy ( bts->edit_mode, "\000" );      /* no special edits allowed/desired */
197: strcpy ( bts->output_mode, "32" );      /* 32nds format (not ticks/55 ) */
198: strcpy ( bts->update_mode, "M" );       /* manual (not auto-pilot) */
199: strcpy ( bts->freeze, "X" );            /* no freeze yet */
200: strcpy ( bts->logon_date, atoday() );   /* init prev logon as today's date */
201: strcpy ( bts->settlement, "X" );        /* init assuming eXplicit settlement */
202: strcpy ( bts->explicit_date, atoday() ); /* default explicit date to today */
203: 
204: /* --- init "indicative" data for all possible traders --- */
205: for ( itrader=0; itrader < MAX_TRADERS; itrader++ )
206:     { strcpy ( bts->trader[itrader], "none" ); /* no trader in this slot */
207:       bts->ibasis[itrader] = (-1);      /* no basis issue for trader */
208:       strcpy ( bts->basis[itrader], "none" ); /* no issue name, e.g., "USZ9" */
209:       strcpy ( bts->btrading[itrader], "F" ); /* not trading basis issues */
210:       strcpy ( bts->bupdating[itrader], "F" ); /* not updating basis issues */
211:       strcpy ( bts->autorange[itrader], "F" ); /*don't set basis automatically*/
212:       strcpy ( bts->relation_mode[itrader], "P" ); /*Price (not Spread,Quote)*/
213:       (bts->recalc_options)[itrader].odd_adjust = TRUE; /*adjust odd mat dates*/
214:       (bts->recalc_options)[itrader].price_rounding = 0; /* no price rounding */
215:       (bts->recalc_options)[itrader].isclosing = FALSE; /* not closing */
216:     } /* --- end-of-for(itrader) --- */
217: 
218: /* --- init various bts switches --- */
219: bts->isdump = FALSE;                    /* don't dump universe unless set */
220: bts->isexternal = FALSE;                /* initially, no server updates */
221: bts->isclosing = FALSE;                 /* not yet accepting closing prices */
222: bts->isrecalc = FALSE;                  /* no need for continuous recalcs */
223: bts->isabort = FALSE;                   /* job hasn't been aborted */
224: 
225: /* --- init command-line defaults if no command-line args override --- */
226: bts->msglevel = MSGLEVEL;               /* establish default debugging level */
227: isinput = FALSE;  isbasis = TRUE;       /* not a data entry person */
228: isreadonly = FALSE;                     /* readonly flag not found yet */
229: isrefresh = FALSE;                      /* refresh only if explicit request */
230: trader = bts->trader[0];                /* ptr to first trader name slot */
231: strcpy ( trader, TRADER );              /* default trader name if no -t's */
232: strupper(trim(ltrim(trader)));          /* trim and convert to uppercase */
233: strcpy ( priv_file, BPATH );            /* start with default directory */
234: strcat ( priv_file, PRIV_FILE );        /* followed by privilege filename */
235: if ( strchr(priv_file,'.') == NULL )    /* privilige file has no extension */
236:         strcat ( priv_file, ".PRV" );   /* so use default .PRV extension */
237: 
238: /* --- xlate hostname --- */
239: *hostname = '\000';                     /* no hostname yet */
240: status = trnlnm( 1, HOSTLOG, hostname ); /* try xlating logical with host */
241: if ( !memcmp(hostname,HOSTLOG,strlen(hostname)) ) /* no xlation available */
242:         *hostname = '\000';             /* so no hostname yet */
243: 
244: /* -------------------------------------------------------------------------
245: Get command-line args
246: -------------------------------------------------------------------------- */
247: /* ---Loop over each command-line argument --- */
248: for ( iarg=1; iarg < argc; iarg++ )     /* skip image name in argv[0] */
249:     {
250:     /* --- Make sure arg is a switch and then get its opcode --- */
251:     strcpy ( argfld, argv[iarg] );      /* local copy of current arg */
252:     argptr = argfld;                    /* ptr to first char of this arg */
253:     strupper(trim(ltrim(argptr)));      /* trim and convert arg to uppercase */
254:     if (*argptr == '-')                 /* got a switched arg */
255:         argptr++;                       /* just skip over the dash */
256:     opcode = toupper(*argptr++);        /* opcode is char after '-' */
257: 
258:     /* --- First check for a q-filename for a universe data file --- */
259:     for ( iqtype=0; *(qtypes[iqtype])!='\000'; iqtype++ )
260:         { if ( opcode == *(qtypes[iqtype]) ) /* opcode is a qtype */
261:             {
262:             *(qfiles[iqtype]) = '\000'; /* destroy default filename */
263:             if ( !memcmp(argptr,"NONE",4) ) /* no file with qtype data */
264:                 goto next_iarg;         /* so we're done with this arg */
265:             strcpy ( qfiles[iqtype], argptr );  /* new universe file to open */
266:             if ( strchr(qfiles[iqtype],'.') == NULL ) /* no file extension */
267:                 strcat ( qfiles[iqtype], ".PRM" ); /* so use .PRM extension */
268:             goto next_iarg;             /* get next command-line arg */
269:             } /* --- end-of-if(opcode) --- */
270:         } /* --- end-of-for(iqtype) --- */
271: 
272:     /* --- Else switch on opcode which tells us what needs to be done --- */
273:     switch ( opcode )                   /* check the char following '-' */
274:         {
275:         /* --- Just ignore anything unrecognizable --- */
276:         default:                        /* got an unrecognized switch */
277:             if ( bts->msglevel >= ERRLEVEL )    /* so print an error msg */
278:                 { sprintf ( msgbuff, "Unrecognized switch=%c, arg=%s",
279:                         opcode, argptr );
280:                   prtmsg ( ERR_ROW, msgbuff ); }
281:             break;
282:         /* --- trader --- */
283:         case 'T':
284:             if ( (ntraders=bts->ntraders) >= MAX_TRADERS ) /* no more allowed */
285:                 { if ( bts->msglevel >= ERRLEVEL ) /* report error */
286:                     { sprintf(msgbuff,"Trader %s exceeds max of %d traders",
287:                         argptr, MAX_TRADERS );
288:                       prtmsg ( ERR_ROW, msgbuff ); }
289:                   break; }              /* just ignore switch */
290:             if ( strchr(READONLY,*argptr) != (char *)NULL ) /*got an r/o user*/
291:                 { isreadonly = TRUE;    /* set readonly flag for user */
292:                   /* argptr++; */ }     /* bump argptr past readonly flag */
293:             trader = bts->trader[ntraders]; /* ptr to next trader slot */
294:             strcpy ( trader, argptr );  /* trader's real "name" supplied */
295:             strupper(trim(ltrim(trader))); /* trim and convert to uppercase */
296:             bts->ibasis[ntraders] = (-1); /* no basis issue for trader */
297:             strcpy ( bts->basis[ntraders], "none" ); /* no basis issue name */
298:             (bts->ntraders)++;          /* bump trader count */
299:             break;
300:         /* --- privilege level --- */
301:         case 'P':
302:             if ( (bts->privileges = atoi(argptr)) /* try interpreting as int */
303:             < 0 ) bts->privileges = 0;  /* but don't go negative */
304:             break;
305:         /* --- message level --- */
306:         case 'M':
307:             if ( (bts->msglevel = atoi(argptr)) /* try interpreting it as int */
308:             < BUGLEVEL ) bts->msglevel = BUGLEVEL; /* but always report bugs */
309:             break;
310:         /* --- server host --- */
311:         case 'H':
312:             strcpy ( hostname, argptr ); /* node where server running */
313:             break;
314:         /* --- dump universe (on exit) --- */
315:         case 'D':
316:             bts->isdump = !(bts->isdump); /* flip dump flag */
317:             strcpy ( qext, argptr );    /* extension for dumped files */
318:             break;
319:         /* --- refresh (from journal file or previous INPUT data files) --- */
320:         case 'R':
321:             isrefresh = !(isrefresh); /* flip refresh flag */
322:             break;
323:         } /* --- end of opcode switch --- */
324: 
325:     next_iarg: ;
326:     }  /* --- end of iarg loop --- */
327: 
328: /* -------------------------------------------------------------------------
329: Set user type from first/primary trader name
330: -------------------------------------------------------------------------- */
331: /* --- see if we're the administrator or salesperson or data entry person --- */
332: trader = bts->trader[0];                /* ptr to first trader name slot */
333: if ( !memcmp ( trader, ADMINISTRATOR, strlen(ADMINISTRATOR) ) ) /* matched */
334:         bts->user_type = ADMIN_TYPE;    /* flip user type to administrator */
335: if ( !memcmp ( trader,   SALESPERSON,   strlen(SALESPERSON) ) ) /* matched */
336:         bts->user_type = SALES_TYPE;    /* flip user type to salesperson */
337: if ( !memcmp ( trader,      INPUTTER,   strlen(INPUTTER) ) )    /* matched */
338:         { isinput = TRUE;               /* flip inputter flag */
339:           isbasis = FALSE;              /* rewrite files as quote files */
340:           bts->user_type = TRADER_TYPE; /* and flip user type to trader */
341:           memset ( trdrlogval, '\000', 48 ); /* init translated input date */
342:           trnlnm ( 1, "BINPUT", trdrlogval ); /* translate prev input date */
343:           if ( !memcmp(trdrlogval,atoday(),8) ) /* previous input today */
344:             isrefresh = TRUE;           /* so refresh from last input files */
345:         } /* --- end-of-if(trader==INPUT) --- */
346: /* --- check for read/only status --- */
347: if ( isreadonly )                       /* readonly prefix found on trader */
348:         bts->user_type = SALES_TYPE;    /* demote privileges to sales */
349: /* --- if no -t switches, then we have one default trader/salesperson --- */
350: if ( bts->ntraders < 1 ) bts->ntraders = 1; /* so set minimum count */
351: 
352: /* -------------------------------------------------------------------------
353: Check for duplicate logon, and assign logical if this is the first
354: -------------------------------------------------------------------------- */
355: /* if ( !isreadonly ) { */              /* let anybody read */
356:   strcpy ( trdrlognam, "&" );           /* start logical name with an & */
357:   strcat ( trdrlognam, trader );        /* followed by trader name */
358:   memset ( trdrlogval, '\000', 48 );    /* init translated name to nulls */
359:   trnlnm ( 1, trdrlognam, trdrlogval ); /* translate trader's primary name */
360:   if ( memcmp(trdrlognam,trdrlogval,strlen(trdrlognam)) ) /* we got xlation */
361:     {
362:     sprintf (bts->msgbuff,"Duplicate logon for %s.",trader);
363:     strcpy ( trader, "NONAM" );         /* to avoid deleting logical */
364:     return ( -1 );                      /* error return will force exit */
365:     } /* --- end-of-if(translation exists) --- */
366:   crelnm ( "", trdrlognam, daytime(0) ); /* associate date/time of logon */
367: /*  }  */ /* --- end-of-if(!isreadonly) --- */
368: 
369: /* -------------------------------------------------------------------------
370: Allocate universe buffers for everybody (i.e., for every type of user)
371: -------------------------------------------------------------------------- */
372: /* --- allocate memory-resident universe buffers --- */
373: cap = calloc ( MAX_UNIVERSE, sizeof(BUS) ); /* char ptr to universe buffer */
374: if ( cap == NULL )                      /* can't calloc buffers */
375:     { sprintf ( bts->msgbuff, "Can't alloc %d issue buffers of %d bytes each",
376:           MAX_UNIVERSE, sizeof(BUS));   /* format error message */
377:       return ( -1 ); }                  /* error return will force exit */
378: 
379: /* --- clear universe and place universe ptr in bts --- */
380: memset ( cap, '\000', MAX_UNIVERSE*sizeof(BUS) ); /* clear universe buffers */
381: bts->universe = up = (BUS *)(cap);      /* cap as universe ptr */
382: 
383: /* -------------------------------------------------------------------------
384: Allocate Trader List for System Administrator
385: -------------------------------------------------------------------------- */
386: /* --- administrator will need a trader list for his assignments --- */
387: if ( bts->user_type == ADMIN_TYPE )     /* and this is the administrator */
388:     { cap = calloc ( MAX_UNIVERSE, 16 ); /* alloc one trader name per issue */
389:       if ( cap == NULL )                /* can't continue if we failed */
390:         { sprintf ( bts->msgbuff, "Can't alloc trader list.");
391:           return ( -1 ); }              /* error return will force exit */
392:       memset ( cap, '\000', 16*MAX_UNIVERSE ); /* clear traderlist buffer */
393:       bts->traderlist = cap;            /* ptr to traderlist stored in bts */
394:     } /* --- end-of-if(user==ADMIN) --- */
395: 
396: /* -------------------------------------------------------------------------
397: Allocate relation buffers for everybody except the administrator
398: -------------------------------------------------------------------------- */
399: /* --- allocate memory-resident relation buffers --- */
400: if ( bts->user_type != ADMIN_TYPE )     /* this isn't the administrator */
401:     { cap = calloc ( MAX_UNIVERSE, sizeof(BRS) ); /* ptr to relation buffers */
402:       if ( cap == NULL )                /* failed to calloc buffers */
403:         { sprintf(bts->msgbuff,"Can't alloc %d relation buffs of %d bytes each",
404:                 MAX_UNIVERSE,sizeof(BRS) ); /* format error message */
405:            return ( -1 );               /* error return will force exit */
406:         } /* --- end-of-if(cap==NULL) --- */
407:       memset(cap,'\000',MAX_UNIVERSE*sizeof(BRS)); /* clear relation buffs */
408:       bts->relation = rp = (BRS *)(cap); /* ptr to relations in bts */
409: 
410:       /* --- init important relation elements that aren't explicitly zero --- */
411:       for ( iuniverse=0; iuniverse < MAX_UNIVERSE; iuniverse++ )
412:         { rp[iuniverse].privileges = (-1); /* unused, and no privileges yet */
413:           rp[iuniverse].ibasis = (-1);  /* no basis issue for issue either */
414:           rp[iuniverse].inext = (-1);   /* no next issue with same ibasis */
415:           rp[iuniverse].irefresh = 0;   /* no outstanding refresh for relt'n */
416:           rp[iuniverse].spread = 0.0;   /* no spread from basis */
417:           rp[iuniverse].nrelated = 0;   /* no issues spread from this one */
418:           rp[iuniverse].ihead = (-1); } /* no index of issue spread from this */
419:     } /* --- end-of-if(user!=ADMIN) --- */
420: 
421: /* -------------------------------------------------------------------------
422: Initialize calendar
423: -------------------------------------------------------------------------- */
424: if ( setbusday ( HOLIDAY_FILE, HOLIDAY_ICAL )   /* init the calendar file */
425:  < 0 )                                          /* init failed */
426:     { sprintf ( bts->msgbuff, "Holiday file %s init failed.", HOLIDAY_FILE );
427:       return ( -1 ); }
428: 
429: /* --- reset settlement date for input trader, then set previous bus day --- */
430: if ( isinput )                          /* probably wants day after tomorrow */
431:     { strcpy ( bts->settlement, "X" );  /* always explicit settlement date */
432:       numsetdays = 2;                   /* usually want two business days out */
433:       daytime(&sincemid);               /* 100ths secs since 12am */
434:       sincemid = (sincemid/100)/1800;   /* # half hours since 12am */
435:       if ( sincemid <= 8 ) numsetdays = 1; /* before 4:30am use one day out */
436:       strcpy ( bts->explicit_date,      /* set explicit_date accordingly */
437:                 anextbusday(atoday(),HOLIDAY_ICAL,numsetdays) );
438:       itrader = 0;                      /* inputter is primary trader */
439:       (bts->recalc_options)[itrader].isclosing = TRUE; /* inputter is closing */
440:     } /* --- end-of-if(isinput) --- */
441: strcpy ( bts->prev_busday, anextbusday(bts->explicit_date,HOLIDAY_ICAL,(-1)) );
442: 
443: /* -------------------------------------------------------------------------
444: Load initial universe data
445: -------------------------------------------------------------------------- */
446: for ( iqtype=0; *(qtypes[iqtype]) != '\000'; iqtype++ ) /* for each type */
447:     { nloaded[iqtype] = 0;              /* nothing loaded for qtype */
448:       *(qsettlements[iqtype]) = '\000'; /* no settlement date for qtype */
449:       if ( *(qfiles[iqtype]) != '\000' ) /* check that we have filename */
450:         { /* --- load file contents if we got a filename --- */
451:         if ( isinput )                  /* want settlement date for inputter */
452:             strcpy ( qsettlements[iqtype], bts->explicit_date ); /*so copy it*/
453:         nloaded[iqtype] = qload ( qtypes[iqtype], qrenamer(bts,iqtype,FALSE),
454:                           &up[nuniverse], qsettlements[iqtype] );
455:         if ( nloaded[iqtype] > 0 )      /* if we loaded anything from file */
456:             { if ( *(bts->explicit_date) != '\000' /* already got an old date */
457:               &&   memcmp(qsettlements[iqtype],"00/00/00",8) ) /*and a new one*/
458:                 { if ( memcmp(bts->explicit_date,qsettlements[iqtype],8) )
459:                     if ( bts->msglevel >= BUGLEVEL ) /* inconsistent dates */
460:                         { sprintf(msgbuff,"Settlement dates %s, %s disagree.",
461:                                 bts->explicit_date, qsettlements[iqtype] );
462:                           prtmsg ( MSG_ROW, msgbuff ); }
463:                 } /* --- end-of-if(*explicit_date) --- */
464:             nuniverse += nloaded[iqtype]; /* bump total buffered issues count */
465:             if ( !isinput )             /* leave inputter's settlement as is */
466:                strcpy ( bts->explicit_date, qsettlements[iqtype] ); /* latest */
467:             } /* --- end-of-if(nloaded>0) --- */
468:         if ( bts->msglevel >= INITLEVEL ) /* display number of issues loaded */
469:             { sprintf ( msgbuff, "%d %s-issues read from quote file %s for %s",
470:                 nloaded[iqtype], qtypes[iqtype], qrenamer(bts,iqtype,FALSE),
471:                 qsettlements[iqtype] );
472:               prtmsg ( MSG_ROW, msgbuff ); }
473:         } /* --- end-of-if(*qfiles[iqtype]) --- */
474:     } /* --- end-of-for(*qtypes[iqtype]) --- */
475: 
476: /* --- report total number of issues --- */
477: if ( bts->msglevel >= INITLEVEL )
478:     { sprintf ( msgbuff, "%d issues in universe.", nuniverse );
479:       prtmsg ( MSG_ROW2, msgbuff ); }
480: 
481: /* --- sort the universe by last four chars of security id --- */
482: bts->nuniverse = nuniverse;             /* number of issues in universe */
483: global_bus = up;
484: global_nbus = nuniverse;
485: nsorted = sort_universe ( 1 );
486: if ( nsorted != nuniverse )
487:     { sprintf ( bts->msgbuff, "Failed to sort issues in universe." );
488:       return ( -1 ); }
489: 
490: /* --- dummy trailing issue indicates end-of-data (see ulookup()) --- */
491: memset ( (unsigned char *)(&up[nuniverse]), '\000', sizeof(BUS)); /* clear it */
492: strcpy ( up[nuniverse].sec_id, END_OF_DATA ); /* copy #define-ed end sec_id */
493: 
494: /* --- other initialized data --- */
495: strcpy ( menu_fields[EXPLICIT_DATE].str_field, bts->explicit_date );
496: 
497: /* -------------------------------------------------------------------------
498: Initialize universe control information as necessary
499: -------------------------------------------------------------------------- */
500: for ( iuniverse=0; iuniverse < nuniverse; iuniverse++ )
501:     {
502:     /* --- set change number (so every issue needs a recalc at once) --- */
503:     if ( RECALC1 )                      /* true to force initial recalc */
504:         up[iuniverse].change_num = INIT_CHANGE_NUM; /* force initial recalc */
505:     else up[iuniverse].change_num = bts->change_num; /* current change num */
506:     /* --- dump universe if debugging --- */
507:     if ( bts->msglevel >= LOADLEVEL     /* shouldn't normally need this */
508:     && ( iuniverse<9 || iuniverse>=nuniverse-9 ) ) /* 1st and last 10 only */
509:         printf("\nbasis> issue#%d: id=%s, issdat=%s, matdat=%s, askprice=%lf",
510:         iuniverse+1, up[iuniverse].sec_id, up[iuniverse].iss_date,
511:         up[iuniverse].mat_date, up[iuniverse].ask_val );
512:     } /* --- end-of-for(iuniverse) --- */
513: 
514: /* -------------------------------------------------------------------------
515: Load privileges (assigned by administrator) for this trader (or traders)
516: -------------------------------------------------------------------------- */
517: /* --- load privileges --- */
518: if ( bts->user_type != SALES_TYPE       /* no privileges for salesperson */
519: &&   !isinput )                         /* inputter "trades" everything */
520:     if ( *priv_file != '\000' )         /* got a privilege file to load */
521:         { /* --- open the priv file and call scanfile with setpriv() --- */
522:         if ( (tr_priv = fopen(priv_file,"r")) /* open the file for read */
523:         == NULL )                       /* failed to open */
524:                 { /* --- quit of can't open priv_file --- */
525:                 sprintf (bts->msgbuff,"Failed to open priv file %s.",priv_file);
526:                 return ( -1 ); }        /* error return will force exit */
527:         /* --- load privileges --- */
528:         nscanned = (bts->user_type==ADMIN_TYPE)? /* load privileges */
529:             scanfile ( tr_priv, priv_delims, bts, asetadmin ) : /* admin or */
530:             scanfile ( tr_priv, priv_delims, bts, asetpriv ); /* usual case */
531:         fclose ( tr_priv );             /* done reading priv_file */
532:         if ( bts->user_type != ADMIN_TYPE ) /* admin trades nothing */
533:           if ( bts->ntrading < 1 )      /* nothing authorized for this guy */
534:             { bts->user_type = SALES_TYPE; /* so flip him to a salesperson */
535:               bts->privileges = 0;      /* no privileges allowed for sales */
536:               if ( bts->msglevel >= ERRLEVEL ) /* and print a "warning" */
537:                 { sprintf(msgbuff,"No issues trading, treated as Salesperson.");
538:                   prtmsg ( MSG_ROW, msgbuff ); }
539:             } /* --- end-of-if(!ADMIN_TYPE&&ntrading<1) --- */
540:         } /* --- end-of-if(!SALES_TYPE&&!isinput&&*priv_file) --- */
541: 
542: /* --- set privileges for user --- */
543: if ( isinput ) bts->privileges = 3;     /* inputter entitled to everything */
544: if ( bts->user_type == TRADER_TYPE )    /* for a trader */
545:     { if ( bts->privileges < 1 )        /* minimum privilege level is 1 */
546:         bts->privileges = 1; }          /* so make sure he gets it */
547:    else bts->privileges = 0;            /* everyone else has zero privs */
548: 
549: /* --- re-report total number of issues/#trading --- */
550: if ( bts->msglevel >= INITLEVEL )
551:   if ( bts->ntrading > 0 )
552:     { sprintf ( msgbuff, "%d issues in universe, you are trading %d of them.",
553:         nuniverse,bts->ntrading );
554:       prtmsg ( MSG_ROW2, msgbuff ); }
555: 
556: /* -------------------------------------------------------------------------
557: Allocate window buffers by user_type and #traders, and open the windows.
558: -------------------------------------------------------------------------- */
559: /* --- allocate window structs (with #objects by screen type) --- */
560: x_screens = t_screens;                  /* assume we want trader screens */
561: if ( bts->user_type==SALES_TYPE )       /* unless we're a a salesperson */
562:         x_screens = s_screens;                  /* point to sales screens */
563: if ( bts->user_type==ADMIN_TYPE )       /* or unless we're the administrator */
564:         { x_screens = a_screens;                /* point to admin screens */
565:           bts->ntraders = 1; }                  /* and force to single trader */
566: bts->nwindows = nwindows = 0;           /* no windows created yet */
567: for ( iwindow=0; (screen=x_screens[iwindow])>=0; iwindow++ ) /* by user type */
568:     {
569:     max_objects = MAX_OBJECTS;          /* default window size */
570:     for ( iscreen=0; screen_size[iscreen].screen >= 0; iscreen++ )
571:         { if ( screen_size[iscreen].screen == screen )          /* got screen */
572:             { max_objects = screen_size[iscreen].max_objects;   /* and size */
573:               break; }                                          /* end loop */
574:         } /* --- end-of-for(iscreen) --- */
575:     if ( isinput )                      /* modifications for data entry */
576:         { if ( screen == TRADER_SCREEN ) max_objects = MAX_UNIVERSE+2; /*max*/
577:         } /* --- end-of-if(isinput) --- */
578:     if ( screen == TRADER_SCREEN ) ntraders = bts->ntraders; /* 1 per trader */
579:         else    ntraders = 1;           /* only 1 window for other screens */
580:     for ( itrader=0; itrader < ntraders; itrader++ ) /* all windows for screen */
581:       {
582:       /* --- first create the window with full complement of objects --- */
583:       if ((bts->wptrs[nwindows]=(BWS *)create_window(max_objects))==(BWS *)NULL)
584:         { /* --- quit if failed to calloc/init window --- */
585:         sprintf( bts->msgbuff, "Failed to alloc window buff#%d with %d objects",
586:                 nwindows+1, max_objects );
587:         return ( -1 ); }                /* error return will force exit */
588:       /* --- then open it as per its screen type --- */
589:       (bts->nwindows)++;                /* open_window() will check this */
590:       owindow = open_window ( bts, nwindows, screen, -1, -1 );
591:       if ( owindow != nwindows )        /* didn't open it as requested */
592:         { if ( bts->msglevel >= BUGLEVEL ) /* so report error */
593:             { sprintf(msgbuff,"Opened window#%d as #%d.",nwindows,owindow);
594:               prtmsg ( BUG_ROW, msgbuff ); }
595:           owindow = (-1); }             /* assume we just lost the window */
596:       /* --- store the opened window's index by its screen type --- */
597:       switch ( screen )                 /* assign window index by screen type */
598:         { default:                      /* allocated unidientifiable screen */
599:             sprintf ( bts->msgbuff, "Unidentified screen type #%d allocated.",
600:                 screen);                /* format error message */
601:             return ( -1 );              /* error return will force exit */
602:         case TRADER_SCREEN:     bts->iwtrader[itrader] = owindow; break;
603:         case DETAIL_SCREEN:     bts->iwdetail          = owindow; break;
604:         case RELATION_SCREEN:   bts->iwrelation        = owindow; break;
605:         case PROFILE_SCREEN:    bts->iwprofile         = owindow;
606:             if ( owindow == nwindows )  /* load profile window if successful */
607:                 { nobjects = load_window ( bts, owindow, -1, 1, &(-9999) );
608:                   if ( nobjects != nuniverse ) /* not everything loaded */
609:                     if ( bts->msglevel >= BUGLEVEL ) /* so report error */
610:                         { sprintf(msgbuff,"Only %d of %d objects in profile",
611:                                 nobjects,nuniverse);
612:                           prtmsg ( ERR_ROW, msgbuff ); }
613:                 } /* --- end-of-if(owindow==nwindows) --- */
614:             break;
615:         case ADMIN_SCREEN:      bts->iwtrader[itrader] = owindow;
616:             if ( owindow == nwindows )  /* load admin window if successful */
617:                 { nobjects = load_window ( bts, owindow, -1, 0, &(-9999) );
618:                   if ( nobjects != nuniverse ) /* not everything loaded */
619:                     if ( bts->msglevel >= BUGLEVEL ) /* so report error */
620:                         { sprintf(msgbuff,"Only %d of %d objects in admin",
621:                                 nobjects,nuniverse);
622:                           prtmsg ( ERR_ROW, msgbuff ); }
623:                   (bts->wptrs[owindow])->iwsorting = (-2); /* sort on typ&mat */
624:                 } /* --- end-of-if(owindow==nwindows) --- */
625:             break;
626:         } /* --- end-of-switch(screen) --- */
627:       if ( owindow >= 0 ) nwindows++;   /* successful, so bump window counter */
628:       } /* --- end-of-for(itrader) --- */
629:     } /* --- end-of-for(iwindow) --- */
630: if ( bts->nwindows != nwindows )        /* should have opened everything */
631:         { sprintf(bts->msgbuff,"Failed to open %d windows.",
632:                 bts->nwindows-nwindows);
633:           return ( -1 ); }              /* so can't do anything */
634: 
635: /* -------------------------------------------------------------------------
636: Load profile file(s) for each trader this user is representing
637: -------------------------------------------------------------------------- */
638: /* --- load profile --- */
639: if ( bts->user_type != ADMIN_TYPE       /* administrator has no profile */
640: /* &&   !isinput */ )                   /* and inputter doesn't need one */
641:   for ( itrader=0; itrader < bts->ntraders; itrader++ ) /* each trader has prof */
642:     {
643:     bts->itrader = itrader;             /* set current trader in bts */
644:     bts->iwindow = bts->iwtrader[itrader]; /* and set current trader window */
645:     trader = bts->trader[itrader];      /* ptr to his name slot */
646:     if ( strchr(READONLY,*trader) != (char *)NULL ) /* name has a r/o prefix */
647:         trader++;                       /* so skip past it */
648:     strcpy ( prof_file, BPATH );        /* start with default directory */
649:     strcat ( prof_file, trader );       /* profile file is trader's name */
650:     if ( !isrefresh )                   /* usually use normal profile */
651:         strcat ( prof_file, ".PRF" );   /* with .PRF extension */
652:         else strcat ( prof_file, ".JOU" ); /* or refresh with journal file */
653:     if ( !isinput )                     /* don't want profile for inputter */
654:       { /* --- open profile and load it for traders/salespersons --- */
655:       if ( (tr_prof = fopen(prof_file,"r")) /* open the file for read */
656:       == NULL )                         /* failed to open */
657:         { /* --- can't open prof_file (probably a new trader) --- */
658:         if ( bts->msglevel >= ERRLEVEL )
659:           { sprintf(msgbuff,"Profile file %s not found for trader %s.",
660:                 prof_file,trader);
661:             prtmsg ( ERR_ROW, msgbuff ); }
662:         }
663:       else
664:         { /* --- load profile --- */
665:         if ( !isinput || itrader>0 )    /* ignore profile for INPUTTER screen */
666:             nscanned = scanfile ( tr_prof, prof_delims, bts, asetprof );
667:         fclose ( tr_prof );             /* done reading prof_file */
668:         /* sort_window ( bts, bts->iwindow, 2 ); */ /* don't want it sorted */
669:         }
670:       } /* --- end-of-if(!isinput) --- */
671: 
672:     /* --- make sure trader window has all issues he's trading --- */
673:     nnewobj = 0;                        /* no new objects added yet */
674:     sprintf ( msgbuff, "New issues:" ); /* stub for new issues list */
675:     wp = bts->wptrs[bts->iwindow];      /* ptr to current trader's window */
676:     for ( iuniverse=0; iuniverse < nuniverse; iuniverse++ )
677:         {
678:         if ( !isinput || itrader>0 )    /* inputter trading everything */
679:           if ( rp[iuniverse].privileges != (itrader+1) ) /*our guy not trading*/
680:             continue;                   /* so we don't care if window has it */
681:         nobjects = wp->nobjects;        /* #objects currently in his window */
682:         op = wp->objects;               /* ptr to first object */
683:         for ( iobject=wp->nstatic; iobject < nobjects; iobject++ )
684:             if ( op[iobject].descrip.index == iuniverse ) /* he's got it */
685:                 break;                  /* so we can stop looking */
686:         if ( iobject >= nobjects )      /* finished loop without finding it */
687:             { objlist[0] = iuniverse;   /* so we need to add iuniverse */
688:               objlist[1] = (-1);        /* and that's all so far */
689:               iobject = wp->nstatic + nnewobj; /* place new obj after static */
690:               if ( load_window(bts,-1,iobject,0,objlist) /* add to window */
691:               > 0 )                     /* added successfully */
692:                 { nnewobj++;            /* one more new object added */
693:                   if ( strlen(msgbuff) < 60 ) /* got room for another issue */
694:                     sprintf(msgbuff+strlen(msgbuff)," %s",up[iuniverse].sec_id);
695:                   /* op[iobject].ismarked = TRUE; */ } /* mark new objects */
696:             } /* --- end-of-if(iobject>=nobjects) --- */
697:         } /* --- end-of-for(iuniverse) --- */
698:     if ( nnewobj > 0                    /* added something to window */
699:     &&   !isinput )                     /* input unmarked in sort_window() */
700:       if ( bts->msglevel >= 2 )         /* and want that fact reported */
701:         { /* sprintf(msgbuff,"You have %d new issues.  Press C to unmark them.",
702:           nnewobj); */
703:           prtmsg ( ERR_ROW, msgbuff ); }
704:     if ( isinput && itrader==0 )        /* got input trader's window */
705:         wp->iwsorting = (-2);           /* so force sort on type&maturity */
706:     if ( nnewobj > 0 )                  /*if there are newly-assigned objects*/
707:         wp->iwsorting = (-2);           /* all trader windows sorted */
708:     } /* --- end-of-for(itrader) --- */
709: 
710: /* --- reset to primary trader --- */
711: bts->itrader = 0;                       /* always come up as primary trader */
712: if ( isinput )                          /* if we're the input trader */
713:     if ( strchr(bts->edit_mode,'C') == NULL ) /* check for change field edit */
714:         strcat(bts->edit_mode,"C");     /* inputter can edit change field */
715: 
716: /* --- check freeze mode --- */
717: switch ( bts->user_type )               /* constraints depend on user type */
718:     {
719:     default: /* --- really bad trouble without type --- */
720:         strcpy ( bts->msgbuff, "Can't identify user type" );
721:         return ( -1 );
722:     case ADMIN_TYPE: /* --- for the administrator --- */
723:         strcpy ( bts->freeze, "B" );    /* no Server so freeze everything */
724:         break;
725:     case SALES_TYPE: /* --- for a salesperson --- */
726:         strcpy ( bts->relation_mode[0], "Q" ); /* sales can't update */
727:         if ( *(bts->freeze) == 'X' )    /* if has no freeze */
728:             strcpy ( bts->freeze, "O" ); /* promote it to Output */
729:         if ( *(bts->freeze) == 'I' )    /* if he only has an incoming freeze */
730:             strcpy ( bts->freeze, "B" ); /* promote it to Both */
731:         break;
732:     case TRADER_TYPE: /* --- for a trader --- */
733:         break;
734:     } /* --- end-of-switch(user_type) --- */
735: 
736: return ( 1 );                           /* back home with successful init */
737: 
738: /* -------------------------------------------------------------------------
739: Shutdown request at end-of-job
740: -------------------------------------------------------------------------- */
741: shutdown:
742: 
743: /* if ( !isreadonly ) { */              /* no logical for readonly user */
744:     strcpy ( trdrlognam, "&" );         /* start logical name with an & */
745:     if ( bts->user_type == ADMIN_TYPE ) /* admin may have changed his name */
746:         strcat ( trdrlognam, ADMINISTRATOR ); /* so force logical to "ADMIN" */
747:     else strcat ( trdrlognam, bts->trader[0] ); /* normal name for others */
748:     dellnm ( "", trdrlognam );          /* delete logical trader name */
749: /*  }  */ /* --- end-of-if(!isreadonly) --- */
750: 
751: if ( !bts->isabort )                    /* don't rewrite files if aborting */
752:     {
753:     /* --- rewrite profile file (see load profile above) --- */
754:     if ( bts->user_type != ADMIN_TYPE   /* administrator has no profile */
755:     &&   !isreadonly )                  /* readonly user can't rewrite */
756:       for ( itrader=0; itrader < bts->ntraders; itrader++ ) /* each trader */
757:         {
758:         if ( isinput && itrader==0 ) continue; /* forget INPUT screen profile */
759:         bts->itrader = itrader;         /* set current trader in bts */
760:         bts->iwindow = bts->iwtrader[itrader]; /* set current trader window */
761:         trader = bts->trader[itrader];  /* ptr to his name slot */
762:         strcpy ( prof_file, BPATH );    /* start with default directory */
763:         strcat ( prof_file, trader );   /* profile file is trader's name */
764:         strcat ( prof_file, ".PRF" );   /* with .PRF extension */
765:         putprof ( bts, prof_file );     /* write new profile file */
766:         } /* --- end-of-for(itrader) --- */
767: 
768:     /* --- rewrite universe files --- */
769:     if ( bts->isdump                    /* flag requesting universe dump set */
770:     /* &&   bts->user_type == TRADER_TYPE */ ) /* and we're a trader */
771:         {
772:         /* --- first recalculate the universe on price --- */
773:         if ( bts->msglevel >= INITLEVEL ) /* display recalc message */
774:             prtmsg ( MSG_ROW, "Recalculating universe." );
775:         itrader = 0;                    /* default to primary trader */
776:         for ( iuniverse=0; iuniverse < bts->nuniverse; iuniverse++ )
777:           { recalc  ( &(bts->universe[iuniverse]), 1, bts->explicit_date,
778:                         bts->change_num, &(bts->recalc_options[itrader]) );
779:             bidcalc ( &(bts->universe[iuniverse]), bts->explicit_date );    }
780:         /* --- see if input trader wants temp "basis-formatted" files --- */
781:         if ( isinput )                  /* this guy's the input trader */
782:           { if ( !memcmp(bts->attn_buff,"EXIT",4) ) /* and he used exit cmd */
783:                 isbasis = TRUE;         /* so dump files in Basis format */
784:             else dellnm ( "", "BINPUT" ); /* delete input date flag on last */
785:           } /* --- end-of-if(isinput) --- */
786:         /* --- dump all the files --- */
787:         for ( iqtype=0; *(qtypes[iqtype]) != '\000'; iqtype++ )
788:             {
789:             if ( *(qfiles[iqtype]) == '\000' ) continue; /* no file */
790:             if ( nloaded[iqtype] <= 0 ) continue; /* nothing loaded */
791:             if ( isbasis ) qdate = qsettlements[iqtype]; /* normal trader */
792:                 else qdate = bts->explicit_date; /* for data entry */
793:             ndumped[iqtype] =
794:               qdump ( qtypes[iqtype], qfiles[iqtype], qrenamer(bts,iqtype,TRUE),
795:                         bts->universe, qdate, isbasis );
796:             if ( bts->msglevel >= INITLEVEL ) /* display #issues dumped */
797:                 { sprintf ( msgbuff, "%d %s-issues dumped to %s",
798:                     ndumped[iqtype],qtypes[iqtype],qrenamer(bts,iqtype,TRUE) );
799:                   prtmsg ( MSG_ROW, msgbuff ); }
800:             } /* --- end-of-for(*qtypes[iqtype]) --- */
801:         if ( isinput )                  /* inputter completed file rewrite */
802:           { if ( !memcmp(bts->attn_buff,"EXIT",4) ) /* and he used exit cmd */
803:                  crelnm ( "", "BINPUT", atoday() ); /* so store date */
804:             else dellnm ( "", "BINPUT" ); /* delete input date flag on last */
805:           } /* --- end-of-if(isinput) --- */
806:         } /* --- end-of-if(isdump) --- */
807: 
808:     } /* --- end-of-if(!isabort) --- */
809: 
810: /* --- close Basis windows --- */
811: /* close_window ( bts, -1 ); */         /* close all opened windows */
812: 
813: return ( 1 );                           /* back home with successful shutdown */
814: } /* --- end-of-function basis_init() --- */
815: 
816: 
817: /* --- entry point --- */
818: char    *qrenamer ( bts, iqtype, isoutfile ) /*name of quotefile to read/write*/
819: BTS     *bts;                           /* addr of basis trader struct */
820: int     iqtype;                         /* filetype index, see qdescrip.h */
821: int     isoutfile;                      /* true to name an output file */
822: {
823: /* --- Allocations and Declarations --- */
824: static  char filename[64];              /* filename returned to caller */
825: static  char qprefix[64], qsuffix[64];  /* constructed filename prefix,suffix */
826: static  char qdate[64];                 /* date for naming file (if needed) */
827: char    *atoday(), *anextbusday();      /* to determine dates */
828: char    *delim, *strchr();              /* to locate delimiters in filename */
829: 
830: /* --- initialization --- */
831: *filename = '\000';                     /* init as null string in case of err */
832: if ( *(qfiles[iqtype]) == '\000' )      /* no default filename */
833:     return ( filename );                /*so we're not read/writing this file*/
834: 
835: /* --- determine name of input file --- */
836: if ( !isoutfile )                       /* not an output file, must be input */
837:     {
838:     if ( !isinput                       /* we're trader/sales/admin */
839:     ||   !isrefresh )                   /* or input and not refreshing */
840:         { strcpy ( filename, qfiles[iqtype] ); /* so copy default file name */
841:           return ( filename ); }        /* and return it to caller */
842:     /* --- got an input trader who wants refresh --- */
843:     strcpy ( qdate, anextbusday(atoday(),HOLIDAY_ICAL,2) ); /*day after tomrrw*/
844:     goto outfile_name;                  /* otherwise identical to outfile */
845:     } /* --- end-of-if(!isoutfile) --- */
846: 
847: /* --- determine name of output file --- */
848: if ( isoutfile )                        /* caller wants output filename */
849:     {
850:     strcpy ( qdate, bts->explicit_date ); /* default uses settlement date */
851:   outfile_name:;
852:     *qsuffix = '\000';                  /* no suffix unless INPUT trader */
853:     if ( isinput )                      /* unless we're the INPUT trader */
854:         { memcpy ( qsuffix+0, qdate+6, 2 ); /* start suffix with yy */
855:           memcpy ( qsuffix+2, qdate+0, 2 ); /* followed by mm */
856:           memcpy ( qsuffix+4, qdate+3, 2 ); /* and finish up with dd */
857:           qsuffix[6] = '\000';          /* null-terminate yymmdd suffix */
858:         } /* --- end-of-if(isinput) --- */
859:     if ( *qext == '\000' )              /* 1st call and no command-line arg */
860:         { strcpy ( qext, "DUMP" );      /* usually just a dummy .extension */
861:           if ( isinput )                /* unless we're the INPUT trader */
862:             strcpy ( qext, "VAX" );     /* use .VAX as extension */
863:         } /* --- end-of-if(*qext=='\000') --- */
864:     if ( (delim=strchr(qext,'.')) != (char *)NULL ) /* extension has a dot */
865:         { /* --- need to separate suffix + extension --- */
866:         strcpy ( qsuffix, qext );       /* copy of suffix+extension in suffix */
867:         strcpy ( qext, delim+1 );       /* shift out suffix from extension */
868:         if ( (delim=strchr(qsuffix,'.')) != (char *)NULL ) /* find dot again */
869:             *delim = '\000';            /* and null-terminate suffix at it */
870:         } /* --- end-of-if(qext has a .) --- */
871:     *filename = '\000';                 /* init filename */
872:     strcpy ( qprefix, qfiles[iqtype] ); /* default filename in prefix */
873:     if ( isinput )                      /* unless we're the INPUT trader */
874:         {
875:         strcpy ( filename, TRANSFER );  /* need transfer directory for INPUT */
876:         qprefix[0] = 'Q';               /* get 'Q' as first char of filename */
877:         qprefix[1] = *(qtypes[iqtype]); /* followed by BNAZF... filetype char */
878:         qprefix[2] = '\000';            /* null-terminate after QB,QN,... */
879:         } /* --- end-of-if(isinput) --- */
880:     strcat ( filename, qprefix );       /* get directory+QA or full filename */
881:     if ( (delim=strchr(filename,'.')) != (char *)NULL ) /* remove input ext */
882:         *delim = '\000';                /* terminate filename at dot */
883:     strcat ( filename, qsuffix );       /* add suffix (yymmdd or nothing) */
884:     strcat ( filename, "." );           /* restore dot after name */
885:     strcat ( filename, qext );          /* and finish up with extension */
886:     } /* --- end-of-if(isoutfile) --- */
887: 
888: return ( filename );                    /* constructed quote file name */
889: } /* --- end-of-function qnamer() --- */
890: /* ----------------------- END-OF-FILE BASIS_INIT.C ------------------------- */


BBBBBBBB        AA      SSSSSSS    IIIIII     SSSSSSS               OOOOOO   BBBBBBBB  
BBBBBBBBB      AAAA    SSSSSSSSS   IIIIII    SSSSSSSSS             OOOOOOOO  BBBBBBBBB 
 BB     BB    AA  AA  SS             II     SS                    OO      OO  BB     BB
 BBBBBBBB    AA    AA  SSSSSSS       II      SSSSSSS              OO      OO  BBBBBBBB 
 BBBBBBBB   AAAAAAAAA   SSSSSSS      II       SSSSSSS             OO      OO  BBBBBBBB 
 BB     BB AAAAAAAAAA         SS     II             SS            OO      OO  BB     BB
BBBBBBBBB  AA      AA SSSSSSSSS    IIIIII   SSSSSSSSS  __________  OOOOOOOO  BBBBBBBBB 
BBBBBBBB   AA      AA  SSSSSSS     IIIIII    SSSSSSS   __________   OOOOOO   BBBBBBBB  

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Function:    basis_object ( bts, iwindow, item )
  7:  *
  8:  * Purpose:     Displays/updates the basis object in the header of
  9:  *              the trader/salesperson screen.
 10:  *
 11:  * Arguments:
 12:  *              bts (I)         addr of Basis Trader Struct.
 13:  *
 14:  *              iwindow (I)     int containing index of current window
 15:  *                              (which sould be one of the TRADER_SCREEN's)
 16:  *                              whose basis object should be edited.
 17:  *
 18:  *              item (I/O)      addr of int containing any number >=0 if basis
 19:  *                              item to be edited, or -1 for display-only mode,
 20:  *                              returns unchanged, or -1 if any editable error.
 21:  *
 22:  * Returns:     -int            if *item>=0 returns last (unprocessed) keypress,
 23:  *                              else returns 0,
 24:  *                              or -1 if some error.
 25:  *
 26:  * Notes:     o
 27:  *
 28:  * Source:      BASIS_OBJECT.C
 29:  *
 30:  * --------------------------------------------------------------------------
 31:  * Revision History:
 32:  *
 33:  * 01/17/89     J.Forkosh       Installation.
 34:  * 02/09/89     J.Forkosh       Modified for Version 2.
 35:  *
 36:  ****************************************************************************/
 37: 
 38: /* -------------------------------------------------------------------------
 39: Header files
 40: -------------------------------------------------------------------------- */
 41: /* --- basis headers --- */
 42: #include "basis.h"
 43: #include "trader.h"
 44: #include "screens.h"
 45: #include "keys.h"
 46: #define ed_arglist EDTYPE
 47: /* ----------------------------------------------------------------------- */
 48: 
 49: /* --- entry point --- */
 50: int     basis_object ( bts, iwindow, item )
 51: BTS     *bts;
 52: int     iwindow;
 53: int     *item;
 54: {
 55: /* -------------------------------------------------------------------------
 56: Allocations and Declarations
 57: -------------------------------------------------------------------------- */
 58: ed_arglist ed_args[4];                  /* args to construct/pass to edit */
 59: BWS     *wp;                            /* wptrs[iwindow] */
 60: int     itrader;                        /* trader whose window we're in */
 61: int     ibasis;                         /* universe index of basis (or -1) */
 62: BUS     *bup;                           /* universe ptr for basis issue */
 63: int     nfields;                        /* number of edit fields formatted */
 64: int     isprotected;                    /* true if called for display-only */
 65: int     isbreak;                        /* true to break from edit loop */
 66: int     irow, icol;                     /* position of basis on screen */
 67: int     e_disp;                         /* edit disposition */
 68: int     is32nds;                        /* true for 32nds */
 69: double  oldprice,newprice,diffprice;    /* to see if basis price changed */
 70: double  amount;                         /* plus/minus increment = .01 or 1/32 */
 71: double  change;                         /* from yesterday's closing price */
 72: char    achange[16], *dtoau();          /* local conversion to 32nds string */
 73: int     keypress;                       /* keypress from edit_object() */
 74: short   edit();                         /* edit returns next item as a short */
 75: 
 76: /* -------------------------------------------------------------------------
 77: Initialization
 78: -------------------------------------------------------------------------- */
 79: /* --- check iwindow input, retrieve a window ptr, check screen type --- */
 80: if ( iwindow<0 || iwindow>=bts->nwindows ) /* index out-of-bounds */
 81:         { *item = (-1); return ( -1 ); } /* so back to caller with error */
 82: wp = bts->wptrs[iwindow];               /* ptr to window */
 83: if ( wp->window_type != TRADER_SCREEN ) /* basis object must be in trader scr */
 84:         { *item = (-1); return ( TOGGLE_FUTURE ); } /* or back to caller */
 85: /* --- match iwindow to a trader window --- */
 86: for ( itrader=0; itrader < bts->ntraders; itrader++ )
 87:     { if ( iwindow == bts->iwtrader[itrader] ) /*trader whose window we're in*/
 88:         break; }                        /* we know who we are, so get out */
 89: if ( itrader >= bts->ntraders )         /* we completed loop with no match */
 90:     { itrader = bts->itrader;           /* so choose current trader */
 91:       if ( itrader<0 || itrader>=bts->ntraders ) /* but he's no good either */
 92:         itrader = 0; }                  /* so choose primary trader */
 93: /* --- get basis issue for chosen trader --- */
 94: ibasis = bts->ibasis[itrader];          /* universe index of basis issue */
 95: if ( ibasis<0 || ibasis>=bts->nuniverse ) /* index out-of-bounds */
 96:         { *item = (-1); return ( TOGGLE_FUTURE ); } /* so back to caller */
 97: bup = &(bts->universe[ibasis]);         /* universe ptr to basis issue */
 98: /* --- set plus/minus increment --- */
 99: is32nds = TRUE;                         /* default is 32nds */
100: amount = (1.0/32.0);                    /* default amount is 1/32 */
101: if ( !memcmp(bts->basis[itrader],"TB",2)   /* except for treasury bills */
102: ||   !memcmp(bts->basis[itrader],"ED",2) ) /* and eurodollars */
103:         { is32nds = FALSE;              /* not 32nds */
104:           amount = 0.01; }              /* in which case it's hundredths */
105: /* --- extract protection from input we were passed --- */
106: isprotected = ((*item)>=0)? FALSE:TRUE; /* sign of item is protection mode */
107: e_disp = (isprotected)? DISP_ONLY : DISP_EDIT; /* read-only if protected */
108: 
109: /* -------------------------------------------------------------------------
110: Locate position of basis on screen
111: -------------------------------------------------------------------------- */
112: irow = wp->row1 + 1;                    /* basis price is on 2nd hdr line */
113: icol = 67;                              /* starting on col 67 (1st col=0) */
114: 
115: /* -------------------------------------------------------------------------
116: Set up specially-formatted fields that edit_setup() can't handle via table
117: -------------------------------------------------------------------------- */
118: nfields = 0;                            /* no edit args set up yet */
119: /* --- format price for basis issue --- */
120: if ( is32nds )
121:   {
122:   /* --- price field --- */
123:   edarg_setup ( &(ed_args[nfields]), irow, icol, &(bup->computed.price),
124:     0x0703, D_SFS, "%7.3lf", (IS_INC|SFS_32_8|SFS_I_32|SFS_COLON|SFS_LEADZ),
125:     e_disp, 0 );
126:   nfields++;                            /* got one more field to do */
127:   }
128: else
129:   {
130:   /* --- price field --- */
131:   edarg_setup ( &(ed_args[nfields]), irow, icol, &(bup->computed.price),
132:     0x0703, D_DBL, "%7.3lf", (NO_NEG|IS_INC|(IS_DECIN|0x0002)),
133:     e_disp, 0 );
134:   nfields++;                            /* got one more field to do */
135:   }
136: 
137: /* -------------------------------------------------------------------------
138: Got ed_args for edit(), so issue the toolbox calls
139: -------------------------------------------------------------------------- */
140: /* --- init for display/editing --- */
141: isbreak = FALSE;
142: oldprice = bup->computed.price;         /* original basis price */
143: while ( TRUE )
144:     {
145:     /* --- always recalculate change (even when not really required) --- */
146:     change = bup->computed.price - bup->computed.close_price;
147:     if ( is32nds )
148:         { strcpy ( achange, dtoau(change,32,8,":") );
149:           achange[5] = '\000'; }
150:     else
151:         { sprintf ( achange, "%lf", change );
152:           achange[5] = '\000'; }
153:     prts ( irow,75, bts->bold,bts->bg, achange );
154:     /* --- first display the current basis price --- */
155:     edit( (short)0, &ed_args[0], (short)nfields, (short)DISP_ONLY );
156:     if ( isprotected ) return ( 0 );    /* all done if not editing */
157:     /* --- see if re-calculation required --- */
158:     newprice = bup->computed.price;
159:     if ( (diffprice=newprice-oldprice) < 0.0 )
160:         diffprice = (-diffprice);
161:     if ( diffprice > 0.0005 )
162:         update_relations(bts,ibasis,TRUE,FALSE);
163:     oldprice = newprice;
164:     if ( isbreak ) break;
165:     /* --- get price change --- */
166:     keypress = (int)edit ((short)0,&ed_args[0],(short)nfields,(short)DISP_EDIT);
167:     if ( keypress>='a' && keypress<='z' )
168:         keypress = toupper(keypress);
169:     switch ( keypress )
170:         {
171:         case PLUS:      /* bup->computed.price += amount; break; */
172:         case LOWER:     /* bup->computed.price -= amount; break; */
173:         default: isbreak = TRUE; break; /* unrecognized keystroke */
174:         }
175:     } /* --- end-of-while(TRUE) --- */
176: 
177: /* -------------------------------------------------------------------------
178: Everything is presumably displayed as requested
179: -------------------------------------------------------------------------- */
180: end_of_job:
181: return ( keypress );                    /* and last unprocessed keypress */
182: } /* --- end-of-function basis_object() --- */
183: /* --------------------- END-OF-FILE BASIS_OBJECT.C ---------------------- */


BBBBBBBB        AA      SSSSSSS    IIIIII     SSSSSSS               SSSSSSS  WW      WW
BBBBBBBBB      AAAA    SSSSSSSSS   IIIIII    SSSSSSSSS             SSSSSSSSS WW      WW
 BB     BB    AA  AA  SS             II     SS                    SS         WW      WW
 BBBBBBBB    AA    AA  SSSSSSS       II      SSSSSSS               SSSSSSS   WW  WW  WW
 BBBBBBBB   AAAAAAAAA   SSSSSSS      II       SSSSSSS               SSSSSSS  WW WWWW WW
 BB     BB AAAAAAAAAA         SS     II             SS                    SS WWWW  WWWW
BBBBBBBBB  AA      AA SSSSSSSSS    IIIIII   SSSSSSSSS  __________ SSSSSSSSS  WWW    WWW
BBBBBBBB   AA      AA  SSSSSSS     IIIIII    SSSSSSS   __________  SSSSSSS   WW      WW

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Function:    basis_switch ( bts )
  7:  *
  8:  * Purpose:     Controls the online program flow of the user.
  9:  *
 10:  * Arguments:
 11:  *              bts (I)         addr of the Basis Trader Struct.
 12:  *
 13:  * Returns:     ( int )         1 for successful completion (ready to exit),
 14:  *                              -1 if some error (abort).
 15:  *
 16:  * Notes:     o
 17:  *
 18:  * Source:      BASIS_SWITCH.C
 19:  *
 20:  * --------------------------------------------------------------------------
 21:  * Revision History:
 22:  *
 23:  * 02/07/89     J.Forkosh       Installation for Version 2.
 24:  *
 25:  ****************************************************************************/
 26: 
 27: /* -------------------------------------------------------------------------
 28: Header files
 29: -------------------------------------------------------------------------- */
 30: /* --- Basis headers --- */
 31: #include "basis.h"
 32: #include "trader.h"
 33: #include "screens.h"
 34: #include "reports.h"
 35: #include "menus.h"
 36: #include "keys.h"
 37: #define BCLOCK
 38: #include "bglobals.h"
 39: #define BACKUP 3600                     /* backup profile to .tmp every #secs */
 40: /* ----------------------------------------------------------------------- */
 41: 
 42: /* --- entry point --- */
 43: int     basis_switch ( bts )
 44: BTS     *bts;
 45: {
 46: /* -------------------------------------------------------------------------
 47: Allocations and Declarations
 48: -------------------------------------------------------------------------- */
 49: int     state, prev_state,next_state,   /* current, change of state */
 50:         itrader, prev_trader,next_trader; /* trader index in above states */
 51: int     screen,  prev_screen,next_screen; /* screen type that goes with state */
 52: int     istate, iscreen,                /* to look up next_screen in table */
 53:         iwindow;                        /* to look up window with next_screen */
 54: BWS     *wp;                            /* ptr to iwindow */
 55: int     keypress;                       /* user keystroke */
 56: int     isedit;                         /* true while user in edit mode */
 57: int     isredraw;                       /* true to re-draw current screen */
 58: int     status;                         /* return status from various calls */
 59: int     nloops = 0;                     /* number of passes thru main loop */
 60: int     naborts = 0;                    /* number of consecutive aborts */
 61: int     nprices;                        /* #closing prices sent to server */
 62: int     ncopied;                        /* #objects copied by copy_window() */
 63: int     ivalue;                         /* atoi(msgbuff) when appropriate */
 64: int     prev_attn = ATTN_FIND;          /* previous attention command */
 65: int     backup = BACKUP, lastback=0, thisback=0; /* backup interval and times */
 66: char    *chptr, *strchr(), *index();    /* to search for various chars */
 67: char    *strupper(), *trim(), *ltrim(); /* trim and toupper a string */
 68: char    *daytime();                     /* to print date-time stamp */
 69: char    msgbuff[132], *getmsg();        /* local buff, also for attention msg */
 70: /* ----------------------------------------------------------------------- */
 71: 
 72: /* -------------------------------------------------------------------------
 73: Initialization
 74: -------------------------------------------------------------------------- */
 75: /* --- init to bring trader up in default state (whatever next_state is) --- */
 76: bts->state = prev_state = next_state = (-1); /* no state selected yet */
 77: bts->itrader = prev_trader = next_trader = (-1); /* no trader selected yet */
 78: bts->iwindow = iwindow = screen = (-1); /* no window up yet */
 79: screen = prev_screen = next_screen = (-1); /* no screen on no window */
 80: isedit = 0;                             /* default to read-only mode */
 81: isredraw = TRUE;                        /* redraw everything 1st time around */
 82: status = 0;                             /* no return status yet */
 83: *msgbuff = '\000';                      /* no message to report yet */
 84: *(bts->msgbuff) = '\000';               /* no message for main() yet either */
 85: lastback = 0;                           /* set for immediate backup */
 86: 
 87: /* --- set initial user state/trader by user type --- */
 88: switch ( bts->user_type )
 89:     { default: return ( -1 );           /* invalid user type */
 90:     case TRADER_TYPE:
 91:     case SALES_TYPE:
 92:         next_state = TRADER_STATE;      /* default state for trader/sales */
 93:         next_trader = 0;
 94:         break;
 95:     case ADMIN_TYPE:
 96:         next_state = ADMIN_STATE;       /* default state for administrator */
 97:         next_trader = 0;
 98:         break; }
 99: 
100: /* --- switch trader state context as necessary until he exits from Basis --- */
101: while ( ++nloops )                      /* keep processing input till eoj */
102:     {
103:     /* ---------------------------------------------------------------------
104:     Debugging output
105:     ---------------------------------------------------------------------- */
106:     if ( bts->msglevel >= DEBLEVEL )
107:         { sprintf ( msgbuff, "switch> loop#%d, state=%d,%d,%d, trader=%d,%d,%d",
108:                 nloops, prev_state,bts->state,next_state,
109:                 prev_trader,bts->itrader,next_trader );
110:           prtmsg ( BUG_ROW2, msgbuff ); }
111: 
112:     /* ---------------------------------------------------------------------
113:     Check for periodic backup
114:     ---------------------------------------------------------------------- */
115:     if ( backup > 0 )                   /* if doing backups */
116:      {
117:      daytime ( &thisback );             /* time in 100ths secs since 12am */
118:      thisback /= 100;                   /* clock time in secs since midnight */
119:      if ( nloops > 1 )                  /* can't backup till after init */
120:       if ( (thisback-lastback) > backup ) /* time to do another backup */
121:         {
122:         lastback = thisback;            /* don't forget to reset backup time */
123:         if ( bts->user_type != ADMIN_TYPE ) /* admin has no profile */
124:           putprof(bts,".JOU");          /* "journal" trader's profile */
125:         } /* --- end-of-if(this-last>backup) --- */
126:      } /* --- end-of-if(backup>0) --- */
127: 
128:     /* ---------------------------------------------------------------------
129:     If trader changed state, bring up corresponding screen/window for him.
130:     ---------------------------------------------------------------------- */
131:     state = bts->state;                 /* get user's current state from bts */
132:     itrader = bts->itrader;             /* and his trader index */
133:     if ( state != next_state            /* change-of-state required */
134:     ||   itrader != next_trader         /* even if just a different trader */
135:     ||   isredraw )                     /* or if asked/need to re-draw screen */
136:         {
137:         /* --- save current state as previous state and set new state --- */
138:         prev_state = state;             /* save current state as previous */
139:         prev_trader = itrader;          /* and prev trader index */
140:         bts->state = next_state;        /* set current state to next */
141:         bts->itrader = next_trader;     /* and next trader index */
142:         /* --- look up screen corresponding to next state --- */
143:         prev_screen = screen;           /* save previous screen type */
144:         next_screen = (-1);             /* init for failure */
145:         for ( iscreen=0; (istate=state_screen[iscreen].state) >= 0; iscreen++ )
146:            if ( next_state == istate )  /* found match in state_screen[] */
147:                 { next_screen = state_screen[iscreen].screen; break; }
148: 
149:         /* --- see if we need to redraw a new screen --- */
150:         if ( next_screen != screen      /* need new screen state or trader */
151:         ||   (next_screen==TRADER_SCREEN && prev_trader!=next_trader)
152:         ||   isredraw )                 /* or just want same screen redrawn */
153:             {
154:             for ( iwindow=0; iwindow < bts->nwindows; iwindow++ )
155:                 { wp = bts->wptrs[iwindow]; /* ptr to current window */
156:                   if ( !(wp->isopened) ) /* current window not opened */
157:                     continue;           /* so can't use it */
158:                   if ( wp->window_type == next_screen ) /* right screen type */
159:                     { if ( next_screen != TRADER_SCREEN ) /* is all we need */
160:                         break;          /* so quit with window to open */
161:                       else              /* need right trader index too */
162:                         if ( iwindow == bts->iwtrader[next_trader] ) /*got it*/
163:                             break;      /* so quit with window to open */
164:                     } /* --- end-of-if(window_type==next_screen) --- */
165:                 } /* --- end-of-for(iwindow) --- */
166:             if ( iwindow >= bts->nwindows ) /* no match so need new screen */
167:                 { /* --- open a new window with required screen type --- */
168:                 if ( bts->msglevel >= BUGLEVEL )
169:                   { sprintf(msgbuff,"switch>failed to open screen#%d,trader#%d",
170:                         next_screen,next_trader);
171:                     prtmsg ( ERR_ROW, msgbuff ); }
172:                 iwindow = open_window ( bts, -1, next_screen, -1, -1 );
173:                 if ( iwindow < 0 )
174:                     { status = (-1);    /* set error status */
175:                       sprintf ( msgbuff, "Can't open window for screen %d.",
176:                         screen );
177:                       goto end_of_job; }
178:                 wp = bts->wptrs[iwindow]; /* pointer to window */
179:                 } /* --- end-of-if(iwindow) --- */
180:             /* bts->iwindow = iwindow; */ /* current top window */
181:             if ( isredraw ) display_window ( bts, -1, -1 );
182:             else            display_window ( bts, iwindow, -1 );
183:             isedit = 1;                 /* edit and update related objects */
184:             if ( wp->isprotected )      /* check window's protection */
185:                 isedit = 0;             /* can't edit if window protected */
186:             } /* --- end-of-if(screen) --- */
187:         screen = next_screen;           /* now have current screen */
188:         } /* --- end-of-if(state) --- */
189:     isredraw = FALSE;                   /* only one redraw request at a time */
190:     if ( wp->iwsorting < 0 )            /* window was just sorted */
191:         wp->iwsorting = (-(wp->iwsorting)); /* don't resort till next change */
192:     if ( nloops == 1 )                  /* on first pass */
193:         { if ( TIMR_FLAG >= 0 )         /* clock wanted */
194:                 { timr_reqidt = timrefn ( 0, TIMR_INTERVAL, TIMR_FLAG );
195:                 } /* --- end-of-if(TIMRFLAG>=0) --- */
196:           status = pwd_expdays();       /* check #days till password expires */
197:           if ( status <= 5 )            /* expiring within one business week */
198:             { /* --- print a warning and maybe force a new password --- */
199:             sprintf(msgbuff,"Warning: Password expires in %d days.",status);
200:             prtmsg(ERR_ROW,msgbuff);
201:             if ( status <= 3 )          /*force password change within 3 days*/
202:                 { setpass(bts);         /* by calling setpass() */
203:                   isredraw = TRUE;      /* then set redraw flag */
204:                   continue; }           /* and redraw screen immediately */
205:             } /* --- end-of-if(status<=5) --- */
206:           status = 0;                   /* reset status (just in case) */
207:         } /* --- end-of-if(nloops==1) --- */
208: 
209:     /* ---------------------------------------------------------------------
210:     Let trader make his move
211:     ---------------------------------------------------------------------- */
212:     keypress = navigate_window ( bts, iwindow, isedit );
213:     process_keypress: ;
214:     if ( keypress < 0 )
215:         { ; /* hook for any additional error-handling desired */
216:         }
217:     if ( keypress>='a' && keypress<='z' ) keypress=toupper(keypress);
218:     if ( keypress != ABORT ) naborts = 0; /* need two aborts in succession */
219:     clrows ( MSG_ROW, 1 );
220: 
221:     /* ---------------------------------------------------------------------
222:     Handle keypress - either directly or bring up main menu if unrecognized
223:     ---------------------------------------------------------------------- */
224:     switch ( keypress )
225:         { default: /* --- note: error keypress<0 trapped here by default --- */
226:                 state = display_menu ( bts, -1, -1 );
227:                 break;
228:         case CONTINUE_KEY: /* --- no operation requested --- */
229:         case CANCEL_ENTRY:
230:                 state = NOOP_STATE;
231:                 break;
232:         case TOGGLE_STATE: /* --- flip back to last state user was in --- */
233:                 state = NOOP_STATE; /* default in case no prev state */
234:                 if ( prev_state >= 0 )
235:                         { state = prev_state;
236:                           /* --- state includes trader index --- */
237:                           if ( prev_trader >= 0 /*check for legal prev trader*/
238:                           &&   prev_trader < bts->ntraders )
239:                                 next_trader = prev_trader;
240:                         }
241:                 break;
242:         case TOGGLE_EDIT:
243:                 state = NOOP_STATE;
244:                 if ( screen == TRADER_SCREEN
245:                 ||   screen == RELATION_SCREEN
246:                 ||   screen == ADMIN_SCREEN )
247:                         { wp->isprotected = !(wp->isprotected);
248:                           isedit = (wp->isprotected)? 0:1; }
249:                 break;
250:         case TOGGLE_SETUP: /* --- setup menu requested --- */
251:                 if ( bts->user_type != ADMIN_TYPE  /* no setup for admin */
252:                 ||   TRUE )                     /* actually, allow it */
253:                   { status = display_setup ( bts, -1, -1 ); /* do the setup */
254:                   if ( status > 1 )     /* serious change needs recalculation */
255:                     (bts->change_num)++; /* all issues now out-of-date */
256:                   if ( status > 0 )     /* only re-display required */
257:                     { isredraw = TRUE;  /* so set flag to redraw windows */
258:                       /* --- kludge to handle window sorting request --- */
259:                       if ( bts->iwsorting > 0 ) /* user set a sorting type */
260:                         { wp->iwsorting = (-(bts->iwsorting)); /* sort window */
261:                           bts->iwsorting = 0; } /* but don't sort any others */
262:                     } /* --- end-of-if(status>0) --- */
263:                   } /* --- end-of-if(!isadmin) --- */
264:                 state = NOOP_STATE;
265:                 break;
266:         case TOGGLE_SELECT: /* --- explicit security selection requested --- */
267:                 status = display_setup ( bts, -1, 0 ); /* do the select */
268:                 if ( status > 0 )       /* re-display required */
269:                     isredraw = TRUE;    /* so set flag to redraw windows */
270:                 state = NOOP_STATE;
271:                 break;
272:         case TOGGLE_PROFILE:
273:                 state = NOOP_STATE;
274:                 if ( bts->user_type != ADMIN_TYPE ) /* no profile for admin */
275:                         state = PROFILE_STATE;
276:                 break;
277:         case TOGGLE_RELATION:
278:                 state = NOOP_STATE;
279:                 if ( bts->user_type != ADMIN_TYPE ) /* no relations for admin */
280:                         state = RELATION_STATE;
281:                 break;
282:         case TOGGLE_DETAIL:
283:                 state = NOOP_STATE;
284:                 if ( bts->user_type != ADMIN_TYPE ) /* no detail for admin */
285:                         state = DETAIL_STATE;
286:                 break;
287:         case TOGGLE_TRADER:
288:                 state = NOOP_STATE;
289:                 if ( bts->user_type == ADMIN_TYPE ) /* no traders for admin */
290:                         break;
291:                 next_trader = bts->itrader + 1;
292:                 if ( next_trader >= bts->ntraders ) /* wrap to first */
293:                     next_trader = 0;
294:                 state = TRADER_STATE;
295:                 break;
296:         case TOGGLE_CHARTS: /* --- enter Chris Bellingham's chaRTS system --- */
297:                 /* --- run chaRTS --- */
298:                 clearbox ( (short)0,  (short)0, /* give chaRTS a clear screen */
299:                            (short)25, (short)80, (short)(FG), (short)(BG) );
300:                 status = charts("");            /* no default worksheet yet */
301:                 if ( status == (-1) )           /* got a problem */
302:                     { status = 1;               /*can't handle chaRTS problems*/
303:                       goto end_of_job; }        /*so ignore it, but terminate*/
304:                 /* --- back from chaRTS so continue with previous action --- */
305:                 status = 1;                     /* always reset normal status */
306:                 clearbox ( (short)0,  (short)0, /* clear the screen again */
307:                            (short)25, (short)80, (short)(FG), (short)(BG) );
308:                 state = NOOP_STATE;             /* continue with prev screen */
309:                 isredraw = TRUE;                /* but redraw it */
310:                 break;
311:         case TOGGLE_FUTURE: /* --- wants to edit/stop future basis issue --- */
312:                 state = NOOP_STATE;
313:                 if ( bts->user_type != ADMIN_TYPE ) /* no basis for admin */
314:                     { if ( next_state == BASIS_STATE ) /* already was editing */
315:                         state = TRADER_STATE;   /* so stop editing basis */
316:                         else state = BASIS_STATE; } /* else start editing it */
317:                 break;
318:         case SECTOR_DN: /* --- navigate to next sector --- */
319:         case SECTOR_UP: /* --- navigate to previous sector --- */
320:                 if ( keypress == SECTOR_DN )
321:                         ivalue = find_sector ( bts, -1, "" );   /* down */
322:                    else ivalue = find_sector ( bts, -1, "U" );  /* up */
323:                 if ( ivalue >= 0 )      /* located window object */
324:                     { ivalue = setwtop(bts,-1,ivalue); /*reset window*/
325:                       if ( ivalue >= 0 ) isredraw = TRUE; }
326:                 state = NOOP_STATE;
327:                 break;
328:         case REFRESH: /* --- full screen refresh --- */
329:                 isredraw = TRUE;
330:                 state = NOOP_STATE;
331:                 break;
332:         case REPORT_KEY:
333:                 state = display_menu ( bts, -1, REPORT_MENU );
334:                 switch ( state )
335:                     { default: break;
336:                       case INPUTSHEET_REPORT:
337:                         prtmsg(MENU_ROW,
338:                         "Please wait a moment while Input Sheet is prepared.");
339:                         status = qsheet(bts,INPUTSHEET_REPORT,"");
340:                         if ( status > 0 )
341:                           sprintf ( msgbuff, "%d issues on report.", status );
342:                         else sprintf ( msgbuff, "Input Sheet Report failed." );
343:                         prtmsg ( MENU_ROW, msgbuff );
344:                         break;
345:                       case TRADERSCREEN_REPORT:
346:                         prtmsg(MENU_ROW,
347:                         "Please wait a moment while Print Screen is prepared.");
348:                         status = qsheet(bts,TRADERSCREEN_REPORT,"");
349:                         if ( status > 0 )
350:                           sprintf ( msgbuff, "%d issues on report.", status );
351:                         else sprintf ( msgbuff, "Print Screen Report failed." );
352:                         prtmsg ( MENU_ROW, msgbuff );
353:                         break;
354:                       case HELP_REPORT:
355:                         display_help(bts,-1,"REPORTS");
356:                         break;
357:                     } /* --- end-of-switch(state) --- */
358:                 state = NOOP_STATE;
359:                 break;
360:         case EXPAND: /* --- enlarge current window (not yet implemented) --- */
361:                 state = NOOP_STATE;
362:                 break;                  /* will remove this when/if ready */
363:                 wp = bts->wptrs[iwindow];
364:                 if ( wp->nrows < 20 )
365:                     {
366:                     (wp->nrows)++;
367:                     if ( wp->row1 + wp->nrows > 20 )
368:                         if ( wp->row1 > 0 ) (wp->row1)--;
369:                     isredraw = TRUE;
370:                     }
371:                 break;
372:         case SHRINK: /* --- shrink current window (not yet implemented) --- */
373:                 state = NOOP_STATE;
374:                 break;                  /* will remove this when/if ready */
375:                 wp = bts->wptrs[iwindow];
376:                 if ( wp->nrows > 5 )
377:                     {
378:                     (wp->nrows)--;
379:                     if ( wp->row1 + wp->nrows > 20 )
380:                         if ( wp->row1 > 5 ) (wp->row1)++;
381:                     isredraw = TRUE;
382:                     }
383:                 break;
384:         case HELP: /* --- help requested by pressing HELP key --- */
385:                 keypress = display_help ( bts, -1, "NAV" );
386:                 goto process_keypress;
387:                 state = NOOP_STATE;
388:                 break;
389:         case ATTENTION: /* --- special attention commands --- */
390:                 /* --- reset previous attention parameters --- */
391:                 bts->attn_command = (-1);       /* reset previous command */
392:                 *(bts->attn_buff) = '\000';     /* and buffer */
393:                 state = NOOP_STATE;             /* no state change needed */
394:                 /* --- get new attention command --- */
395:                 getmsg ( MSG_ROW,0, ATTN_PROMPT, msgbuff );
396:                 strupper(trim(ltrim(msgbuff))); /* always trim and uppercase */
397:                 if ( strlen(msgbuff) < 1 ) break; /* no command given */
398:                 if ( !memcmp(msgbuff,"EXIT",4) ) /* explicit exit command */
399:                     { strcpy( bts->attn_buff, "EXIT" ); /* copy cmd to buff */
400:                       sprintf ( bts->msgbuff, "End-of-Job requested by User." );
401:                       status = 1;
402:                       goto end_of_job;  /* so clean up and exit */
403:                     } /* --- end-of-if(explicit exit) --- */
404:                 /* --- check for command delimiter --- */
405:                 if ( (chptr=strchr(msgbuff,ATTN_DELIM)) == NULL ) /* no delim */
406:                   { ivalue = prev_attn;         /* no delim, use prev command */
407:                     strcpy ( bts->attn_buff, msgbuff ); /* current params */
408:                     if ( !memcmp(msgbuff,"HELP",strlen(msgbuff)) ) /* do help */
409:                         ivalue = ATTN_HELP; }
410:                 else                            /* new command precedes delim */
411:                   { /* --- look up new attention command in table --- */
412:                   *chptr = '\000';              /* terminate token at delim */
413:                   strcpy ( bts->attn_buff, chptr+1 ); /* params follow delim */
414:                   strupper(trim(ltrim(bts->attn_buff))); /* trim & uppercase */
415:                   strupper(trim(ltrim(msgbuff))); /* command also */
416:                   ivalue = 0;                   /* index attn commands */
417:                   while ( *(chptr=attn_table[ivalue].command) != '\000' )
418:                     { if ( index(chptr,msgbuff) != NULL ) break;
419:                       ivalue++; }               /* keep looking for a match */
420:                   if ( *chptr == '\000' )       /* command wasn't recognized */
421:                     { sprintf (bts->attn_buff, "%s is unrecognized.", msgbuff);
422:                       prtmsg(MSG_ROW,bts->attn_buff);
423:                       break; }                  /* so ignore it */
424:                   } /* --- end-of-if(delim!=NULL) --- */
425:                 /* --- execute command --- */
426:                 bts->attn_command = ivalue;     /* command is table index */
427:                 prev_attn = ivalue;             /* save current for next time */
428:                 if ( ivalue < 0 )               /* no command */
429:                     { sprintf (bts->attn_buff, "No command pending.");
430:                       prtmsg(MSG_ROW,bts->attn_buff);
431:                       break; }                  /* so ignore it */
432:                 switch ( ivalue )               /* some handled locally */
433:                     {
434:                     default: break; /* --- presumably handled elsewheres --- */
435:                     case ATTN_HELP: /* --- help screen for attention --- */
436:                         keypress = display_help ( bts, -1, "ATTENTION" );
437:                         goto process_keypress;
438:                     case ATTN_MSGLEVEL: /* --- set message level (for me) --- */
439:                         ivalue = atoi(bts->attn_buff);  /* interpret msglevel */
440:                         bts->msglevel = ivalue; /* set new message level */
441:                         sprintf (bts->attn_buff, "New msglevel=%d.", ivalue );
442:                         prtmsg(MSG_ROW,bts->attn_buff);
443:                         ivalue = (-1);          /* reset command */
444:                         break;
445:                     case ATTN_SUBSTITUTE: /* --- substitute current --- */
446:                         ivalue = subst_window(bts,-1,-1,bts->attn_buff);
447:                         if ( ivalue >= 0 )
448:                               { sprintf(msgbuff,"%d substitutions made for %s.",
449:                                         ivalue, bts->attn_buff);
450:                                 isredraw = TRUE; }
451:                         else  { sprintf(msgbuff,"Error substituting %s.",
452:                                         bts->attn_buff); }
453:                         prtmsg(MSG_ROW,msgbuff);
454:                         ivalue = (-1);          /* reset command */
455:                         break;
456:                     case ATTN_SET: /* --- set marked --- */
457:                         ivalue = set_window(bts,iwindow,-1,bts->attn_buff);
458:                         if ( ivalue >= 0 )
459:                               { sprintf(msgbuff,"%d objects set to %s.",
460:                                         ivalue, bts->attn_buff);
461:                                 isredraw = TRUE; }
462:                         else  { sprintf(msgbuff,"Error setting %s.",
463:                                         bts->attn_buff); }
464:                         prtmsg(MSG_ROW,msgbuff);
465:                         ivalue = (-1);          /* reset command */
466:                         break;
467:                     case ATTN_MESSAGE: /* --- send msgs to other traders --- */
468:                         ivalue = sendinfo ( bts, bts->attn_buff );
469:                         sprintf (bts->attn_buff, "Message sent." );
470:                         prtmsg(MSG_ROW,bts->attn_buff);
471:                         ivalue = (-1);          /* reset command */
472:                         break;
473:                     case ATTN_FIND: /* --- navigate window to object --- */
474:                         ivalue = find_secid ( bts, -1, bts->attn_buff );
475:                         if ( ivalue >= 0 )      /* located window object */
476:                             { ivalue = setwtop(bts,-1,ivalue); /*reset window*/
477:                               if ( ivalue >= 0 ) isredraw = TRUE; }
478:                         ivalue = (-1);          /* reset command */
479:                         break;
480:                     case ATTN_CHANGE: /* --- change price/yield by #ticks --- */
481:                         ivalue = atoi(bts->attn_buff);  /* interpret nticks */
482:                         update_marks ( bts, -1, ivalue );
483:                         ivalue = (-1);          /* reset command */
484:                         break;
485:                     } /* --- end-of-switch(attn_command) --- */
486:                 if ( ivalue < 0 )               /* command handled above */
487:                     { bts->attn_command = (-1); /* so reset command */
488:                       *(bts->attn_buff) = '\000'; } /* and buffer */
489:                 break;
490:         case ABORT: /* --- exit, files not rewritten --- */
491:                 naborts++;                      /* count another abort */
492:                 if ( naborts > 1 )
493:                     { strcpy ( bts->msgbuff, "Execution aborted by user." );
494:                       status = (-1);
495:                       if ( nloops > 1 )         /* (just a double-check) */
496:                         if ( bts->user_type != ADMIN_TYPE ) /* no admin prof */
497:                           putprof(bts,".JOU");  /* journal profile on abort */
498:                       goto end_of_job; }
499:                 sprintf (msgbuff,"\007Press %c again to abort.",ABORT);
500:                 prtmsg ( MSG_ROW, msgbuff );
501:                 state = NOOP_STATE;
502:                 break;
503:         case LOGOFF_KEY: /* --- dequeuer() sent getkey1() a server logoff --- */
504:                 sprintf(bts->msgbuff,"Execution terminated by Server.");
505:                 strcpy ( bts->attn_buff, "EXIT" );
506:                 status = 1;
507:                 goto end_of_job;
508:         } /* --- end-of-switch(keypress) --- */
509: 
510:     /* ---------------------------------------------------------------------
511:     Handle state
512:     ---------------------------------------------------------------------- */
513:     switch ( state )
514:         {
515:         /* -----------------------------------------------------------------
516:         Easy cases
517:         ------------------------------------------------------------------ */
518:         default: /* --- shouldn't happen - bug --- */
519:                 sprintf ( bts->msgbuff, "Unrecognized next_state=%d.", state );
520:                 status = (-1);
521:                 goto end_of_job;
522:         case EXIT_STATE: /* --- user wants out --- */
523:                 sprintf ( bts->msgbuff, "End-of-Job requested by User." );
524:                 status = 1;
525:                 goto end_of_job;        /* so clean up and exit */
526:         case NOOP_STATE: /* --- ignore the keystroke --- */
527:                 break;
528:         case HELP_STATE: /* --- help requested from the menu --- */
529:                 keypress = display_help ( bts, bts->state, "NAV" );
530:                 goto process_keypress;
531:                 break;
532:         case DELETE_STATE: /* --- delete marked objects from window --- */
533:                 if ( delete_marks ( bts, iwindow )              /* delete */
534:                 > 0 ) display_window ( bts, iwindow, -1 );      /* re-display */
535:                 break;
536:         case MOVE_STATE: /* --- move marked objects before current cursor --- */
537:                 if ( move_marks ( bts, iwindow )                /* move */
538:                 > 0 ) display_window ( bts, iwindow, -1 );      /* re-display */
539:                 break;
540:         case TRADER_STATE:
541:                 next_state = state;
542:                 break;
543:         case BASIS_STATE:
544:                 next_state = state;
545:                 break;
546:         case PROFILE_STATE:
547:                 next_state = state;
548:                 break;
549:         case CLOSING_STATE: /* --- closing selected from trader menu --- */
550:                 /* if ( isclosing ) ... to be added later */
551:                 nprices = send3pm ( bts, "FULL" ); /* send all closing prices */
552:                 sprintf(msgbuff,"%d closing prices sent to server.",nprices);
553:                 prtmsg ( MSG_ROW, msgbuff );
554:                 break;
555: 
556:         /* --- system administrator states --- */
557:         case ADMIN_STATE:
558:                 if ( bts->user_type == ADMIN_TYPE )
559:                         next_state = state;
560:                 else    { sprintf(msgbuff,"Only permitted for Administrator,");
561:                           prtmsg ( MSG_ROW, msgbuff ); }
562:                 break;
563:         case ADMIN_COPY_STATE:
564:         case ADMIN_DELETE_STATE:
565:                 if ( set_window ( bts, iwindow, state, "" )
566:                 > 0 ) isredraw = TRUE;
567:                 next_state = ADMIN_STATE;
568:                 break;
569:         case ADMIN_WRITE_STATE:
570:                 if ( !putpriv ( bts, "\000" ) ) /* let it construct filename */
571:                     { sprintf (bts->msgbuff,"Failed to write privilege file.");
572:                       goto end_of_job; }
573:                 next_state = ADMIN_STATE;
574:                 break;
575: 
576:         /* -----------------------------------------------------------------
577:         Bring up detail window on top of current window and with same objects
578:         ------------------------------------------------------------------ */
579:         case DETAIL_STATE:
580:                 if ( screen == DETAIL_SCREEN ) break; /* don't detail detail */
581:                 /* --- load detail window with current window's data --- */
582:                 ncopied =               /* let trader scroll thru detail */
583:                  copy_window (bts, iwindow,0, bts->iwdetail,0, 1, 9999);
584:                 if ( ncopied > 0 )
585:                         next_state = state;
586:                 else  { prtmsg(MSG_ROW,"Failed to initialize detail window."); }
587:                 break;
588: 
589:         /* -----------------------------------------------------------------
590:         Bring up relation window on top of current window and with same objects
591:         ------------------------------------------------------------------ */
592:         case RELATION_STATE:
593:                 /* --- load relation screen with trader screen data --- */
594:                 if ( screen != TRADER_SCREEN ) /* not currently trader screen */
595:                     { prtmsg ( MSG_ROW, "Can't change relations from here." );
596:                       break; }
597:                 ncopied =               /* let trader scroll thru relations */
598:                  copy_window(bts, iwindow,0, bts->iwrelation,0, 0, 9999);
599:                 if ( ncopied > 0 )
600:                         next_state = state;
601:                 else  {prtmsg(MSG_ROW,"Failed to initialize relation window.");}
602:                 break;
603: 
604:         /* -----------------------------------------------------------------
605:         Copy marked objects from current window to window directly underneath
606:         ------------------------------------------------------------------ */
607:         case COPY_STATE:
608:                 /* --- copy marked issues --- */
609:                 if ( iwindow != bts->iwprofile  /* double check so that we */
610:                 ||   screen != PROFILE_SCREEN ) /* copy only from profile */
611:                     { prtmsg ( MSG_ROW, "Can't copy issues from this window." );
612:                       break; }
613:                 if ( /*    prev_state != TRADER_STATE */ FALSE
614:                      /* || bts->wlist[1] != bts->iwtrader[bts->itrader] */ )
615:                     { prtmsg (MSG_ROW,"Can't copy issues to previous window.");
616:                       break; }
617:                 if ( bts->nwopen < 2 )  /* no window underneath to copy to */
618:                     { prtmsg ( MSG_ROW, "No target window to copy to." );
619:                       break; }
620:                 ncopied =               /* copy all marks (write-enabled) */
621:                     copy_window ( bts, iwindow,-1,
622:                                 bts->iwtrader[bts->itrader],-1, 0, -1 );
623:                 if ( ncopied > 0 )
624:                         next_state = TRADER_STATE; /* back to see copies */
625:                 else  { prtmsg (MSG_ROW,"No issues marked (or copy failed)."); }
626:                 break;
627:         } /* --- end-of-switch(state) --- */
628:     } /* --- end-of-while(nloops) --- */
629: end_of_job:
630:  return ( status );                     /* back to main() for logoff */
631: } /* --- end-of-function basis_switch() --- */
632: /* ----------------------- END-OF-FILE BASIS_SWITCH.C ----------------------- */


BBBBBBBB     CCCCCCC  LLLLL        OOOOOO     SSSSSSS  EEEEEEEEEE              CCCCCCC 
BBBBBBBBB   CCCCCCCCC LLLLL       OOOOOOOO   SSSSSSSSS EEEEEEEEEE             CCCCCCCCC
 BB     BB CC      CC  LL        OO      OO SS          EE     EE            CC      CC
 BBBBBBBB  CC          LL        OO      OO  SSSSSSS    EEEEEE      .        CC        
 BBBBBBBB  CC          LL        OO      OO   SSSSSSS   EEEEEE     ...       CC        
 BB     BB CC      CC  LL     LL OO      OO         SS  EE     EE .....      CC      CC
BBBBBBBBB   CCCCCCCCC LLLLLLLLLL  OOOOOOOO  SSSSSSSSS  EEEEEEEEEE  ...        CCCCCCCCC
BBBBBBBB     CCCCCCC  LLLLLLLLLL   OOOOOO    SSSSSSS   EEEEEEEEEE   .          CCCCCCC 

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Function:    bclose ( iclose )
  7:  *
  8:  * Purpose:     Initialization to receive 3pm/5pm closing prices.
  9:  *
 10:  * Arguments:
 11:  *              skt (I)         addr of skt_control_struct for server's
 12:  *                              datagram channel (only needed here to be
 13:  *                              passed on to binfo() in case we need
 14:  *                              to ask a trader for his closing prices).
 15:  *
 16:  *              iclose (I)      int containing 0 to init arrays for closing,
 17:  *                              1 to write 3pm files, 2 to write 5pm files.
 18:  *
 19:  * Returns:     ( int )         #issues initialized or written,
 20:  *                              or -1 for any error.
 21:  *
 22:  * Notes:
 23:  *
 24:  * Source:      BCLOSE.C
 25:  *
 26:  * --------------------------------------------------------------------------
 27:  * Revision History:
 28:  *
 29:  * 01/09/89     J.Forkosh       Installation.
 30:  * 02/13/89     J.Forkosh       Modified for Version 2.
 31:  *
 32:  ****************************************************************************/
 33: 
 34: /* ---------------------------------------------------------------------------
 35: Header files and other #define-ed Symbols
 36: --------------------------------------------------------------------------- */
 37: /* --- standard vms headers --- */
 38: #include < stdio.h >
 39: /* --- Basis message headers --- */
 40: #include "bserver.h"
 41: #include "sktmsgdef.h"
 42: /* --- Basis universe headers --- */
 43: #define BUNIVERSE
 44: #include "bglobals.h"
 45: #include "bdump.h"
 46: #include "qdescrip.h"
 47: #define MAX_RETRIES     3               /* close even if trader(s) missing */
 48: #define WAIT_SECS       30              /* wait so long between retries */
 49: static  int nretries = 0;               /* number of retries so far */
 50: #define CLOSESTR "@BRUN:bcloser.com"    /* issues next retry after 30 secs */
 51: #define DUMPSTR  "@BRUN:bdumper.com"    /* dump the closing prices to disk */
 52: /* ------------------------------------------------------------------------ */
 53: 
 54: /* --- entry point --- */
 55: bclose ( skt, iclose )
 56: struct  skt_control_struct *skt;
 57: int     iclose;
 58: {
 59: /* ---------------------------------------------------------------------------
 60: Allocations and Declarations
 61: --------------------------------------------------------------------------- */
 62: /* --- internal universe data --- */
 63: struct  bunshdr_struct *bunshdr, *buns3pmhdr; /* ctl struct before universe */
 64: unsigned char *cup, *cup3pm;            /* to allocate MAX_ISSUES buffers */
 65: BUS     *up3pm;                         /* pointer to calloc-ed buffers */
 66: BUS     *uptr;                          /* and to a particular issue within */
 67: int     usize;                          /* #bytes in a universe struct */
 68: int     iuniverse, nuniverse;           /* number universe issues in memory */
 69: double  price;                          /* price of iuniverse-th issue */
 70: /* --- variables to construct outgoing price request message --- */
 71: struct  sktmsghdr_struct *replyhdr;     /* interpret start of msg as hdr */
 72: struct  sktpricemsg_struct *pricemsg;   /* interpret price msg */
 73: int     msglen;                         /* #bytes in message iobuff */
 74: struct  skt_ioctl_struct *ioctl;        /* trader's TCP/IP return address */
 75: struct  msg_control_struct reply;       /* outgoing formatted reply */
 76: char    replybuff[SKT_MAXMSG];          /* allocated iobuff for reply */
 77: /* --- other variables --- */
 78: int     idump;                          /* 3 or 5, for 3pm or 5pm closing */
 79: int     itrader;                        /* index of msg sender in nodes[] tbl */
 80: int     iqtype;                         /* index to qfiles[] for file dumping */
 81: int     ndumped;                        /* number issues dumped to each qfile */
 82: int     notclosed = 0;                  /* how many traders not closed */
 83: int     nissues;                        /* tot# closing prices from all trdrs */
 84: int     vms_stat;                       /* status of spawned retry procedure */
 85: char    infomsg[132];                   /* tell trader to send his prices */
 86: char    cmdstr[132];                    /* retry command string */
 87: char    qfile[64];                      /* qfile name with 3pm/5pm extension */
 88: char    errmsg[132] = "\000";           /* buffer for error message */
 89: char    *strchr(),*delim;               /* find extensions in qfiles[] */
 90: char    *vmsmsg();                      /* xlate vms status to string */
 91: /* ------------------------------------------------------------------------ */
 92: 
 93: /* -------------------------------------------------------------------------
 94: Initialization
 95: -------------------------------------------------------------------------- */
 96: /* --- initialize universe pointers (needed for all iclose values) --- */
 97: usize = sizeof( BUS );
 98: cup = pbuns + sizeof(struct bunshdr_struct); /* ptr to universe buffers */
 99: cup3pm = p3pmbuns + sizeof(struct bunshdr_struct); /* to 3pm universe buffers */
100: up3pm = (BUS *)(cup3pm);                        /* cup as universe ptr */
101: bunshdr = (struct bunshdr_struct *)(pbuns); /* header preceding universe */
102: buns3pmhdr = (struct bunshdr_struct *)(p3pmbuns); /* and 3pm/5pm universe */
103: nuniverse = bunshdr->nuniverse;         /* #issues in "normal" universe */
104: 
105: if ( iclose==1 || iclose==2 )
106:     { /* --- may need stub for price request msg to "unclosed" traders --- */
107:     msglen = sizeof(struct sktmsghdr_struct) /* message will have a header */
108:         + sizeof(int) + sizeof(struct sktquote_struct); /* plus one quote */
109:     reply.iobuff = replybuff;           /* point reply to its formatted buff */
110:     reply.maxmsg = SKT_MAXMSG;          /* set max msg size, */
111:     reply.msgsz = msglen;               /* and set size of actual reply */
112:     memset ( &(reply.iosb), '\000', sizeof(struct skt_iosb_struct) );
113:     replyhdr = (struct sktmsghdr_struct *)(replybuff);/* interpret hdr in msg */
114:     pricemsg = (struct sktpricemsg_struct *)(replybuff);/* interpret prc msg */
115:     replyhdr->opcode = SKT$_REQPRICEMSG; /* set message type */
116:     memset ( replyhdr->sender, '\000', 16 ); /* null-fill sender field */
117:     strcpy ( replyhdr->sender, "SERVER" ); /* and use our name */
118:     memset ( pricemsg->quote[0].sec_id, '\000', 6 ); /* null-fill sec_id */
119:     strcpy ( pricemsg->quote[0].sec_id, "FULL" ); /* request full download */
120:     pricemsg->quote[0].price = 0.0;     /* just stub out price */
121:     pricemsg->quote[0].spread = 0.0;    /* and spread */
122:     pricemsg->nquotes = 1;              /* one quote */
123:     } /* --- end-of-if(iclose==1,2) --- */
124: 
125: /* ---------------------------------------------------------------------------
126: Array initialization (prior to accumulating closing prices from traders)
127: --------------------------------------------------------------------------- */
128: if ( iclose == 0 )
129:     {
130:     /* ---------------------------------------------------------------------
131:     Tell all traders that closing is commencing
132:     ---------------------------------------------------------------------- */
133:     strcpy ( infomsg, "Traders please begin sending your closing prices." );
134:     binfo ( skt, infomsg, -1, "" );     /* prompt all the traders */
135: 
136:     /* ---------------------------------------------------------------------
137:     Clear traders' closing flags
138:     ---------------------------------------------------------------------- */
139:     for ( itrader = 0; itrader < ntraders; itrader++ )
140:         {
141:         nodes[itrader].isclosed = 0;    /* closing message not received */
142:         nodes[itrader].nissues = 0;     /* no closing prices received yet */
143:         } /* --- end-of-for(itrader) --- */
144: 
145:     /* ---------------------------------------------------------------------
146:     Initialize universe structs
147:     ---------------------------------------------------------------------- */
148:     /* --- first null-fill all areas --- */
149:     memset ( (unsigned char *)(buns3pmhdr),     /* clear 3pm buffer header */
150:         '\000', sizeof(struct bunshdr_struct) );
151:     memset ( cup3pm, '\000', usize*MAX_UNIVERSE ); /* clear 3pm buffers */
152:     /* --- then copy all data --- */
153:     memcpy ( (unsigned char *)(buns3pmhdr),     /* copy header to 3pm header */
154:         (unsigned char *)(bunshdr), sizeof(struct bunshdr_struct) );
155:     strcpy ( buns3pmhdr->gsdnam, GSD3PMNAM );   /* but tag the 3pm header */
156:     memcpy ( (unsigned char *)(cup3pm),         /* copy universe */
157:         (unsigned char *)(cup), usize*nuniverse );
158: 
159:     /* ---------------------------------------------------------------------
160:     Data that can't be copied
161:     ---------------------------------------------------------------------- */
162:     /* --- extra header data --- */
163:     buns3pmhdr->nuniverse = nuniverse;  /* #issues in universe */
164:     buns3pmhdr->nupdates = 0;           /* no closing messages yet */
165:     buns3pmhdr->isdumping = 0;          /* no dumps in progress yet */
166:     buns3pmhdr->isclosing = 1;          /* doing closing prices */
167:     memset ( bunshdr->tstamp, '\000', 8 ); /* no time-stamp yet */
168: 
169:     /* ---- initialize universe control information as necessary --- */
170:     for ( iuniverse=0; iuniverse < nuniverse; iuniverse++ )
171:         {
172:         uptr = &(up3pm[iuniverse]);
173:         /* --- set change number --- */
174:         uptr->change_num = 0;           /* not (yet) vital */
175:         } /* --- end-of-for(iuniverse) --- */
176: 
177:     /* --- dummy trailing issue at end of universe indicates end-of-list --- */
178:     uptr = &(up3pm[nuniverse]);         /* ptr to trailing universe issue */
179:     memset ( (unsigned char *)uptr, '\000', usize ); /* zero-fill issue */
180:     strcpy ( uptr->sec_id, END_OF_DATA ); /* copy end-of-universe sec_id */
181: 
182:     /* --- set global closing flag --- */
183:     isclosing = 1;                      /* will now accept closing prices */
184:     nretries = 0;                       /* no retries yet */
185:     return ( nuniverse );               /* return to caller with #issues init */
186:     } /* --- end-of-if(iclose==0) --- */
187: 
188: /* -------------------------------------------------------------------------
189: Rewrite closing universe files
190: -------------------------------------------------------------------------- */
191: if ( iclose==1 || iclose==2 )
192:     {
193: 
194:     /* ---------------------------------------------------------------------
195:     Check that all traders' prices received
196:     ---------------------------------------------------------------------- */
197:     /* --- check all traders' flags in nodes[] table --- */
198:     notclosed = 0;                      /* no problems yet */
199:     nissues = 0;                        /* reset tot# prices from all traders */
200:     for ( itrader = 0; itrader < ntraders; itrader++ )
201:         { nissues += nodes[itrader].nissues; /* add #prices from this trader */
202:           if ( nodes[itrader].isclosed == 0 )   /* this trader not closed */
203:             { notclosed++;                      /* bump the notclosed count */
204:             /* -------------------------------------------------------------
205:             Send info message "demanding" immediate download
206:             -------------------------------------------------------------- */
207:             strcpy ( infomsg, "Closing prices are being automatically taken." );
208:             binfo ( skt, infomsg, -1, nodes[itrader].trader ); /* prompt him */
209:             /* -------------------------------------------------------------
210:             And force it regardless of whether trader "manually" responds
211:             -------------------------------------------------------------- */
212:             memcpy ( (unsigned char *)(&(reply.ioctl)), /* set ioctl in reply */
213:                 (unsigned char *)(&(nodes[itrader].ioctl)), /* trader's ioctl */
214:                     sizeof(struct skt_ioctl_struct) );  /* #bytes in ioctl */
215:             /* --- need message sequence number for each trader --- */
216:             nodes[itrader].msgseqout += 1;      /* bump last seq# used */
217:             replyhdr->msgseqnum = nodes[itrader].msgseqout; /*and set new one*/
218:             /* --- send the price request message --- */
219:             vms_stat = sendsktw ( skt, &reply ); /* send reply to trader */
220:             if ( vms_stat != SS$_NORMAL )       /* failed to send reply */
221:                 { if ( msglevel > 0 )           /* so print error message */
222:                     printf( "\nbclose> trader=%s, sendsktw error=%s",
223:                         nodes[itrader].trader, vmsmsg(vms_stat) ); }
224:             } /* ---end-of-if(isclosed==0) --- */
225:         } /* --- end-of-for(itrader) --- */
226: 
227:     /* --- if not all received, spawn procedure to re-close in 30 seconds --- */
228:     if ( notclosed > 0                  /* at least ont trader not closed */
229:     &&   nretries < MAX_RETRIES )       /* and we haven't given up yet */
230:         { nretries++;                   /* bump retry count */
231:         sprintf(cmdstr,"%s %d %d",CLOSESTR,iclose,WAIT_SECS); /* build cmdstr */
232:         vms_stat = spawn( cmdstr, 0, FALSE ); /* and spawn it */
233:         if ( vms_stat == SS$_NORMAL )   /* spawned ok, so let's wait for it */
234:             return ( -1 );              /* try again later */
235:         else { if ( msglevel > 0 )      /* failed to spawn bcloser procedure */
236:                 printf ( "\nbclose> failed to spawn %s, err=%s",
237:                 cmdstr, vmsmsg(vms_stat) ); }
238:         } /* --- end-of-if(notclosed) --- */
239: 
240:     /* ---------------------------------------------------------------------
241:     OK to close the 3pm/5pm files
242:     ---------------------------------------------------------------------- */
243:     /* --- first reset global closing flag --- */
244:     isclosing = 0;                      /* no more closing prices accepted */
245: 
246:     /* --- store current prices as closing prices and recalc hi/lo --- */
247:     for ( iuniverse=0; iuniverse < nuniverse; iuniverse++ )
248:         {
249:         uptr = &(up3pm[iuniverse]);
250:         /* --- set closing price, compare to current hi/lo --- */
251:         price = uptr->computed.price;   /* price as of close */
252:         uptr->computed.close_price = price; /* save as closing price */
253:         if ( price > uptr->high_val ) uptr->high_val = price;
254:         if ( price < uptr->low_val  ) uptr->low_val  = price;
255:         } /* --- end-of-for(iuniverse) --- */
256: 
257:     /* --- submit procedure to actually do the dump --- */
258:     idump = (iclose==1)? 3 : 5;         /* iclose=1 for 3pm dump, else 5pm */
259:     sprintf(cmdstr,"%s %d",DUMPSTR,idump); /* build cmdstr */
260:     vms_stat = spawn( cmdstr, 0, FALSE ); /* and spawn it */
261:     if ( vms_stat != SS$_NORMAL )       /* spawned failed, so issue err msg */
262:         { if ( msglevel > 0 )           /* failed to spawn bdumper procedure */
263:                 printf ( "\nbclose> failed to spawn %s, err=%s",
264:                 cmdstr, vmsmsg(vms_stat) ); }
265: 
266: #if 0
267:     for ( iqtype=0; *(qtypes[iqtype]) != '\000'; iqtype++ )
268:         {
269:         /* --- set up filename for closing prices --- */
270:         strcpy ( qfile, qfiles[iqtype] ); /* local copy of filename for type */
271:         if ( *qfile == '\000' ) continue; /* no file so forget it */
272:         if ( (delim=strchr(qfile,'.')) != NULL ) /* filename has an extension */
273:             *delim = '\000';            /* so truncate it */
274:         if ( iclose==1 ) strcat ( qfile, EXT_3PM ); /* and add 3pm extension */
275:                 else     strcat ( qfile, EXT_5PM ); /* or 5pm extension */
276:         /* --- update all issues in universe of current type --- */
277:         for ( iuniverse=0; iuniverse < nuniverse; iuniverse++ )
278:             if ( *(up[iuniverse].sec_type) == *(qtypes[iqtype]) )
279:                 recalc ( &(up3pm[iuniverse]), 1,
280:                         &(buns3pmhdr->qsettlements[iqtype][0]), -1, NULL );
281:         /* --- dump the updated universe --- */
282:         ndumped = qdump ( qtypes[iqtype], qfiles[iqtype],qfile,
283:                     &up3pm[0], &(buns3pmhdr->qsettlements[iqtype][0]), TRUE );
284:         if ( msglevel > 1 )     /* display number of issues dumped */
285:             { printf ( "\nbclose> %d %s-issues dumped to %s at %s",
286:                 ndumped, qtypes[iqtype], qfile, daytime(0) ); }
287:         } /* --- end-of-for(*qtypes[iqtype]) --- */
288:     vms_stat = SS$_NORMAL;              /* issue ok message to traders */
289: #endif
290: 
291:     /* ---------------------------------------------------------------------
292:     Tell all traders that closing is in progress (or failed)
293:     ---------------------------------------------------------------------- */
294:     if ( vms_stat == SS$_NORMAL )
295:         sprintf ( infomsg, "%d closing prices are being recorded.  Thank you.",
296:                 nissues );
297:     else strcpy(infomsg,"Closing procedure failed, Please tell Administrator.");
298:     binfo ( skt, infomsg, -1, "" );     /* prompt all the traders */
299: 
300:     return ( nuniverse );               /* #issues written returned to caller */
301:     } /* --- end-of-if(iclose==1,2) --- */
302: 
303: return ( -1 );                          /* must be iclose!=0,1,2 to get here */
304: } /* --- end-of-function bclose() --- */
305: /* -------------------------- END-OF-FILE BCLOSE.C -------------------------- */


BBBBBBBB   DDDDDDDD   UUUU  UUUU MM      MM PPPPPPPP              HHHH  HHHH
BBBBBBBBB  DDDDDDDDD  UUUU  UUUU MMM    MMM PPPPPPPPP             HHHH  HHHH
 BB     BB  DD     DD  UU    UU  MMMM  MMMM  PP     PP             HH    HH 
 BBBBBBBB   DD     DD  UU    UU  MM MMMM MM  PPPPPPPP    .         HHHHHHHH 
 BBBBBBBB   DD     DD  UU    UU  MM  MM  MM  PPPPPPP    ...        HHHHHHHH 
 BB     BB  DD     DD  UU    UU  MM      MM  PP        .....       HH    HH 
BBBBBBBBB  DDDDDDDDD    UUUUUU   MM      MM PPPP        ...       HHHH  HHHH
BBBBBBBB   DDDDDDDD      UUUU    MM      MM PPPP         .        HHHH  HHHH

  1: #ifndef _BDUMP
  2: #define _BDUMP
  3: /****************************************************************************
  4:  *
  5:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  6:  * --------------------------------------------------------------------------
  7:  *
  8:  * Header:      bdump.h
  9:  *
 10:  * Purpose:     Defines structures that the server and dump process use
 11:  *              to manage the global section containing the "master" universe.
 12:  *
 13:  * Notes:     o
 14:  *
 15:  * Source:      BDUMP.H
 16:  *
 17:  * --------------------------------------------------------------------------
 18:  * Revision History:
 19:  *
 20:  * 12/27/88     J.Forkosh       Installation.
 21:  *
 22:  ****************************************************************************/
 23: 
 24: /* --------------------------------------------------------------------------
 25: See whether we're defining or referring to global tables/variables
 26: -------------------------------------------------------------------------- */
 27: #ifdef BALLOCATE
 28: #define BEXTERN         /* globaldef */
 29: #else
 30: #define BEXTERN         extern
 31: #endif
 32: 
 33: /* --------------------------------------------------------------------------
 34: Name of the global section and (process-local) pointer to it.
 35: -------------------------------------------------------------------------- */
 36: #define GSDNAM          "BUNS"          /* Basis UNiverse Structures */
 37: #define GSD3PMNAM       "B3PMUNS"       /* 3PM/5PM closing universe structs */
 38: BEXTERN unsigned char   *pbuns;         /* pointer to calloc()-ed universe */
 39: BEXTERN unsigned char   *p3pmbuns;      /* and to 3PM/5PM closing universe */
 40: 
 41: /* --------------------------------------------------------------------------
 42: Global section header info preceding array of universe structs
 43: -------------------------------------------------------------------------- */
 44: struct  bunshdr_struct
 45:         {
 46:         int             nuniverse;      /* # issues loaded to universe */
 47:         int             nupdates;       /* # updates since files last dumped */
 48:         int             isdumping;      /* set true while dump in progress */
 49:         int             isclosing;      /* true while 3pm/5pm in progress */
 50:         char            gsdnam[16];     /* global section name */
 51:         unsigned char   tstamp[8];      /* time last dump completed (VAX fmt) */
 52:         char            qsettlements[16][32]; /* settlement date by file type */
 53:         } ; /* --- end-of-bunshdr_struct --- */
 54: 
 55: /* ------------------------------- End-of-File ---------------------------- */
 56: #endif


BBBBBBBB   DDDDDDDD   UUUU  UUUU MM      MM PPPPPPPP   EEEEEEEEEE RRRRRRRR             
BBBBBBBBB  DDDDDDDDD  UUUU  UUUU MMM    MMM PPPPPPPPP  EEEEEEEEEE RRRRRRRRR            
 BB     BB  DD     DD  UU    UU  MMMM  MMMM  PP     PP  EE     EE  RR     RR           
 BBBBBBBB   DD     DD  UU    UU  MM MMMM MM  PPPPPPPP   EEEEEE     RRRRRRRR    .       
 BBBBBBBB   DD     DD  UU    UU  MM  MM  MM  PPPPPPP    EEEEEE     RRRRRRR    ...      
 BB     BB  DD     DD  UU    UU  MM      MM  PP         EE     EE  RR   RR   .....     
BBBBBBBBB  DDDDDDDDD    UUUUUU   MM      MM PPPP       EEEEEEEEEE  RR    RR   ...      
BBBBBBBB   DDDDDDDD      UUUU    MM      MM PPPP       EEEEEEEEEE  RR     RR   .       

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Program:     Bdumper
  7:  *
  8:  * Purpose:     Main entry point for Basis Universe Dump process.
  9:  *
 10:  * Call:        $ bdumper -mMSGLEVEL -pCLOSING
 11:  *                        -bFILE -nFILE -aFILE -cFILE -zFILE -fFILE
 12:  *              (where $bdumper :== $sys$sysdevice:[]bdumper.exe
 13:  *              has been installed as a foreign command)
 14:  *
 15:  * Command-line Arguments:
 16:  *
 17:  *              -mMSGLEVEL      controls level of reporting detail
 18:  *                              (should always be >0 unless no sys$output
 19:  *                              available for server)
 20:  *
 21:  *              -pCLOSING       either -p3PM or -p5PM for 3PM or 5PM closings.
 22:  *                              if switch not present, a normal backup
 23:  *                              is performed.
 24:  *                              Note: if -p99 is set, a normal dump is forced,
 25:  *                              regardless of whether or not it's required.
 26:  *
 27:  *              -sSETTLEMENT    settlement date in the form mm/dd/yy
 28:  *                              (overrides file defaults if present)
 29:  *
 30:  *              -q              rewrites files in quote-file format
 31:  *                              without extra Basis fields.
 32:  *
 33:  *              -b,...,-fFILE   specify filenames to override the defaults
 34:  *                              used for bills,...,futures.  If an extension
 35:  *                              is not supplied, ".PRM" is concatanated.
 36:  *
 37:  * Notes:
 38:  *
 39:  * Source:      BDUMPER.C
 40:  *
 41:  * --------------------------------------------------------------------------
 42:  * Revision History:
 43:  *
 44:  * 12/27/88     J.Forkosh       Installation.
 45:  * 02/13/89     J.Forkosh       Modified for Version 2.
 46:  *
 47:  ****************************************************************************/
 48: 
 49: /* ---------------------------------------------------------------------------
 50: Header files and other #define-ed Symbols
 51: --------------------------------------------------------------------------- */
 52: /* --- standard vms headers --- */
 53: #include < stdio.h >
 54: #include  < ssdef.h >
 55: /* --- Dumper Defaults --- */
 56: #define MSGLEVEL 3                      /* default message level */
 57: #define CLOSING 0                       /* changed to 3 or 5 by -p switch */
 58: #define HOLIDAY_FILE    "BDAT:DATEFILE.DAT" /* holiday file for isbusday() */
 59: #define HOLIDAY_ICAL    1               /* default calendar number */
 60: #define SETLOG "BSET"                   /* settlement date logical */
 61: /* --- Basis universe headers --- */
 62: #define BALLOCATE                       /* initialize tables and queues */
 63: #define BSERVER
 64: #include "bglobals.h"
 65: int     msglevel;                       /* message level (ref as extern) */
 66: #include "bdump.h"
 67: #include "qdescrip.h"
 68: #include "recalc.h"
 69: /* ------------------------------------------------------------------------ */
 70: 
 71: /* --- entry point --- */
 72: main ( argc, argv)
 73: int     argc;
 74: char    *argv[];
 75: {
 76: /* ---------------------------------------------------------------------------
 77: Allocations and Declarations
 78: --------------------------------------------------------------------------- */
 79: /* --- internal universe data --- */
 80: char    gsdnam[64] = GSDNAM;            /* name of universe global section */
 81: int     pagcnt;                         /* # 512-byte pages in global section */
 82: struct  bunshdr_struct *bunshdr;        /* control struct preceding universe */
 83: unsigned char *cup;                     /* ptr to MAX_ISSUES universe buffers */
 84: BUS     *up;                            /* pointer to calloc-ed buffer */
 85: BUS     *uptr;                          /* and to a particular issue within */
 86: int     usize;                          /* #bytes in a universe struct */
 87: int     utem;                           /* item = ulayout[utem].item */
 88: int     iuniverse, nuniverse;           /* number universe issues in memory */
 89: int     iqtype, ndumped[16];            /* number of issues dumped for iqtype */
 90: BCS     recalc_options;                 /* options for recalc */
 91: /* --- command-line argument processing --- */
 92: int     ivalue;                         /* atoi(...) whenever needed */
 93: int     iarg;                           /* counter over command-line switches */
 94: int     closing = CLOSING;              /* normally not a closing price dump */
 95: char    *argptr, argop;                 /* ptr to argv[iarg], 1st char of arg */
 96: /* --- other variables --- */
 97: int     isdump;                         /* true if everything ok for dump */
 98: int     isforced = FALSE;               /* dump not forced unless -p99 set */
 99: int     isbasis = TRUE;                 /* true for Basis-formatted dump */
100: int     issettle = FALSE;               /*true if got settlement from cmdline*/
101: int     iszero;                         /*true if file settlement is 00/00/00*/
102: int     vms_stat, status;               /* vms status returns */
103: char    errmsg[132] = "\000";           /* buffer for error message */
104: char    outfile[64];                    /* output filename for 3,5pm closings */
105: char    settlement[64], *psettle;       /* default settlement if not in file */
106: char    *vmsmsg(),                      /* xlate vms_stat to string */
107:         *daytime();                     /* time stamp and secs since midnight */
108: char    *delim, *strchr(), *index();    /* to parse messsages */
109: char    *strupper(), *trim(), *ltrim(); /* trim and toupper a string */
110: /* ------------------------------------------------------------------------ */
111: 
112: /* ---------------------------------------------------------------------------
113: Dumper Initialization
114: --------------------------------------------------------------------------- */
115: /* --- defaults (unless over-ridden by command line args) --- */
116: msglevel = MSGLEVEL;                    /* default message level */
117: closing = CLOSING;                      /* normally not a closing price dump */
118: isforced = FALSE;                       /* dump not forced unless -p99 set */
119: isbasis = TRUE;                         /* dump files in Basis format */
120: issettle = FALSE;                       /* no settlement from command line */
121: *settlement = '\000';                   /* no default settlement yet */
122: recalc_options.odd_adjust = TRUE;       /* adjust for odd maturities */
123: recalc_options.price_rounding = 0;      /* no rounding */
124: recalc_options.isclosing = FALSE;       /* only closing for 3pm,5pm */
125: 
126: /* -------------------------------------------------------------------------
127: Universe Initialization
128: -------------------------------------------------------------------------- */
129: /* --- rescale ulayout[] from absolute address to offsets --- */
130: for ( utem=0; ulayout[utem].item >= 0; utem++ )
131:         ulayout[utem].offset -= (int)(&dummy_universe);
132: 
133: /* --------------------------------------------------------------------------
134: Get command-line args
135: -------------------------------------------------------------------------- */
136: /* ---Loop over each command-line argument --- */
137: for ( iarg=1; iarg < argc; iarg++ )     /* skip image name in argv[0] */
138:     {
139:     /* --- make sure arg is a switch and then use its 1st char as opcode --- */
140:     argptr = argv[iarg];                /* ptr to first char of this arg */
141:     if ( *argptr == '-' )               /* got a switched arg */
142:         argptr++;                       /* just skip over the dash */
143:     argop = toupper(*argptr++);         /* opcode is char after '-' */
144:     ivalue = atoi( argptr );            /* convert remainder of arg to int */
145: 
146:     /* --- first check for a q-filename for a universe data file --- */
147:     for ( iqtype=0; *(qtypes[iqtype])!='\000'; iqtype++ )
148:         { if ( argop == *(qtypes[iqtype]) ) /* opcode is a qtype */
149:             {
150:             strcpy ( qfiles[iqtype], argptr );  /* new universe file to open */
151:             if ( strchr(qfiles[iqtype],'.') == NULL ) /* no file extension */
152:                 strcat ( qfiles[iqtype], ".PRM" ); /* so use .PRM extension */
153:             goto next_iarg;             /* get next command-line arg */
154:             } /* --- end-of-if(opcode) --- */
155:         } /* --- end-of-for(iqtype) --- */
156: 
157:     /* --- else switch on argop tells us what kind of command we've got --- */
158:     switch ( argop )                    /* check the char following '-' */
159:         {
160:         /* --- Just ignore anything unrecognizable --- */
161:         default:                        /* got an unrecognized switch */
162:             if ( msglevel > 0 )         /* so print an error msg */
163:                 printf("\nbdumper> unrecognized command-line switch=%c, arg=%s",
164:                 argop, argptr );
165:             break;
166:         /* --- message level --- */
167:         case 'M':
168:             if ( ivalue >= 0 )          /* 0 means no sys$output available */
169:                 msglevel = ivalue;
170:             break;
171:         /* --- closing prices --- */
172:         case 'P':
173:             if ( *argptr == '3' ) closing = 3;  /* must be 3 for 3pm */
174:             if ( *argptr == '5' ) closing = 5;  /* or 5 for 5pm closings */
175:             if ( !memcmp(argptr,"99",2) )       /* forced dump requested */
176:                 isforced = TRUE;                /* so set flag accordingly */
177:             break;
178:         /* --- settlement date --- */
179:         case 'S':
180:             strcpy ( settlement, argptr );      /* copy settlement date */
181:             issettle = TRUE;                    /* and set flag */
182:             break;
183:         /* --- flip default file format --- */
184:         case 'Q':
185:             isbasis = !(isbasis);               /* flip from true to false */
186:             break;
187:         } /* --- end-of-switch(argop) --- */
188: 
189:     next_iarg: ;
190:     }  /* --- end-of-for(iarg) --- */
191: 
192: /* -------------------------------------------------------------------------
193: Allocate universe buffers
194: -------------------------------------------------------------------------- */
195: /* --- map memory-resident universe buffers to global section --- */
196: usize = sizeof( BUS );
197: pagcnt = 2 + ( MAX_UNIVERSE*usize + sizeof(struct bunshdr_struct) )/512;
198: if ( closing != 0 )                     /* doing a closing dump */
199:     { strcpy ( gsdnam, GSD3PMNAM );     /* use closing universe */
200:       recalc_options.isclosing = TRUE; } /* closing for 3pm,5pm */
201: vms_stat = crmpsc ( gsdnam, pagcnt, &pbuns );
202: if ( vms_stat == SS$_CREATED )          /* shouldn't create it ourselves */
203:         { /* --- quit if server hasn't already created universe --- */
204:         if ( msglevel > 0 )
205:           printf ( "\nbdumper> crmpsc created section, server not running." );
206:         goto end_of_job; }
207: if ( vms_stat != SS$_NORMAL )           /* can't map to global section */
208:         { /* --- quit if can't crmpsc() universe --- */
209:         if ( msglevel > 0 )
210:           printf ( "\nbdumper> Can't crmpsc, err=%s", vmsmsg(vms_stat) );
211:         goto end_of_job; }
212: /* --- extract control variables from header --- */
213: bunshdr = (struct bunshdr_struct *)(pbuns); /* header preceding universe */
214: if ( msglevel > 0 )
215:     printf("\nbdumper> mapped %d pages to global section %s, section tag=%s",
216:     pagcnt,gsdnam,bunshdr->gsdnam);
217: nuniverse = bunshdr->nuniverse;         /* # universe issues in memory */
218: isdump = ( ( (bunshdr->nupdates) > 0    /* got something to update */
219:              || closing != 0 )          /* or if we're closing */
220:            && !(bunshdr->isdumping)     /* and no-one now dumping */
221:            )? 1 : 0;                    /* dump if we've updated anything */
222: 
223: /* --- initialize universe structs --- */
224: cup = pbuns + sizeof(struct bunshdr_struct);    /* char ptr to universe */
225: up = (BUS *)(cup);                      /* cup as universe ptr */
226: global_bus = up;                        /* available globally (in universe.h) */
227: global_nbus = nuniverse;                /* ditto */
228: 
229: /* -------------------------------------------------------------------------
230: Rewrite universe files
231: -------------------------------------------------------------------------- */
232: if ( isdump                     /* flag requesting universe dump set */
233: ||   isforced )                 /* or forced dump requested */
234:     {
235:     /* --- initialize calendar --- */
236:     if ( setbusday ( HOLIDAY_FILE, HOLIDAY_ICAL ) /* init the calendar file */
237:      < 0 )                              /* init failed */
238:         { if ( msglevel > 0 )
239:             printf ( "\nbdumper> holiday file %s init failed.", HOLIDAY_FILE );
240:           goto end_of_job; }
241: 
242:     /* --- check for explicit settlement date --- */
243:     if ( !issettle )            /* nothing on command line so check logicals */
244:         {
245:         status = trnlnm(1,SETLOG,settlement); /* translate settlement logical */
246:         if ( !memcmp(settlement,SETLOG,strlen(settlement)) ) /* no xlation */
247:                 { issettle = FALSE; *settlement = '\000'; } /* so reset */
248:            else { issettle = TRUE; } /* got settlement from logical */
249:         } /* --- end-of-if(!issettle) --- */
250:     if ( issettle )             /* check validity of explicit settlement date */
251:         {
252:         if ( adatetoi(settlement) < 19800101 ) /* must be something wrong */
253:             { if ( msglevel >= 1 ) /* print error message */
254:                 printf ( "\nbdumper> illegal settlement date %s ignored.",
255:                 settlement );
256:               issettle = FALSE; } /* can't use explicit date so reset flag */
257:         } /* --- end-of-if(issettle) --- */
258: 
259:     /* --- re-initialize header --- */
260:     bunshdr->nupdates = 0;      /* reset update messages count */
261:     bunshdr->isdumping = 1;     /* set dump in progress flag */
262: 
263:     for ( iqtype=0; *(qtypes[iqtype]) != '\000'; iqtype++ )
264:         {
265:         if ( *(qfiles[iqtype]) == '\000' ) continue; /* no file */
266:         /* --- check settlement date --- */
267:         if ( !memcmp(bunshdr->qsettlements[iqtype],"00/00/00",8) ) /*no date*/
268:             iszero = TRUE; else iszero = FALSE; /* set flag for zero date */
269:         if ( !issettle )        /* no explicitly-given settlement date */
270:           if ( !iszero )        /* and got non-zero date in file */
271:             strcpy ( settlement, bunshdr->qsettlements[iqtype] ); /*so use it*/
272:         /* --- update all issues in universe of current type --- */
273:         for ( iuniverse=0; iuniverse < nuniverse; iuniverse++ )
274:             if ( *(up[iuniverse].sec_type) == *(qtypes[iqtype]) )
275:                 { /* --- iuniverse in current quote file so update it --- */
276:                 uptr = &(up[iuniverse]);        /* ptr to iuniverse issue */
277:                 /* --- ask side recalculation (normal) --- */
278:                 recalc(uptr,1,settlement,-1,&recalc_options ); /*init recalc*/
279:                 /* --- bid side recalculation --- */
280:                 bidcalc ( uptr, settlement );   /* calculate bid side */
281:                 } /* --- end-of-if(sec_type==iqtype) --- */
282:         /* --- dump the updated universe --- */
283:         strcpy ( outfile, qfiles[iqtype] );     /* assume outfile=infile */
284:         if ( closing != 0 )     /* but change outfilename for closing prices */
285:             { delim = strchr(outfile,'.');      /* see if we got an extension */
286:               if ( delim != NULL ) *delim='\000'; /* if so, zap it */
287:               if ( closing == 3 ) strcat ( outfile, EXT_3PM ); /*3pm extension*/
288:               if ( closing == 5 ) strcat ( outfile, EXT_5PM ); /*5pm extension*/
289:             }
290:         psettle = (issettle && !iszero)? /* got settlement and non-zero file */
291:                 settlement : &(bunshdr->qsettlements[iqtype][0]);
292:         ndumped[iqtype] = qdump ( qtypes[iqtype], qfiles[iqtype], outfile,
293:                                         &up[0], psettle, isbasis );
294:         if ( msglevel > 1 )     /* display number of issues dumped */
295:             { printf ( "\nbdumper> %d %s-issues dumped to %s for set %s at %s",
296:                 ndumped[iqtype], qtypes[iqtype], outfile, psettle,
297:                 daytime(0) ); }
298:         } /* --- end-of-for(*qtypes[iqtype]) --- */
299: 
300:     /* --- re-initialize header stuff --- */
301:     bunshdr->isdumping = 0;             /* dump completed */
302:     } /* --- end-of-if(isdump) --- */
303: 
304: 
305: /* ---------------------------------------------------------------------------
306: End-of-Job
307: --------------------------------------------------------------------------- */
308: end_of_job:
309:     exit ( vms_stat );                  /* exit with SS$_NORMAL or error */
310: } /* --- end-of-program main() for Basis Dumper process --- */
311: /* ------------------------- END-OF-FILE BDUMPER.C -------------------------- */


BBBBBBBB   DDDDDDDD   UUUU  UUUU MM      MM PPPPPPPP   EEEEEEEEEE RRRRRRRR             
BBBBBBBBB  DDDDDDDDD  UUUU  UUUU MMM    MMM PPPPPPPPP  EEEEEEEEEE RRRRRRRRR            
 BB     BB  DD     DD  UU    UU  MMMM  MMMM  PP     PP  EE     EE  RR     RR           
 BBBBBBBB   DD     DD  UU    UU  MM MMMM MM  PPPPPPPP   EEEEEE     RRRRRRRR    .       
 BBBBBBBB   DD     DD  UU    UU  MM  MM  MM  PPPPPPP    EEEEEE     RRRRRRR    ...      
 BB     BB  DD     DD  UU    UU  MM      MM  PP         EE     EE  RR   RR   .....     
BBBBBBBBB  DDDDDDDDD    UUUUUU   MM      MM PPPP       EEEEEEEEEE  RR    RR   ...      
BBBBBBBB   DDDDDDDD      UUUU    MM      MM PPPP       EEEEEEEEEE  RR     RR   .       

  1: $ set noverify
  2: $!-----------------------------------------------------------------------------
  3: $! Procedure:   BDUMPER.COM  idump
  4: $! Purpose:     Detaches a command file that runs bdumper.exe
  5: $!              for the (normal) 15 minute backups or for the 3pm and 5pm files.
  6: $! Parameters:
  7: $!              idump           0 for a normal 15-minute interval dump,
  8: $!                              1 for the 3pm closing file dump,
  9: $!                              2 for the 5pm closing file dump.
 10: $!-----------------------------------------------------------------------------
 11: $!
 12: $! --- Initialization ---
 13: $ @brun:bass j                          ! get a new job number
 14: $ idump = p1                            ! and a local copy of command-line param
 15: $ say "bdumper#''jobnum'> idump=''idump' spawned at ",f$time()
 16: $!
 17: $! --- Assign a group logical for idump to be picked up by bdumper_run.com ---
 18: $ if f$trnlnm("b$dump").nes."" then deassign/group b$dump
 19: $ if idump.nes."" then assign/group 'idump' b$dump
 20: $!
 21: $! --- Output for closing only
 22: $ outfile = "nl:"                       ! default to null file
 23: $ if idump.eqs."1".or.idump.eqs."2".or.idump.eqs."3".or.idump.eqs."5" then -
 24:         outfile = "bout:bdumper.log"
 25: $!
 26: $! --- Detach process to dump the files from the "universe" global section ---
 27: $ run/detach/uic='user'/authorize/proc=bdumper'jobnum' sys$system:loginout.exe-
 28: /input=brun:bdumper_run.com/output='outfile'-
 29: /priv=all/buffer_limit=64000
 30: $ exit                                  ! end-of-procedure
 31: $! ------------------------------- END-OF-FILE --------------------------------


BBBBBBBB   DDDDDDDD   UUUU  UUUU MM      MM PPPPPPPP   EEEEEEEEEE RRRRRRRR             
BBBBBBBBB  DDDDDDDDD  UUUU  UUUU MMM    MMM PPPPPPPPP  EEEEEEEEEE RRRRRRRRR            
 BB     BB  DD     DD  UU    UU  MMMM  MMMM  PP     PP  EE     EE  RR     RR           
 BBBBBBBB   DD     DD  UU    UU  MM MMMM MM  PPPPPPPP   EEEEEE     RRRRRRRR            
 BBBBBBBB   DD     DD  UU    UU  MM  MM  MM  PPPPPPP    EEEEEE     RRRRRRR             
 BB     BB  DD     DD  UU    UU  MM      MM  PP         EE     EE  RR   RR             
BBBBBBBBB  DDDDDDDDD    UUUUUU   MM      MM PPPP       EEEEEEEEEE  RR    RR  __________
BBBBBBBB   DDDDDDDD      UUUU    MM      MM PPPP       EEEEEEEEEE  RR     RR __________

  1: $ set verify
  2: $!-----------------------------------------------------------------------------
  3: $! Procedure:   BDUMPER_RUN.COM (no params)
  4: $! Purpose:     Run bdumper.exe to dump the universe of issues from
  5: $!              the global section to q-formatted files.
  6: $! Notes:     o This procedure is detached by bdumper.com which "passes"
  7: $!              parameters to it through a group logical (see below).
  8: $!-----------------------------------------------------------------------------
  9: $!
 10: $! --- Initialization ---
 11: $ nkeep = "4"                           ! internal parameter for bdat: purge
 12: $ @brun:bass                            ! set symbols
 13: $ set verify
 14: $ idump = f$trnlnm("b$dump")            ! get idump parameter
 15: $ logfile = "bout:bdumper.out"          ! logfile
 16: $!
 17: $! --- set process priority ---
 18: $ host = f$trnlnm("BASIS$HOST")
 19: $ host = f$edit(host,"UPCASE,COLLAPSE")
 20: $ if host.eqs."VEGA" then set proc/prio=3 ! lower Dumper's priority on Vega
 21: $ if host.eqs."BETELGEUSE" then set proc/prio=2 ! on Betelgeuse (BASIS1::)
 22: $!
 23: $! --- De-assign parameter logical and default param as necessary ---
 24: $ if idump.nes."" then deassign/group b$dump
 25: $ if idump.eqs."" then idump="0"
 26: $!
 27: $! --- run the dumper process, passing it the idump parameter ---
 28: $ set def brun
 29: $ @brun:joulog "bdumper_run#''jobnum' idump=''idump' started" 'logfile'
 30: $ bd -m3 -p'idump'
 31: $ if nkeep.nes."" then purge/log/keep='nkeep' bdat:
 32: $ @brun:joulog "bdumper_run#''jobnum' idump=''idump' completed" 'logfile'
 33: $!
 34: $! --- xfr to prime ---
 35: $ xdump = idump
 36: $ if xdump.eqs."3" then xdump="1"
 37: $ if xdump.eqs."5" then xdump="2"
 38: $ if xdump.nes."1".and.xdump.nes."2" then goto end_of_job
 39: $ @brun:joulog "ftpxfr#''jobnum' idump=''idump' started" "bout:autoclose.out"
 40: $ @ftpxfr 'xdump'
 41: $ @brun:joulog "ftpxfr#''jobnum' idump=''idump' completed" "bout:autoclose.out"
 42: $!
 43: $! --- end-of-job ---
 44: $ end_of_job:
 45: $ set noverify
 46: $ exit                                  ! end-of-procedure
 47: $! ------------------------------- END-OF-FILE --------------------------------


BBBBBBBB     GGGGGG   LLLLL        OOOOOO   BBBBBBBB        AA    LLLLL        SSSSSSS 
BBBBBBBBB   GGGGGGGG  LLLLL       OOOOOOOO  BBBBBBBBB      AAAA   LLLLL       SSSSSSSSS
 BB     BB GG          LL        OO      OO  BB     BB    AA  AA   LL        SS        
 BBBBBBBB  GG    GGG   LL        OO      OO  BBBBBBBB    AA    AA  LL         SSSSSSS  
 BBBBBBBB  GG   GGGGG  LL        OO      OO  BBBBBBBB   AAAAAAAAA  LL          SSSSSSS 
 BB     BB GG      GG  LL     LL OO      OO  BB     BB AAAAAAAAAA  LL     LL         SS
BBBBBBBBB   GGGGGGGG  LLLLLLLLLL  OOOOOOOO  BBBBBBBBB  AA      AA LLLLLLLLLL SSSSSSSSS 
BBBBBBBB     GGGGGG   LLLLLLLLLL   OOOOOO   BBBBBBBB   AA      AA LLLLLLLLLL  SSSSSSS  

  1: #ifndef _BGLOBALS
  2: #define _BGLOBALS
  3: /****************************************************************************
  4:  *
  5:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  6:  * --------------------------------------------------------------------------
  7:  *
  8:  * Header:      bglobals
  9:  *
 10:  * Purpose:     Defines global variables for Basis.
 11:  *
 12:  * Notes:     o Main() should #define BALLOCATE (to a null or comment) so that
 13:  *              global variables will be allocated.  If BALLOCATE is not
 14:  *              defined, global variables will be declared extern.
 15:  *            o In addition, one or more of the symbols BTRADER, BUNIVERSE,
 16:  *              BCLOCK, BSOCKET should be #define-ed to extract just those
 17:  *              globals needed.
 18:  *
 19:  * Source:      BGLOBALS.H
 20:  *
 21:  * --------------------------------------------------------------------------
 22:  * Revision History:
 23:  *
 24:  * 02/03/89     J.Forkosh       Installation.
 25:  *
 26:  ****************************************************************************/
 27: 
 28: /* -----------------------------------------------------------------------------
 29: First see if we're allocating/defining or referring to global variables
 30: ----------------------------------------------------------------------------- */
 31: #ifdef  BALLOCATE
 32: #define BEXTERN /* globaldef */
 33: #define BUNIVERSE       1
 34: #ifndef BSERVER
 35: #define BTRADER         1
 36: #define BSOCKET         1
 37: #define BCLOCK          1
 38: #endif
 39: #else
 40: #define BEXTERN extern
 41: #endif
 42: 
 43: /* -----------------------------------------------------------------------------
 44: Global Variables
 45: ----------------------------------------------------------------------------- */
 46: /* --- some routines only need universe (not full trader struct) --- */
 47: #ifdef BUNIVERSE
 48: #undef BUNIVERSE
 49: #ifndef _UNIVERSE
 50: #include "universe.h"
 51: #endif
 52: BEXTERN BUS     *global_bus;    /* for global universe, only need universe.h */
 53: BEXTERN int     global_nbus;    /* also need #issues in universe */
 54: #endif
 55: 
 56: /* --- some routines need BTS but can't get it through calling sequence --- */
 57: #ifdef BTRADER
 58: #undef BTRADER
 59: #ifndef _TRADER
 60: #include "trader.h"
 61: #endif
 62: BEXTERN BTS     *global_bts;    /* copy of ptr to basis trader structure */
 63:                                 /* note: need to include trader.h for BTS */
 64: #endif
 65: 
 66: /* --- tcp/ip socket communications --- */
 67: #ifdef BSOCKET
 68: #undef BSOCKET
 69: #ifndef _SKTHEADER
 70: #include "skt_header.h"
 71: #endif
 72: #ifndef _SKTMSGDEF
 73: #include "sktmsgdef.h"
 74: #endif
 75: #ifndef _MSGQUEUE
 76: #include "msgqueue.h"
 77: #endif
 78: #define HOSTNAME        "VEGA"  /* default node on which server is running */
 79: BEXTERN char    hostname[64];   /* actual host name */
 80: BEXTERN int     ishostup;       /* true if host connection established */
 81: BEXTERN int     sktseqin, sktseqout; /* incoming,outgoing msg sequence #'s */
 82: BEXTERN struct  skt_control_struct *sktctl; /* our channel for send/receive */
 83: BEXTERN struct  msg_control_struct  sktmsg; /* ioctl targeted towards server */
 84: BEXTERN unsigned char sktmsgbuf[SKT_MAXMSG]; /* msg buff pointed to in sktmsg*/
 85: #endif
 86: 
 87: /* --- display clock (can't be in BTS because getkey1() doesn't have BTS) --- */
 88: #ifdef BCLOCK
 89: #undef BCLOCK
 90: BEXTERN int     timr_reqidt;    /* request id for clock timer */
 91: #define TIMR_FLAG       10      /* timer event flag (<0 to turn off) */
 92: #define TIMR_INTERVAL   "0 0:0:2"  /* delta time for re-display */
 93: #define TIMR_ROW        0       /* row where clock displayed */
 94: #define TIMR_COL        3       /* and column */
 95: #endif
 96: /* -------------------------- END-OF-FILE BGLOBALS.H ------------------------ */
 97: #endif


BBBBBBBB     IIIIII   NN      NN FFFFFFFFFF   OOOOOO                CCCCCCC 
BBBBBBBBB    IIIIII   NNN     NN FFFFFFFFFF  OOOOOOOO              CCCCCCCCC
 BB     BB     II     NNNN    NN  FF     FF OO      OO            CC      CC
 BBBBBBBB      II     NN NN   NN  FFFFFF    OO      OO   .        CC        
 BBBBBBBB      II     NN   NN NN  FFFFFF    OO      OO  ...       CC        
 BB     BB     II     NN    NNNN  FF        OO      OO .....      CC      CC
BBBBBBBBB    IIIIII   NN     NNN FFFF        OOOOOOOO   ...        CCCCCCCCC
BBBBBBBB     IIIIII   NN      NN FFFF         OOOOOO     .          CCCCCCC 

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Function:    binfo ( skt, msg, itrader, trader )
  7:  *
  8:  * Purpose:     Sends an info message from itrader to trader, or
  9:  *              to all traders in the nodes[] table (if *trader=='\000').
 10:  *
 11:  * Arguments:
 12:  *              skt (I)         addr of skt_control_struct needed to send
 13:  *                              messages to other traders through
 14:  *                              bserver()'s datagram socket.
 15:  *
 16:  *              msg (I)         addr of string containing the message
 17:  *                              to be sent.
 18:  *
 19:  *              itrader (I)     int containing index of sending trader
 20:  *                              in nodes[] table.
 21:  *
 22:  *              trader (I)      addr of char string containing trader name
 23:  *                              of trader to whom info msg is to be sent,
 24:  *                              or *trader=='\000' to send msg to all traders.
 25:  *
 26:  * Returns:     (int)           SS$_NORMAL or error status.
 27:  *
 28:  * Notes:
 29:  *
 30:  * Source:      BINFO.C
 31:  *
 32:  * --------------------------------------------------------------------------
 33:  * Revision History:
 34:  *
 35:  * 01/06/89     J.Forkosh       Installation.
 36:  * 02/13/89     J.Forkosh       Modified for Version 2.
 37:  *
 38:  ****************************************************************************/
 39: 
 40: /* ---------------------------------------------------------------------------
 41: Header files
 42: --------------------------------------------------------------------------- */
 43: /* --- standard vms headers --- */
 44: #include < stdio.h >
 45: /* --- Basis message headers --- */
 46: #include "bserver.h"
 47: #include "sktmsgdef.h"
 48: /* ------------------------------------------------------------------------ */
 49: 
 50: /* --- entry point --- */
 51: int     binfo ( skt, msg, itrader, trader )
 52: struct  skt_control_struct *skt;
 53: char    *msg;
 54: int     itrader;
 55: char    *trader;
 56: {
 57: /* ---------------------------------------------------------------------------
 58: Allocations and Declarations
 59: --------------------------------------------------------------------------- */
 60: /* --- application-level message processing --- */
 61: struct  sktmsghdr_struct *replyhdr;     /* interpret start of msg as hdr */
 62: struct  sktmsg_struct *sktmsg;          /* interpret info msg */
 63: unsigned char *msgbuff;                 /* pointer to iobuff in message */
 64: int     msglen;                         /* #bytes in message iobuff */
 65: /* --- nodes[] table variables --- */
 66: int     inode;                          /* index of traders receiving price */
 67: /* --- variables to construct outgoing price message --- */
 68: struct  skt_ioctl_struct *ioctl;        /* trader's TCP/IP return address */
 69: struct  msg_control_struct reply;       /* outgoing formatted reply */
 70: char    replybuff[SKT_MAXMSG];          /* allocated iobuff for reply */
 71: /* --- other variables --- */
 72: int     vms_stat;                       /* input message status */
 73: int     status;                         /* return status */
 74: int     tlen = 0;                       /* #chars in caller's trader arg */
 75: int     nsent = 0;                      /* #traders to which info msg sent */
 76: char    *delim, *strchr(), *index();    /* to parse messsages */
 77: char    *strupper(), *trim(), *ltrim(); /* trim and toupper a string */
 78: char    *daytime();                     /* trader's last incoming msg time */
 79: /* ------------------------------------------------------------------------ */
 80: 
 81: /* ---------------------------------------------------------------------------
 82: Initialization
 83: --------------------------------------------------------------------------- */
 84: /* --- see whether caller passed us a specific target trader for msg --- */
 85: tlen = 0;                               /* no chars in trader arg yet */
 86: if ( trader != 0 )                      /* caller passed us an address */
 87:     tlen = strlen(trader);              /* so see how much is in there */
 88: 
 89: /* --- set up stub for reply message --- */
 90: msglen = sizeof(struct sktmsghdr_struct) /* message will have a header */
 91:         + strlen(msg) + 1;              /* plus text message and its null */
 92: reply.iobuff = replybuff;               /* point reply to its formatted buff */
 93: reply.maxmsg = SKT_MAXMSG;              /* set max msg size, */
 94: reply.msgsz = msglen;                   /* and set size of actual reply */
 95: memset ( &(reply.iosb), '\000', sizeof(struct skt_iosb_struct) ); /*zero iosb*/
 96: replyhdr = (struct sktmsghdr_struct *)(replybuff);/* interpret hdr in msg */
 97: sktmsg = (struct sktmsg_struct *)(replybuff);/* interpret info msg */
 98: replyhdr->opcode = SKT$_INFOMSG;        /* set message type */
 99: memset ( replyhdr->sender, '\000', 16 ); /* null-fill sender field */
100: if ( itrader>=0 && itrader < ntraders ) /* and if passed a legal trader */
101:     strcpy ( replyhdr->sender, nodes[itrader].trader ); /* then copy his name */
102: else strcpy ( replyhdr->sender, "SERVER" ); /* else use stub name */
103: strcpy ( sktmsg->msg, msg );            /* finally, copy the message text */
104: 
105: /* ---------------------------------------------------------------------------
106: Send constructed info message to all traders in the nodes[] table
107: --------------------------------------------------------------------------- */
108: nsent = 0;                              /* nothing sent yet */
109: for ( inode=0; inode < ntraders; inode++ )
110:     {
111:     /* --- check for originator --- */
112:     if ( inode == itrader ) continue;   /* don't send info to ourselves */
113:     /* --- check for trader (if caller specified one) --- */
114:     if ( tlen > 0 )                     /* got a specific trader for info */
115:         { if ( memcmp(trader,nodes[inode].trader,tlen) ) /* this isn't him */
116:             continue; }                 /* so keep looking for trader we want */
117: 
118:     /* --- set reply's ioctl to that of the trader in the table --- */
119:     memcpy ( (unsigned char *)(&(reply.ioctl)),         /* ioctl in reply */
120:                 (unsigned char *)(&(nodes[inode].ioctl)), /* trader's ioctl */
121:                     sizeof(struct skt_ioctl_struct) );  /* #bytes in ioctl */
122: 
123:     /* --- need message sequence number for each trader --- */
124:     nodes[inode].msgseqout += 1;        /* bump last sequence number used */
125:     replyhdr->msgseqnum = nodes[inode].msgseqout;       /* and set new one */
126: 
127:     /* --- send the info message --- */
128:     vms_stat = sendsktw ( skt, &reply ); /* send reply to trader */
129:     if ( vms_stat == SS$_NORMAL )       /* sent ok */
130:         nsent++;                        /* so bump count of sent messages */
131:     else                                /* failed to send msg */
132:         { if ( msglevel > 0 )           /* so print error message */
133:             printf( "\nbinfo> trader=%s, sendsktw error=%s",
134:                 nodes[inode].trader, vmsmsg(vms_stat) ); }
135:     if ( tlen > 0 ) break;              /* did one and only target, so done */
136:     } /* --- end-of-for(inode) --- */
137: 
138: /* --- report info message --- */
139: if ( msglevel > 2 )
140:     printf ( "\nbinfo> trader#%d=%s info msg=%s sent to %d traders at %s",
141:         itrader+1, replyhdr->sender, msg, nsent, daytime(0) );
142: 
143: /* ---------------------------------------------------------------------------
144: Back to caller with status
145: --------------------------------------------------------------------------- */
146: status = SS$_NORMAL;
147: return ( status );
148: } /* --- end-of-function binfo() --- */
149: /* ------------------------ END-OF-FILE BINFO.C --------------------------- */


BBBBBBBB   LLLLL        OOOOOO     GGGGGG     OOOOOO   FFFFFFFFFF FFFFFFFFFF           
BBBBBBBBB  LLLLL       OOOOOOOO   GGGGGGGG   OOOOOOOO  FFFFFFFFFF FFFFFFFFFF           
 BB     BB  LL        OO      OO GG         OO      OO  FF     FF  FF     FF           
 BBBBBBBB   LL        OO      OO GG    GGG  OO      OO  FFFFFF     FFFFFF      .       
 BBBBBBBB   LL        OO      OO GG   GGGGG OO      OO  FFFFFF     FFFFFF     ...      
 BB     BB  LL     LL OO      OO GG      GG OO      OO  FF         FF        .....     
BBBBBBBBB  LLLLLLLLLL  OOOOOOOO   GGGGGGGG   OOOOOOOO  FFFF       FFFF        ...      
BBBBBBBB   LLLLLLLLLL   OOOOOO     GGGGGG     OOOOOO   FFFF       FFFF         .       

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Function:    blogoff ( msg, itrader )
  7:  *
  8:  * Purpose:     Logs off a trader by removing him from the nodes[] table.
  9:  *
 10:  * Arguments:
 11:  *              msg (I)         addr of msg_control_struct with SKT$_LOGOFF
 12:  *                              opcode in its message header, and name of
 13:  *                              trader in sender field.
 14:  *
 15:  *              itrader (I/O)   addr of int containing index of trader
 16:  *                              in nodes[] table before he logs off,
 17:  *                              and returning index after logoff (usually -1).
 18:  *
 19:  * Returns:     (int)           SS$_NORMAL or error status.
 20:  *
 21:  * Notes:
 22:  *
 23:  * Source:      BLOGOFF.C
 24:  *
 25:  * --------------------------------------------------------------------------
 26:  * Revision History:
 27:  *
 28:  * 12/15/88     J.Forkosh       Installation.
 29:  * 02/13/89     J.Forkosh       Modified for Version 2.
 30:  *
 31:  ****************************************************************************/
 32: 
 33: /* ---------------------------------------------------------------------------
 34: Header files
 35: --------------------------------------------------------------------------- */
 36: /* --- standard vms headers --- */
 37: #include < stdio.h >
 38: /* --- Basis message headers --- */
 39: #include "bserver.h"
 40: #include "sktmsgdef.h"
 41: /* ------------------------------------------------------------------------ */
 42: 
 43: /* --- entry point --- */
 44: int     blogoff ( msg, itrader )
 45: struct  msg_control_struct *msg;
 46: int     *itrader;
 47: {
 48: /* ---------------------------------------------------------------------------
 49: Allocations and Declarations
 50: --------------------------------------------------------------------------- */
 51: /* --- communication-level message processing --- */
 52: struct  skt_ioctl_struct *ioctl;        /* trader's TCP/IP return address */
 53: /* --- application-level message processing --- */
 54: struct  sktmsghdr_struct *msghdr;       /* interpret beginning of msg as hdr */
 55: int     opcode;                         /* and process it according to opcode */
 56: unsigned char *msgbuff;                 /* pointer to iobuff in message */
 57: int     msglen;                         /* #bytes in message iobuff */
 58: int     msgseqin;                       /* incoming message sequence number */
 59: /* --- nodes[] table variables --- */
 60: int     inode;                          /* =*itrader, nodes[] index of trader */
 61: unsigned char *ntable;                  /* ptr to beginning of node table */
 62: int     nsize = sizeof(struct node_control_struct); /* #bytes per table entry */
 63: /* --- other variables --- */
 64: int     vms_stat;                       /* input message status */
 65: int     status;                         /* blogon() return status */
 66: char    *delim, *strchr(), *index();    /* to parse messsages */
 67: char    *strupper(), *trim(), *ltrim(); /* trim and toupper a string */
 68: char    *daytime();                     /* trader's logon time */
 69: /* ------------------------------------------------------------------------ */
 70: 
 71: /* ---------------------------------------------------------------------------
 72: Initialization
 73: --------------------------------------------------------------------------- */
 74: /* --- extract message fields and check message --- */
 75: vms_stat = msg->iosb.status;            /* i/o status of input message */
 76: if ( vms_stat != SS$_NORMAL )           /* some problem receiving it */
 77:         return ( vms_stat );            /* let caller figure out what to do */
 78: ioctl = &(msg->ioctl);                  /* pointer to ioctl in message */
 79: msgbuff = msg->iobuff;                  /* set pointer to actual msg */
 80: msglen = msg->msgsz;                    /* # bytes in received msg */
 81: msghdr = (struct sktmsghdr_struct *)(msgbuff);/* interpret hdr in msg */
 82: msgseqin = msghdr->msgseqnum;           /* incoming message sequence number */
 83: opcode = msghdr->opcode;                /* and get opcode from hdr */
 84: if ( opcode != SKT$_LOGOFFMSG )         /* not my job (man) */
 85:         return ( SS$_BADPARAM );        /* let caller re-route it if he can */
 86: 
 87: /* ---------------------------------------------------------------------------
 88: Check index of trader
 89: --------------------------------------------------------------------------- */
 90: inode = *itrader;                       /* local copy of trader's index */
 91: if ( inode<0 || inode>=ntraders )       /* index out-of-bounds */
 92:     { if ( msglevel > 0 )               /* report error */
 93:         printf ( "\nblogoff> can't logoff index#%d, trader=%s, not logged on.",
 94:         inode,msghdr->sender );
 95:       return ( SS$_BADPARAM ); }        /* can't logoff non-existent trader */
 96: 
 97: /* ---------------------------------------------------------------------------
 98: Remove trader from node table by "shift left" compression
 99: --------------------------------------------------------------------------- */
100: /* --- remove trader from the table --- */
101: ntable = (unsigned char *)(nodes);      /* ptr to beginning of nodes[] table */
102: if ( inode < (ntraders-1) )             /* no need to shift last trader */
103:     memcpy ( ntable + (inode*nsize),    /* location of trader to be removed */
104:                 ntable + ((inode+1)*nsize), /* location of trader after him */
105:                     nsize*(ntraders-(inode+1)) ); /* nsize*(#traders after) */
106: ntraders--;                             /* decrement total trader count */
107: 
108: /* --- report logoff --- */
109: if ( msglevel > 1 )
110:     printf ( "\nblogoff> trader#%d=%s logged off %s",
111:         inode+1, msghdr->sender, daytime(0) );
112: *itrader = (-1);                        /* and reset his index for caller */
113: 
114: /* ---------------------------------------------------------------------------
115: Back to caller with status
116: --------------------------------------------------------------------------- */
117: status = SS$_NORMAL;
118: return ( status );
119: } /* --- end-of-function blogoff() --- */
120: /* ------------------------ END-OF-FILE BLOGOFF.C ------------------------- */


BBBBBBBB   LLLLL        OOOOOO     GGGGGG     OOOOOO   NN      NN              CCCCCCC 
BBBBBBBBB  LLLLL       OOOOOOOO   GGGGGGGG   OOOOOOOO  NNN     NN             CCCCCCCCC
 BB     BB  LL        OO      OO GG         OO      OO NNNN    NN            CC      CC
 BBBBBBBB   LL        OO      OO GG    GGG  OO      OO NN NN   NN   .        CC        
 BBBBBBBB   LL        OO      OO GG   GGGGG OO      OO NN   NN NN  ...       CC        
 BB     BB  LL     LL OO      OO GG      GG OO      OO NN    NNNN .....      CC      CC
BBBBBBBBB  LLLLLLLLLL  OOOOOOOO   GGGGGGGG   OOOOOOOO  NN     NNN  ...        CCCCCCCCC
BBBBBBBB   LLLLLLLLLL   OOOOOO     GGGGGG     OOOOOO   NN      NN   .          CCCCCCC 

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Function:    blogon ( msg, itrader )
  7:  *
  8:  * Purpose:     Logs on a new trader by placing him in the nodes[] table.
  9:  *
 10:  * Arguments:
 11:  *              msg (I)         addr of msg_control_struct with SKT$_LOGON
 12:  *                              opcode in its message header, and name of
 13:  *                              trader in sender field.
 14:  *
 15:  *              itrader (O)     addr of int returning index of new trader
 16:  *                              in nodes[] table, or -1 for failure.
 17:  *
 18:  * Returns:     (int)           SS$_NORMAL or error status.
 19:  *
 20:  * Notes:
 21:  *
 22:  * Source:      BLOGON.C
 23:  *
 24:  * --------------------------------------------------------------------------
 25:  * Revision History:
 26:  *
 27:  * 12/15/88     J.Forkosh       Installation.
 28:  * 02/13/89     J.Forkosh       Modified for Version 2.
 29:  *
 30:  ****************************************************************************/
 31: 
 32: /* ---------------------------------------------------------------------------
 33: Header files
 34: --------------------------------------------------------------------------- */
 35: /* --- standard vms headers --- */
 36: #include < stdio.h >
 37: /* --- Basis message headers --- */
 38: #include "bserver.h"
 39: #include "sktmsgdef.h"
 40: /* ------------------------------------------------------------------------ */
 41: 
 42: /* --- entry point --- */
 43: int     blogon ( msg, itrader )
 44: struct  msg_control_struct *msg;
 45: int     *itrader;
 46: {
 47: /* ---------------------------------------------------------------------------
 48: Allocations and Declarations
 49: --------------------------------------------------------------------------- */
 50: /* --- communication-level message processing --- */
 51: struct  skt_ioctl_struct *ioctl;        /* trader's TCP/IP return address */
 52: /* --- application-level message processing --- */
 53: struct  sktmsghdr_struct *msghdr;       /* interpret beginning of msg as hdr */
 54: int     opcode;                         /* and process it according to opcode */
 55: unsigned char *msgbuff;                 /* pointer to iobuff in message */
 56: int     msglen;                         /* #bytes in message iobuff */
 57: int     msgseqin;                       /* incoming message sequence number */
 58: /* --- nodes[] table variables --- */
 59: int     inode;                          /* index through nodes[] table */
 60: char    trader[16];                     /* copy of sender in message header */
 61: int     tlen;                           /* strlen(trader) */
 62: /* --- other variables --- */
 63: int     vms_stat;                       /* input message status */
 64: int     status;                         /* blogon() return status */
 65: char    *delim, *strchr(), *index();    /* to parse messsages */
 66: char    *strupper(), *trim(), *ltrim(); /* trim and toupper a string */
 67: char    *daytime();                     /* trader's logon time */
 68: /* ------------------------------------------------------------------------ */
 69: 
 70: /* ---------------------------------------------------------------------------
 71: Initialization
 72: --------------------------------------------------------------------------- */
 73: *itrader = (-1);                        /* init for bad return (just in case) */
 74: /* --- first make sure table not already full --- */
 75: if ( ntraders >= MAX_TRADERS )          /* no room for another logon */
 76:     { if ( msglevel > 0 )               /* print error message */
 77:         printf ( "\nblogon> #nodes=%d (table full), can't logon trader=%s",
 78:                 ntraders, trader );
 79:       return ( SS$_BADPARAM ); }
 80: 
 81: /* --- extract message fields and check message --- */
 82: vms_stat = msg->iosb.status;            /* i/o status of input message */
 83: if ( vms_stat != SS$_NORMAL )           /* some problem receiving it */
 84:         return ( vms_stat );            /* let caller figure out what to do */
 85: ioctl = &(msg->ioctl);                  /* pointer to ioctl in message */
 86: msgbuff = msg->iobuff;                  /* set pointer to actual msg */
 87: msglen = msg->msgsz;                    /* # bytes in received msg */
 88: msghdr = (struct sktmsghdr_struct *)(msgbuff);/* interpret hdr in msg */
 89: msgseqin = msghdr->msgseqnum;           /* incoming message sequence number */
 90: opcode = msghdr->opcode;                /* and get opcode from hdr */
 91: if ( opcode != SKT$_LOGONMSG )          /* not my job (man) */
 92:         return ( SS$_BADPARAM );        /* let caller re-route it if he can */
 93: 
 94: /* --- get local copy of logging-on trader name --- */
 95: memcpy ( trader, msghdr->sender, 16 );  /* max 16-byte field */
 96: trader[15] = '\000';                    /* should already have a null */
 97: strupper(trim(ltrim(trader)));          /* get rid of all white space and
 98:                                            uppercase the trader name */
 99: tlen = strlen ( trader );               /* number of chars remaining */
100: 
101: /* ---------------------------------------------------------------------------
102: First make sure trader not already logged on
103: --------------------------------------------------------------------------- */
104: for ( inode=0; inode < ntraders; inode++ )
105:     {
106:     if ( memcmp ( trader, nodes[inode].trader, tlen ) ) /* not dup trader */
107:         continue;                       /* so continue checking others */
108:     if ( msglevel > 0 )                 /* report possible security breach */
109:         printf ( "\nblogon> duplicate logon attempted, trader=%s", trader );
110:     return ( SS$_BADPARAM );            /* only one logon per trader */
111:     } /* --- end-of-for(inode) --- */
112: 
113: /* ---------------------------------------------------------------------------
114: Add new trader to end of node table
115: --------------------------------------------------------------------------- */
116: /* --- index returned to caller --- */
117: *itrader = ntraders;                    /* trader put at end of table */
118: /* --- trader name --- */
119: memset ( nodes[ntraders].trader, '\000', 16 ); /* zero out trader name field */
120: strcpy ( nodes[ntraders].trader, trader ); /* and copy current trader's name */
121: /* --- his ioctl (TCP/IP address info) --- */
122: memcpy ( (unsigned char *)(&(nodes[ntraders].ioctl)), /* copy ioctl */
123:         (unsigned char *)(ioctl), sizeof(struct skt_ioctl_struct) );
124: /* --- counters, etc --- */
125: nodes[ntraders].msgseqin = msgseqin;    /* reset incoming msg sequence # */
126: nodes[ntraders].msgseqout = 0;          /* and outgoing msg sequence # */
127: daytime ( &(nodes[ntraders].insecs) );  /* last msg received was this logon */
128: nodes[ntraders].isclosed = 0;           /* closing message not received yet */
129: nodes[ntraders].nissues = 0;            /* no closing prices received yet */
130: ntraders++;                             /* bump total trader count */
131: /* --- report logon --- */
132: if ( msglevel > 1 )
133:     printf ( "\nblogon> trader#%d=%s logged on %s",
134:         ntraders, trader, daytime(0) );
135: 
136: /* ---------------------------------------------------------------------------
137: Back to caller with status
138: --------------------------------------------------------------------------- */
139: status = SS$_NORMAL;
140: return ( status );
141: } /* --- end-of-function blogon() --- */
142: /* ------------------------ END-OF-FILE BLOGON.C -------------------------- */


BBBBBBBB   PPPPPPPP   RRRRRRRR     IIIIII     CCCCCCC  EEEEEEEEEE              CCCCCCC 
BBBBBBBBB  PPPPPPPPP  RRRRRRRRR    IIIIII    CCCCCCCCC EEEEEEEEEE             CCCCCCCCC
 BB     BB  PP     PP  RR     RR     II     CC      CC  EE     EE            CC      CC
 BBBBBBBB   PPPPPPPP   RRRRRRRR      II     CC          EEEEEE      .        CC        
 BBBBBBBB   PPPPPPP    RRRRRRR       II     CC          EEEEEE     ...       CC        
 BB     BB  PP         RR   RR       II     CC      CC  EE     EE .....      CC      CC
BBBBBBBBB  PPPP        RR    RR    IIIIII    CCCCCCCCC EEEEEEEEEE  ...        CCCCCCCCC
BBBBBBBB   PPPP        RR     RR   IIIIII     CCCCCCC  EEEEEEEEEE   .          CCCCCCC 

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Function:    bprice ( skt, msg, itrader )
  7:  *
  8:  * Purpose:     Sends a price message to all traders in the nodes[] table.
  9:  *
 10:  * Arguments:
 11:  *              skt (I)         addr of skt_control_struct needed to send
 12:  *                              price messages to other traders through
 13:  *                              bserver()'s datagram socket.
 14:  *
 15:  *              msg (I)         addr of msg_control_struct with SKT$_PRICEMSG
 16:  *                              opcode in its message header, and name of
 17:  *                              trader in sender field.
 18:  *
 19:  *              itrader (I)     int containing index of trader in nodes[] table.
 20:  *
 21:  * Returns:     (int)           SS$_NORMAL or error status.
 22:  *
 23:  * Notes:
 24:  *
 25:  * Source:      BPRICE.C
 26:  *
 27:  * --------------------------------------------------------------------------
 28:  * Revision History:
 29:  *
 30:  * 12/15/88     J.Forkosh       Installation.
 31:  * 02/13/89     J.Forkosh       Modified for Version 2.
 32:  *
 33:  ****************************************************************************/
 34: 
 35: /* ---------------------------------------------------------------------------
 36: Header files
 37: --------------------------------------------------------------------------- */
 38: /* --- standard vms headers --- */
 39: #include < stdio.h >
 40: /* --- Basis message headers --- */
 41: #include "bserver.h"
 42: #include "sktmsgdef.h"
 43: /* ------------------------------------------------------------------------ */
 44: 
 45: /* --- entry point --- */
 46: int     bprice ( skt, msg, itrader )
 47: struct  skt_control_struct *skt;
 48: struct  msg_control_struct *msg;
 49: int     itrader;
 50: {
 51: /* ---------------------------------------------------------------------------
 52: Allocations and Declarations
 53: --------------------------------------------------------------------------- */
 54: /* --- application-level message processing --- */
 55: struct  sktmsghdr_struct *msghdr, *replyhdr; /* interpret start of msg as hdr */
 56: struct  sktpricemsg_struct *pricemsg;   /* interpret msg as a pricemsg */
 57: int     opcode;                         /* and process it according to opcode */
 58: unsigned char *msgbuff;                 /* pointer to iobuff in message */
 59: int     msglen;                         /* #bytes in message iobuff */
 60: int     msgseqin;                       /* sequence # of incoming message */
 61: int     iquote, nquotes;                /* index, #quotes packed in price msg */
 62: /* --- nodes[] table variables --- */
 63: int     inode;                          /* index of traders receiving price */
 64: /* --- variables to construct outgoing price message --- */
 65: struct  skt_ioctl_struct *ioctl;        /* trader's TCP/IP return address */
 66: struct  msg_control_struct reply;       /* outgoing formatted reply */
 67: char    replybuff[SKT_MAXMSG];          /* allocated iobuff for reply */
 68: /* --- other variables --- */
 69: int     vms_stat;                       /* input message status */
 70: int     status;                         /* blogon() return status */
 71: char    *delim, *strchr(), *index();    /* to parse messsages */
 72: char    *strupper(), *trim(), *ltrim(); /* trim and toupper a string */
 73: char    *daytime();                     /* trader's last incoming msg time */
 74: /* ------------------------------------------------------------------------ */
 75: 
 76: /* ---------------------------------------------------------------------------
 77: Initialization
 78: --------------------------------------------------------------------------- */
 79: /* --- extract message fields and check message --- */
 80: vms_stat = msg->iosb.status;            /* i/o status of input message */
 81: if ( vms_stat != SS$_NORMAL )           /* some problem receiving it */
 82:         return ( vms_stat );            /* let caller figure out what to do */
 83: msgbuff = msg->iobuff;                  /* set pointer to actual msg */
 84: msglen = msg->msgsz;                    /* # bytes in received msg */
 85: msghdr = (struct sktmsghdr_struct *)(msgbuff);/* interpret hdr in msg */
 86: pricemsg = (struct sktpricemsg_struct *)(msgbuff);/* interpret as a price msg */
 87: msgseqin = msghdr->msgseqnum;           /* incoming message sequence number */
 88: opcode = msghdr->opcode;                /* and get opcode from hdr */
 89: if ( opcode != SKT$_PRICEMSG )          /* not my job (man) */
 90:         return ( SS$_BADPARAM );        /* let caller re-route it if he can */
 91: 
 92: /* ---------------------------------------------------------------------------
 93: Construct a local copy of the price message
 94: --------------------------------------------------------------------------- */
 95: /* --- copy communications envelope --- */
 96: memcpy ( (unsigned char *)(&reply), (unsigned char *)(msg),
 97:         sizeof(struct msg_control_struct) );    /* copy msg control */
 98: 
 99: /* --- copy the whole message (msghdr plus following sec_ids/prices) --- */
100: memcpy ( replybuff, msgbuff, msglen );  /* copy message to reply */
101: 
102: /* --- point reply to its new buffer and send it out --- */
103: reply.iobuff = replybuff;               /* point reply to its formatted buff */
104: reply.msgsz = msglen;                   /* and set size of reply */
105: replyhdr = (struct sktmsghdr_struct *)(replybuff);/* interpret hdr in msg */
106: 
107: /* ---------------------------------------------------------------------------
108: Send constructed price message to all traders in the nodes[] table
109: --------------------------------------------------------------------------- */
110: for ( inode=0; inode < ntraders; inode++ )
111:     {
112:     /* --- check for originator --- */
113:     if ( inode == itrader ) continue;   /* don't send price to ourselves */
114: 
115:     /* --- set reply's ioctl to that of the trader in the table --- */
116:     memcpy ( (unsigned char *)(&(reply.ioctl)),         /* ioctl in reply */
117:                 (unsigned char *)(&(nodes[inode].ioctl)), /* trader's ioctl */
118:                     sizeof(struct skt_ioctl_struct) );  /* #bytes in ioctl */
119: 
120:     /* --- need message sequence number for each trader --- */
121:     nodes[inode].msgseqout += 1;        /* bump last sequence number used */
122:     replyhdr->msgseqnum = nodes[inode].msgseqout;       /* and set new one */
123: 
124:     /* --- send the price message --- */
125:     vms_stat = sendsktw ( skt, &reply ); /* send reply to trader */
126:     if ( vms_stat != SS$_NORMAL )       /* failed to send reply */
127:         { if ( msglevel > 0 )           /* so print error message */
128:             printf( "\nbprice> trader=%s, sendsktw error=%s",
129:                 nodes[inode].trader, vmsmsg(vms_stat) );
130:           continue; }                   /* and try next trader */
131:     } /* --- end-of-for(inode) --- */
132: 
133: /* --- report price message --- */
134: if ( msglevel > 3 )
135:     printf ( "\nbprice> trader#%d=%s price msg, sec_id1=%s, price1=%lf at %s",
136:         itrader+1, msghdr->sender,
137:         pricemsg->quote[0].sec_id, pricemsg->quote[0].price, daytime(0) );
138: 
139: /* ---------------------------------------------------------------------------
140: Back to caller with status
141: --------------------------------------------------------------------------- */
142: status = SS$_NORMAL;
143: return ( status );
144: } /* --- end-of-function bprice() --- */
145: /* ------------------------ END-OF-FILE BPRICE.C -------------------------- */


BBBBBBBB   RRRRRRRR   EEEEEEEEEE   CCCCCCC       AA    LLLLL        CCCCCCC            
BBBBBBBBB  RRRRRRRRR  EEEEEEEEEE  CCCCCCCCC     AAAA   LLLLL       CCCCCCCCC           
 BB     BB  RR     RR  EE     EE CC      CC    AA  AA   LL        CC      CC           
 BBBBBBBB   RRRRRRRR   EEEEEE    CC           AA    AA  LL        CC           .       
 BBBBBBBB   RRRRRRR    EEEEEE    CC          AAAAAAAAA  LL        CC          ...      
 BB     BB  RR   RR    EE     EE CC      CC AAAAAAAAAA  LL     LL CC      CC .....     
BBBBBBBBB   RR    RR  EEEEEEEEEE  CCCCCCCCC AA      AA LLLLLLLLLL  CCCCCCCCC  ...      
BBBBBBBB    RR     RR EEEEEEEEEE   CCCCCCC  AA      AA LLLLLLLLLL   CCCCCCC    .       

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Function:    brecalc ( uptr, settlement, msg, nmsgs )
  7:  *
  8:  * Purpose:     Recalculates the computed variables of an issue in the universe
  9:  *              given a price message from the server.  (Unpacks the price
 10:  *              message and calls recalc() with each updated issue.)
 11:  *
 12:  * Arguments:
 13:  *              uptr (I)        addr of universe_struct
 14:  *                              pointing to the first issue in the universe.
 15:  *
 16:  *              settlement (I)  addr of char string containing settlement date
 17:  *                              to be used for reclaculation.
 18:  *
 19:  *              msg (I)         addr of msg_control_struct
 20:  *                              containing the price message.
 21:  *
 22:  *              nmsgs (O)       addr of int returning #quotes packed in msg
 23:  *                              (whether or not actually recalc-ed).
 24:  *
 25:  * Returns:     -int            #issues in message recalculated successfully,
 26:  *                              or -1 if some error.
 27:  *
 28:  * Source:      BRECALC.C
 29:  *
 30:  * --------------------------------------------------------------------------
 31:  * Revision History:
 32:  *
 33:  * 12/28/88     J.Forkosh       Installation.
 34:  * 02/13/89     J.Forkosh       Modified for Version 2.
 35:  * 02/16/89     J.Forkosh       Spread added to sktpricemsg.
 36:  *
 37:  ****************************************************************************/
 38: 
 39: /* -------------------------------------------------------------------------
 40: Header files
 41: -------------------------------------------------------------------------- */
 42: /* --- standard headers --- */
 43: #include < stdio.h >
 44: /* --- Basis message headers --- */
 45: #include "skt_header.h"
 46: #include "sktmsgdef.h"
 47: /* --- universe headers --- */
 48: #define BUNIVERSE
 49: #include "bglobals.h"
 50: #include "qdescrip.h"
 51: extern  int     msglevel;
 52: static  int     change_num = 0;
 53: /* --- switch to dynamically recalc --- */
 54: #define ISRECALC FALSE  /* only need to recalc just before dumping */
 55: /* ----------------------------------------------------------------------- */
 56: 
 57: /* --- entry point --- */
 58: int     brecalc ( uptr, settlement, msg, nmsgs )
 59: BUS     *uptr;
 60: char    *settlement;
 61: struct  msg_control_struct *msg;
 62: int     *nmsgs;
 63: {
 64: /* -------------------------------------------------------------------------
 65: Allocations and Declarations
 66: -------------------------------------------------------------------------- */
 67: /* --- application-level message processing --- */
 68: struct  sktmsghdr_struct *msghdr;       /* interpret start of msg as hdr */
 69: int     opcode;                         /* and process it according to opcode */
 70: struct  sktpricemsg_struct *pricemsg;   /* interpret msgbuff as a price msg */
 71: unsigned char *msgbuff;                 /* pointer to iobuff in message */
 72: int     iquote, nquotes, nrecalc;       /* index, #quotes packed in price msg */
 73: int     msglen, quolen;                 /* #bytes in quote[] part of msg */
 74: int     vms_stat;                       /* input message status */
 75: /* --- universe variables --- */
 76: int     iuniverse;                      /* index into universe structs */
 77: int     ipoy = 1;                       /* usually 1=have price, want yield */
 78: double  price, spread;                  /* price, spread from the message */
 79: double  diffprice, diffspread;          /* see if we really need a recalc */
 80: char    trader[32], qtime[32];          /* msghdr->sender field, time of quote*/
 81: char    sec_id[16];                     /* security id from the price message */
 82: BUS     *up;                            /* ptr to message's universe_struct */
 83: char    *daytime(), *atime();           /* timestamp to report errors */
 84: 
 85: /* ---------------------------------------------------------------------------
 86: Initialization
 87: --------------------------------------------------------------------------- */
 88: /* --- extract message fields and check message --- */
 89: *nmsgs = 0;                             /* nothing unpacked yet */
 90: vms_stat = msg->iosb.status;            /* i/o status of input message */
 91: if ( vms_stat != SS$_NORMAL )           /* some problem receiving it */
 92:         return ( vms_stat );            /* let caller figure out what to do */
 93: msgbuff = msg->iobuff;                  /* set pointer to actual msg */
 94: msglen = msg->msgsz;                    /* total #bytes in message */
 95: msghdr = (struct sktmsghdr_struct *)(msgbuff);/* interpret hdr in msg */
 96: opcode = msghdr->opcode;                /* and get opcode from hdr */
 97: if ( opcode != SKT$_PRICEMSG            /* not my job (man) */
 98: &&   opcode != SKT$_3PMPRICEMSG )
 99:         return ( SS$_BADPARAM );        /* let caller re-route it if he can */
100: memset ( trader, '\000', 31 );          /* make sure there's a null */
101: memcpy ( trader, msghdr->sender, 16 );  /* trader who sent pricemsg */
102: strcat ( trader, "        " );          /* pad to 8 chars */
103: trader[8] = '\000';                     /* 8-char max always followed by null */
104: strcpy ( qtime, atime() );              /* time at which we got quote */
105: strcat ( qtime, "        " );           /* pad to 8 chars */
106: qtime[8] = '\000';                      /* just make sure it's not too long */
107: pricemsg = (struct sktpricemsg_struct *)(msgbuff); /* ok, it's a price msg */
108: nquotes = pricemsg->nquotes;            /* #prices we'll have to update */
109: nrecalc = 0;                            /* no successful updates yet */
110: 
111: /* --- check that message size is consistent with #quotes reported --- */
112: msglen -= (sizeof(struct sktmsghdr_struct) + sizeof(int)); /*#bytes for quotes*/
113: quolen = nquotes*sizeof(struct sktquote_struct);  /*#bytes needed for nquotes*/
114: if ( quolen != msglen )                 /* oops, too much or too little */
115:     { if ( msglevel > 1 )
116:         printf("\nbrecalc> price msg from %s, #quotes=%d msglen=%d, at %s",
117:         msghdr->sender, nquotes,msglen, daytime(0) );
118:     if ( msglen < quolen )              /* take the smaller value to be safe */
119:         nquotes = msglen/sizeof(struct sktquote_struct); /*and maybe truncate*/
120:     } /* --- end-of-if(quolen!=msglen) --- */
121: 
122: /* -------------------------------------------------------------------------
123: Update Each quote in the order they're packed in the message
124: -------------------------------------------------------------------------- */
125: /* --- initialization before starting to unpack prices --- */
126: vms_stat == SS$_NORMAL;                 /* so far, so good */
127: change_num++;                           /* just a dummy counter for now */
128: 
129: /* --- loop over each quote --- */
130: for ( iquote=0; iquote < nquotes; iquote++ )
131:     {
132:     /* ---------------------------------------------------------------------
133:     Get universe pointer to issue being recalculated
134:     ---------------------------------------------------------------------- */
135:     /* --- extract price, spread and sec_id from the price message --- */
136:     price = pricemsg->quote[iquote].price; /* next price quote packed in msg */
137:     spread = pricemsg->quote[iquote].spread; /* and accompanying spread */
138:     memcpy ( sec_id, pricemsg->quote[iquote].sec_id, 6 ); /* and security id */
139:     sec_id[5] = '\000';                 /* make sure local copy has a null */
140:     /* --- look up the security id in our universe --- */
141:     iuniverse = ulookup ( _SEC_ID, uptr, sec_id ); /*universe index of sec_id*/
142:     if ( iuniverse < 0 )                /* price msg not in our universe */
143:         { if ( msglevel > 2 )
144:             printf("\nbrecalc> unidentified sec_id=%s received from %s at %s",
145:             sec_id, msghdr->sender, daytime(0) );
146:           vms_stat = SS$_BADPARAM;      /* set status for bad return */
147:           continue; }                   /* bad problem- universe out of synch */
148:     up = &(uptr[iuniverse]);            /* ptr to universe struct with sec_id */
149:     memset ( up->sec_trader, '\000', 9 ); /* null-fill trader field */
150:     memset ( up->sec_time,   '\000', 9 ); /* null-fill time field, too */
151:     strcpy ( up->sec_trader, trader );  /* latest trader sending a quote */
152:     strcpy ( up->sec_time,   qtime );   /* and time we got quote */
153: 
154:     /* ---------------------------------------------------------------------
155:     See if we really got new information in the quote
156:     ---------------------------------------------------------------------- */
157:     diffprice = price - up->computed.price; /* price difference */
158:     diffspread = spread - up->spread;   /* spread difference */
159:     if ( diffprice  < 0.0 ) diffprice  = (-(diffprice));  /* absolute value */
160:     if ( diffspread < 0.0 ) diffspread = (-(diffspread)); /* ditto */
161:     if ( diffprice < 0.00005            /* no price difference */
162:     &&   diffspread < 0.00005 )         /* no spread difference either */
163:         continue;                       /* so we can ignore this quote */
164: 
165:     /* ---------------------------------------------------------------------
166:     Format input params and issue call to recalc/poy
167:     ---------------------------------------------------------------------- */
168:     /* --- we always get price --- */
169:     up->computed.price = price;         /* set new price */
170:     up->spread = spread;                /* and spread */
171:     if ( *(up->sec_type) == '3' )       /* got a mortgage backed issue */
172:         { up->bid_val = price + ((double)unpkf(spread,1,15))/32.0;
173:           up->computed.yield = price - ((double)unpkf(spread,2,15))/32.0;
174:           up->indicators.m_type.price3 =
175:                 up->computed.yield - ((double)unpkf(spread,3,15))/32.0; }
176:     ipoy = 1;                           /* and flag to use it */
177:     if ( ISRECALC )                     /* bdumper() usually does recalc() */
178:         recalc ( up, ipoy, settlement, change_num, NULL ); /* do the recalc */
179:     else                                /* check life-high and -low locally */
180:         {
181:         if ( FALSE )                    /* only done at closing in recalc() */
182:           { if ( price > up->high_val ) up->high_val = price; /* got new high */
183:             if ( price < up->low_val ) up->low_val = price; } /* got new low */
184:         }
185:     nrecalc++;                          /* bump update count */
186:     } /* --- end-of-for(iquote) --- */
187: 
188: *nmsgs = nquotes;               /* #quotes in msg, whether or not recalc-ed */
189: return ( nrecalc );             /* #issues recalculated successfully */
190: } /* --- end-of-function brecalc() --- */
191: /* ------------------------- END-OF-FILE BRECALC.C ------------------------ */


BBBBBBBB   RRRRRRRR   EEEEEEEEEE   QQQQQQ   PPPPPPPP   RRRRRRRR     IIIIII     CCCCCCC 
BBBBBBBBB  RRRRRRRRR  EEEEEEEEEE  QQQQQQQQ  PPPPPPPPP  RRRRRRRRR    IIIIII    CCCCCCCCC
 BB     BB  RR     RR  EE     EE QQ      QQ  PP     PP  RR     RR     II     CC      CC
 BBBBBBBB   RRRRRRRR   EEEEEE    QQ      QQ  PPPPPPPP   RRRRRRRR      II     CC        
 BBBBBBBB   RRRRRRR    EEEEEE    QQ    Q QQ  PPPPPPP    RRRRRRR       II     CC        
 BB     BB  RR   RR    EE     EE QQ     QQQ  PP         RR   RR       II     CC      CC
BBBBBBBBB   RR    RR  EEEEEEEEEE  QQQQQQQQ  PPPP        RR    RR    IIIIII    CCCCCCCCC
BBBBBBBB    RR     RR EEEEEEEEEE   QQQQQQ Q PPPP        RR     RR   IIIIII     CCCCCCC 

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Function:    breqprice ( skt, uptr, msg, itrader )
  7:  *
  8:  * Purpose:     Sends a price message to the trader requesting it.
  9:  *              If the trader sends a price in his message,
 10:  *              then a reply is sent only if the server's current price
 11:  *              disagrees with the price sent by the trader.
 12:  *
 13:  * Arguments:
 14:  *              skt (I)         addr of skt_control_struct needed to send
 15:  *                              requested price message to the trader through
 16:  *                              bserver()'s datagram socket.
 17:  *
 18:  *              uptr (I)        addr of internal_universe_struct
 19:  *                              pointing to the first issue in the universe.
 20:  *
 21:  *              msg (I)         addr of msg_control_struct with SKT$_REQPRICEMSG
 22:  *                              opcode in its message header, and name of
 23:  *                              requesting trader in sender field.
 24:  *
 25:  *              itrader (I)     int containing index in nodes[] table of trader.
 26:  *
 27:  * Returns:     (int)           SS$_NORMAL or error status.
 28:  *
 29:  * Notes:
 30:  *
 31:  * Source:      BREQPRICE.C
 32:  *
 33:  * --------------------------------------------------------------------------
 34:  * Revision History:
 35:  *
 36:  * 12/29/88     J.Forkosh       Installation.
 37:  * 02/13/89     J.Forkosh       Modified for Version 2.
 38:  * 02/16/89     J.Forkosh       Spread field added to sktpricemsg.
 39:  *
 40:  ****************************************************************************/
 41: 
 42: /* ---------------------------------------------------------------------------
 43: Header files
 44: --------------------------------------------------------------------------- */
 45: /* --- standard vms headers --- */
 46: #include < stdio.h >
 47: /* --- Basis message headers --- */
 48: #include "bserver.h"
 49: #include "sktmsgdef.h"
 50: /* --- universe headers --- */
 51: #define BUNIVERSE
 52: #include "bglobals.h"
 53: /* ------------------------------------------------------------------------ */
 54: 
 55: /* --- entry point --- */
 56: int     breqprice ( skt, uptr, msg, itrader )
 57: struct  skt_control_struct *skt;
 58: BUS     *uptr;
 59: struct  msg_control_struct *msg;
 60: int     itrader;
 61: {
 62: /* ---------------------------------------------------------------------------
 63: Allocations and Declarations
 64: --------------------------------------------------------------------------- */
 65: /* --- application-level message processing --- */
 66: struct  sktmsghdr_struct *msghdr, *replyhdr; /* interpret start of msg as hdr */
 67: struct  sktpricemsg_struct *pricemsg;   /* interpret msgbuff as a price msg */
 68: unsigned char *msgbuff;                 /* pointer to iobuff in message */
 69: int     opcode;                         /* and process it according to opcode */
 70: int     msglen, quolen;                 /* #bytes in message iobuff */
 71: int     nquotes, iquote, nqreply;       /* index,#quotes in, #quotes in reply */
 72: /* --- universe variables --- */
 73: int     iuniverse;                      /* index into universe structs */
 74: double  oldprice, price, diffprice;     /* price from/to the message */
 75: double  oldspread, spread, diffspread;  /* spread from/to the message */
 76: int     isdiff;                         /* true if oldprice/sprd!=price/sprd */
 77: char    sec_id[16];                     /* security id from the price message */
 78: BUS     *up;                            /* ptr to message's universe_struct */
 79: /* --- variables to construct outgoing price message --- */
 80: struct  sktpricemsg_struct *replymsg;   /* interpret replybuff as a price msg */
 81: struct  msg_control_struct reply;       /* outgoing formatted reply */
 82: char    replybuff[SKT_MAXMSG];          /* allocated iobuff for reply */
 83: /* --- other variables --- */
 84: int     vms_stat;                       /* input message status */
 85: int     status;                         /* breqprice() return status */
 86: char    *delim, *strchr(), *index();    /* to parse messsages */
 87: char    *strupper(), *trim(), *ltrim(); /* trim and toupper a string */
 88: char    *daytime();                     /* trader's last incoming msg time */
 89: /* ------------------------------------------------------------------------ */
 90: 
 91: /* ---------------------------------------------------------------------------
 92: Initialization
 93: --------------------------------------------------------------------------- */
 94: /* --- extract message fields and check message --- */
 95: vms_stat = msg->iosb.status;            /* i/o status of input message */
 96: if ( vms_stat != SS$_NORMAL )           /* some problem receiving it */
 97:         return ( vms_stat );            /* let caller figure out what to do */
 98: msgbuff = msg->iobuff;                  /* set pointer to actual msg */
 99: msglen = msg->msgsz;                    /* # bytes in received msg */
100: msghdr = (struct sktmsghdr_struct *)(msgbuff);/* interpret hdr in msg */
101: opcode = msghdr->opcode;                /* and get opcode from hdr */
102: if ( opcode != SKT$_REQPRICEMSG )       /* not my job (man) */
103:         return ( SS$_BADPARAM );        /* let caller re-route it if he can */
104: pricemsg = (struct sktpricemsg_struct *)(msgbuff); /* req formatted as price */
105: nquotes = pricemsg->nquotes;            /* #price quotes requested by caller */
106: 
107: /* --- check size of message against #quotes supposedly in it --- */
108: msglen -= (sizeof(struct sktmsghdr_struct) + sizeof(int)); /*#bytes for quotes*/
109: quolen = nquotes*sizeof(struct sktquote_struct); /* #bytes needed for nquotes */
110: if ( msglen != quolen )
111:     { if ( msglevel > 1 )
112:         printf("\nbreqprice> sender=%s, #quotes=%d msglen=%d, at %s",
113:         msghdr->sender, nquotes,msglen, daytime(0) );
114:     if ( msglen < quolen )              /* take smaller # for safety */
115:         nquotes = msglen/sizeof(struct sktquote_struct); /*and maybe truncate*/
116:     } /* --- end-of-if(msglen!=quolen) --- */
117: 
118: /* ---------------------------------------------------------------------------
119: Construct a local copy of the price request message for skeleton reply
120: --------------------------------------------------------------------------- */
121: /* --- copy communications envelope --- */
122: memcpy ( (unsigned char *)(&reply), (unsigned char *)(msg),
123:         sizeof(struct msg_control_struct) );    /* copy msg control */
124: 
125: /* --- point reply to its new buffer --- */
126: reply.iobuff = replybuff;               /* point reply to its formatted buff */
127: reply.msgsz = 0;                        /* nothing to send yet */
128: 
129: /* --- pointer to format quotes in replybuff --- */
130: replymsg = (struct sktpricemsg_struct *)(replybuff); /* interpret as price */
131: replymsg->nquotes = nqreply = 0;        /* no quotes in reply yet */
132: 
133: /* --- re-format message header for reply --- */
134: replyhdr = (struct sktmsghdr_struct *)(replybuff); /* hdr in reply */
135: memset ( replyhdr->sender, '\000', 16 ); /* zero out sender */
136: strcpy ( replyhdr->sender, "BSERVER" ); /* identify ourselves */
137: replyhdr->opcode = SKT$_PRICEMSG;       /* place opcode for reply in hdr */
138: 
139: /* -------------------------------------------------------------------------
140: Now get a price reply for each price in caller's request
141: -------------------------------------------------------------------------- */
142: status = SS$_NORMAL;                    /* no problems yet */
143: for ( iquote=0; iquote < nquotes; iquote++ )
144:     {
145:     /* ---------------------------------------------------------------------
146:     Get universe pointer to requested issue and extract its price
147:     ---------------------------------------------------------------------- */
148:     /* --- extract and sec_id from the price request message --- */
149:     memcpy ( sec_id, pricemsg->quote[iquote].sec_id, 6 ); /* security id */
150:     sec_id[5] = '\000';                 /* make sure local copy has a null */
151:     oldprice = pricemsg->quote[iquote].price; /* ask price supplied by trader */
152:     oldspread = pricemsg->quote[iquote].spread; /* and ask-bid spread */
153: 
154:     /* --- look up the security id in our universe --- */
155:     iuniverse = ulookup ( _SEC_ID, uptr, sec_id ); /*universe index of sec_id*/
156:     if ( iuniverse < 0 )                /* price msg not in our universe */
157:         { status = SS$_BADPARAM;        /* bad problem- universe out of synch */
158:           continue; }                   /* try the next requested security */
159:     up = &(uptr[iuniverse]);            /* ptr to universe struct with sec_id */
160:     price = up->computed.price;         /* get the current ask price */
161:     spread = up->spread;                /* and ask-bid spread */
162: 
163:     /* --- next see if we need to send the already-formatted reply --- */
164:     isdiff = 1;                         /* assume we'll need to send price */
165:     diffprice = price - oldprice;       /* our price - trader's price */
166:     diffspread = spread - oldspread;    /* and spread */
167:     if ( diffprice < 0.0 ) diffprice = (-diffprice); /* absolute price diff */
168:     if ( diffspread < 0.0 ) diffspread = (-diffspread); /* and spread diff */
169:     if ( diffprice < 0.0005             /* no price difference */
170:     &&   diffspread < 0.0005 )          /* and no spread difference */
171:         isdiff = 0;                     /* so set flag not to send reply */
172: 
173:     /* --- pack the price into reply if we need it --- */
174:     if ( isdiff )                       /* we need it */
175:         {
176:         memcpy ( replymsg->quote[nqreply].sec_id, sec_id, 6 ); /* security id */
177:         replymsg->quote[nqreply].sec_id[5] = '\000'; /* null-terminated */
178:         replymsg->quote[nqreply].price = price; /* new ask price for security */
179:         replymsg->quote[nqreply].spread = spread; /* and ask-bid spread */
180:         nqreply++;                      /* bump count of quotes in reply */
181:         } /* --- end-of-if(isdiff) --- */
182:     } /* --- end-of-for(iquote) --- */
183: 
184: /* ---------------------------------------------------------------------------
185: Send constructed price message to requesting trader (if needed)
186: --------------------------------------------------------------------------- */
187: /* --- first report price request message --- */
188: if ( msglevel > 3 )
189:     printf ( "\nbreqprice> trader#%d=%s price request message at %s",
190:         itrader+1, msghdr->sender, daytime(0) );
191: 
192: /* --- send the price message --- */
193: if ( nqreply > 0 )                      /* only send if needed */
194:     {
195:     /* --- set #quotes and msgsz appropriately --- */
196:     replymsg->nquotes = nqreply;        /* # price quotes in this msg */
197:     reply.msgsz = sizeof(struct sktmsghdr_struct) /* size includes a msg hdr */
198:         + sizeof(int)                   /* plus an int for 'nquotes' */
199:         + nqreply*sizeof(struct sktquote_struct); /* plus all the quotes */
200:     /* --- get outgoing message sequence # if trader is lgged on --- */
201:     if ( itrader>=0 && itrader < ntraders ) /* get a new outgoing seq# */
202:         { nodes[itrader].msgseqout += 1;  /* bump last sequence number used */
203:           replyhdr->msgseqnum = nodes[itrader].msgseqout; } /* set new one */
204:     /* --- now send the message to him --- */
205:     vms_stat = sendsktw ( skt, &reply ); /* send reply to requesting trader */
206:     /* --- and check return status --- */
207:     if ( vms_stat != SS$_NORMAL )       /* failed to send reply */
208:         { if ( msglevel > 0 )           /* so print error message */
209:           printf( "\nbreqprice> trader=%s, sendsktw error=%s",
210:           msghdr->sender, vmsmsg(vms_stat) ); }
211:     } /* --- end-of-if(nqreply>0) --- */
212: 
213: /* ---------------------------------------------------------------------------
214: Back to caller with status
215: --------------------------------------------------------------------------- */
216: end_of_job:
217:     return ( status );
218: } /* --- end-of-function breqprice() --- */
219: /* ----------------------- END-OF-FILE BREQPRICE.C ------------------------ */


BBBBBBBB     SSSSSSS    CCCCCCC  LLLLL        OOOOOO     CCCCCCC  KKKK    KK           
BBBBBBBBB   SSSSSSSSS  CCCCCCCCC LLLLL       OOOOOOOO   CCCCCCCCC KKKK   KK            
 BB     BB SS         CC      CC  LL        OO      OO CC      CC  KK   KK             
 BBBBBBBB   SSSSSSS   CC          LL        OO      OO CC          KKKKKK      .       
 BBBBBBBB    SSSSSSS  CC          LL        OO      OO CC          KKKKK      ...      
 BB     BB         SS CC      CC  LL     LL OO      OO CC      CC  KK  KKK   .....     
BBBBBBBBB  SSSSSSSSS   CCCCCCCCC LLLLLLLLLL  OOOOOOOO   CCCCCCCCC KKKK   KK   ...      
BBBBBBBB    SSSSSSS     CCCCCCC  LLLLLLLLLL   OOOOOO     CCCCCCC  KKKK    KK   .       

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Function:    bsclock ( )
  7:  *
  8:  * Purpose:     Displays the clock and re-submits timer for next display.
  9:  *
 10:  * Arguments:   - none
 11:  *
 12:  * Returns:     -int            TRUE if successful (we assume it always is).
 13:  *
 14:  * Notes:     o Uses the global variable timr_reqidt declared extern in basis.h
 15:  *              and the global timer request table used by timrefn().
 16:  *              These cannot be passed as args because bsclock() is called
 17:  *              from the toolbox's getkey1() rotuine, which knows nothing
 18:  *              about Basis or its data structures.
 19:  *
 20:  * Source:      BSCLOCK.C
 21:  *
 22:  * --------------------------------------------------------------------------
 23:  * Revision History:
 24:  *
 25:  * 01/19/88     J.Forkosh       Installation.
 26:  * 02/09/89     J.Forkosh       Modified for Version 2.
 27:  *
 28:  ****************************************************************************/
 29: 
 30: /* -------------------------------------------------------------------------
 31: Header files
 32: -------------------------------------------------------------------------- */
 33: #define BCLOCK                  /* get clock globals */
 34: #include "bglobals.h"           /* has "extern int timr_reqidt", etc. */
 35: #include "basis.h"              /* includes toolbox stuff for display */
 36: #include "timrast.h"            /* extern timer table needed to reset state */
 37: /* ----------------------------------------------------------------------- */
 38: 
 39: /* --- entry point --- */
 40: int     bsclock ( )
 41: {
 42: /* -------------------------------------------------------------------------
 43: Allocations and Declarations
 44: -------------------------------------------------------------------------- */
 45: char    *atime();                       /* read the clock */
 46: char    msgbuff[64];                    /* clock buffer */
 47: int     itimer;                         /* index of request */
 48: struct  timrast_struct *preqidt;        /* pointer to request */
 49: 
 50: /* -------------------------------------------------------------------------
 51: Display the current wall clock time
 52: -------------------------------------------------------------------------- */
 53: strcpy ( msgbuff, atime() );            /* current time */
 54: msgbuff[8] = '\000';                    /* make sure it's not too long */
 55: prts(TIMR_ROW,TIMR_COL,FG,BG,msgbuff);  /* display hh:mm:ss */
 56: 
 57: /* -------------------------------------------------------------------------
 58: Resubmit the timer (state must be reset before resubmit, so we need table)
 59: -------------------------------------------------------------------------- */
 60: if ( timr_reqidt < 0 ) return ( FALSE ); /* trouble */
 61: itimer = cvtreqidt ( timr_reqidt );     /* table index for reqidt */
 62: preqidt = &(timrast_tbl[itimer]);       /* ptr to table entry for this index */
 63: preqidt->state = 0;                     /* reset state for timr_reqidt */
 64: timr_reqidt = timrefn ( timr_reqidt, 0, 0 ); /* and re-submit timer */
 65: return ( TRUE );                        /* back home */
 66: } /* --- end-of-function bsclock() --- */
 67: /* ------------------------- END-OF-FILE BSCLOCK.C ------------------------ */


BBBBBBBB     SSSSSSS  EEEEEEEEEE RRRRRRRR   VV      VV EEEEEEEEEE RRRRRRRR             
BBBBBBBBB   SSSSSSSSS EEEEEEEEEE RRRRRRRRR  VV      VV EEEEEEEEEE RRRRRRRRR            
 BB     BB SS          EE     EE  RR     RR VV      VV  EE     EE  RR     RR           
 BBBBBBBB   SSSSSSS    EEEEEE     RRRRRRRR  VV      VV  EEEEEE     RRRRRRRR    .       
 BBBBBBBB    SSSSSSS   EEEEEE     RRRRRRR    VV    VV   EEEEEE     RRRRRRR    ...      
 BB     BB         SS  EE     EE  RR   RR     VV  VV    EE     EE  RR   RR   .....     
BBBBBBBBB  SSSSSSSSS  EEEEEEEEEE  RR    RR     VVVV    EEEEEEEEEE  RR    RR   ...      
BBBBBBBB    SSSSSSS   EEEEEEEEEE  RR     RR     VV     EEEEEEEEEE  RR     RR   .       

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Program:     Bserver
  7:  *
  8:  * Purpose:     Main entry point for Basis Server process.
  9:  *
 10:  * Call:        $ bserver -mMSGLEVEL -dMINUTES -hHOST -sCMDSTR
 11:  *                        -bFILE -nFILE -aFILEN -cFILE -zFILE -fFILE
 12:  *              (where $bserver :== $sys$sysdevice:[]bserver.exe
 13:  *              has been installed as a foreign command)
 14:  *
 15:  * Command-line Arguments:
 16:  *
 17:  *              -mMSGLEVEL      controls level of reporting detail
 18:  *                              (should always be >0 unless no sys$output
 19:  *                              available for server)
 20:  *
 21:  *              -dMINUTES       interval in minutes at which to dump the
 22:  *                              universe files (<=0 means no dumps).
 23:  *
 24:  *              -hHOST          override default TCP/IP hostname
 25:  *                              (-hNONE for no UDP packets is the only
 26:  *                              option currently supported)
 27:  *
 28:  *              -sCMDSTR        command string spawned every interval minutes.
 29:  *
 30:  *              -b,...,-fFILE   specify filenames to override the defaults
 31:  *                              used for bills,...,futures.  If an extension
 32:  *                              is not supplied, ".PRM" is concatanated.
 33:  *
 34:  * Notes:       Before running bserver, the logical BRUN should be assigned
 35:  *              to the directory containing the Basis runtime images,
 36:  *              and BDAT should be assigned to the directory containing
 37:  *              the q?.prm data files.
 38:  *
 39:  * Source:      BSERVER.C
 40:  *
 41:  * --------------------------------------------------------------------------
 42:  * Revision History:
 43:  *
 44:  * 12/15/88     J.Forkosh       Installation.
 45:  * 02/13/89     J.Forkosh       Modified for Version 2.
 46:  *
 47:  ****************************************************************************/
 48: 
 49: /* ---------------------------------------------------------------------------
 50: Header files and other #define-ed Symbols
 51: --------------------------------------------------------------------------- */
 52: /* --- standard vms headers --- */
 53: #include < stdio.h >
 54: /* --- Server Defaults --- */
 55: #define MSGLEVEL 3                      /* default message level */
 56: #define CMDSTR  "@BRUN:BDUMPER.COM"     /* submit to timspawn() */
 57: #define INTERVAL 900                    /* every interval seconds */
 58: #define HOLIDAY_FILE    "BDAT:DATEFILE.DAT" /* holiday file for isbusday() */
 59: #define HOLIDAY_ICAL    1               /* default calendar number */
 60: /* --- Basis headers --- */
 61: #define BALLOCATE                       /* initialize tables and queues */
 62: #define BSERVER                         /* but only those for server */
 63: #include "bglobals.h"
 64: #include "skt_header.h"
 65: #include "msgqueue.h"
 66: #include "sktmsgdef.h"
 67: #include "bserver.h"
 68: #include "bdump.h"
 69: #include "qdescrip.h"
 70: /* ------------------------------------------------------------------------ */
 71: 
 72: /* --- entry point --- */
 73: main ( argc, argv)
 74: int     argc;
 75: char    *argv[];
 76: {
 77: /* ---------------------------------------------------------------------------
 78: Allocations and Declarations
 79: --------------------------------------------------------------------------- */
 80: /* --- communication-level message variables --- */
 81: struct  skt_control_struct *skt;        /* bserver's created socket */
 82: struct  msg_control_struct              /* --- messages --- */
 83:         *msg,                           /* incoming msg from queue */
 84:         reply;                          /* outgoing formatted reply */
 85: char    *msgbuff,                       /* ptr to iobuff in msg */
 86:         replybuff[SKT_MAXMSG];          /* allocated iobuff for reply */
 87: int     msglen, replylen;               /* length of message and reply */
 88: char    hostname[64] = "THIS VAX";      /*local copy of BGLOBALS.H for -hNONE*/
 89: /* --- application-level message processing --- */
 90: struct  sktmsghdr_struct *msghdr;       /* interpret beginning of msg as hdr */
 91: struct  sktmsg_struct *sktmsg;          /* default msg (e.g., for directives) */
 92: char    *dirbuff;                       /* directive buffer = sktmsg->msg */
 93: int     dirlen;                         /* #bytes in dirbuff */
 94: int     opcode;                         /* and process it according to opcode */
 95: int     msgseqin;                       /* incoming message sequence number */
 96: int     sendack;                        /* -1 or opcode of reply to the msg */
 97: int     tlen;                           /* length of sender/trader hdr field */
 98: int     itrader;                        /* index of msg sender in nodes[] tbl */
 99: char    trader[16];                     /* local copy of msghdr->sender */
100: /* --- internal universe data --- */
101: char    gsdnam[64] = GSDNAM,            /* name of universe global section */
102:         gsd3pmnam[64] = GSD3PMNAM;      /* section for 3PM/5PM closing prices */
103: int     pagcnt;                         /* # 512-byte pages in global section */
104: struct  bunshdr_struct *bunshdr, *buns3pmhdr; /* ctl struct before universe */
105: unsigned char *calloc(), *cup, *cup3pm; /* to allocate MAX_ISSUES buffers */
106: BUS     *up, *up3pm;                    /* universe ptr to calloc-ed buffers */
107: BUS     *uptr;                          /* and to a particular issue within */
108: char    settlement[64];                 /* settlement date used for recalc */
109: int     usize;                          /* #bytes in a universe struct */
110: int     utem;                           /* item = ulayout[utem].item */
111: int     iuniverse, nuniverse, nsorted;  /* number universe issues in memory */
112: int     iqtype, nloaded[16],ndumped[16]; /* # issues loaded for iqtype */
113: /* --- timspawn arguments --- */
114: int     interval = INTERVAL;            /* wake up timer every interval secs */
115: char    cmdstr[64] = CMDSTR;            /* and spawn this command string */
116: /* --- command-line argument processing --- */
117: int     ivalue;                         /* atoi(...) whenever needed */
118: int     iarg;                           /* counter over command-line switches */
119: char    *argptr, argop;                 /* ptr to argv[iarg], 1st char of arg */
120: /* --- other variables --- */
121: int     msgseqnum = 0;                  /* count of all messages received */
122: int     isdump;                         /* true if final dump needed at eoj */
123: int     iclose=(-1);                    /* closing 0=init, 1,2=3pm,5pm write */
124: int     vms_stat;                       /* vms status returns */
125: int     status;                         /* stat from message-processing funcs */
126: int     nquotes;                        /* #quotes in a price message */
127: char    errmsg[132] = "\000",           /* buffer for error message */
128:         infomsg[132], totrader[32];     /* buffers for binfo() calls */
129: char    *vmsmsg(),                      /* xlate vms_stat to string */
130:         *daytime();                     /* time stamp and secs since midnight */
131: char    *delim, *strchr(), *index();    /* to parse messsages */
132: char    *strupper(), *trim(), *ltrim(); /* trim and toupper a string */
133: /* ------------------------------------------------------------------------ */
134: 
135: /* ---------------------------------------------------------------------------
136: Server Initialization
137: --------------------------------------------------------------------------- */
138: /* --- defaults (unless over-ridden by command line args) --- */
139: msglevel = MSGLEVEL;                    /* set default message level */
140: isclosing = 0;                          /* not doing closing prices */
141: 
142: /* -------------------------------------------------------------------------
143: Universe Initialization
144: -------------------------------------------------------------------------- */
145: /* --- rescale ulayout[] from absolute address to offsets --- */
146: for ( utem=0; ulayout[utem].item >= 0; utem++ )
147:         ulayout[utem].offset -= (int)(&dummy_universe);
148: 
149: /* --------------------------------------------------------------------------
150: Get command-line args
151: -------------------------------------------------------------------------- */
152: /* ---Loop over each command-line argument --- */
153: for ( iarg=1; iarg < argc; iarg++ )     /* skip image name in argv[0] */
154:     {
155:     /* --- make sure arg is a switch and then use its 1st char as opcode --- */
156:     argptr = argv[iarg];                /* ptr to first char of this arg */
157:     if ( *argptr == '-' )               /* got a switched arg */
158:         argptr++;                       /* just skip over the dash */
159:     strupper(argptr);                   /* uppercase the whole argument */
160:     argop = toupper(*argptr++);         /* opcode is char after '-' */
161:     ivalue = atoi( argptr );            /* convert remainder of arg to int */
162: 
163:     /* --- first check for a q-filename for a universe data file --- */
164:     for ( iqtype=0; *(qtypes[iqtype])!='\000'; iqtype++ )
165:         { if ( argop == *(qtypes[iqtype]) ) /* opcode is a qtype */
166:             {
167:             strcpy ( qfiles[iqtype], argptr );  /* new universe file to open */
168:             if ( strchr(qfiles[iqtype],'.') == NULL ) /* no file extension */
169:                 strcat ( qfiles[iqtype], ".PRM" ); /* so use .PRM extension */
170:             goto next_iarg;             /* get next command-line arg */
171:             } /* --- end-of-if(opcode) --- */
172:         } /* --- end-of-for(iqtype) --- */
173: 
174:     /* --- else switch on argop tells us what kind of command we've got --- */
175:     switch ( argop )                    /* check the char following '-' */
176:         {
177:         /* --- Just ignore anything unrecognizable --- */
178:         default:                        /* got an unrecognized switch */
179:             if ( msglevel > 0 )         /* so print an error msg */
180:                 printf("\nbserver> unrecognized command-line switch=%c, arg=%s",
181:                 argop, argptr );
182:             break;
183:         /* --- message level --- */
184:         case 'M':
185:             if ( ivalue >= 0 )          /* 0 means no sys$output available */
186:                 msglevel = ivalue;
187:             break;
188:         /* --- new interval --- */
189:         case 'D':
190:             interval = 60*ivalue;       /* convert from mins to secs */
191:             break;
192:         /* --- new command string --- */
193:         case 'S':
194:             strcpy ( cmdstr, argptr );  /* copy new command string */
195:             break;
196:         /* --- -hNONE turns off TCP/IP --- */
197:         case 'H':
198:             strcpy ( hostname, argptr ); /* irrelevant unless NONE */
199:             break;
200:         } /* --- end-of-switch(argop) --- */
201: 
202:     next_iarg: ;
203:     }  /* --- end-of-for(iarg) --- */
204: 
205: /* ---------------------------------------------------------------------------
206: Zero out global tables and variables
207: --------------------------------------------------------------------------- */
208: /* --- clear #traders and table of logged-on traders --- */
209: ntraders = 0;                           /* no logon messages yet */
210: memset ( nodes, '\000', MAX_TRADERS*sizeof(struct node_control_struct) );
211: 
212: /* ---------------------------------------------------------------------------
213: Create socket for server and arm ast routine to receive first message
214: --------------------------------------------------------------------------- */
215: if ( memcmp(hostname,"NONE",4) )                /* if host not none */
216:     {
217:     /* --- create the socket --- */
218:     vms_stat = creskt ( &skt, "", SERVER_PORT ); /* try creating socket */
219:     if ( vms_stat != SS$_NORMAL )               /* can't proceed without it */
220:         { if ( msglevel > 0 )                   /* print termination message */
221:                 printf ( "\ncreskt> error=%s", vmsmsg(vms_stat) );
222:           exit ( vms_stat ); }                  /* and quit */
223: 
224:     /* --- arm ast so that first qio to socket is posted --- */
225:     vms_stat = recvskt ( skt );                 /* try arming ast */
226:     if ( vms_stat != SS$_NORMAL )               /* can't proceed without it */
227:         { if ( msglevel > 0 )                   /* print termination message */
228:                 printf( "\nrecvskt> error=%s", vmsmsg(vms_stat) );
229:           delskt ( skt, TRUE );                 /* close and deassign socket */
230:           exit ( vms_stat ); }                  /* and quit */
231:     } /* ---end-of-if(host!=none) --- */
232: 
233: /* -------------------------------------------------------------------------
234: Allocate universe buffers
235: -------------------------------------------------------------------------- */
236: /* --- map memory-resident universe buffers to global section --- */
237: usize = sizeof( BUS );
238: pagcnt = 2 + ( MAX_UNIVERSE*usize + sizeof(struct bunshdr_struct) )/512;
239: /* --- normal universe --- */
240: vms_stat = crmpsc ( gsdnam, pagcnt, &pbuns );
241: if ( /* vms_stat != SS$_NORMAL */       /* can't map to global section */
242: /* && */   vms_stat != SS$_CREATED )    /* and can't create it either */
243:         { /* --- quit if can't crmpsc() universe --- */
244:         if ( msglevel > 0 )
245:           printf ( "\nbserver> Can't crmpsc, err=%s", vmsmsg(vms_stat) );
246:         goto end_of_job; }
247: /* --- 3pm/5pm closing universe --- */
248: vms_stat = crmpsc ( gsd3pmnam, pagcnt, &p3pmbuns );
249: if ( /* vms_stat != SS$_NORMAL */       /* can't map to global section */
250: /* && */   vms_stat != SS$_CREATED )    /* and can't create it either */
251:         { /* --- quit if can't crmpsc() 3pm/5pm universe --- */
252:         if ( msglevel > 0 )
253:           printf ( "\nbserver> Can't crmpsc 3pm, err=%s", vmsmsg(vms_stat) );
254:         goto end_of_job; }
255: /* --- global section offset --- */
256: ivalue = (int)p3pmbuns - (int)pbuns;    /* offset between sections */
257: if ( msglevel > 0 )
258:     printf("\nbserver> global section offset: 3pm-normal = %d bytes.",ivalue);
259: /* --- initialize header --- */
260: bunshdr = (struct bunshdr_struct *)(pbuns); /* header preceding universe */
261: memset ( (unsigned char *)(bunshdr), '\000', sizeof(struct bunshdr_struct) );
262: bunshdr->nuniverse = 0;                 /* nothing loaded yet */
263: bunshdr->nupdates = 0;                  /* no update messages yet */
264: bunshdr->isdumping = 0;                 /* no dumps in progress yet */
265: bunshdr->isclosing = 0;                 /* not doing closing prices */
266: strcpy ( bunshdr->gsdnam, gsdnam );     /* tag the global section */
267: memset ( bunshdr->tstamp, '\000', 8 );  /* no time-stamp yet */
268: buns3pmhdr = (struct bunshdr_struct *)(p3pmbuns); /* hdr preceding 3pm univ */
269: strcpy ( buns3pmhdr->gsdnam, gsd3pmnam ); /* tag the 3pm global section */
270: /* --- initialize universe structs --- */
271: cup = pbuns + sizeof(struct bunshdr_struct); /* char ptr to universe buffers */
272: memset ( cup, '\000', usize*MAX_UNIVERSE ); /* clear universe buffers */
273: up = (BUS *)(cup);                      /* cup as universe ptr */
274: global_bus = up;                        /* normal universe available globally */
275: nuniverse = 0;                          /* no universe issues in memory yet */
276: cup3pm = p3pmbuns + sizeof(struct bunshdr_struct); /*char ptr to 3pm universe*/
277: up3pm = (BUS *)(cup3pm);                /*cup3pm as universe ptr*/
278: 
279: /* -------------------------------------------------------------------------
280: Initialize calendar
281: -------------------------------------------------------------------------- */
282: if ( setbusday ( HOLIDAY_FILE, HOLIDAY_ICAL )   /* init the calendar file */
283:  < 0 )                                          /* init failed */
284:     { if ( msglevel > 0 )
285:         printf ( "\nbserver> holiday file %s init failed.", HOLIDAY_FILE );
286:       goto end_of_job; }
287: 
288: /* -------------------------------------------------------------------------
289: Load initial universe data
290: -------------------------------------------------------------------------- */
291: for ( iqtype=0; *(qtypes[iqtype]) != '\000'; iqtype++ ) /* for each type */
292:     {
293:     nloaded[iqtype] = 0;                /* nothing loaded for qtype */
294:     *(bunshdr->qsettlements[iqtype]) = '\000'; /* no settlement for qtype */
295:     if ( *(qfiles[iqtype]) != '\000' )  /* check that we have filename */
296:         {
297:         /* --- load file contents --- */
298:         nloaded[iqtype] = qload ( qtypes[iqtype], qfiles[iqtype],
299:                           &up[nuniverse], &(bunshdr->qsettlements[iqtype][0]) );
300:         if ( nloaded[iqtype] > 0 )      /* if we loaded anything from file */
301:           { nuniverse += nloaded[iqtype]; /* bump total buffered issues count */
302:             if ( memcmp(bunshdr->qsettlements[iqtype],"00/00/00",8) ) /*settle*/
303:               strcpy ( settlement, bunshdr->qsettlements[iqtype] ); } /*if got*/
304:         if ( msglevel > 1 )             /* display number of issues loaded */
305:             { printf ( "\nbserver> %d %s-issues loaded from %s for %s",
306:                 nloaded[iqtype], qtypes[iqtype], qfiles[iqtype],
307:                 bunshdr->qsettlements[iqtype] ); }
308:         } /* --- end-of-if(*qfiles[iqtype]) --- */
309:     } /* --- end-of-for(*qtypes[iqtype]) --- */
310: 
311: /* --- sort the universe for binary search in ulookup() --- */
312: global_bus = up;                        /* normal universe available globally */
313: global_nbus = nuniverse;
314: nsorted = sort_universe ( 1 );
315: if ( nsorted != nuniverse )
316:     { if ( msglevel > 0 )
317:         printf ( "\nbserver> failed to sort universe." );
318:       goto end_of_job; }
319: 
320: /* --- dummy trailing issue at end of universe to indicate end-of-list --- */
321: uptr = &up[nuniverse];                  /* ptr to trailing universe issue */
322: memset ( (unsigned char *)uptr, '\000', usize ); /* zero-fill entire issue */
323: strcpy ( uptr->sec_id, END_OF_DATA );   /* copy #define-ed end-of-universe id */
324: 
325: /* --- set global control structure --- */
326: bunshdr->nuniverse = nuniverse;         /* #loaded issues in universe */
327: global_nbus = nuniverse;                /* also available globally */
328: 
329: /* -------------------------------------------------------------------------
330: Initialize universe control information as necessary
331: -------------------------------------------------------------------------- */
332: for ( iuniverse=0; iuniverse < nuniverse; iuniverse++ )
333:     {
334:     uptr = &up[iuniverse];
335:     /* --- set change number --- */
336:     uptr->change_num = 0;               /* not (yet) vital for server */
337:     /* --- initialization recalculation of universe --- */
338:     recalc ( uptr, 1, settlement, -1, NULL );
339:     /* --- print universe --- */
340:     if ( msglevel > 6                   /* if print wanted */
341:     && ( iuniverse<=9 || iuniverse>=nuniverse-10 ) ) /* 1st and last 10 only */
342:         printf("\nbserver> index#%d: id=%s, issdat=%s, matdat=%s, coupon=%lf",
343:         iuniverse+1, uptr->sec_id,uptr->iss_date,uptr->mat_date,uptr->coupon );
344:     } /* --- end-of-for(iuniverse) --- */
345: 
346: /* ---------------------------------------------------------------------------
347: Set timer if requested (cmdstr presumably dumps the database at every interval)
348: --------------------------------------------------------------------------- */
349: if ( interval > 0 )
350:         {
351:         vms_stat = timspawn ( interval, cmdstr );
352:         if ( vms_stat != SS$_NORMAL )
353:             { if ( msglevel > 0 )
354:                 printf ( "\nbserver> timspawn err=%s", vmsmsg(vms_stat) );
355:             }
356:         } /* --- end-of-if(interval>0) --- */
357: 
358: /* ---------------------------------------------------------------------------
359: Wait for received messages and process them
360: --------------------------------------------------------------------------- */
361: while ( 1 )
362:     {
363: 
364:     /* -----------------------------------------------------------------------
365:     Event flag will be set by ast as soon as it queues a message for processing
366:     ----------------------------------------------------------------------- */
367:     if ( MSGQUEUEFLAG >= 0 )                    /* ast will set this flag */
368:         { /* --- wait for ast to tell us that at least one msg is queued --- */
369:         vms_stat = sys$waitfr ( MSGQUEUEFLAG ); /* wait for ast to set flag */
370:         if ( vms_stat != SS$_NORMAL )           /* make sure flag set ok */
371:             { if ( msglevel > 0 )               /* else print termination msg */
372:                 printf( "\nwaitfr> error=%s", vmsmsg(vms_stat) );
373:               goto end_of_job; }                /* and quit */
374:         vms_stat = sys$clref ( MSGQUEUEFLAG );  /* flag ok, so reset it quick */
375:         if ( vms_stat != SS$_WASSET )           /* oops, flag wasn't set */
376:             { if ( msglevel > 0 )               /* print termination message */
377:                 printf( "\nclref> error=%s", vmsmsg(vms_stat) );
378:               goto end_of_job; }                /* and quit */
379:         } /* --- end-of-if(MSGQUEUEFLAG) --- */
380: 
381:     /* -----------------------------------------------------------------------
382:     Dequeue and process all pending messages
383:     ----------------------------------------------------------------------- */
384:     while ( iqueued != idequeued )
385:         { /* --- we've caught up to queue when indexes match --- */
386: 
387:         /* -------------------------------------------------------------------
388:         Check next available message (and bump queue index)
389:         ------------------------------------------------------------------- */
390:         msgseqnum++;                            /* bump total message count */
391:         msg = &(msgqueue[idequeued]);           /* pointer to queued message */
392:         idequeued++;                            /* got msg so bump queue */
393:         if ( idequeued >= MAXMSGQUEUE )         /* but when we reach end */
394:                 idequeued = 0;                  /* wrap to beginning of queue */
395:         vms_stat = msg->iosb.status;            /* i/o status of this message */
396:         if ( vms_stat != SS$_NORMAL )           /* some problem receiving it */
397:             { if ( msglevel > 0 )               /* so print error message */
398:                 printf( "\nqueue#%d> error=%s", idequeued,vmsmsg(vms_stat) );
399:               continue; }                       /* and try next message */
400:         msgbuff = msg->iobuff;                  /* set pointer to actual msg */
401:         msglen = msg->msgsz;                    /* # bytes in received msg */
402:         sendack = (-1);                         /* no reply formatted yet */
403: 
404:         /* -------------------------------------------------------------------
405:         Look up sender, check incoming seq#, and update his nodes[] table entry
406:         ------------------------------------------------------------------- */
407:         msghdr = (struct sktmsghdr_struct *)(msgbuff);/* interpret hdr in msg */
408:         sktmsg = (struct sktmsg_struct *)(msgbuff); /* interpret default msg */
409:         msgseqin = msghdr->msgseqnum;           /* incoming message sequence# */
410:         opcode = msghdr->opcode;                /* and get opcode from hdr */
411:         memcpy ( trader, msghdr->sender, 16 );  /* max 16-byte field */
412:         trader[15] = '\000';                    /* should already have a null */
413:         strupper(trim(ltrim(trader)));          /* trim space & uppercase */
414:         tlen = strlen ( trader );               /* number of chars remaining */
415:         itrader = (-1);                         /* haven't found trader yet */
416: 
417:         if ( opcode != SKT$_LOGONMSG )          /* can't lookup if not on yet */
418:           { /* --- anyone logged on should be in table --- */
419:           for ( itrader=0; itrader < ntraders; itrader++ )
420:             { /* --- find mathcing trader in nodes[] --- */
421:             if ( memcmp (trader,nodes[itrader].trader,tlen) ) /* not a match */
422:                 continue;                       /* so try the next nodes[] */
423:             /* --- check sequence number of incoming message for trader --- */
424:             if ( msgseqin != 1 + nodes[itrader].msgseqin ) /* wanted next # */
425:                 if ( msglevel > 1 )     /* report error if we didn't get it */
426:                     printf ("\nbserver> trader#%d=%s, got msg#%d expected #%d.",
427:                     itrader,trader, msgseqin, 1+nodes[itrader].msgseqin );
428:             nodes[itrader].msgseqin = msgseqin; /* always reset sequence # */
429:             /* --- record incoming message time --- */
430:             daytime ( &(nodes[itrader].insecs) ); /* 100ths secs since 12am */
431:             break;                              /* itrader entry updated */
432:             } /* --- end-of-for(itrader) --- */
433:           if ( itrader >= ntraders )            /* failed to find trader */
434:             { if ( msglevel > 0 )               /* so print error message */
435:                 printf("\nbserver> msg from sender=%s, not logged on.",trader);
436:               itrader = (-1);                   /* reset index "not found" */
437:             } /* --- end-of-if(itrader) --- */
438:           } /* --- end-of-if(opcode) --- */
439: 
440:         /* -------------------------------------------------------------------
441:         Process dequeued message by opcode in its header
442:         ------------------------------------------------------------------- */
443:         switch ( opcode )
444:             { /* --- decide who gets to process the message --- */
445:             default:                            /* no one seems to want it */
446:                 if ( msglevel > 0 )             /* so print error message */
447:                     printf( "\nqueue#%d> unrecognized opcode=%d, trader=%s",
448:                         idequeued, opcode, trader );
449:                 sendack = SKT$_NAKMSG;          /* nak the message */
450:                 break;
451: 
452:             /* --- logon message --- */
453:             case SKT$_LOGONMSG:                 /* new trader just ran Basis */
454:                 status = blogon ( msg, &itrader ); /* update the nodes table */
455:                 if ( status == SS$_NORMAL )     /* logon successful */
456:                     { sprintf ( infomsg,
457:                         "Welcome to Basis.  Logged on as %s (%d other users",
458:                         trader, ntraders-1 );
459:                       if ( ntraders > 1 )
460:                         { strcat ( infomsg, ":" );
461:                         for ( ivalue=0; ivalue < ntraders; ivalue++ )
462:                             { if ( ivalue == itrader ) continue;
463:                               if ( strlen(infomsg) > 55 )
464:                                 { strcat ( infomsg, " etc" ); break; }
465:                               sprintf(infomsg+strlen(infomsg)," %s",
466:                                 nodes[ivalue].trader ); }
467:                         } /* --- end-of-if(ntraders>1) --- */
468:                       strcat ( infomsg, ")." );
469:                       binfo ( skt, infomsg, -1, trader); }
470:                 else { sendack = SKT$_NAKMSG;   /* target will reset ishostup */
471:                 /*binfo(skt,"Logon failed (probably duplicate).",-1,trader);*/ }
472:                 break;
473: 
474:             /* --- logoff message --- */
475:             case SKT$_LOGOFFMSG:                /* old trader just exited */
476:                 status = blogoff ( msg, &itrader ); /* update the nodes table */
477:                 if ( status != SS$_NORMAL )     /* failed to logoff */
478:                         sendack = SKT$_NAKMSG;
479:                 break;
480: 
481:             /* --- price message --- */
482:             case SKT$_PRICEMSG:                 /* trader changed a price */
483:                 status = brecalc ( up, settlement, msg, &nquotes ); /* update */
484:                 if ( status > 0 )               /* actually got new data */
485:                     { (bunshdr->nupdates)++;    /* bump update count */
486:                       status = bprice ( skt, msg, itrader ); } /* send info */
487:                 else status = SS$_NORMAL;       /* just flip status to ok */
488:                 if ( status != SS$_NORMAL )     /* some problem with update */
489:                     { if ( msglevel > 0 ) /* print err msg if failed */
490:                         printf("\nbserver> recalc/bprice error for trader %s",
491:                         trader);
492:                       sendack = SKT$_NAKMSG; }
493:                 break;
494: 
495:             /* --- 3pm/5pm closing price message --- */
496:             case SKT$_3PMPRICEMSG:              /* trader sent closing price */
497:                 if ( isclosing )                /* accepting closing prices */
498:                     { if ( itrader>=0 && itrader < ntraders ) /* if identified */
499:                         { if ( nodes[itrader].isclosed > 0 ) /*and prev close*/
500:                             { nodes[itrader].isclosed = 0; /* then reset flag */
501:                               nodes[itrader].nissues = 0; } /*and reset count*/
502:                         } /* --- end-of-if(0 <= itrader < ntraders) --- */
503:                       status = brecalc ( up3pm, settlement, msg, &nquotes );
504:                       if ( status >= 0 ) nodes[itrader].nissues += nquotes;
505:                       else                      /* bump #recv'd or report err */
506:                         { sendack = SKT$_NAKMSG; /* couldn't recalc so nak it */
507:                           if ( msglevel > 0 )   /* print err msg if failed */
508:                             printf( "\nbserver> 3pm recalc error for trader %s",
509:                             trader ); }
510:                       /* --- easy way out: trader closed with any 3pm msg --- */
511:                       if ( itrader>=0 && itrader < ntraders ) /* if identified */
512:                         /* (nodes[itrader].isclosed)++ */; /* mark him closed */
513:                     } /* --- end-of-if(isclosing) --- */
514:                 else                            /* not accepting closing data */
515:                     { /* status = binfo ( skt, "Not accepting closing prices",
516:                                 -1, trader ) */ ; } /* so reject msg */
517:                 break;
518: 
519:             /* --- closing message --- */
520:             case SKT$_3PMCLOSEMSG:              /* all trader prices sent */
521:                 if ( itrader>=0 && itrader < ntraders )   /* trader identified */
522:                    { if ( isclosing )           /* and we're closing */
523:                       { nodes[itrader].isclosed = 99;   /* so mark him closed */
524:                         sprintf ( infomsg, "%d closing prices accepted.",
525:                                 nodes[itrader].nissues );
526:                         binfo ( skt, infomsg, -1, trader ); }
527:                      else binfo ( skt, "Not accepting closing prices",
528:                         -1, trader );           /* not closing, reject msg */
529:                     } else sendack = SKT$_NAKMSG; /* if no id, nak the msg */
530:                 if ( msglevel > 2 )
531:                     printf ( "\nbserver> closing message from trader=%s at %s",
532:                     trader,daytime(0) );
533:                 break;
534: 
535:             /* --- request for price message --- */
536:             case SKT$_REQPRICEMSG:              /* trader wants current price */
537:                 status = breqprice ( skt, up, msg, itrader ); /*send to trader*/
538:                 if ( status != SS$_NORMAL )     /* breqprice() failed */
539:                         sendack = SKT$_NAKMSG;
540:                 break;
541: 
542:             /* --- info message (distribute to everybody) --- */
543:             case SKT$_INFOMSG:                  /* send informational text */
544:                 strcpy ( infomsg, sktmsg->msg ); /* local copy of message */
545:                 *totrader = '\000';             /* default to all traders */
546:                 delim = strchr(infomsg,':');    /* format is trader:message */
547:                 if ( delim != NULL )            /* found a colon somewheres */
548:                   if ( delim-infomsg <= 6 )     /* max 6-char trader name */
549:                     { *delim = '\000';          /* null terminate trader name */
550:                       strcpy ( totrader, infomsg ); /* copy leading name */
551:                       strcpy ( infomsg, delim+1 ); } /* and shift message */
552:                 status = binfo ( skt, infomsg, itrader, totrader );/*send info*/
553:                 if ( status != SS$_NORMAL )     /* binfo() failed */
554:                         sendack = SKT$_NAKMSG;
555:                 break;
556: 
557:             /* --- directive messages --- */
558:             case SKT$_DIRECTIVEMSG:
559:                 dirlen = msglen - sizeof(struct sktmsghdr_struct);/*dirbuff sz*/
560:                 if ( dirlen < 0 ) dirlen = 0;   /* just to be safe */
561:                 dirbuff = sktmsg->msg;          /* use dirbuff as ptr to text */
562:                 dirbuff[dirlen] = '\000';       /* null-terminate msg text */
563:                 strupper ( dirbuff );           /* uppercase the text */
564:                 if ( msglevel > 1 )
565:                     printf("\nbserver> directive=%s from %s at %s",
566:                     dirbuff, trader, daytime(0) );
567:                 /* --- immediate exit --- */
568:                 if ( !memcmp(dirbuff,"EXIT",4) ) /* got an exit directive */
569:                     { babort(skt,"ALL","Server is exiting."); /* zap traders */
570:                       goto end_of_job; }        /* so exit immediately */
571:                 /* --- abort traders --- */
572:                 if ( !memcmp(dirbuff,"ABOR",4) ) /* got an abort directive */
573:                     { delim = strchr(dirbuff,'='); /* want "abort=xxx" */
574:                       if ( delim != NULL )      /* found '=' as expected */
575:                         babort(skt,delim+1,"Server is logging you off."); }
576:                 /* --- reset message level --- */
577:                 if ( !memcmp(dirbuff,"MSGL",4) ) /* got a msglevel directive */
578:                     { delim = strchr(dirbuff,'='); /* want "msglevel=xxx" */
579:                       if ( delim != NULL )      /* found '=' as expected */
580:                         msglevel = atoi(delim+1); } /* set msglevel as asked */
581:                 /* --- start closing procedures --- */
582:                 if ( !memcmp(dirbuff,"CLOS",4) ) /* got a closing directive */
583:                     { iclose = 0;               /* default if no delim */
584:                       delim = strchr(dirbuff,'='); /* want "close=[0,1,2]" */
585:                       if ( delim != NULL )      /* found '=' as expected */
586:                         iclose = atoi(delim+1); /* set iclose as asked */
587:                       if ( iclose<0 || iclose>2 ) /* bad close argument */
588:                         { sendack = SKT$_NAKMSG;  /* so nak it */
589:                           break; }              /* and forget bclose() call */
590:                       status = bclose ( skt, iclose ); /* call bclose() */
591:                       if ( status < 0 )         /* failed to close */
592:                         { ; /* note: bclose() already re-submitted itself */
593:                         } /* --- end-of-if(status<0) --- */
594:                     } /* --- end-of-if("CLOSING") --- */
595:                 break;
596:             } /* --- end-of-switch(opcode) --- */
597: 
598:         /* -------------------------------------------------------------------
599:         Send formatted reply (if there is one)
600:         ------------------------------------------------------------------- */
601:         if ( sendack > 0 )              /* got some kind of reply to message */
602:             {
603:             /* --- copy communications envelope so reply echoes to sender --- */
604:             memcpy ( (unsigned char *)(&reply), (unsigned char *)(msg),
605:                 sizeof(struct msg_control_struct) );    /* copy msg control */
606: 
607:             /* --- copy the whole message (msghdr plus following) --- */
608:             memcpy ( replybuff, msgbuff, msglen );      /* and message */
609:             replylen = msglen;          /* duplicate reply=msg length */
610: 
611:             /* --- need next outgoing sequence number --- */
612:             msghdr = (struct sktmsghdr_struct *)(replybuff); /* hdr in reply */
613:             if ( itrader >= 0 )         /* trader logged on */
614:                 { nodes[itrader].msgseqout += 1; /* next sequence # for msg */
615:                   msghdr->msgseqnum = nodes[itrader].msgseqout; }
616: 
617:             /* --- now re-format rest of message header for reply --- */
618:             memset ( msghdr->sender, '\000', 16 );      /* zero out sender */
619:             strcpy ( msghdr->sender, "BSERVER" );       /* identify ourselves */
620:             msghdr->opcode = sendack;   /* place opcode for reply in hdr */
621: 
622:             /* --- point reply to its new buffer and send it out --- */
623:             reply.iobuff = replybuff;   /* point reply to its formatted buff */
624:             reply.msgsz = replylen;     /* and set size of reply */
625:             vms_stat = sendsktw ( skt, &reply ); /* send reply to trader */
626:             if ( vms_stat != SS$_NORMAL ) /* failed to send reply */
627:                 { if ( msglevel > 0 )   /* so print error message */
628:                     printf( "\nsendsktw> error=%s", vmsmsg(vms_stat) );
629:                   continue; }           /* and try next message */
630:             } /* --- end-of-if(sendack) --- */
631: 
632:         /* -------------------------------------------------------------------
633:         Continue till current message queue exhausted
634:         ------------------------------------------------------------------- */
635:         /* --- release malloc-ed memory after processing message --- */
636:         if ( !ISMSGBUFFSTATIC )         /* buffers aren't static */
637:             { if ( msg->iobuff != 0 )   /* shouldn't be since we just did it */
638:                 { free ( msg->iobuff ); /* so free the malloc-ed buffer */
639:                   msg->iobuff = 0; }    /* and reset its pointer */
640:             } /* --- end-of-if(!static) --- */
641:         } /* --- end-of-while(iqueued) --- */
642: 
643:     /* -----------------------------------------------------------------------
644:     Then wait (on event flag) for ast to supply new messages in queue
645:     ----------------------------------------------------------------------- */
646:     } /* --- end-of-while(1) --- */
647: 
648: /* ---------------------------------------------------------------------------
649: End-of-Job
650: --------------------------------------------------------------------------- */
651: end_of_job:
652:     /* -----------------------------------------------------------------------
653:     Rewrite universe files if necessary
654:     ----------------------------------------------------------------------- */
655:     /* --- see whether or not local dump needed --- */
656:     isdump =    ( !(bunshdr->isdumping) /* dump already in progress */
657:                 && ((bunshdr->nupdates) > 0) /* and got something new to dump */
658:                 )? 1 : 0;
659:     /* --- perform the dump if necessary --- */
660:     if ( isdump )               /* flag requesting universe dump set */
661:       {
662:       if ( msglevel > 0 )
663:         printf ( "\nbserver> performing final dump at %s", daytime(0) );
664:       bunshdr->isdumping = 1;   /* set dumping-in-progress flag */
665:       bunshdr->nupdates = 0;    /* and reset #updates counter */
666:       for ( iqtype=0; *(qtypes[iqtype]) != '\000'; iqtype++ )
667:         {
668:         if ( *(qfiles[iqtype]) == '\000' ) continue; /* no file */
669:         if ( nloaded[iqtype] <= 0 ) continue; /* nothing loaded */
670:         /* --- check settlement date --- */
671:         if ( memcmp(bunshdr->qsettlements[iqtype],"00/00/00",8) ) /*got a date*/
672:             strcpy ( settlement, bunshdr->qsettlements[iqtype] ); /*so use it*/
673:         /* --- update all issues in universe of current type --- */
674:         for ( iuniverse=0; iuniverse < nuniverse; iuniverse++ )
675:             if ( *(up[iuniverse].sec_type) == *(qtypes[iqtype]) )
676:                 recalc ( &(up[iuniverse]), 1, settlement, -1, NULL );
677:         /* --- dump the updated universe --- */
678:         ndumped[iqtype] =
679:                 qdump ( qtypes[iqtype], qfiles[iqtype],qfiles[iqtype],
680:                         &up[0], &(bunshdr->qsettlements[iqtype][0]), TRUE );
681:         if ( msglevel > 1 )     /* display number of issues dumped */
682:             { printf ( "\nbserver> %d %s-issues dumped to %s at %s",
683:                 ndumped[iqtype], qtypes[iqtype], qfiles[iqtype], daytime(0) ); }
684:         } /* --- end-of-for(*qtypes[iqtype]) --- */
685:     /* Note: leave the bunshdr->isdumping flag set after completion,
686:         just in case bdumper is spawned one more time after bserver exits. */
687:     } /* --- end-of-if(isdump) --- */
688: 
689:     /* -----------------------------------------------------------------------
690:     Finish end-of-job housekeeping
691:     ----------------------------------------------------------------------- */
692:     delskt ( skt, TRUE );               /* close and deassign socket */
693:     if ( msglevel > 0 )
694:         printf("\nbserver> exiting at %s",daytime(0));
695:     exit ( vms_stat );                  /* exit with SS$_NORMAL or error */
696: } /* --- end-of-program main() for Basis Server process --- */
697: /* ------------------------- END-OF-FILE BSERVER.C -------------------------- */


BBBBBBBB     SSSSSSS  EEEEEEEEEE RRRRRRRR   VV      VV EEEEEEEEEE RRRRRRRR             
BBBBBBBBB   SSSSSSSSS EEEEEEEEEE RRRRRRRRR  VV      VV EEEEEEEEEE RRRRRRRRR            
 BB     BB SS          EE     EE  RR     RR VV      VV  EE     EE  RR     RR           
 BBBBBBBB   SSSSSSS    EEEEEE     RRRRRRRR  VV      VV  EEEEEE     RRRRRRRR    .       
 BBBBBBBB    SSSSSSS   EEEEEE     RRRRRRR    VV    VV   EEEEEE     RRRRRRR    ...      
 BB     BB         SS  EE     EE  RR   RR     VV  VV    EE     EE  RR   RR   .....     
BBBBBBBBB  SSSSSSSSS  EEEEEEEEEE  RR    RR     VVVV    EEEEEEEEEE  RR    RR   ...      
BBBBBBBB    SSSSSSS   EEEEEEEEEE  RR     RR     VV     EEEEEEEEEE  RR     RR   .       

  1: #ifndef _BSERVER
  2: #define _BSERVER
  3: /****************************************************************************
  4:  *
  5:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  6:  * --------------------------------------------------------------------------
  7:  *
  8:  * Header:      bserver.h
  9:  *
 10:  * Purpose:     Defines structures that the server uses
 11:  *              to manage communications among the trader population.
 12:  *
 13:  * Notes:     o
 14:  *
 15:  * Source:      BSERVER.H
 16:  *
 17:  * --------------------------------------------------------------------------
 18:  * Revision History:
 19:  *
 20:  * 12/15/88     J.Forkosh       Installation.
 21:  *
 22:  ****************************************************************************/
 23: 
 24: /* --------------------------------------------------------------------------
 25: Need socket header for ioctl structure (which identifies a TCP/IP target)
 26: -------------------------------------------------------------------------- */
 27: #ifndef _SKTHEADER
 28: #include "skt_header.h"
 29: #endif
 30: 
 31: /* --------------------------------------------------------------------------
 32: See whether we're defining or referring to global tables/variables
 33: -------------------------------------------------------------------------- */
 34: #ifdef BALLOCATE
 35: #define BEXTERN         /* globaldef */
 36: #else
 37: #define BEXTERN         extern
 38: #endif
 39: 
 40: /* --------------------------------------------------------------------------
 41: These symbols define default server parameters
 42: -------------------------------------------------------------------------- */
 43: /* --- program flow control --- */
 44: BEXTERN int             msglevel;               /* level of reporting detail */
 45: BEXTERN int             isclosing;              /* true while 3pm/5pm prices */
 46: 
 47: /* --- number of traders --- */
 48: #define MAX_TRADERS     96                      /* max # logged-on traders */
 49: BEXTERN int             ntraders;               /* actual # logged-on traders */
 50: 
 51: /* --------------------------------------------------------------------------
 52: Table of logged-on traders and information to control communication with them.
 53: -------------------------------------------------------------------------- */
 54: /* --- table layout --- */
 55: struct  node_control_struct
 56:         {
 57:         /* --- node/trader identification --- */
 58:         unsigned char   trader[32];             /* name of trader at node */
 59:         struct  skt_ioctl_struct ioctl;         /* copy of trader's ioctl */
 60:         /* --- message synchronization (and timeout control) --- */
 61:         int             msgseqout;              /* outgoing msg sequence # */
 62:         int             msgseqin;               /* incoming msg sequence # */
 63:         int             insecs;                 /* time of last incoming msg
 64:                                                    (seconds since midnight) */
 65:         /* --- got closing message flag --- */
 66:         int             isclosed;               /* true if 3pm/5pm received */
 67:         int             nissues;                /* #closing prices received */
 68:         } ;
 69: 
 70: /* --- table allocation --- */
 71: struct  node_control_struct
 72: #ifdef BALLOCATE
 73:         nodes[MAX_TRADERS];
 74: #else
 75:         extern nodes[];
 76: #endif
 77: 
 78: /* ------------------------------- End-of-File ---------------------------- */
 79: #endif


BBBBBBBB     SSSSSSS  EEEEEEEEEE RRRRRRRR   VV      VV EEEEEEEEEE RRRRRRRR             
BBBBBBBBB   SSSSSSSSS EEEEEEEEEE RRRRRRRRR  VV      VV EEEEEEEEEE RRRRRRRRR            
 BB     BB SS          EE     EE  RR     RR VV      VV  EE     EE  RR     RR           
 BBBBBBBB   SSSSSSS    EEEEEE     RRRRRRRR  VV      VV  EEEEEE     RRRRRRRR            
 BBBBBBBB    SSSSSSS   EEEEEE     RRRRRRR    VV    VV   EEEEEE     RRRRRRR             
 BB     BB         SS  EE     EE  RR   RR     VV  VV    EE     EE  RR   RR             
BBBBBBBBB  SSSSSSSSS  EEEEEEEEEE  RR    RR     VVVV    EEEEEEEEEE  RR    RR  __________
BBBBBBBB    SSSSSSS   EEEEEEEEEE  RR     RR     VV     EEEEEEEEEE  RR     RR __________

  1: /****************************************************************************
  2:  *
  3:  * Copyright (c) 1988,1989 John Forkosh Associates, Inc.  All rights reserved.
  4:  * --------------------------------------------------------------------------
  5:  *
  6:  * Program:     bserver_comm -mMSGLEVEL -dDIRECTIVE -hHOSTNAME -pHOSTPORT
  7:  *
  8:  * Purpose:     Formats and sends messages to the server (either interactively
  9:  *              or from a command-line directive), permitting control of
 10:  *              the detached server process.
 11:  *
 12:  * Command-line Arguments:
 13:  *
 14:  *              -mMSGLEVEL      specifies the amount of output produced
 15:  *
 16:  *              -dDIRECTIVE     if present, a single directive is sent to
 17:  *                              the server and then the program exits,
 18:  *                              thus allowing its use from command procedures
 19:  *
 20:  *              -hHOSTNAME      name of host where server running
 21:  *
 22:  *              -pHOSTPORT      port on which server's socket created
 23:  *
 24:  * Notes:     o 
 25:  *
 26:  * Source:      BSERVER_COMM.C
 27:  *
 28:  * --------------------------------------------------------------------------
 29:  * Revision History:
 30:  *
 31:  * 01/04/89     J.Forkosh       Installation.
 32:  * 02/13/89     J.Forkosh       Modified for Version 2.
 33:  * 02/16/89     J.Forkosh       Spread added to sktpricemsg.
 34:  *
 35:  ****************************************************************************/
 36: 
 37: /* ----------------------------------------------------------------------------
 38: Header files and Defined symbols
 39: ---------------------------------------------------------------------------- */
 40: /* --- Standard VMS headers --- */
 41: #include < stdio.h >
 42: /* --- Basis communications headers --- */
 43: #define BALLOCATE                       /* "globaldef" all externs */
 44: #include "skt_header.h"
 45: #include "sktmsgdef.h"
 46: #include "msgqueue.h"
 47: /* --- Other symbols and variables --- */
 48: #define MSGLEVEL        3               /* default message level */
 49: int     msglevel = MSGLEVEL;            /* referenced externally */
 50: #define HOSTNAME        "VEGA"          /* default node where server running */
 51: #define HOSTLOG         "BASIS$HOST"    /* logical xlating to server node */
 52: /* ------------------------------------------------------------------------- */
 53: 
 54: /* ----------------------------------------------------------------------------
 55: Table of command mnemonics and their xlated message or command opcodes
 56: ---------------------------------------------------------------------------- */
 57: /* --- terminator --- */
 58: #define TERMINATOR      "/"             /* multiple commands per line */
 59: 
 60: /* --- commands --- */
 61: #define CMDDELIM        "="             /* char (or string) delimiting cmds */
 62: #define CMD$_MSGLEVEL   12439           /* oddball number to avoid collisions */
 63: #define CMD$_SENDER     (CMD$_MSGLEVEL + 1)
 64: #define CMD$_SECID      (CMD$_SENDER + 1)
 65: #define CMD$_PRICE      (CMD$_SECID + 1)
 66: #define CMD$_INFO       (CMD$_PRICE + 1)
 67: #define CMD$_DITTOS     (CMD$_INFO + 1)
 68: #define CMD$_READ       (CMD$_DITTOS + 1)
 69: #define CMD$_WAIT       (CMD$_READ + 1)
 70: #define CMD$_EXIT       (CMD$_WAIT + 1)
 71: static struct
 72:     { char      *mnemonic;              /* user enters this */
 73:       int       cmdcode; }              /* to generate this command */
 74: cmdtbl[] =
 75:     { /* --- mnemonic   cmdcode --- */
 76:         { "MSG",        CMD$_MSGLEVEL },        /* reset message level */
 77:         { "SEN",        CMD$_SENDER },          /* define sender[] string */
 78:         { "SEC",        CMD$_SECID },           /* define sec_id[] string */
 79:         { "QUO",        CMD$_PRICE },           /* define security price */
 80:         { "TEX",        CMD$_INFO },            /* define text for info msg */
 81:         { "DIT",        CMD$_DITTOS },          /* #times to repeat sends */
 82:         { "READ",       CMD$_READ },            /* dequeue any waiting msgs */
 83:         { "WAIT",       CMD$_WAIT },            /* sleep for nsecs */
 84:         { "EX",         CMD$_EXIT },            /* exit program */
 85:         { "\000",       -1 }                    /* table termination trailer */
 86:     } ; /* --- end-of-cmdtbl[] --- */
 87: 
 88: /* --- message opcodes --- */
 89: #define OPDELIM         ":"             /* char (or string) delimiting opcode */
 90: static struct
 91:     { char      *mnemonic;              /* user enters this */
 92:       int       opcode; }               /* to generate msg with this */
 93: optbl[] =
 94:     { /* --- mnemonic   opcode --- */
 95:         { "ON",         SKT$_LOGONMSG },        /* logon to server */
 96:         { "OFF",        SKT$_LOGOFFMSG },       /* logoff from server */
 97:         { "DIR",        SKT$_DIRECTIVEMSG },    /* directive (most common) */
 98:         { "PRICE",      SKT$_PRICEMSG },        /* set a security price */
 99:         { "INFO",       SKT$_INFOMSG },         /* set an info msg */
100:         { "REQP",       SKT$_REQPRICEMSG },     /* request a security price */
101:         { "\000",       -1 }                    /* table termination trailer */
102:     } ; /* --- end-of-optbl[] --- */
103: 
104: /* --- opcodes translation --- */
105: static struct
106:     { int       opcode;         /* this message opcode */
107:       char      *mnemonic; }    /* is displayed like this */
108: opnametbl[] =
109:     { /* --- opcode             mnemonic --- */
110:         { SKT$_ACKMSG,          "ack" },        /* server ack */
111:         { SKT$_NAKMSG,          "nak" },        /* server nak */
112:         { SKT$_LOGONMSG,        "logon" },      /* logon to server */
113:         { SKT$_LOGOFFMSG,       "logoff" },     /* logoff from server */
114:         { SKT$_DIRECTIVEMSG,    "directive" },  /* directive (most common) */
115:         { SKT$_PRICEMSG,        "price" },      /* set a security price */
116:         { SKT$_3PMPRICEMSG,     "3pmprice" },   /* set a 3pm/5pm price */
117:         { SKT$_3PMCLOSEMSG,     "3pmclose" },   /* closing */
118:         { SKT$_INFOMSG,         "info" },       /* set an info msg */
119:         { SKT$_REQPRICEMSG,     "reqprice" },   /* request a security price */
120:         { -1,   "\000" }                        /* table termination trailer */
121:     } ; /* --- end-of-optbl[] --- */
122: /* ------------------------------------------------------------------------- */
123: 
124: /* --- entry point --- */
125: main ( argc, argv )
126: int     argc;
127: char    *argv[];
128: {
129: /* ----------------------------------------------------------------------------
130: Allocations and Declarations
131: ---------------------------------------------------------------------------- */
132: /* --- message control variables --- */
133: struct  skt_control_struct *skt;        /* ptr to our created socket */
134: struct  msg_control_struct msg, *reply; /* ioctl to server, ptr to ioctl from */
135: char    msgbuf[SKT_MAXMSG], *replybuf;  /* msg to server, ptr to msg from */
136: struct  sktmsghdr_struct *msghdr;       /* every msg starts with a header */
137: struct  sktmsg_struct *sktmsg;          /* unformatted (e.g., directive) msg */
138: int     opcode = SKT$_LOGONMSG;         /* opcode of message */
139: int     msgsz;                          /* #bytes in iobuff of msg */
140: int     msgseqin=0, msgseqout=0;        /* incoming,outgoing sequence numbers */
141: /* --- default server identification --- */
142: char    hostname[64] = HOSTNAME;        /* server running on host */
143: int     hostport = SERVER_PORT;         /* port where server's socket created */
144: /* --- price message variables --- */
145: struct  sktpricemsg_struct *pricemsg;
146: char    sec_id[16] = " 1000";           /* id of security whose price given */
147: double  price=100.0, spread=0.0, dvalue, autod(); /* price,spread of security */
148: /* --- command-line argument processing --- */
149: int     ivalue;                         /* atoi(...) whenever needed */
150: int     iarg;                           /* counter over command-line switches */
151: char    *argptr, argop;                 /* ptr to argv[iarg], 1st char of arg */
152: /* --- user input processing --- */
153: char    *gets(), *index(), *strchr();   /* read and parse interactive input */
154: char    *delim;                         /* ptr to token */
155: char    *trim(),*ltrim(),*strupper();   /* trim and uppercase user input */
156: char    cmd[128], cmdbuf[128]="\000";   /* buffer for interactive commands */
157: int     itbl,tblcode, icode = (-1);     /* opcode for command/message */
158: /* --- other variables --- */
159: char    sender[32] = "ADMIN";           /* identify ourselves to server */
160: char    directive[64]="\000";           /* directive to server */
161: char    infotext[64]="nomessage";       /* text of info message */
162: char    opname[64]; int iopname;        /* result of opnametbl[] lookup */
163: int     isdirective = FALSE;            /* set true if we get command-line -d */
164: int     iditto, ndittos=1;              /* #times to repeat sending a message */
165: char    *vmsmsg();                      /* interpret vms error codes */
166: int     status;                         /* vms return status */
167: long    eflags;                         /* event flags returned from readef */
168: /* ------------------------------------------------------------------------- */
169: 
170: /* ----------------------------------------------------------------------------
171: Initialization - Get command-line args
172: ---------------------------------------------------------------------------- */
173: /* --- first determine default host node from logical --- */
174: status = trnlnm ( 1, HOSTLOG, hostname ); /* try xlating logical with host */
175: if ( !memcmp(hostname,HOSTLOG,strlen(hostname)) ) /* no xlation available */
176:         strcpy ( hostname, HOSTNAME );  /* so restore default hostname */
177: 
178: /* ---Loop over each command-line argument --- */
179: for ( iarg=1; iarg < argc; iarg++ )     /* skip image name in argv[0] */
180:     {
181:     /* --- make sure arg is a switch and then use its 1st char as opcode --- */
182:     argptr = argv[iarg];                /* ptr to first char of this arg */
183:     if ( *argptr == '-' )               /* got a switched arg */
184:         argptr++;                       /* just skip over the dash */
185:     argop = toupper(*argptr++);         /* opcode is char after '-' */
186:     ivalue = atoi( argptr );            /* convert remainder of arg to int */
187:     /* --- switch on argop tells us what kind of command we've got --- */
188:     switch ( argop )                    /* check the char following '-' */
189:         {
190:         /* --- Just ignore anything unrecognizable --- */
191:         default:                        /* got an unrecognized switch */
192:             if ( msglevel > 0 )         /* so print an error msg */
193:                 printf("\nbcomm> unrecognized command-line switch=%c, arg=%s",
194:                 argop, argptr );
195:             break;
196:         /* --- message level --- */
197:         case 'M':
198:             if ( ivalue >= 0 )          /* 0 means no sys$output available */
199:                 msglevel = ivalue;
200:             break;
201:         /* --- directive --- */
202:         case 'D':
203:             strcpy ( cmdbuf, argptr );
204:             isdirective = TRUE;
205:             break;
206:         /* --- hostname --- */
207:         case 'H':
208:             strcpy ( hostname, argptr );
209:             break;
210:         /* --- hostport --- */
211:         case 'P':
212:             if ( ivalue > 0 )           /* 0 isn't a legal port anyway */
213:                 hostport = ivalue;
214:             break;
215:         } /* --- end-of-switch(argop) --- */
216:     }  /* --- end-of-for(iarg) --- */
217: 
218: /* ----------------------------------------------------------------------------
219: Initialization - Create Socket and Arm QIOs for Receiving Messages
220: ---------------------------------------------------------------------------- */
221: /* --- create socket for ourselves --- */
222: status = creskt ( &skt, "", 0 );
223: if (status != SS$_NORMAL)
224:         { if ( msglevel > 0 )
225:                 printf ( "\ncreskt> err=%s", vmsmsg(status) );
226:           exit ( status ); }
227: 
228: /* --- arm message receipt on created socket --- */
229: status = recvskt ( skt );
230: if (status != SS$_NORMAL)
231:         { if ( msglevel > 0 )
232:                 printf ( "\nrecvskt> err=%s", vmsmsg(status) );
233:           goto end_of_job; }
234: 
235: /* --- initialize "stub" items for send buffer shell --- */
236: status = fmtskt ( &(msg.ioctl), hostname, hostport );
237: if ( status != SS$_NORMAL )
238:         { if ( msglevel > 0 )
239:                 printf ( "\nfmtskt> err=%s", vmsmsg(status) );
240:           goto end_of_job; }
241: msg.iobuff = msgbuf;                    /* point to our allocated buffer */
242: msg.maxmsg = SKT_MAXMSG;                /* and set its max length */
243: 
244: /* ----------------------------------------------------------------------------
245: Construct messages from user input, send them to server, capture replies
246: ---------------------------------------------------------------------------- */
247: while ( TRUE )                          /* loop until user requests exit */
248:     {
249: 
250:     /* ------------------------------------------------------------------------
251:     Pop the next command from the command buffer
252:     ------------------------------------------------------------------------ */
253:     /* --- refresh the command buffer whenever necessary --- */
254:     if ( strlen(cmdbuf) < 1 )           /* nothing left to process */
255:         {
256:         if ( isdirective ) goto end_of_job; /* not in interactive mode */
257:         printf ( "\n\nEnter command --> " ); /* prompt user for input */
258:         if ( gets(cmdbuf) == NULL )     /* read failed */
259:             { if ( msglevel > 0 )       /* so print fatal err msg */
260:                 printf ( "\nUnable to read command input." );
261:               goto end_of_job; }        /* and quit */
262:         if ( strlen(cmdbuf) < 1 ) goto reader; /* blank line is read request */
263:         } /* --- end-of-if(strlen(cmdbuf)) --- */
264: 
265:     /* --- pop the next command off the buffer --- */
266:     delim = index(cmdbuf,TERMINATOR);   /* look for end of command */
267:     if ( delim != NULL )                /* got a terminator */
268:         { *delim = '\000';              /* place a null terminator there */
269:           strcpy ( cmd, cmdbuf );       /* pop off current command */
270:           strcpy ( cmdbuf, delim+strlen(TERMINATOR) ); } /* ready for next */
271:     else { strcpy ( cmd, cmdbuf );      /* only one command so copy it */
272:           *cmdbuf = '\000'; }           /* and "empty" the command buff */
273:     strupper(trim(ltrim(cmd)));         /* trim lead/trailing and uppercase */
274:     if ( strlen(cmd) < 1 )              /* null buffer */
275:         goto next_cmd;                  /* so skip it */
276: 
277:     /* ------------------------------------------------------------------------
278:     Determine code
279:     ------------------------------------------------------------------------ */
280:     /* --- see if cmd[] starts with one of mnemonics in cmdtbl[] --- */
281:     for ( itbl=0; (tblcode=cmdtbl[itbl].cmdcode)>=0; itbl++ )
282:         if ( index(cmd,cmdtbl[itbl].mnemonic) == cmd ) break;
283:     if ( tblcode >= 0 )                 /* found cmdtbl[] mnemonic in cmd[] */
284:         {
285:         icode = tblcode;                /* this is our new code */
286:         if ( (delim=index(cmd,CMDDELIM)) != NULL ) /* delim after mnemonic */
287:             { strcpy ( cmd, delim+strlen(CMDDELIM) ); /* so shift operand */
288:               trim(ltrim(cmd)); }       /* and trim it */
289:         else *cmd = '\000';             /* no operand so null out cmd */
290:         goto switcher;                  /* go switch on code */
291:         } /* --- end-of-if(tblcode) --- */
292: 
293:     /* --- not in cmdtbl[], see if cmd[] starts with mnemonic in optbl[] --- */
294:     for ( itbl=0; (tblcode=optbl[itbl].opcode)>=0; itbl++ )
295:         if ( index(cmd,optbl[itbl].mnemonic) == cmd ) break;
296:     if ( tblcode >= 0 )                 /* found optbl[] mnemonic in cmd[] */
297:         {
298:         icode = tblcode;                /* this is our new code */
299:         opcode = tblcode;               /* and it's the opcode for message */
300:         if ( (delim=index(cmd,OPDELIM)) != NULL ) /* delim after mnemonic */
301:             { strcpy ( cmd, delim+strlen(OPDELIM) ); /* so shift operand */
302:               trim(ltrim(cmd)); }       /* and trim it */
303:         else *cmd = '\000';             /* no operand so null out cmd */
304:         goto switcher;                  /* go switch on code */
305:         } /* --- end-of-if(tblcode) --- */
306: 
307:     /* --- command not in either table, so re-use previous icode --- */
308:     goto switcher;                      /* just go and do it */
309: 
310:     /* ------------------------------------------------------------------------
311:     Switch on code
312:     ------------------------------------------------------------------------ */
313:     switcher:
314:     switch ( icode )                    /* determined above or defaulted */
315:         {
316:         /* --------------------------------------------------------------------
317:         Unrecognized code
318:         -------------------------------------------------------------------- */
319:         default:
320:             if ( msglevel > 0 )
321:                 printf ( "\nUnrecognized request: %s", cmd );
322:             goto next_cmd;
323: 
324:         /* --------------------------------------------------------------------
325:         Commands
326:         -------------------------------------------------------------------- */
327:         case CMD$_EXIT:                         /* user wants out */
328:             goto end_of_job;
329:         case CMD$_MSGLEVEL:
330:             ivalue = atoi(cmd);                 /* see what we got */
331:             if ( ivalue > 0 ) msglevel=ivalue;  /* and set new msglevel */
332:             if ( msglevel > 0 )
333:                 printf ( "\nCurrent msglevel = %d.", msglevel );
334:             goto next_cmd;
335:         case CMD$_WAIT:
336:             ivalue = atoi(cmd);                 /* see what we got */
337:             if ( ivalue<1 || ivalue>29 ) ivalue=1; /* don't sleep too long */
338:             sleep(ivalue);                      /* sleep requested #secs */
339:             if ( msglevel > 0 )
340:                 printf ( "\nWoke after sleeping %d seconds.", ivalue );
341:             goto next_cmd;
342:         case CMD$_SENDER:
343:             if ( strlen(cmd) > 0 )              /* got an operand */
344:                 strcpy ( sender, cmd );         /* so it's sender */
345:             if ( msglevel > 0 )
346:                 printf ( "\nCurrent sender = %s.", sender );
347:             goto next_cmd;
348:         case CMD$_INFO:
349:             if ( strlen(cmd) > 0 )              /* got an operand */
350:                 strcpy ( infotext, cmd );       /* so it's info msg text */
351:             if ( msglevel > 0 )
352:                 printf ( "\nCurrent info text = %s.", infotext );
353:             goto next_cmd;
354:         case CMD$_SECID:
355:             if ( strlen(cmd) > 0 )              /* got an operand */
356:                 { *sec_id = '\000';             /* reset old security id */
357:                   if ( strlen(cmd) < 5 )        /* got a 4-digit sec_id */
358:                     strcpy ( sec_id, " " );     /* so need a leading blank */
359:                   strcat ( sec_id, cmd ); }     /* followed by security id */
360:             if ( msglevel > 0 )
361:                 printf ( "\nCurrent sec_id = %s.", sec_id );
362:             goto next_cmd;
363:         case CMD$_PRICE:
364:             if ( strlen(cmd) > 0 )              /* got an operand */
365:                 {
366:                 delim = strchr(cmd,',');        /*find ',' between price,sprd*/
367:                 if ( delim != NULL )            /* got a ',' somewheres */
368:                     { *delim = '\000';          /* so terminate on it */
369:                       trim(ltrim(cmd)); }       /* and trim it */
370:                 dvalue = autod(cmd,32,8);       /* convert to double from 32 */
371:                 if ( dvalue > 0.0 ) price = dvalue; /* use it if ok */
372:                 if ( delim != NULL )            /* got spread after price */
373:                     { dvalue = autod(delim+1,32,8); /* so convert to double */
374:                       if ( dvalue > 0.0 )       /* and use it if ok */
375:                         spread = dvalue; }
376:                 }
377:             if ( msglevel > 0 )
378:                 printf ( "\nCurrent price, spread = %lf, %lf.", price, spread );
379:             goto next_cmd;
380:         case CMD$_DITTOS:
381:             ivalue = atoi(cmd);                 /* see what we got */
382:             if ( ivalue > 0 ) ndittos=ivalue;   /* and set new repeat count */
383:             if ( msglevel > 0 )
384:                 printf ( "\nCurrent ndittos = %d.", ndittos );
385:             goto next_cmd;
386:         case CMD$_READ:
387:             goto reader;
388: 
389:         /* --------------------------------------------------------------------
390:         Messages
391:         -------------------------------------------------------------------- */
392:         case SKT$_LOGONMSG:
393:         case SKT$_LOGOFFMSG:
394:             if ( strlen(cmd) > 0 )              /* got an operand */
395:                 strcpy ( sender, cmd );         /* so it's sender */
396:             goto writer;
397:         case SKT$_DIRECTIVEMSG:
398:             if ( strlen(cmd) > 0 )              /* got an operand */
399:                 strcpy ( directive, cmd );      /* so it's a directive */
400:             goto writer;
401:         case SKT$_INFOMSG:
402:             if ( strlen(cmd) > 0 )              /* got an operand */
403:                 strcpy ( infotext, cmd );       /* so it's info text */
404:             goto writer;
405:         case SKT$_PRICEMSG:
406:         case SKT$_REQPRICEMSG:
407:             if ( strlen(cmd) > 0 )              /* may have sec_id,price */
408:                 {
409:                 delim = strchr(cmd,',');        /* find ',' between id,price */
410:                 if ( delim != NULL )            /* got a ',' somewheres */
411:                     { *delim = '\000';          /* so terminate on it */
412:                       trim(ltrim(cmd)); }       /* and trim it */
413:                 *sec_id = '\000';               /* reset old security id */
414:                 if ( strlen(cmd) < 5 )          /* got a 4-digit sec_id */
415:                     strcpy ( sec_id, " " );     /* so need a leading blank */
416:                 strcat ( sec_id, cmd );         /* followed by security id */
417:                 if ( delim != NULL )            /* got price after sec_id */
418:                     { dvalue = autod(delim+1,32,8); /* so convert to double */
419:                       if ( dvalue > 0.0 )       /* and use it if ok */
420:                         price = dvalue; }
421:                 } /* --- end-of-if(strlen(cmd)) --- */
422:             goto writer;
423:         } /* --- end-of-switch(icode) --- */
424: 
425: 
426:     /* ------------------------------------------------------------------------
427:     Write message to server
428:     ------------------------------------------------------------------------ */
429:     writer:
430:     /* --- this will be a message, so init for it --- */
431:     msghdr = (struct sktmsghdr_struct *)(msgbuf);       /* always got a hdr */
432:     pricemsg = (struct sktpricemsg_struct *)(msgbuf);   /* maybe a price msg */
433:     sktmsg = (struct sktmsg_struct *)(msgbuf);          /* maybe no format */
434:     strcpy ( msghdr->sender, sender );                  /* sender of message */
435:     msghdr->opcode = opcode;                            /* opcode for message */
436:     msg.msgsz = sizeof ( struct sktmsghdr_struct );     /* got a hdr at least */
437:     if ( opcode == SKT$_PRICEMSG                        /* init for price msg */
438:     ||   opcode == SKT$_REQPRICEMSG )                   /* or price request */
439:         { strcpy ( pricemsg->quote[0].sec_id, sec_id );
440:           pricemsg->quote[0].price = price;
441:           pricemsg->quote[0].spread = spread;
442:           pricemsg->nquotes = 1;
443:           msg.msgsz += (sizeof(int)+sizeof(struct sktquote_struct)); }
444:     if ( opcode == SKT$_DIRECTIVEMSG )                  /* init for directive */
445:         { strcpy ( sktmsg->msg, directive );
446:           msg.msgsz += (strlen(directive) + 1); }
447:     if ( opcode == SKT$_INFOMSG )                       /* init for info */
448:         { strcpy ( sktmsg->msg, infotext );
449:           msg.msgsz += (strlen(infotext) + 1); }
450: 
451:     /* --- write message to the server --- */
452:     for ( iditto=0; iditto < ndittos; iditto++ )
453:         {
454:         /* --- assign sequence number and issue send --- */
455:         msghdr->msgseqnum = ++msgseqout;
456:         status = sendsktw ( skt, &msg );
457:             if ( (status != SS$_NORMAL) )
458:                 { if ( msglevel > 0 )
459:                         printf("\nsendsktw> err=%s",vmsmsg(status));
460:                   goto end_of_job; }
461:         } /* --- end-of-for(iditto) --- */
462: 
463:     /* ------------------------------------------------------------------------
464:     Read message from  server
465:     ------------------------------------------------------------------------ */
466:     reader:
467:     /* --- check whether messages waiting in queue --- */
468:     status = sys$readef ( MSGQUEUEFLAG, &eflags );      /* check queue flag */
469:     if ( status == SS$_WASCLR )                         /* wasn't set */
470:         { if ( opcode==CMD$_READ && msglevel>1 )
471:                 printf("\nNo messages waiting." );
472:           goto next_cmd; }
473:     if ( status != SS$_WASSET )                         /* must be clr or set */
474:         { if ( msglevel > 0 )                           /* else got an error */
475:                 printf("\nreadef> err=%s",vmsmsg(status));
476:           goto end_of_job; }
477:     sys$clref ( MSGQUEUEFLAG );                         /* clear flag if set */
478: 
479:     /* --- dequeue all waiting messages --- */
480:     while ( iqueued != idequeued )
481:         {
482:         /* --- check next message in queue --- */
483:         reply = &(msgqueue[idequeued]);
484:         idequeued++;
485:         if ( idequeued >= MAXMSGQUEUE )
486:             idequeued = 0;
487:         status = reply->iosb.status;
488:         if (status != SS$_NORMAL)
489:             { printf("\nbcomm> queue#%d, err=%s",idequeued,vmsmsg(status));
490:               goto end_of_job; }
491: 
492:         /* --- display message --- */
493:         if ( msglevel > 0 )
494:             {
495:             /* --- various ptrs for different message interpretations --- */
496:             replybuf = reply->iobuff;
497:             msghdr = (struct sktmsghdr_struct *)(replybuf);
498:             sktmsg = (struct sktmsg_struct *)(replybuf);
499:             pricemsg = (struct sktpricemsg_struct *)(replybuf);
500:             /* --- look up display "name" for opcode --- */
501:             strcpy ( opname, "???" );   /* default if no lookup match */
502:             for ( iopname=0; opnametbl[iopname].opcode >= 0; iopname++ )
503:                 if ( opnametbl[iopname].opcode == msghdr->opcode )
504:                     { strcpy ( opname, opnametbl[iopname].mnemonic );
505:                       break; }
506:             /* --- print common header information --- */
507:             printf("\nbcomm> from sender=%s, seq#%d, opcode#%d=%s",
508:                 msghdr->sender, msghdr->msgseqnum, msghdr->opcode,opname );
509:             /* --- print additional info by opcode/message type --- */
510:             if ( msghdr->opcode == SKT$_PRICEMSG
511:             ||   msghdr->opcode == SKT$_3PMPRICEMSG
512:             ||   msghdr->opcode == SKT$_REQPRICEMSG )
513:               printf(", #quotes=%d, sec_id1=%s, price,spread1=%7.3lf,%7.3lf",
514:                 pricemsg->nquotes, pricemsg->quote[0].sec_id,
515:                 pricemsg->quote[0].price, pricemsg->quote[0].spread);
516:             if ( msghdr->opcode == SKT$_INFOMSG )
517:                 printf(", info msg=%s", sktmsg->msg );
518:             }
519:         } /* --- end-of-while(iqueued) --- */
520: 
521:     /* ------------------------------------------------------------------------
522:     Next command
523:     ------------------------------------------------------------------------ */
524:     next_cmd: ;                         /* dummy target for bottom of loop */
525:     } /* --- end-of-while(TRUE) --- */
526: 
527: /* ----------------------------------------------------------------------------
528: End of job.
529: ---------------------------------------------------------------------------- */
530: end_of_job:
531:     sys$dassgn((short)skt->chan);       /* release creskt()'s chan */
532:     if ( msglevel > 0 )                 /* signoff msg (for directives) */
533:         printf ( "\nbcomm> end-of-job" );
534:     exit ( status );                    /* exit (with status for directives) */
535: } /* --- end-of-program bserver_comm() --- */
536: /* ----------------------- END-OF-FILE BSERVER_COMM.C ----------------------- */

Copyright © 1988-2010, John Forkosh Associates, Inc.
email: john@forkosh.com
You're the     Visitor to this Page.