1 
2 #include <sys/utsname.h>
3 #include <sys/time.h>
4 #include <signal.h>
5 #include <unistd.h>
6 
7 /*------------------------------------------------------------------------*/
THD_death_now_now_now(int sig)8 static void THD_death_now_now_now(int sig)
9 {
10 #if 0
11   fprintf(stderr,"\n** AFNI version check exits via safety timer **\n") ;
12 #endif
13   _exit(0) ;
14 }
15 
16 /***-------------------------------------------------------------------***/
17 /*!  This function is intended to be called from within a fork()-ed
18      off child, and it will cause the child process to die after so
19      many milliseconds have passed -- the intention is to prevent
20      any zombies from hanging around, in case the child fails to
21      complete itself properly for some hideously grotesque reason.
22 *//*-------------------------------------------------------------------***/
23 
THD_death_setup(int msec)24 void THD_death_setup( int msec )
25 {
26    struct itimerval itval ;
27    struct timeval tva, tvb ;
28 
29    if( msec <= 0 ) return ;
30    tva.tv_sec  = msec/1000 ;
31    tva.tv_usec = (msec%1000)*1000 ;
32    tvb.tv_sec  = tvb.tv_usec = 0 ;
33 
34    itval.it_interval = tvb ;
35    itval.it_value    = tva ;
36 
37    signal(SIGALRM,THD_death_now_now_now) ;  /* invoked when timer ends */
38    (void)setitimer( ITIMER_REAL , &itval , NULL ) ;
39    return ;
40 }
41 
42 /*------------------------------------------------------------------------*/
43 #ifndef ENABLE_THD_check_AFNI_version   /* 13 Jul 2020 */
44 
THD_check_AFNI_version(char * pname)45 void THD_check_AFNI_version( char *pname ){ return ; }
46 
47 /*------------------------------------------------------------------------*/
48 #else  /*-------- version checking from a 3d*.c program ------------------*/
49 
50 #include "afni.h"
51 
52 /*------------------------------------------------------------------------*/
53 
54 #undef  VSIZE
55 #define VSIZE  1066
56 #undef  VDELAY
57 #define VDELAY 429999  /* 429999 s = 5 days */
58 
59 /*------------------------------------------------------------------------*/
60 /*! Function to check AFNI version.  Forks and returns to caller almost
61     instantly.  The only output is from the child process to stderr;
62     a message will be printed if the version check doesn't match.
63 --------------------------------------------------------------------------*/
64 
THD_check_AFNI_version(char * pname)65 void THD_check_AFNI_version( char *pname )
66 {
67    int nbuf ;
68    pid_t ppp ;
69    char *vbuf=NULL , vv[128]="none" , *vvaa ;
70    char *home , mname[VSIZE]="file:" ;
71    char *motd=NULL ;
72    NI_stream ns ;
73 
74    /* This function breaks MOTD usage.
75       Ponder, do we use a new .afni.vctime.cmdline file?
76                                    30 Dec 2015 [RCR/DRG] */
77    return ;
78 
79    if( ! AFNI_yesenv("AFNI_VERSION_CHECK") || machdep_be_quiet() ) return ;
80 
81    /* get time of last check -- do nothing if was very recent */
82 
83    home=getenv("HOME") ;
84    if( home != NULL ) strcat(mname,home);
85    strcat(mname,"/.afni.vctime") ;
86 
87    ns = NI_stream_open( mname , "r" ) ;
88    if( ns != NULL ){
89      NI_element *nel = NI_read_element(ns,11) ;
90      NI_stream_close(ns) ;
91      if( nel != NULL ){
92        char *rhs ; int done=0 ;
93        rhs = NI_get_attribute(nel,"version_check_time") ;
94        if( rhs != NULL ){
95          int last_time = (int)strtol(rhs,NULL,10) ;
96          int dtime     = ((int)time(NULL)) - last_time ;
97          done = ( dtime >= 0 && dtime < VDELAY ) ;  /* too soon */
98        }
99        rhs = NI_get_attribute(nel,"motd") ;      /* 29 Nov 2005 */
100        if( rhs != NULL ) motd = strdup(rhs) ;
101        NI_free_element(nel) ;
102        if( done ) return ;
103      }
104    }
105 
106    /* recall that fork() return value is
107         < 0 for an error
108         > 0 in the parent
109        == 0 in the child  */
110 
111    ppp = fork() ;
112 
113    if( ppp < 0 ) return ; /* fork failed */
114 
115    /* parent: wait for child to exit (happens almost instantly) */
116 
117    if( ppp > 0 ){ waitpid(ppp,NULL,0); return; }  /* parent */
118 
119    /* below here is the child, which never returns:
120       fork again immediately, then this child exits;
121       this is to prevent zombie processes from hanging around */
122 
123    ppp = fork() ; if( ppp != 0 ) _exit(0) ;
124 
125    /* grandchild process continues to do the actual work */
126 
127    THD_death_setup( 12345 ) ; /* die in 12.345 seconds, no matter what */
128 
129    /*-- setup the "User-agent:" header for HTTP --*/
130 
131 #define USE_HTTP_10
132 
133 #ifdef USE_HTTP_10
134 #  undef PCLAB
135 #  ifdef SHOWOFF
136 #    undef SHSH
137 #    undef SHSHSH
138 #    define SHSH(x)   #x
139 #    define SHSHSH(x) SHSH(x)
140 #    define PCLAB     SHSHSH(SHOWOFF)
141 #  else
142 #    define PCLAB     "Unknown"
143 #  endif
144 #endif
145 
146 #ifdef USE_HTTP_10
147      { int jj ;
148        struct utsname ubuf ;
149        char ua[512] ;
150 
151        if( pname == NULL ) pname = "afni" ;
152        ubuf.nodename[0] = ubuf.sysname[0] = ubuf.machine[0] = '\0' ;
153        jj = uname( &ubuf ) ;
154        if( jj >= 0 && ubuf.nodename[0] != '\0' )
155          sprintf( ua ,
156                  "%s (avers='%s'; prec='%s' node='%s'; sys='%s'; mach='%s')" ,
157                   pname,AVERZHN,PCLAB,ubuf.nodename,ubuf.sysname,ubuf.machine );
158        else
159          sprintf( ua , "%s (avers='%s'; prec='%s')" , pname , AVERZHN , PCLAB );
160 
161        set_HTTP_10( 1 ) ;
162        set_HTTP_user_agent( ua ) ;
163      }
164 #else
165      set_HTTP_10( 0 ) ;
166 #endif
167 
168    /*-- NOW, fetch information from the AFNI master computer --*/
169 
170    nbuf = read_URL( AFNI_VERSION_URL , &vbuf ) ;  /* see thd_http.c */
171 
172 #ifdef USE_HTTP_10
173    set_HTTP_10( 0 ) ;
174 #endif
175 
176    if( nbuf <= 0 || vbuf == NULL || vbuf[0] == '\0' ) _exit(0) ; /* failed */
177 
178    vvaa = strstr(vbuf,"AFNI_") ;   if( vvaa == NULL ) _exit(0) ;
179 
180    /* get the first string -- that is the current AFNI version number */
181 
182    sscanf( vvaa , "%127s" , vv ) ;
183 
184    /* compare with compiled-in version (from afni.h) */
185 
186    if( strcmp(vv,AVERZHN) != 0 )
187     fprintf(stderr,"\n"
188                    "++ VERSION CHECK!  This program = %s\n"
189                    "++         Current AFNI website = %s\n" ,
190             AVERZHN , vv ) ;
191 
192    /* record the current time and AVERZHN, so we don't check too often */
193 
194    ns = NI_stream_open( mname , "w" ) ;
195    if( ns != NULL ){
196      NI_element *nel=NI_new_data_element("AFNI_vctime",0); char rhs[32];
197      sprintf(rhs,"%d",(int)time(NULL)) ;
198      NI_set_attribute( nel , "version_check_time" , rhs ) ;
199      if( strcmp(vv,"none") != 0 )
200        NI_set_attribute( nel , "version_string" , AVERZHN ) ;
201      if( motd != NULL ){     /* 29 Nov 2005 */
202        NI_set_attribute( nel , "motd" , motd ); free((void *)motd) ;
203      }
204      NI_write_element( ns , nel , NI_TEXT_MODE ) ;
205      NI_stream_close(ns) ;
206      NI_free_element(nel) ;
207    }
208 
209    /* Alas, poor Version Check, I knew him well */
210 
211    _exit(0) ;
212 }
213 #endif /* ENABLE_THD_check_AFNI_version */
214