aboutsummaryrefslogtreecommitdiff
path: root/src/sman/nagman.c.pamphlet
diff options
context:
space:
mode:
authordos-reis <gdr@axiomatics.org>2007-08-14 05:14:52 +0000
committerdos-reis <gdr@axiomatics.org>2007-08-14 05:14:52 +0000
commitab8cc85adde879fb963c94d15675783f2cf4b183 (patch)
treec202482327f474583b750b2c45dedfc4e4312b1d /src/sman/nagman.c.pamphlet
downloadopen-axiom-ab8cc85adde879fb963c94d15675783f2cf4b183.tar.gz
Initial population.
Diffstat (limited to 'src/sman/nagman.c.pamphlet')
-rw-r--r--src/sman/nagman.c.pamphlet636
1 files changed, 636 insertions, 0 deletions
diff --git a/src/sman/nagman.c.pamphlet b/src/sman/nagman.c.pamphlet
new file mode 100644
index 00000000..c8db5f61
--- /dev/null
+++ b/src/sman/nagman.c.pamphlet
@@ -0,0 +1,636 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/sman nagman.c}
+\author{The Axiom Team}
+\maketitle
+\begin{abstract}
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+\section{nag.x}
+<<nag.x>>=
+
+/*
+ * msg.x: Remote message printing protocol
+ */
+const MAXASP = 10;
+
+/*
+ * the nago structure is essentially a variable length string
+ */
+
+struct nago {
+ opaque z <>;
+ };
+struct nagerr {
+nago p;
+nago q;
+};
+
+struct host{
+nago h <>;
+};
+
+struct nagst {
+
+/* Okay, if you understand this bit you know the essentials of how the link
+ * works. h <> is an array of nago, which is an array of fortran source
+ * code, the length of the array being the no. of asps (0 for most routines).
+ * y is the actual (XDR) input data for the routine. nm is the name of the
+ * routine. id is a tag identifying the host/axiom session. Finally per is a
+ * number telling whether or not to erase old fortran files on the remote
+ * machine (persistence - the number per distinct fortran files will be
+ * stored, any more than this and earlier ones will be deleted.
+ */
+
+ nago h <>;
+ nago y;
+ nago nm;
+ nago id;
+ int per;
+ };
+program NAGPROG {
+ version NAGVERS {
+ nagerr CALLNAG(nagst) = 1;
+ nago NAGMON(int)=2;
+ void AXEND(nago)=3;
+ } = 1;
+/*
+ * the following number is very important. It tells the
+ * portmapper what number to register the nag daemon under.
+ * There are rules about which number to pick - check SUN
+ * technical info for more details
+ */
+} = 100088;
+
+
+@
+\section{nagman}
+\subsection{includes}
+<<includes>>=
+#include "axiom-c-macros.h"
+#include "useproto.h"
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <termios.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <rpc/rpc.h> /* always needed */
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include "nag.h" /* generated by rpcgen */
+#include "com.h"
+#include "bsdsignal.h"
+#include "sockio-c.H1"
+#include "bsdsignal.H1"
+#include "nagman.H1"
+
+@
+\subsection{variables}
+<<variables>>=
+#ifdef ALPHAplatform
+extern int getdomainname( char *, int );
+#endif
+#ifdef SUN4OS5platform
+extern int getdomainname( char *, int );
+extern int gethostname( char *, int );
+#endif
+
+#ifdef _NO_PROTO
+nagerr * callnag_1();
+nago * nagmon_1();
+void * axend_1();
+#else
+nagerr * callnag_1(nagst *,CLIENT *);
+nago * nagmon_1(int *,CLIENT *);
+void * axend_1(nago *,CLIENT *);
+#endif
+
+#define DO 1
+#define DONT 0
+
+int hnum, vmax;
+char *datafile, *resultsfile;
+
+struct hostnode {
+ char * name;
+ struct hostnode *next;
+} *hlist=NULL;
+
+nagst nag4;
+Sock *sock1;
+
+@
+\subsection{term}
+this code runs when the user quits axiom. before nagman dies, it does
+an rpc call to nagd to tell it to get rid of files etc. The rpc call in
+question is [[axend_1]]
+we also send a USR1 to sman to beget another nagman
+<<term>>=
+static void
+#ifdef _NO_PROTO
+term(sig)
+ int sig;
+#else
+term(int sig)
+#endif
+{
+ CLIENT *cld;
+ void *res;
+ struct hostnode *pnode;
+
+#ifndef HP9platform /* can't figure out a way to do this on HP/UX 9 */
+ kill(atoi(getenv("SPADNUM")) , SIGUSR1);
+#endif
+
+
+ if(hnum!=0)
+ {
+ unlink(datafile);
+ unlink(resultsfile);
+ }
+
+ for(pnode=hlist;pnode!=NULL;pnode=pnode->next)
+ {
+ cld=clnt_create(pnode->name,NAGPROG, NAGVERS, "tcp");
+ if (cld == NULL)
+ goto NOHOST;
+
+ res=axend_1(&(nag4.id),cld);
+ NOHOST:
+ clnt_destroy(cld);
+ }
+ exit(0);
+}
+
+@
+\subsection{size\_of\_file}
+<<sizeoffile>>=
+static long
+#ifdef _NO_PROTO
+size_of_file(filename)
+ char *filename;
+#else
+size_of_file(char *filename)
+#endif
+{
+ struct stat buf_stat;
+
+ stat(filename,&buf_stat);
+ return (buf_stat.st_size);
+
+}
+
+@
+\subsection{rpcloop}
+<<rpcloop>>=
+static void
+#ifdef _NO_PROTO
+rpcloop()
+#else
+rpcloop(void)
+#endif
+{
+ CLIENT *cl;
+ int res,j,v=0,u,showMessage;
+ long i;
+ register struct hostent *alias1, *alias2;
+ struct in_addr *addrnum;
+ u_long junk;
+ struct timeval tv;
+ nagerr *result;
+ char *Buf , *buf1;
+ char *ffile[MAXASP];
+ char routine[12], naghost[256];
+ FILE *nfp1, *nfp2, *nfp3;
+ struct hostnode *phost;
+ int fd;
+
+ for (;;)
+ {
+
+ if((Buf=get_string(sock1))==NULL) term(1); /* one string carries all */
+
+ if(hnum!=0)
+ {
+ /* call parameters */
+ free(nag4.nm.z.z_val); /* the routine name */
+ free(nag4.y.z.z_val); /* the XDR data */
+ for(i=0;i<v;i++)
+ {
+ unlink(ffile[i]);
+ free(ffile[i]); /* the asp filenames */
+ free(nag4.h.h_val[i].z.z_val); /* the asps themselves*/
+ }
+ free(nag4.h.h_val); /* the asps array */
+ unlink(datafile);
+ unlink(resultsfile);
+ free(resultsfile);
+ free(datafile);
+ vmax= (v>vmax)? v : vmax;
+ }
+
+
+
+
+ buf1=strtok(Buf," ");
+ if (buf1) strcpy(naghost,buf1);
+ else printf("can't parse the naghost\n");
+ /* INFO printf("%s\n",naghost);*/
+
+ buf1=strtok(NULL," ");
+ if (buf1) strcpy(routine,buf1);
+ else printf("can't parse the routine\n");
+ /* INFO printf("%s\n",routine);*/
+
+ /* make copy of filenames because we will reuse Buf before deleting the files*/
+ buf1=strtok(NULL," ");
+ if (buf1) resultsfile=strdup(buf1);
+ else printf("can't parse the resultsfile file\n");
+ /* INFO printf("%s\n",resultsfile);*/
+
+ buf1=strtok(NULL," ");
+ if (buf1) datafile=strdup(buf1);
+ else printf("can't parse the datafile file\n");
+ /* INFO printf("%s\n",datafile);*/
+
+ buf1=strtok(NULL," ");
+ if (buf1) nag4.per=atoi(buf1);
+ else printf("can't parse the persistence\n");
+ /* INFO printf("%d\n",nag4.per);*/
+
+ buf1=strtok(NULL," ");
+ if (buf1) {
+ if (!strcmp(buf1,"on")) showMessage=DO;
+ else showMessage=DONT;
+ }
+ else printf("can't parse the messages flag\n");
+ /* INFO printf("%s\n",buf1);*/
+
+ v=0; /* asp counter */
+ while( (buf1=strtok(NULL," ")) )
+ {
+ ffile[v++]=strdup(buf1);
+ /* INFO printf("%s\n",ffile[v-1]);*/
+ }
+
+ /* INFO printf("number of asps seen %d\n",v);*/
+
+ if(showMessage==DO) printf("nagman:acknowledging request for %s\n",routine);
+
+ res=0; /* prepare result integer to be sent to Lisp */
+
+ if((nfp3=fopen(resultsfile,"w"))==NULL)
+ {
+ printf("can't open output file\n");
+ goto END;
+ }
+
+ /* nag4.h is the XDR array of asp text */
+ nag4.h.h_len=v;
+ nag4.h.h_val=(nago *)malloc((v)*sizeof(nago));
+
+
+ /* get asp text in call argument */
+ for(u=0;u<v;u++)
+ {
+ /* this should be done by mmap */
+ if((nfp1=fopen(ffile[u],"r"))==NULL)
+ {
+ fprintf(stderr,"can't open asp file %s\n",ffile[u]);
+ fclose(nfp1);
+ goto END;
+ }
+ fclose(nfp1);
+ i=size_of_file(ffile[u]);
+
+ /* allocs memory for the file */
+ nag4.h.h_val[u].z.z_val= (char *)malloc((i+1)*sizeof(char));
+
+ fd=open(ffile[u],O_RDONLY);
+ read(fd,nag4.h.h_val[u].z.z_val,i);
+ close(fd);
+ /* make null-term. string */
+ nag4.h.h_val[u].z.z_val[i]='\0';
+ /* set the length */
+ nag4.h.h_val[u].z.z_len=strlen(nag4.h.h_val[u].z.z_val);
+ }
+
+
+ nag4.nm.z.z_val=strdup(routine);
+ nag4.nm.z.z_len=strlen(routine);
+
+ /* get XDR data in call argument */
+ /* should be done by mmap */
+ if((nfp2=fopen(datafile,"r"))==NULL)
+ {
+ fprintf(stderr,"can't open data file\n");
+ fclose(nfp2);
+ goto END;
+ }
+
+ fclose(nfp2);
+ i=size_of_file(datafile);
+ nag4.y.z.z_val=(char *)malloc(i*sizeof(char));
+
+ fd=open(datafile,O_RDONLY);
+ read(fd,nag4.y.z.z_val,i);
+ close(fd);
+ nag4.y.z.z_len=i;
+
+
+ /*
+ * Create client "handle" used for calling MESSAGEPROG on
+ * the server designated on the command line. We tell
+ * the RPC package to use the "tcp" protocol when
+ * contacting the server.
+ */
+
+ /* update naghost by lookup */
+
+ if ((junk = inet_addr(naghost))!=-1)
+ {
+ addrnum=(struct in_addr *)junk;
+ if((alias2=gethostbyaddr((char *)&addrnum,
+ sizeof(addrnum),
+ AF_INET))!=NULL)
+ strcpy(naghost,alias2->h_name);
+ else
+ if((alias1=gethostbyname(naghost))!=NULL)
+ strcpy(naghost,alias1->h_name);
+ }
+ else
+ if((alias1=gethostbyname(naghost))!=NULL)
+ strcpy(naghost,alias1->h_name);
+
+
+
+
+ cl = clnt_create(naghost, NAGPROG, NAGVERS, "tcp");
+ if (cl == NULL)
+ {
+ /*
+ * Couldn't establish connection with server.
+ * Print error message and die.
+ */
+ clnt_pcreateerror(naghost);
+ goto END;
+ }
+ else
+ if (showMessage==DO)
+ printf("nagman:connection successful to %s\n",naghost);
+
+ /*
+ * this number here sets the "timeout" for the rpc call. after this number
+ * of seconds, the call will quit if no response is received
+ *
+ */
+
+ tv.tv_sec=1000000;
+ tv.tv_usec=0;
+ clnt_control(cl,CLSET_TIMEOUT,(char *)&tv);
+
+
+ result = callnag_1(&nag4, cl);
+
+ for(phost=hlist;phost!=NULL;phost=phost->next)
+ {
+ /*
+ * hlist is the "hostlist" of sites that have been contacted by nagman.
+ * here we check if this call is contacting a new site, and if so add it
+ * to the hostlist
+ *
+ */
+
+ if(!strcmp(phost->name,naghost))
+ goto SKIP;
+ }
+
+ if(hnum==0) {
+ hlist=(struct hostnode *)malloc(sizeof(struct hostnode));
+ hlist->name=strdup(naghost);
+ hlist->next=NULL;
+ }
+
+ else {
+ phost=(struct hostnode *)malloc(sizeof(struct hostnode));
+ phost->name=strdup(naghost);
+ phost->next=hlist;
+ hlist=phost;
+ }
+ hnum++;
+
+
+ SKIP:
+ if (result == NULL)
+ {
+ /*
+ * An error occurred while calling the server.
+ * Print error message and die.
+ */
+ if (showMessage==DO)
+ printf("nagman:no results (error) from %s\n",naghost);
+ clnt_perror(cl,naghost);
+ clnt_destroy(cl);
+ goto END;
+ }
+
+ /*
+ * (*result).p is the part of the result with the XDRed results in it
+ * (numbers). (*result).q is the part with (text) error messages that
+ * have come from the NAG library. If there is neither an XDR result,
+ * nor a text error message from the library, then something is wrong
+ * so we just print out the "no result or error returned" message.
+ *
+ */
+
+ else if ((*result).p.z.z_len==0)
+ {
+ if((*result).q.z.z_len==0)
+ {
+ if (showMessage==DO)
+ printf("nagman:empty result (error) from %s\n",naghost);
+ clnt_destroy(cl);
+ goto END;
+ }
+ else
+ {
+ if (showMessage==DO)
+ printf("nagman:receiving results from %s\n\n",naghost);
+ for(j=0;j<(*result).q.z.z_len;j++)
+ printf("%c",(*result).q.z.z_val[j]);
+ clnt_destroy(cl);
+ goto END;
+ }
+ }
+ else
+ if (showMessage==DO)
+ printf("nagman:receiving results from %s\n\n",naghost);
+
+ if (showMessage==DO)
+ fwrite(result->q.z.z_val,sizeof(char),result->q.z.z_len,stdout);
+
+ /*INFO printf("\nRESULTS of length %d\n",(*result).p.z.z_len);*/
+
+ fwrite(result->p.z.z_val,sizeof(char),result->p.z.z_len, nfp3);
+ res=1;
+ clnt_destroy(cl);
+
+ /*
+ * in case of any type of error, a goto END in the above code causes
+ * nagman to skip here and return to AXIOM
+ *
+ */
+
+
+ END:
+ fclose(nfp3);
+ /*
+ * if everything has gone alright, send_int returns the integer res=1. If
+ * not it returns res=0. This is detected by the boot code which acts
+ * accordingly.
+ */
+ send_int(sock1,res);
+ free(Buf);
+ }
+
+
+}
+
+@
+\subsection{catchSignals}
+catchSignals sets up signal handling. If nagman gets a sigterm it does not
+die but goes back to rpcloop
+<<catchSignals>>=
+static void
+#ifdef _NO_PROTO
+catchSignals()
+#else
+catchSignals(void)
+#endif
+{
+ bsdSignal(SIGTERM,term,RestartSystemCalls);
+ bsdSignal(SIGSEGV,term,RestartSystemCalls);
+}
+
+@
+\subsection{main}
+<<main>>=
+void
+#ifdef _NO_PROTO
+main(argc,argv)
+int argc;
+char **argv;
+#else
+main(int argc,char **argv)
+#endif
+{
+ char this[256],*hname,*dname,*spadnum;
+ int stat;
+
+ catchSignals();
+ stat=gethostname(this,256);
+ if (stat!=0) perror("gethostname");
+ hname=strdup(this);
+
+ stat=getdomainname(this,256);
+ if (stat!=0) perror("getdomainname");
+ dname=strdup(this);
+ spadnum=getenv("SPADNUM");
+ if (spadnum==0) {
+ fprintf(stderr,"nagman error: SPADNUM is not in the environment\n");
+ exit(0);
+ }
+
+ /* some machines return a full name from hostname
+ need to check hname has a . in it */
+
+ if (strchr(hname,'.'))
+ /* '.' found */
+ sprintf(this,"%s_%i",hname,atoi(spadnum));
+ else
+ /* substring not found */
+ sprintf(this,"%s.%s_%i",hname,dname,atoi(spadnum));
+
+ /* this must contain the Internet address of the current host */
+ nag4.id.z.z_val=strdup(this);
+ nag4.id.z.z_len=strlen(nag4.id.z.z_val);
+ hnum=0;
+ vmax=0;
+ /*
+ * this line sets up a socket for communication with the lisp
+ */
+
+ sock1 = connect_to_local_server(SpadServer, DebugWindow, 120 /*seconds*/);
+ if (!sock1) exit(0);
+
+ rpcloop();
+}
+
+@
+\subsection{nagman}
+<<nagman>>=
+#define _NAGMAN_C
+<<includes>>
+<<variables>>
+<<term>>
+<<sizeoffile>>
+<<rpcloop>>
+<<catchSignals>>
+<<main>>
+@
+\section{License}
+<<license>>=
+/*
+Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+@
+<<*>>=
+<<license>>
+<<nagman>>
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}