#define ident "1B02" /*---------------------------------------------------------------------------*/ #ifdef __DECC #pragma module SinqHM_Client ident #endif /* ** Link_options - Here is the Linker Option File **! sinqhm_client **! sinq_olb/lib/inc=deltat_messages **! pgplot_dir:grpckg.olb/lib **! sys$share:decw$xlibshr/share **!! **!! To build SINQHM_CTRL on LNSA09 **!! **!! $ import tasmad **!! $ define/job deltat_c_tlb sinq_c_tlb **!! $ sss := ud0:[maden.pss123.wind.sinqhm] **!! $ bui 'sss'sinqhm_client debug ** Link_options_end ** ** Building on Alpha OSF/1: ** ** cc -Dmain=MAIN__ -std1 -g -c -o sinqhm_client.o \ ** -I/public/lib/include \ ** ~/SinqHM/sinqhm_client.c ** f77 -g -o ~/bin/sinqhm_client sinqhm_client.o \ ** -L/public/lib -lsinq -lcpgplot -lpgplot -lX11 ** rm sinqhm_client.o ** ** +--------------------------------------------------------------+ ** | Paul Scherrer Institute | ** | Computing Section | ** | | ** | This software may be used freely by non-profit organizations.| ** | It may be copied provided that the name of P.S.I. and of the | ** | author is included. Neither P.S.I. nor the author assume any | ** | responsibility for the use of this software outside of P.S.I.| ** +--------------------------------------------------------------+ ** ** Module Name . . . . . . . . : [...sinqhm]sinqhm_client.c ** ** Author . . . . . . . . . . : D. Maden ** Date of creation . . . . . . : Jan 1997 ** ** SinqHM_Client is the main program of an Internet Client which transmits ** requests to a SinqHM server running on a front-end processor. ** ** Updates: ** 9-Jan-1997 DM. Initial version. ** ** Usage on VMS Systems ** -------------------- ** The following group logical name definitions are used ... ** ** SINQHM_FRONTEND , The node where SINQHM_SRV is running. ** , TCP/IP port number of SINQHM_SRV (dflt = 2400). ** Max packet size for send/rcve (dflt = 8192). ** ** SINQHM_DBG_MODE The setting of in the SQHM_CNCT ** message to SINQHM. Dflt=0. If non-zero, the ** client will suspend itself immediately after ** it has started to allow interactive debugging. ** ** If the logical names cannot be found, DCL symbols will be used instead. ** ** Usage on UNIX Systems ** --------------------- ** The SINQHM_FRONTEND and SINQHM_DBG_MODE environment variables are used ** to obtain the required setup information. **==================================================================== */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __VMS #include #define _DESCRIPTOR $DESCRIPTOR #define PGBEGIN(arg1,arg2,arg3,arg4) pgbegin (&arg1, &arg2, &arg3, &arg4) #define PGASK(arg1) pgask (&arg1) #define PGENV(arg1,arg2,arg3,arg4,arg5,arg6) \ pgenv (&arg1, &arg2, &arg3, &arg4, &arg5, &arg6) #define PGLINE(arg1,arg2,arg3) pgline (&arg1, &arg2, &arg3) #define PGLABEL(arg1,arg2,arg3) pglabel (&arg1, &arg2, &arg3) #define PGRND(arg1,arg2) pgrnd (&arg1, &arg2) void pgbegin (); void pgask (); void pgenv (); void pgline (); void pglabel (); float pgrnd (); #else #include #define _DESCRIPTOR(name,string) char name[] = string #define PGBEGIN(arg1,arg2,arg3,arg4) cpgbeg (arg1, arg2, arg3, arg4) #define PGASK(arg1) cpgask (arg1) #define PGENV(arg1,arg2,arg3,arg4,arg5,arg6) \ cpgenv (arg1, arg2, arg3, arg4, arg5, arg6) #define PGLINE(arg1,arg2,arg3) cpgline (arg1, &arg2, &arg3) #define PGLABEL(arg1,arg2,arg3) cpglab (arg1, arg2, arg3) #define PGRND(arg1,arg2) cpgrnd (arg1, &arg2) #define pgbegin cpgbeg #define pgask cpgask #define pgenv cpgenv #define pgline cpgline #define pglabel cpglab #define pgrnd cpgrnd #endif /* **==================== Global Definitions ===================================== */ #include #include "sinqhm_def.h" #define NIL '\0' #define NL '\n' #define MAXERR 10 #define MAX_HIS 16 #define BSIZE ((128*1024)/512) /* Specify 128 kbyte buffer */ /* ** Define the Data Structures we need */ /* **==================== Global Variables ====================================== */ int My_errno, My_vaxc_errno; struct req_buff_struct Req_buff; struct rply_buff_struct Rply_buff; int Rmt_port; int Pkt_size; char Rmt_node[32]; int Rw_bytes_got, Rw_bytes_put; static int Cnct_skt = 0; /* Connect socket */ static int Rw_skt = 0; /* Read/write socket */ /* ** The buffer for holding Hist Mem data is pointed to ** by Hm_buff_addr. The number of bytes allocated is Hm_buff_size. */ char *Hm_buff_addr = NULL; int Hm_buff_size; int N_hists; /* The number of histograms */ int Hm_nbins; /* The number of bins per histogram */ int Bin_wid; /* The number of bytes per bin */ int Curr_hist; /* The current histogram */ int Max_block; int PGPLOT_started = 0; float P1 = 2000000, P2 = 10000, P3 = 0, P4 = 200000, P5 = 500, P6 = 0; /* **============================================================================= ** Local routines. ** ** do_plot : Plot the data. ** exit_handler : Exit handler in case a forced exit is made. ** gen_data : Generate sum of 2 Lorenzians. ** get_SINQHM_DBG_MODE : Extract info from SINQHM_DBG_MODE environment variable ** get_SINQHM_FRONTEND : Extract info from SINQHM_FRONTEND environment variable ** read_hm : Read block of bins from SINQHM_SRV. ** show_help : Display the help text. **---------------------------------------------------------------------------- ** Prototypes */ void do_plot (int first, int n_bins, int binwid, int total); void exit_handler (); void gen_data (char *p_p1, char *p_p2, char *p_p3, char *p_p4, char *p_p5, char *p_p6); void get_SINQHM_DBG_MODE (int *mode, int mode_dflt); void get_SINQHM_FRONTEND (char *node, int node_l, char *node_dflt, int *port, int port_dflt, int *pktlen, int pktlen_dflt); int openConnection (char *node, int *port, int *pkt_size, int mode, struct rply_buff_struct *reply); int openConnectionGbl (char *node, int *port, int *pkt_size, int mode, struct rply_buff_struct *reply); int read_hm (int f_bin, int n_bins); void show_help (); /* **---------------------------------------------------------------------------- */ void do_plot (int first, int n_bins, int binwid, int total) { /* ======== ** Make a plot of the data. */ int i; int null = 0; int nx = 1; int ny = 1; char total_txt[21]; _DESCRIPTOR(dev, "/XW"); _DESCRIPTOR(xlab, "Bins"); _DESCRIPTOR(ylab, "Counts"); _DESCRIPTOR(totl, total_txt); float xlo, xhi, yhi; float zero = 0.0; float *x; float *y; unsigned char *p_byte; unsigned short int *p_word; unsigned int *p_long; if ((n_bins <= 0) || (total == 0)) { printf ("Nothing to plot!\n"); return; } x = (float *) malloc (n_bins * sizeof (float)); if (x == NULL) { printf ("Cannot get plot memory for x-array\n"); return; } y = (float *) malloc (n_bins * sizeof (float)); if (y == NULL) { printf ("Cannot get plot memory for y-array\n"); free (x); return; } sprintf (total_txt, "Bin Total = %8d", total); total_txt[20] = ' '; p_byte = (unsigned char *) Hm_buff_addr; p_word = (unsigned short int *) Hm_buff_addr; p_long = (unsigned int *) Hm_buff_addr; if (PGPLOT_started == 0) { PGBEGIN (null, dev, nx, ny); PGASK (null); PGPLOT_started = 1; } xlo = (float) first; xhi = (float) first + n_bins + 1; yhi = 10.0; switch (binwid) { case 1: for (i = 0; i < n_bins; i++) { x[i] = first + i; y[i] = p_byte[i]; if (y[i] > yhi) yhi = y[i]; } break; case 2: for (i = 0; i < n_bins; i++) { x[i] = first + i; y[i] = p_word[i]; if (y[i] > yhi) yhi = y[i]; } break; case 4: for (i = 0; i < n_bins; i++) { x[i] = first + i; y[i] = p_long[i]; if (y[i] > yhi) yhi = y[i]; } break; } yhi = PGRND (yhi, i); PGENV (xlo, xhi, zero, yhi, null, null); PGLABEL (xlab, ylab, totl); PGLINE (n_bins, x[0], y[0]); free (x); free (y); } /* **--------------------------------------------------------------------------*/ void exit_handler () { /* ============ ** We must exit. Tidy up first. ** Close TCP/IP link to front-end. */ int status; /* ** Tell server we're quitting. */ if (Rw_skt != 0) { printf ("Closing connection to %s ...\n", Rmt_node); Req_buff.bigend = htonl (0x12345678); Req_buff.cmnd = htonl (SQHM_CLOSE); status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0); Rw_bytes_put += status; if (status == -1) FailInet ("EXIT_HANDLER -- R/W-Socket send error\n"); if (status != sizeof (Req_buff)) { printf ("EXIT_HANDLER -- wrong number of bytes sent: %d", status); exit (EXIT_FAILURE); } status = close (Rw_skt); Rw_skt = 0; if (status != 0) FailInet ("EXIT_HANDLER -- R/W-Socket close error\n"); } } /* **--------------------------------------------------------------------------*/ void gen_data ( /* ======== ** Generate sum of 2 Lorenzians. */ char *p_p1, char *p_p2, char *p_p3, char *p_p4, char *p_p5, char *p_p6) { int i; float p1, p2, p3, p4, p5, p6; float ff; char *p_byte; short int *p_word; int *p_long; /* ** Allocate buffer space for holding the data. */ if ((Hm_nbins * Bin_wid) > Hm_buff_size) { /* Expand buffer space? */ Hm_buff_addr = realloc (Hm_buff_addr, (Hm_nbins * Bin_wid)); /* Yes */ if (Hm_buff_addr != NULL) { Hm_buff_size = Hm_nbins * Bin_wid; }else { printf ("SinqHM_Client -- " "error getting memory buffer for histogram data.\n"); exit (EXIT_FAILURE); } } if (p_p1 != NULL) { i = sscanf (p_p1, "%f", &p1); if (i == 1) P1 = p1; if ((i == 1) && (p_p2 != NULL)) { i = sscanf (p_p2, "%f", &p2); if (i == 1) P2 = p2; if ((i == 1) && (p_p3 != NULL)) { i = sscanf (p_p3, "%f", &p3); if (i == 1) P3 = p3; if ((i == 1) && (p_p4 != NULL)) { i = sscanf (p_p4, "%f", &p4); if (i == 1) P4 = p4; if ((i == 1) && (p_p5 != NULL)) { i = sscanf (p_p5, "%f", &p5); if (i == 1) P5 = p5; if ((i == 1) && (p_p6 != NULL)) { i = sscanf (p_p6, "%f", &p6); if (i == 1) P6 = p6; } } } } } } if (P2 <= 0) P2 = 1000; if (P5 <= 0) P5 = 1000; if (P3 <= 0) P3 = ((float) Hm_nbins) * 0.25; if (P6 <= 0) P6 = ((float) Hm_nbins) * 0.60; p_byte = (char *) Hm_buff_addr; p_word = (short int *) Hm_buff_addr; p_long = (int *) Hm_buff_addr; for (i = 0; i < Hm_nbins; i++) { /* Calculate sum of 2 Lorenzians */ p1 = ((float) i) - P3; /* First Lorenzian */ p1 = p1 * p1; p2 = P1/(P2 + p1); p3 = ((float) i) - P6; /* Second Lorenzian */ p3 = p3 * p3; p4 = P4/(P5 + p3); ff = p2 + p4; switch (Bin_wid) { case 1: *p_byte++ = (char) ff; break; case 2: *p_word++ = (short int) ff; break; case 4: *p_long++ = (int) ff; break; } } } /* **--------------------------------------------------------------------------*/ void get_SINQHM_DBG_MODE ( /* =================== ** Extract info from the SINQHM_DBG_MODE ** environment variable. ** */ int *mode, int mode_dflt) { int env_len; char *p_env, *token; char my_env[100]; p_env = getenv ("SINQHM_DBG_MODE"); /* Get pointer to env var */ if (p_env == NULL) { *mode = mode_dflt; /* Env. var. not found, return default */ }else { /* Make a local copy of it in case the original is in .. ** .. read-protected memory (strtok needs to be able to .. ** .. modify it */ env_len = sizeof (my_env); StrEdit (my_env, p_env, "uncomment compress trim", &env_len); token = (env_len == 0) ? NULL : strtok (my_env, " ,"); /* Get mode token */ if ((token == NULL) || (token[0] == ' ')) { *mode = mode_dflt; /* Mode token not found, return default */ }else { if (sscanf (token, "%d", mode) != 1) { *mode = mode_dflt; /* Mode token illegal, return default */ } } } } /* **--------------------------------------------------------------------------*/ void get_SINQHM_FRONTEND ( /* =================== ** Extract info from the SINQHM_FRONTEND ** environment variable. ** */ char *node, int node_l, char *node_dflt, int *port, int port_dflt, int *pktlen, int pktlen_dflt) { int env_len; char *p_env, *token; char my_env[100]; p_env = getenv ("SINQHM_FRONTEND"); /* Get pointer to env var */ if (p_env == NULL) { /* Env. var. not found, return defaults */ StrJoin (node, node_l, node_dflt, ""); *port = port_dflt; *pktlen = pktlen_dflt; }else { /* Make a local copy of it in case the original is in .. ** .. read-protected memory (strtok needs to be able to .. ** .. modify it */ env_len = sizeof (my_env); StrEdit (my_env, p_env, "uncomment compress trim", &env_len); token = (env_len == 0) ? NULL : strtok (my_env, " ,"); /* Get node token */ if ((token == NULL) || (token[0] == ' ')) { /* Node token not found, return defaults */ StrJoin (node, node_l, node_dflt, ""); *port = port_dflt; *pktlen = pktlen_dflt; }else { StrJoin (node, node_l, token, ""); token = strtok (NULL, " ,"); /* Get port token */ if (token == NULL) { *port = port_dflt; /* Port token not found, return defaults */ *pktlen = pktlen_dflt; }else { if (sscanf (token, "%d", port) != 1) { *port = port_dflt; /* Port token illegal, return defaults */ *pktlen = pktlen_dflt; }else { token = strtok (NULL, " ,"); /* Get packet-size token */ if (token == NULL) { *pktlen = pktlen_dflt; /* Packet-size token not found, use dflt */ }else { if (sscanf (token, "%d", pktlen) != 1) { *pktlen = pktlen_dflt; /* Packet-size token illegal, use dflt */ } } } } } } } /* **--------------------------------------------------------------------------*/ int openConnection ( /* ============== ** Open connection to histogram memory front-end. ** Return value is socket id for communication with server. ** On successful connection, the SQHM_CNCT status reply ** is returned in . */ char *node, int *port, /* <== this arg gets modified! */ int *pkt_size, /* <== this arg gets modified! */ int mode, struct rply_buff_struct *reply) { /* <== this arg gets modified! */ int i, status; int my_skt = 0; struct sockaddr_in lcl_sockname; struct sockaddr_in rmt_sockname; int rmt_inet_addr; struct in_addr *rmt_inet_addr_pntr; struct hostent *rmt_hostent; int rmt_sockname_len; /* ** Get Internet address of the front-end. */ for (i=0; i < strlen (node); i++) node[i] = tolower (node[i]); rmt_hostent = gethostbyname (node); if (rmt_hostent == NULL) { /* ** The following code is to handle nodes which are not yet ** in the BIND data base. */ if (strcmp (node, "sqfe01") == 0) { rmt_inet_addr_pntr = (struct in_addr *) &rmt_inet_addr; rmt_inet_addr = inet_addr ("129.129.56.181"); }else { printf ("Server Node is %s.\n", node); FailInet ("\nGethostbyname error."); } }else { rmt_inet_addr_pntr = (struct in_addr *) rmt_hostent->h_addr_list[0]; } printf (" SinqHM Server is %s ", rmt_hostent->h_name); printf ("(%s),", inet_ntoa (*rmt_inet_addr_pntr)); printf (" Base port %d\n", *port); /* ** Create a TCP/IP socket for prelim. connect to server and bind it. */ Cnct_skt = socket (AF_INET, SOCK_STREAM, 0); if (Cnct_skt == -1) FailInet ("Socket error.\n"); lcl_sockname.sin_family = AF_INET; lcl_sockname.sin_port = htons (0); lcl_sockname.sin_addr.s_addr = 0; status = bind (Cnct_skt, (struct sockaddr *) &lcl_sockname, sizeof (lcl_sockname)); if (status == -1) FailInet ("Bind error.\n"); /* **========================================= Now connect to the server. */ rmt_sockname_len = sizeof (rmt_sockname); rmt_sockname.sin_family = AF_INET; rmt_sockname.sin_port = htons (*port); rmt_sockname.sin_addr.s_addr = rmt_inet_addr_pntr->s_addr; status = connect (Cnct_skt, (struct sockaddr *) &rmt_sockname, sizeof (rmt_sockname)); if (status == -1) { GetErrno (&My_errno, &My_vaxc_errno); FailInet ("Connect error\n"); } /* **============================== Set up and send a connection request message. */ Req_buff.bigend = htonl (0x12345678); Req_buff.cmnd = htonl (SQHM_CNCT); Req_buff.u.cnct.max_pkt = htonl (*pkt_size); Req_buff.u.cnct.strt_mode = htonl (mode); if (mode != 0) { printf ("\007 Warning -- mode = %d\n", mode); printf (" Use the debugger in the Hist Mem to get our server to run.\n"); } status = send (Cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0); if (status == -1) FailInet ("SinqHM_Client -- Cnct-Socket send error\n"); if (status != sizeof (Req_buff)) { printf ("SinqHM_Client -- wrong number of bytes sent: %d\n", status); exit (EXIT_FAILURE); } /* ** Wait for the response telling us the port to use. */ status = recv (Cnct_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0); if (status == -1) { FailInet ("SinqHM_Client -- Cnct-Socket recv error\n"); }else if (status != sizeof (Rply_buff)) { printf ("SinqHM_Client -- Cnct-Socket recv error - "); printf ("unexpected byte count: %d.\n", status); exit (EXIT_FAILURE); } if (ntohl (reply->bigend) != 0x12345678) { printf ("\007" "SinqHM_Client -- big-endian/little-endian problem!\n" " Buffer received in non-network byte order!\n"); exit (EXIT_FAILURE); } if (ntohl (reply->status) != KER__SUCCESS) { printf ("SinqHM_Client -- Bad status from Connect Request: %d.\n", ntohl (reply->status)); exit (EXIT_FAILURE); } status = close (Cnct_skt); Cnct_skt = 0; if (status != 0) FailInet ("SinqHM_Client -- Cnct-Socket close error\n"); *port = ntohl (reply->u.cnct.port); printf (" Server port to use = %6d\n", *port); *pkt_size = ntohl (reply->u.cnct.pkt_size); printf (" Agreed packet size = %6d\n", *pkt_size); /* ** Now create, bind and connect a TCP/IP socket to our remote server port. */ my_skt = socket (AF_INET, SOCK_STREAM, 0); if (my_skt == -1) { FailInet ("Socket error.\n"); return 0; } lcl_sockname.sin_family = AF_INET; lcl_sockname.sin_port = htons (0); lcl_sockname.sin_addr.s_addr = 0; status = bind (my_skt, (struct sockaddr *) &lcl_sockname, sizeof (lcl_sockname)); if (status == -1) { FailInet ("Bind error.\n"); return 0; } rmt_sockname_len = sizeof (rmt_sockname); rmt_sockname.sin_family = AF_INET; rmt_sockname.sin_port = htons (*port); rmt_sockname.sin_addr.s_addr = rmt_inet_addr_pntr->s_addr; status = connect (my_skt, (struct sockaddr *) &rmt_sockname, sizeof (rmt_sockname)); if (status == -1) { GetErrno (&My_errno, &My_vaxc_errno); FailInet ("Connect error\n"); return 0; } Rw_bytes_got = 0; Rw_bytes_put = 0; return my_skt; } /* **--------------------------------------------------------------------------*/ int openConnectionGbl ( /* ================= ** Call openConnection then set up some global variables. * Return value is socket id for communication with server. */ char *node, int *port, /* <== this arg gets modified! */ int *pkt_size, /* <== this arg gets modified! */ int mode, struct rply_buff_struct *reply) { /* <== this arg gets modified! */ int my_skt = 0; my_skt = openConnection (node, port, pkt_size, mode, reply); if (my_skt == 0) return my_skt; N_hists = ntohl (Rply_buff.u.cnct.n_hists); printf (" Number of histograms = %6d\n", N_hists); Hm_nbins = ntohl (Rply_buff.u.cnct.num_bins); printf (" Number of bins per histogram = %6d\n", Hm_nbins); Bin_wid = ntohl (Rply_buff.u.cnct.binwid); printf (" Number of bytes per bin = %6d\n", Hm_nbins); Curr_hist = ntohl (Rply_buff.u.cnct.curr_hist); if (Curr_hist != 0) printf (" Current histogram = %6d\n", Curr_hist); Max_block = ntohl (Rply_buff.u.cnct.max_block); printf (" Biggest block of free memory = %6d bytes\n", Max_block); return my_skt; } /* **--------------------------------------------------------------------------*/ int read_hm (int f_bin, int n_bins) { /* ======= ** Send SQHM_READ request to server to read n_bins hist mem bins ** starting at bin f_bin. On return, the data is in the buffer ** pointed to by Hm_buff_addr. */ int status, is, i; int bytes_to_come; char *nxt_byte; short int *nxt_word; int *nxt_long; char msg0[] = "Histogram memory bin 99999 has overflowed."; status = EXIT_SUCCESS; /* Assume success. */ Req_buff.bigend = htonl (0x12345678); Req_buff.cmnd = htonl (SQHM_READ); Req_buff.u.read.n_bins = htonl (n_bins); Req_buff.u.read.first_bin = htonl (f_bin); Req_buff.u.read.hist_no = htonl (-1); status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0); Rw_bytes_put += status; if (status == -1) FailInet ("READ_HM -- R/W-Socket send error\n"); if (status != sizeof (Req_buff)) { printf ("READ_HM -- wrong number of bytes sent: %d", status); return EXIT_FAILURE; } /* ** Wait for the status response. */ status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0); Rw_bytes_got += status; if (status == -1) { FailInet ("READ_HM -- R/W-Socket recv error\n"); }else if (status != sizeof (Rply_buff)) { printf ("READ_HM -- R/W-Socket recv error - "); printf ("unexpected byte count: %d.\n", status); return EXIT_FAILURE; } if (ntohl (Rply_buff.bigend) != 0x12345678) { printf ("\007" "SinqHM_Client -- big-endian/little-endian problem!\n" " Buffer received in non-network byte order!\n"); return EXIT_FAILURE; } if (ntohl (Rply_buff.status) != KER__SUCCESS) { printf ("READ_HM -- Bad status from SQHM_READ Request: %d.\n", ntohl (Rply_buff.status)); return ntohl (Rply_buff.status); } /* ** Data was read OK so read the data which has been sent. */ bytes_to_come = n_bins * Bin_wid; /* Compute length of Histogram data */ nxt_byte = Hm_buff_addr; while (bytes_to_come > 0) { if (bytes_to_come > Pkt_size) i = Pkt_size; else i = bytes_to_come; status = recv (Rw_skt, nxt_byte, i, 0); Rw_bytes_got += status; if (status == -1) FailInet ("READ_HM -- R/W-Socket data recv error\n"); bytes_to_come = bytes_to_come - status; nxt_byte = nxt_byte + status; } /* ** If byte swapping is necessary, do it! */ if ((Bin_wid > 0) && (Rply_buff.bigend != 0x12345678)) { switch (Bin_wid) { /* Byte swapping is necessary */ case 2: /* Not sure how to do this - this might be wrong! */ nxt_word = (short int *) Hm_buff_addr; for (i = 0; i < n_bins; i++) nxt_word[i] = ntohs (nxt_word[i]); break; case 4: nxt_long = (int *) Hm_buff_addr; for (i = 0; i < n_bins; i++) nxt_long[i] = ntohl (nxt_long[i]); break; } } return EXIT_SUCCESS; } /* **--------------------------------------------------------------------------*/ void show_help () { /* ========= */ printf ("\n" " The following commands are recognised by SinqHM_Client:\n" "\n" " READ <#-bins> - read <#-bins> bins starting at\n" " . Dflt = 0\n" " Dflt <#-bins> = histogram size.\n" "\n" " WRITE - presets the histogram\n" " memory. The 6 parameters are used to generate\n" " a function.\n" "\n" " GO - start data acquisition.\n" "\n" " STOP - stop data acquisition.\n" "\n" " SHOW - show Hist Mem status.\n" "\n" " ZERO <#-bins> - zero <#-bins> bins starting at\n" " . Dflt = 0\n" " Dflt <#-bins> = histogram size.\n" "\n" " OPEN - open the connection to the Hist Mem.\n" "\n" " HELP or ? - generate this help text.\n" "\n" " The following environment variables should be set on Unix systems:\n" "\n" " setenv SINQHM_FRONTEND \" \"\n" " setenv SINQHM_DBG_MODE \n" "\n" " The following logical names should be set on VMS systems:\n" "\n" " define/group sinqhm_frontend \" \"\n" " define/group sinqhm_dbg_mode \n" "\n" " Defaults:\n" " None 0\n" " 2400\n" " 8192\n" "\n" " If is non-zero, the server will suspend to allow debugging.\n" "\n"); } /* **========================================================================== ** Main line program ** ----------------- **==========================================================================*/ main (int argc, char *argv[]) { /*==========================================================================*/ int i, j, k, status, is, nerr; char *cmnd; int bytes_to_come, bytes_to_go; int f_bin, n_bins, binwid, hist_num; unsigned int daq_was, daq_now, filler_mask, server_mask; int mode; char recd[256], recd1[256]; char last_recd[256] = {NIL}; char *verb, *p_p1, *p_p2, *p_p3, *p_p4, *p_p5, *p_p6; int l_recd; unsigned char *p_byte; unsigned short int *p_word; unsigned int *p_long; unsigned int total; /*============================================================================ */ printf ("SinqHM_Client Ident \"%s\" started.\n", ident); /*============================================================================ ** Declare an exit handler to tidy up if we get forced to exit. */ is = atexit (exit_handler); if (is != 0) { printf ("SinqHM_Client -- error setting up exit handler."); exit (is); } /*============================================================================ ** Find out the location of the SINQHM root and make ** a connection to it. Any errors during this phase cause the program ** to exit with an error status. */ get_SINQHM_FRONTEND (Rmt_node, sizeof (Rmt_node), "", &Rmt_port, PORT_BASE, &Pkt_size, 8192); if (Rmt_node[0] == NIL) { show_help (); printf ("\007\n" " The histogram memory is not defined correctly.\n" "\n" " If this is a UNIX system, check that the environment variable\n" " \"SINQHM_FRONTEND\" is defined correctly.\n" "\n" " If this is a VMS system, check that the logical name " "\"SINQHM_FRONTEND\" is\n" " defined correctly.\n" "\n"); return EXIT_FAILURE; } get_SINQHM_DBG_MODE (&mode, 0); /*====================================================== Wait for work ========= */ recd[0] = NIL; printf ("> "); while (fgets (recd, sizeof (recd), stdin) != NULL) { nerr = 0; /* Reset error counter for each unit of work. */ if (strlen (recd) == (sizeof (recd) - 1)) { printf ("\n\n\007Input buffer overflow -- command ignored!\n\n"); do { /* Flush the remains */ fgets (recd, sizeof (recd), stdin); } while (strlen (recd) == (sizeof (recd) - 1)); printf ("> "); continue; } i = strlen (recd) - 1; if (recd[i] == NL) recd[i] = NIL; /* Suppress the trailing \n */ if (recd[0] == NIL) { /* If just , repeat */ strcpy (recd, last_recd); } l_recd = sizeof (recd1); StrEdit (recd1, recd, "trim compress uncomment lowercase", &l_recd); if (l_recd <= 0) { /* Skip empty lines */ printf ("\n> "); continue; } /* ** Parse the command */ verb = strtok (recd1, " ,"); if ((strcmp (verb, "r") == 0) || (strcmp (verb, "re") == 0) || (strcmp (verb, "rea") == 0) || (strcmp (verb, "read") == 0)) { if (Rw_skt == 0) { Rw_skt = openConnectionGbl (Rmt_node, &Rmt_port, &Pkt_size, mode, &Rply_buff); if (Rw_skt == 0) FailInet ("\nopenConnection error."); } p_p1 = strtok (NULL, " ,"); /* Get pointers to the 3 args */ p_p2 = strtok (NULL, " ,"); p_p3 = strtok (NULL, " ,"); if ((p_p1 != NULL) && (sscanf (p_p1, "%d", &f_bin) == 1)) { if ((p_p2 != NULL) && (sscanf (p_p2, "%d", &n_bins) == 1)) { if ((p_p3 != NULL) && (sscanf (p_p3, "%d", &hist_num) == 1)) { }else { hist_num = 0; } }else { hist_num = 0; n_bins = Hm_nbins; } }else { hist_num = 0; n_bins = Hm_nbins; f_bin = 0; } printf ("\n Read histogram memory ...\n" " First bin = %5d\n" " Number of bins = %5d\n" " Histogram number = %5d\n", f_bin, n_bins, hist_num); /* ** Send the request message */ Req_buff.bigend = htonl (0x12345678); Req_buff.cmnd = htonl (SQHM_READ); Req_buff.u.read.hist_no = htonl (hist_num); Req_buff.u.read.first_bin = htonl (f_bin); Req_buff.u.read.n_bins = htonl (n_bins); status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0); if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n"); if (status != sizeof (Req_buff)) { printf ("SinqHM_Client -- wrong number of bytes sent: %d", status); exit (EXIT_FAILURE); } /* ** Now get the server's status message. */ status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0); if (status == -1) { FailInet ("SinqHM_Client -- R/W-Socket recv error\n"); exit (EXIT_FAILURE); }else if (status != sizeof (Rply_buff)) { printf ("SinqHM_Client -- Cnct-Socket recv error - "); printf ("unexpected byte count: %d.\n", status); exit (EXIT_FAILURE); } if (ntohl (Rply_buff.bigend) != 0x12345678) { printf ("\007" "SinqHM_Client -- big-endian/little-endian problem!\n" " Buffer received in non-network byte order!\n"); exit (EXIT_FAILURE); }else if (ntohl (Rply_buff.status) != KER__SUCCESS) { printf ("SinqHM_Client -- Bad status from Read Request: %d.\n", ntohl (Rply_buff.status)); printf (" \"%s\"\n", Rply_buff.u.message); exit (EXIT_FAILURE); } /* ** Allocate buffer space for holding the data. */ f_bin = ntohl (Rply_buff.u.read.first_bin); n_bins = ntohl (Rply_buff.u.read.n_bins); binwid = ntohl (Rply_buff.u.read.binwid); bytes_to_come = n_bins * binwid; if (bytes_to_come > Hm_buff_size) { /* Expand buffer space? */ Hm_buff_addr = realloc (Hm_buff_addr, bytes_to_come); /* Yes */ if (Hm_buff_addr != NULL) { Hm_buff_size = bytes_to_come; }else { printf ("SinqHM_Client -- " "error getting memory buffer for histogram data.\n"); exit (EXIT_FAILURE); } } /* ** Now read the data. */ p_byte = (unsigned char *) Hm_buff_addr; while (bytes_to_come > 0) { i = (bytes_to_come > Pkt_size) ? Pkt_size : bytes_to_come; status = recv (Rw_skt, (char *) p_byte, i, 0); if (status <= 0) { FailInet ("SinqHM_Client -- R/W-Socket recv error\n"); exit (EXIT_FAILURE); } bytes_to_come -= status; p_byte += status; } if (0x12345678 != ntohl (0x12345678)) { /* Swap bytes, if necessary */ total = 0; switch (Bin_wid) { case 1: p_byte = (unsigned char *) Hm_buff_addr; for (i=0; i 0) { i = (bytes_to_go > Pkt_size) ? Pkt_size : bytes_to_go; status = send (Rw_skt, (char *) p_byte, i, 0); if (status <= 0) { FailInet ("SinqHM_Client -- R/W-Socket send error\n"); exit (EXIT_FAILURE); } bytes_to_go -= status; p_byte += status; } /* ** Now get the server's status message. */ status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0); if (status == -1) { FailInet ("SinqHM_Client -- R/W-Socket recv error\n"); exit (EXIT_FAILURE); }else if (status != sizeof (Rply_buff)) { printf ("SinqHM_Client -- Cnct-Socket recv error - "); printf ("unexpected byte count: %d.\n", status); exit (EXIT_FAILURE); } if (ntohl (Rply_buff.bigend) != 0x12345678) { printf ("\007" "SinqHM_Client -- big-endian/little-endian problem!\n" " Buffer received in non-network byte order!\n"); exit (EXIT_FAILURE); }else if (ntohl (Rply_buff.status) != KER__SUCCESS) { printf ("SinqHM_Client -- Bad status from Write Request: %d.\n", ntohl (Rply_buff.status)); printf (" \"%s\"\n", Rply_buff.u.message); exit (EXIT_FAILURE); }else { printf (" done.\n"); } }else if ((strcmp (verb, "g") == 0) || (strcmp (verb, "go") == 0)) { if (Rw_skt == 0) { Rw_skt = openConnectionGbl (Rmt_node, &Rmt_port, &Pkt_size, mode, &Rply_buff); if (Rw_skt == 0) FailInet ("\nopenConnection error."); } printf ("\n Starting data acquisition ..."); /* ** Send the request message */ Req_buff.bigend = htonl (0x12345678); Req_buff.cmnd = htonl (SQHM_DAQ); Req_buff.u.daq.sub_cmnd = htonl (DAQ__GO); status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0); if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n"); if (status != sizeof (Req_buff)) { printf ("\007\n" "SinqHM_Client -- wrong number of bytes sent: %d", status); exit (EXIT_FAILURE); } /* ** Now get the server's status message. */ status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0); if (status == -1) { FailInet ("\nSinqHM_Client -- R/W-Socket recv error\n"); exit (EXIT_FAILURE); }else if (status != sizeof (Rply_buff)) { printf ("\007\n" "SinqHM_Client -- Cnct-Socket recv error - " "unexpected byte count: %d.\n", status); exit (EXIT_FAILURE); } if (ntohl (Rply_buff.bigend) != 0x12345678) { printf ("\007\n" "SinqHM_Client -- big-endian/little-endian problem!\n" " Buffer received in non-network byte order!\n"); exit (EXIT_FAILURE); }else if (ntohl (Rply_buff.status) != KER__SUCCESS) { printf ("\007\n" "SinqHM_Client -- Bad status from Go Request: %d.\n", ntohl (Rply_buff.status)); printf (" \"%s\"\n", Rply_buff.u.message); exit (EXIT_FAILURE); }else { daq_was = ntohs (Rply_buff.u.daq.daq_was); daq_now = ntohs (Rply_buff.u.daq.daq_now); filler_mask = ntohs (Rply_buff.u.daq.filler_mask); server_mask = ntohs (Rply_buff.u.daq.server_mask); if (daq_now == 0) { printf (" OK.\n"); if (daq_was == 0) printf ("\007 Actually, data acquisition was already active.\n"); }else { printf ("\007\n" " Data acquisition not yet started. The various masks" " are:\n" " Dsbl_Mask = 0x%08x\n" " Filler_Mask = 0x%08x\n" " Server_Mask = 0x%08x\n", daq_now, filler_mask, server_mask); } } }else if ((strcmp (verb, "st") == 0) || (strcmp (verb, "sto") == 0) || (strcmp (verb, "stop") == 0)) { if (Rw_skt == 0) { Rw_skt = openConnectionGbl (Rmt_node, &Rmt_port, &Pkt_size, mode, &Rply_buff); if (Rw_skt == 0) FailInet ("\nopenConnection error."); } printf ("\n Stopping data acquisition ..."); /* ** Send the request message */ Req_buff.bigend = htonl (0x12345678); Req_buff.cmnd = htonl (SQHM_DAQ); Req_buff.u.daq.sub_cmnd = htonl (DAQ__STOP); status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0); if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n"); if (status != sizeof (Req_buff)) { printf ("\007\n" "SinqHM_Client -- wrong number of bytes sent: %d", status); exit (EXIT_FAILURE); } /* ** Now get the server's status message. */ status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0); if (status == -1) { FailInet ("\nSinqHM_Client -- R/W-Socket recv error\n"); exit (EXIT_FAILURE); }else if (status != sizeof (Rply_buff)) { printf ("\007\n" "SinqHM_Client -- Cnct-Socket recv error - " "unexpected byte count: %d.\n", status); exit (EXIT_FAILURE); } if (ntohl (Rply_buff.bigend) != 0x12345678) { printf ("\007\n" "SinqHM_Client -- big-endian/little-endian problem!\n" " Buffer received in non-network byte order!\n"); exit (EXIT_FAILURE); }else if (ntohl (Rply_buff.status) != KER__SUCCESS) { printf ("\007\n" "SinqHM_Client -- Bad status from Stop Request: %d.\n", ntohl (Rply_buff.status)); printf (" \"%s\"\n", Rply_buff.u.message); exit (EXIT_FAILURE); }else { daq_was = ntohs (Rply_buff.u.daq.daq_was); daq_now = ntohs (Rply_buff.u.daq.daq_now); filler_mask = ntohs (Rply_buff.u.daq.filler_mask); server_mask = ntohs (Rply_buff.u.daq.server_mask); if (daq_now != 0) { printf (" OK. The various masks are:\n" " Dsbl_Mask = 0x%08x\n" " Filler_Mask = 0x%08x\n" " Server_Mask = 0x%08x\n", daq_now, filler_mask, server_mask); }else { printf ("\007\n" " Data acquisition is still active!\n"); } } }else if ((strcmp (verb, "z") == 0) || (strcmp (verb, "ze") == 0) || (strcmp (verb, "zer") == 0) || (strcmp (verb, "zero") == 0)) { if (Rw_skt == 0) { Rw_skt = openConnectionGbl (Rmt_node, &Rmt_port, &Pkt_size, mode, &Rply_buff); if (Rw_skt == 0) FailInet ("\nopenConnection error."); } p_p1 = strtok (NULL, " ,"); /* Get pointers to the 2 args */ p_p2 = strtok (NULL, " ,"); if ((p_p1 != NULL) && (sscanf (p_p1, "%d", &f_bin) == 1)) { if (p_p2 != NULL) { if (sscanf (p_p2, "%d", &n_bins) != 1) n_bins = Hm_nbins; } }else { f_bin = 0; n_bins = Hm_nbins; } printf ("\n Zeroing histogram memory ...\n" " First bin = %d\n" " # bins = %d\n", f_bin, n_bins); /* ** Send the request message first */ Req_buff.bigend = htonl (0x12345678); Req_buff.cmnd = htonl (SQHM_ZERO); Req_buff.u.zero.hist_no = htonl (-1); Req_buff.u.zero.first_bin = htonl (f_bin); Req_buff.u.zero.n_bins = htonl (n_bins); status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0); if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n"); if (status != sizeof (Req_buff)) { printf ("SinqHM_Client -- wrong number of bytes sent: %d", status); exit (EXIT_FAILURE); } /* ** Now get the server's status message. */ status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0); if (status == -1) { FailInet ("SinqHM_Client -- R/W-Socket recv error\n"); exit (EXIT_FAILURE); }else if (status != sizeof (Rply_buff)) { printf ("SinqHM_Client -- Cnct-Socket recv error - "); printf ("unexpected byte count: %d.\n", status); exit (EXIT_FAILURE); } if (ntohl (Rply_buff.bigend) != 0x12345678) { printf ("\007" "SinqHM_Client -- big-endian/little-endian problem!\n" " Buffer received in non-network byte order!\n"); exit (EXIT_FAILURE); }else if (ntohl (Rply_buff.status) != KER__SUCCESS) { printf ("SinqHM_Client -- Bad status from Zero Request: %d.\n", ntohl (Rply_buff.status)); printf (" \"%s\"\n", Rply_buff.u.message); exit (EXIT_FAILURE); }else { printf (" done.\n"); } }else if ((strcmp (verb, "s") == 0) || (strcmp (verb, "sh") == 0) || (strcmp (verb, "sho") == 0) || (strcmp (verb, "show") == 0)) { if (Rw_skt == 0) { Rw_skt = openConnectionGbl (Rmt_node, &Rmt_port, &Pkt_size, mode, &Rply_buff); if (Rw_skt == 0) FailInet ("\nopenConnection error."); } printf ("\n Getting histogram memory status ...\n"); /* ** Send the request message first */ Req_buff.bigend = htonl (0x12345678); Req_buff.cmnd = htonl (SQHM_STATUS); status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0); if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n"); if (status != sizeof (Req_buff)) { printf ("SinqHM_Client -- wrong number of bytes sent: %d", status); exit (EXIT_FAILURE); } /* ** Now get the server's status message. */ status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0); if (status == -1) { FailInet ("SinqHM_Client -- R/W-Socket recv error\n"); exit (EXIT_FAILURE); }else if (status != sizeof (Rply_buff)) { printf ("SinqHM_Client -- Cnct-Socket recv error - "); printf ("unexpected byte count: %d.\n", status); exit (EXIT_FAILURE); } if (ntohl (Rply_buff.bigend) != 0x12345678) { printf ("\007" "SinqHM_Client -- big-endian/little-endian problem!\n" " Buffer received in non-network byte order!\n"); exit (EXIT_FAILURE); }else if (ntohl (Rply_buff.status) != KER__SUCCESS) { printf ("SinqHM_Client -- Bad status from Status Request: %d.\n", ntohl (Rply_buff.status)); printf (" \"%s\"\n", Rply_buff.u.message); exit (EXIT_FAILURE); }else { /* ** Display the status obtained. */ if (Rply_buff.u.status.cfg_state == 0) { printf (" SINQHM has not yet been configured.\n"); printf ("\n Maximum number of parallel connections supported = %d.", Rply_buff.u.status.max_srvrs); printf ("\n Maximum number of histograms = %d.", ntohl (Rply_buff.u.status.max_n_hists)); printf ("\n Maximum number of bins per histogram = %d.", ntohl (Rply_buff.u.status.max_num_bins)); printf ("\n Maximum space available for histograms = %d.\n", ntohl (Rply_buff.u.status.max_block)); }else { memcpy (recd, (char *) &Rply_buff.sub_status, 4); /* Get SinqHM Id */ recd[4] = '\0'; printf ("\n SinqHM Identifier is \"%s\"", recd); printf ("\n Histogramming Mode = 0x%x", ntohl (Rply_buff.u.status.cfg_state)); printf ("\n Number of histograms/Current histogram = %d/%d", ntohs (Rply_buff.u.status.n_hists), (Rply_buff.u.status.curr_hist)); printf ("\n Number of bins per histogram = %d", ntohl (Rply_buff.u.status.num_bins)); printf ("\n Number of bytes per bin = %d", Rply_buff.u.status.binwid); printf ("\n Maximum number of parallel connections supported = %d.", Rply_buff.u.status.max_srvrs); printf ("\n Current number of connections = %d.", Rply_buff.u.status.act_srvrs); printf ("\n Maximum free memory block = %d bytes.", ntohl (Rply_buff.u.status.max_block)); if (Rply_buff.u.status.daq_now == 0) { printf ("\n Data acquisition is active\n"); }else { printf ("\n Data acquisition is not active\n"); } } } }else if ((strcmp (verb, "o") == 0) || (strcmp (verb, "op") == 0) || (strcmp (verb, "ope") == 0) || (strcmp (verb, "open") == 0)) { if (Rw_skt == 0) { printf ("\n Opening the connection ...\n"); Rw_skt = openConnectionGbl (Rmt_node, &Rmt_port, &Pkt_size, mode, &Rply_buff); if (Rw_skt == 0) FailInet ("\nopenConnection error."); }else { printf ("\n The connection is already open!"); } }else if ((strcmp (verb, "?") == 0) || (strcmp (verb, "h") == 0) || (strcmp (verb, "he") == 0) || (strcmp (verb, "hel") == 0) || (strcmp (verb, "help") == 0)) { show_help (); }else { printf ("\n Illegal command - type \"?\" for help.\n"); } strcpy (last_recd, recd); /* ** Get another command. */ printf ("> "); } /* ** Tell server we're quitting. */ printf (" Closing connection to %s ...\n", Rmt_node); Req_buff.bigend = htonl (0x12345678); Req_buff.cmnd = htonl (SQHM_CLOSE); status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0); Rw_bytes_put += status; if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n"); if (status != sizeof (Req_buff)) { printf ("SinqHM_Client -- wrong number of bytes sent: %d", status); exit (EXIT_FAILURE); } status = close (Rw_skt); Rw_skt = 0; if (status != 0) FailInet ("SinqHM_Client -- R/W-Socket close error\n"); exit (EXIT_SUCCESS); } /*============================================= End of SinqHM_Client.C ======*/