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