Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

afni_version.c

Go to the documentation of this file.
00001 #include "afni.h"
00002 #include <sys/utsname.h>
00003 
00004 #define FAIL_MESSAGE(reason)                           \
00005  do{ fprintf(stderr,"\n"                               \
00006                     "\n** Version check disabled: %s", \
00007              reason ) ;                                \
00008      disabled = 1 ; } while(0)
00009 
00010 static int disabled = 0 ;
00011 
00012 #define VERSION_URL "http://afni.nimh.nih.gov/afni/AFNI.version"
00013 #define STR_CHILD   "tcp:localhost:20279"
00014 #define AFNI_HOST   "http://afni.nimh.nih.gov/afni/"
00015 #define VSIZE       1024
00016 
00017 static pid_t vc_child_pid = (pid_t)(-1) ;
00018 static IOCHAN *vc_ioc     = NULL ;
00019 
00020 #undef VERBOSE   /* print messages on failure? */
00021 
00022 /*------------------------------------------------------------------------*/
00023 /*!  This is only called from within the child process. */
00024 
00025 static void vexit( int sig )
00026 {
00027 #ifdef VERBOSE
00028    static volatile int fff=0 ;
00029    if( fff ) _exit(1) ; else fff = 1 ;
00030    fprintf(stderr,"** Version Check: child fails to complete: %d **\n",sig);
00031 #endif
00032    _exit(1);
00033 }
00034 
00035 /*------------------------------------------------------------------------*/
00036 /*! This is called at main AFNI process exit,
00037     to destroy vc_ioc if it is still open.
00038 --------------------------------------------------------------------------*/
00039 
00040 static void vc_exit(void){ iochan_close(vc_ioc) ; }  /* 12 Dec 2002 */
00041 
00042 /*------------------------------------------------------------------------*/
00043 /*! Start the Web fetch to check the AFNI version in a child process.
00044     To complete things, call AFNI_version_check() somewhat later.
00045 --------------------------------------------------------------------------*/
00046 
00047 void AFNI_start_version_check(void)
00048 {
00049    pid_t child_pid ;
00050 
00051 #ifdef CYGWIN  /* 18 Dec 2002 */
00052    FAIL_MESSAGE("not possible under Cygwin") ;
00053    return ;
00054 #else
00055 
00056    /*-- decide if we are to do anything --*/
00057 
00058    if( AFNI_noenv("AFNI_VERSION_CHECK") ){    /* never check */
00059      FAIL_MESSAGE("AFNI_VERSION_CHECK forbids") ;
00060      return ;
00061    }
00062 
00063 #undef  VDELAY
00064 #define VDELAY 429999  /* 429999 s = 5 days */
00065    /* check if we did this in the last VDELAY seconds */
00066 
00067    { char *home=getenv("HOME") , mname[VSIZE]="file:" ;
00068      NI_stream ns ;
00069      if( home != NULL ) strcat(mname,home) ;
00070      strcat(mname,"/.afni.vctime") ;
00071      ns = NI_stream_open( mname , "r" ) ;
00072      if( ns != NULL ){
00073        NI_element *nel = NI_read_element(ns,22) ;
00074        NI_stream_close(ns) ;
00075        if( nel != NULL ){
00076          char *rhs ;
00077          rhs = NI_get_attribute( nel , "version_check_time" ) ;
00078          if( rhs != NULL ){
00079            int last_time = strtol(rhs,NULL,10) ;
00080            int dtime = ((int)time(NULL)) - last_time ;
00081            if( dtime >= 0 && dtime < VDELAY ){ /* don't check */
00082              NI_free_element(nel) ; disabled = 1 ; return ;
00083            }
00084          }
00085          rhs = NI_get_attribute(nel,"version_string") ;  /* 27 Jan 2003 */
00086          if( rhs != NULL && strcmp(rhs,VERSION) != 0 ){
00087            fprintf(stderr,
00088                    "\n** Your AFNI version changed from %s to %s since last check\n",
00089                    rhs , VERSION ) ;
00090          }
00091          NI_free_element(nel) ;
00092        }
00093      }
00094    }
00095 
00096    /*-- OK, start the child process --*/
00097 
00098    child_pid = fork() ;
00099    if( child_pid == (pid_t)(-1) ){  /* bad */
00100      FAIL_MESSAGE("can't fork") ;
00101      return ;
00102    }
00103 
00104    if( child_pid > 0 ){                     /* I'm the parent */
00105 
00106      /*-- save PID of child for later use --*/
00107 
00108      vc_child_pid = child_pid ;
00109 
00110      /*-- open a shared mem segment to talk to child --*/
00111 
00112      vc_ioc = iochan_init( STR_CHILD , "accept" ) ;
00113      if( vc_ioc == NULL ){
00114        kill(child_pid,SIGTERM) ;            /* cf. Abraham and Isaac */
00115        vc_child_pid = (pid_t)(-1) ;
00116        FAIL_MESSAGE("can't open connection to child") ;
00117      } else {
00118        fprintf(stderr,"\n** Version check: " VERSION_URL "\n" ); /* 13 Jan 2003 */
00119        atexit( vc_exit ) ;                                       /* 12 Dec 2002 */
00120      }
00121      return ;
00122 
00123    } else {                                 /* I'm the child */
00124                                             /* (never returns) */
00125      int nbuf=0 , jj ;
00126      char *vbuf=NULL ;
00127      IOCHAN *ioc ;
00128      struct utsname ubuf ;
00129      char ua[512] ;
00130 
00131      iochan_enable_perror(0) ;   /* don't print TCP/IP error messages */
00132      signal( SIGTERM , vexit ) ; /* if parent kills us, call vexit()  */
00133 
00134      /*-- get information from the AFNI server --*/
00135 
00136 #define USE_HTTP_10
00137 
00138 #ifdef USE_HTTP_10
00139 #  undef PCLAB
00140 #  ifdef SHOWOFF
00141 #    undef SHSH
00142 #    undef SHSHSH
00143 #    define SHSH(x)   #x
00144 #    define SHSHSH(x) SHSH(x)
00145 #    define PCLAB     SHSHSH(SHOWOFF)
00146 #  else
00147 #    define PCLAB     "Unknown"
00148 #  endif
00149 #endif
00150 
00151      /** 25 Mar 2005: send more info in the request header **/
00152 
00153 #ifdef USE_HTTP_10
00154      ubuf.nodename[0] = ubuf.sysname[0] = ubuf.machine[0] = '\0' ;
00155      jj = uname( &ubuf ) ;
00156      if( jj >= 0 && ubuf.nodename[0] != '\0' )
00157        sprintf( ua ,
00158                "afni (avers='%s'; prec='%s' node='%s'; sys='%s'; mach='%s')" ,
00159                 VERSION, PCLAB, ubuf.nodename, ubuf.sysname, ubuf.machine   ) ;
00160      else
00161        sprintf( ua , "afni (avers='%s'; prec='%s')" , VERSION , PCLAB ) ;
00162 
00163      set_HTTP_10( 1 ) ;
00164      set_HTTP_user_agent( ua ) ;
00165 #else
00166      set_HTTP_10( 0 ) ;
00167 #endif
00168 
00169      /* send the request */
00170 
00171      nbuf = read_URL( VERSION_URL , &vbuf ) ;  /* may take a while */
00172 
00173      set_HTTP_10( 0 ) ;
00174 
00175      /*-- if this failed, quit --*/
00176 
00177      if( nbuf <= 0 || vbuf == NULL || vbuf[0] == '\0' ) vexit(1);
00178 
00179      /*-- talk to parent process thru shared memory --*/
00180 
00181      ioc = iochan_init( STR_CHILD , "create" ) ;
00182      if( ioc == NULL )                                  vexit(2);
00183 
00184      /*-- wait until ioc is ready for writing --*/
00185 
00186      jj = iochan_writecheck(ioc,-1) ;
00187      if( jj < 0 )                                       vexit(3);
00188 
00189      /*-- send the info in vbuf --*/
00190 
00191      iochan_sendall( ioc , vbuf , nbuf ) ;
00192      while( ! iochan_clearcheck(ioc,10) )  /* loop until cleared */
00193        iochan_sleep(10) ;                  /* by parent process  */
00194 
00195      iochan_sleep(10); /* a little extra napping */     _exit(0);
00196    }
00197 #endif  /* not CYGWIN */
00198 }
00199 
00200 /******************************************/
00201 
00202 #ifdef VERBOSE
00203 # define KAPUT(ss)                                          \
00204   do{ fprintf(stderr,"** Version Check fails: %s **\n",ss); \
00205       return ; } while(0)
00206 #else
00207 # define KAPUT(ss) return
00208 #endif
00209 
00210 /*------------------------------------------------------------------------*/
00211 /*! Complete the version check by seeing if the child process
00212     has any data to report from the AFNI web site.  Returns 1 if the
00213     version at the AFNI site doesn't match the version of this program;
00214     returns 0 if they match, or it can't tell.  Also prints stuff out.
00215 --------------------------------------------------------------------------*/
00216 
00217 int AFNI_version_check(void)
00218 {
00219    int jj , nbuf=0 ;
00220    char *vbuf=NULL ;
00221    char vv[128]="none" ;
00222    char *sname , *vvbuf ;
00223 
00224 #ifdef CYGWIN   /* 30 Jun 2005 [rickr] */
00225 
00226    return 0;
00227 
00228 #else
00229 
00230    /* if something is rotten, then toss it out */
00231 
00232    if( disabled ) return 0 ;   /* 27 Jan 2003 */
00233 
00234    if( vc_ioc == NULL || vc_child_pid == (pid_t)(-1) ) KAPUT("bad child state");
00235 
00236    jj = kill(vc_child_pid,0) ;                /* is child alive? */
00237    if( jj < 0 ){
00238      IOCHAN_CLOSE(vc_ioc); vc_child_pid=(pid_t)(-1);
00239      KAPUT("child not alive");
00240    }
00241 
00242    jj = iochan_readcheck( vc_ioc , 333 ) ;    /* is iochan open yet? */
00243    if( jj <= 0 ){
00244      IOCHAN_CLOSE(vc_ioc); kill(vc_child_pid,SIGTERM); vc_child_pid=(pid_t)(-1);
00245      KAPUT("connection to child gone bad");
00246    }
00247 
00248    /* if here, have data ready to read from child! */
00249 
00250    nbuf = 0 ;
00251    vbuf = AFMALL( char, VSIZE) ;
00252    while(1){
00253      jj = iochan_recv( vc_ioc , vbuf+nbuf , VSIZE-nbuf ) ;
00254      if( jj < 1 ) break ;
00255      nbuf += jj ;
00256      if( nbuf >= VSIZE-1 ) break ;
00257      jj = iochan_readcheck( vc_ioc , 5 ) ;
00258      if( jj < 1 ) break ;
00259    }
00260 
00261    /* now wait for child to kill itself */
00262 
00263    waitpid(vc_child_pid,NULL,WNOHANG); vc_child_pid = (pid_t)(-1);
00264    IOCHAN_CLOSE(vc_ioc);
00265 
00266    /* no data? */
00267 
00268    if( nbuf <= 0 ){ free(vbuf); vbuf = NULL; KAPUT("bad version data"); } /* unlikely */
00269 
00270    /* extract version and data/time strings from data */
00271 
00272 #ifdef USE_HTTP_10
00273    vvbuf = strstr(vbuf,"\r\n\r\n") ;
00274    if( vvbuf == NULL ) vvbuf = vbuf      ;
00275    else                vvbuf = vvbuf + 4 ;
00276 #else
00277    vvbuf = vbuf ;
00278 #endif
00279 
00280    sscanf( vvbuf , "%127s" , vv ); free(vbuf);
00281 
00282    /* record the current time, so we don't check too often */
00283 
00284    { char *home=getenv("HOME") , mname[VSIZE]="file:" ;
00285      NI_stream ns ;
00286      if( home != NULL ) strcat(mname,home) ;
00287      strcat(mname,"/.afni.vctime") ;
00288      ns = NI_stream_open( mname , "w" ) ;
00289      if( ns != NULL ){
00290        NI_element *nel=NI_new_data_element("AFNI_vctime",0); char rhs[32];
00291        sprintf(rhs,"%d",(int)time(NULL)) ;
00292        NI_set_attribute( nel , "version_check_time" , rhs ) ;
00293        if( strcmp(vv,"none") != 0 )                            /* 27 Jan 2003 */
00294          NI_set_attribute( nel , "version_string" , VERSION ) ;
00295        NI_write_element( ns , nel , NI_TEXT_MODE ) ;
00296        NI_stream_close(ns) ;
00297      }
00298    }
00299 
00300    /* compare version strings */
00301 
00302    if( strcmp(vv,VERSION) == 0 ){                    /* versions match */
00303      fprintf(stderr,"\n** Version check: you are up-to-date!\n"
00304                       "** To disable future version checks:\n"
00305                       "** set environment variable AFNI_VERSION_CHECK to NO.\n"
00306                       "** Version checks are done about every %.1f days.\n",
00307              rint(VDELAY/86400.0) ) ;
00308      return 0 ;
00309    }
00310 
00311    /* print a message about version mismatch */
00312 
00313    fprintf(stderr, "\n"
00314                    "****************************************************\n"
00315                    " This AFNI was compiled with the following settings:\n"
00316                    "   Version ID   = %s\n"
00317                    " Latest version at %s\n"
00318                    "   Version ID   = %s\n"
00319                    "****************************************************\n"
00320                    " To disable future version checks:\n"
00321                    " set environment variable AFNI_VERSION_CHECK to NO\n"
00322                    "****************************************************\n"
00323           , VERSION, AFNI_HOST , vv ) ;
00324 
00325    return 1 ;
00326 
00327 #endif /* CYGWIN */
00328 }
00329 
00330 /*----------------------------------------------------------------------*/
00331 /***---------------- 20 Nov 2003: auto-download stuff ----------------***/
00332 
00333 #ifdef SHOWOFF
00334 # undef SHSH
00335 # undef SHSHSH
00336 # define SHSH(x)   #x
00337 # define SHSHSH(x) SHSH(x)
00338 
00339 # define SNAME "AFNI_UPDATER"   /* script file name */
00340 
00341 char * AFNI_make_update_script(void)
00342 {
00343    char *pg_ftp , *pg_afni , *pg_gzip , *pg_tar ;
00344    char hbuf[4096], fname[128], adir[4096], *cpt, cwd[4096] ;
00345    FILE *fp ;
00346    static char sname[4096] ;
00347 
00348    pg_ftp  = THD_find_executable("ftp" ); if( pg_ftp  == NULL ) return NULL;
00349    pg_afni = THD_find_executable("afni"); if( pg_afni == NULL ) return NULL;
00350    pg_gzip = THD_find_executable("gzip"); if( pg_gzip == NULL ) return NULL;
00351    pg_tar  = THD_find_executable("tar" ); if( pg_tar  == NULL ) return NULL;
00352 
00353    strcpy(adir,pg_afni) ;                /* extract name of AFNI directory */
00354    cpt = THD_trailname(adir,0) ;
00355    *cpt = '\0' ;
00356    if( strlen(adir) <= 0 ) return NULL ; /* no AFNI directory? */
00357 
00358    strcpy( cwd , adir ) ;                /* try to write a test file there */
00359    strcat( cwd , "afni_qadgop" ) ;
00360    fp = fopen( cwd , "a" ) ;
00361    if( fp == NULL ) return NULL ;        /* can't write to AFNI directory? */
00362    fclose(fp) ; remove(cwd) ;
00363 
00364    getcwd( cwd , 4096 ) ;   /* get current directory for later use */
00365    chdir( adir ) ;          /* switch to AFNI directory for this work */
00366 
00367    /* write a script to get and install the binary archive via FTP */
00368 
00369    gethostname( hbuf , 4096 ) ;
00370    strcpy( fname , SHSHSH(SHOWOFF) ) ; strcat( fname , ".tgz" ) ;
00371    fp = fopen( SNAME , "w" ) ; if( fp == NULL ){ chdir(cwd); return NULL; }
00372    fprintf( fp ,
00373             "#!/bin/sh\n"
00374             "echo '++ FTP-ing %s from afni.nimh.nih.gov'\n"
00375             "%s -n afni.nimh.nih.gov << EEEEE\n"   /* FTP to get file */
00376             "user anonymous AFNI_UPDATER@%s\n"
00377             "binary\n"
00378             "cd tgz\n"
00379             "get %s\n"
00380             "bye\n"
00381             "EEEEE\n"
00382             "echo '++ Unpacking %s'\n"
00383             "%s -dc %s | %s xf -\n"      /* uncompress and untar .tgz file */
00384             "/bin/rm -f %s\n"            /* delete .tgz file */
00385             "echo '++ Moving files'\n"
00386             "/bin/mv -f %s/* .\n"        /* move untar-ed files up to here */
00387             "/bin/rm -rf %s\n"           /* remove any directory leftovers */
00388             "echo '++ Finished'\n" ,
00389             fname ,                 /* filename to get (for 'FTP-ing' echo) */
00390             pg_ftp ,                /* FTP program */
00391             hbuf ,                  /* hostname, for FTP password */
00392             fname ,                 /* filename to get (for FTP) */
00393             fname ,                 /* ditto (for 'Unpacking' echo) */
00394             pg_gzip, fname, pg_tar, /* GZIP program, filename, TAR program */
00395             fname ,                 /* filename to delete */
00396             SHSHSH(SHOWOFF) ,       /* directory to copy up */
00397             SHSHSH(SHOWOFF)         /* directory to delete */
00398           ) ;
00399    fclose( fp ) ;
00400    chmod( SNAME , S_IRUSR | S_IWUSR | S_IXUSR ) ; /* mark as executable */
00401 
00402    /* get back to current working directory, then leave */
00403 
00404    chdir(cwd) ;
00405    sprintf(sname,"%s%s",adir,SNAME) ; return sname ;
00406 }
00407 
00408 #else /* undefined SHOWOFF */
00409 char * AFNI_make_update_script(void){ return NULL; }
00410 #endif /* SHOWOFF */
 

Powered by Plone

This site conforms to the following standards: