diff options
author | dos-reis <gdr@axiomatics.org> | 2007-08-14 05:14:52 +0000 |
---|---|---|
committer | dos-reis <gdr@axiomatics.org> | 2007-08-14 05:14:52 +0000 |
commit | ab8cc85adde879fb963c94d15675783f2cf4b183 (patch) | |
tree | c202482327f474583b750b2c45dedfc4e4312b1d /src/sman/nagman.c.pamphlet | |
download | open-axiom-ab8cc85adde879fb963c94d15675783f2cf4b183.tar.gz |
Initial population.
Diffstat (limited to 'src/sman/nagman.c.pamphlet')
-rw-r--r-- | src/sman/nagman.c.pamphlet | 636 |
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} |