Main Page | Class List | Directories | File List | Class Members | File Members

cfexecd.c

Go to the documentation of this file.
00001 /* 
00002         Copyright (C) 1995-
00003         Free Software Foundation, Inc.
00004 
00005    This file is part of GNU cfengine - written and maintained 
00006    by Mark Burgess, Dept of Computing and Engineering, Oslo College,
00007    Dept. of Theoretical physics, University of Oslo
00008  
00009    This program is free software; you can redistribute it and/or modify it
00010    under the terms of the GNU General Public License as published by the
00011    Free Software Foundation; either version 2, or (at your option) any
00012    later version.
00013  
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018  
00019   You should have received a copy of the GNU General Public License
00020   along with this program; if not, write to the Free Software
00021   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
00022 
00023 */
00024 
00025 /*******************************************************************/
00026 /*                                                                 */
00027 /* Cfexecd : local scheduling daemon                               */
00028 /*                                                                 */
00029 /*******************************************************************/
00030 
00031 #include "../pub/getopt.h"
00032 #include "cf.defs.h"
00033 #include "cf.extern.h"
00034 
00035 #ifdef NT
00036 #include <process.h>
00037 #endif
00038 
00039 /*******************************************************************/
00040 /* Pthreads                                                        */
00041 /*******************************************************************/
00042 
00043 
00044 #ifdef HAVE_PTHREAD_H
00045 # include <pthread.h>
00046 #endif
00047 
00048 #ifdef HAVE_SCHED_H
00049 # include <sched.h>
00050 #endif
00051 
00052 #ifdef HAVE_PTHREAD_H
00053 pthread_attr_t PTHREADDEFAULTS;
00054 pthread_mutex_t MUTEX_COUNT = PTHREAD_MUTEX_INITIALIZER;
00055 pthread_mutex_t MUTEX_HOSTNAME = PTHREAD_MUTEX_INITIALIZER;
00056 #endif
00057 
00058 /*******************************************************************/
00059 /* GLOBAL VARIABLES                                                */
00060 /*******************************************************************/
00061 
00062 int NO_FORK = false;
00063 int ONCE = false;
00064 
00065 struct option CFDOPTIONS[] =
00066    {
00067    { "help",no_argument,0,'h' },
00068    { "debug",optional_argument,0,'d' }, 
00069    { "verbose",no_argument,0,'v' },
00070    { "file",required_argument,0,'f' },
00071    { "no-fork",no_argument,0,'F' },
00072    { "once",no_argument,0,'1'},
00073    { "foreground",no_argument,0,'g'},
00074    { "parse-only",no_argument,0,'p'},
00075    { "ld-library-path",required_argument,0,'L'},
00076    { NULL,0,0,0 }
00077    };
00078 
00079 char MAILTO[bufsize];
00080 int MAXLINES = -1;
00081 const int INF_LINES = -2;
00082 
00083 /*******************************************************************/
00084 /* Functions internal to cfservd.c                                 */
00085 /*******************************************************************/
00086 
00087 void CheckOptsAndInit ARGLIST((int argc,char **argv));
00088 void StartServer ARGLIST((int argc, char **argv));
00089 void Syntax ARGLIST((void));
00090 void *ExitCleanly ARGLIST((void));
00091 void *LocalExec ARGLIST((void *dummy));
00092 void MailResult ARGLIST((char *filename, char *to));
00093 int ScheduleRun ARGLIST((void));
00094 void AddClassToHeap ARGLIST((char *class));
00095 void DeleteClassFromHeap ARGLIST((char *class));
00096 void Dialogue  ARGLIST((int sd,char *class));
00097 void GetCfStuff ARGLIST((void));
00098 
00099 /* 
00100  * HvB: Bas van der Vlies
00101 */
00102 int CompareResult ARGLIST((char *filename, char *prev_file));
00103 int FileChecksum ARGLIST((char *filename, unsigned char *digest, char type));
00104 
00105 /*******************************************************************/
00106 /* Level 0 : Main                                                  */
00107 /*******************************************************************/
00108 
00109 int main (argc,argv)
00110 
00111 int argc;
00112 char **argv;
00113 
00114 { time_t starttime = time(NULL);
00115  
00116 CheckOptsAndInit(argc,argv);
00117 
00118 if (!ONCE)
00119    {
00120    /* Get a lock as long as no other cfexecd is running. */
00121 
00122    if (!GetLock("cfexecd","execd",0,0,VUQNAME,starttime))
00123       {
00124       snprintf(OUTPUT,bufsize*2,"cfexecd: Couldn't get a lock -- exists or too soon: IfElapsed %d, ExpireAfter %d\n",0,0);
00125       CfLog(cfverbose,OUTPUT,"");
00126       return 1;
00127       }
00128    }
00129    
00130 StartServer(argc,argv);
00131 
00132 if (!ONCE)
00133    {
00134    ReleaseCurrentLock();
00135    }
00136  
00137 return 0;
00138 }
00139 
00140 /********************************************************************/
00141 /* Level 1                                                          */
00142 /********************************************************************/
00143 
00144 void CheckOptsAndInit(argc,argv)
00145 
00146 int argc;
00147 char **argv;
00148 
00149 { extern char *optarg;
00150   int optindex = 0;
00151   char ld_library_path[bufsize];
00152   int c;
00153 
00154 ld_library_path[0] = '\0';
00155 
00156 sprintf(VPREFIX, "cfexecd"); 
00157 openlog(VPREFIX,LOG_PID|LOG_NOWAIT|LOG_ODELAY,LOG_DAEMON);
00158 
00159 while ((c=getopt_long(argc,argv,"L:d:vhpFV1g",CFDOPTIONS,&optindex)) != EOF)
00160   {
00161   switch ((char) c)
00162       {
00163       case 'd': 
00164 
00165                 switch ((optarg==NULL)?3:*optarg)
00166                    {
00167                    case '1': D1 = true;
00168                              break;
00169                    case '2': D2 = true;
00170                              break;
00171                    default:  DEBUG = true;
00172                              break;
00173                    }
00174                 
00175                 NO_FORK = true;
00176                 printf("cfexecd Debug mode: running in foreground\n");
00177                 break;
00178 
00179       case 'v': VERBOSE = true;
00180                 break;
00181 
00182       case 'V': printf("GNU %s-%s daemon\n%s\n",PACKAGE,VERSION,COPYRIGHT);
00183                 printf("This program is covered by the GNU Public License and may be\n");
00184                 printf("copied free of charge. No warrenty is implied.\n\n");
00185                 exit(0);
00186                 break;
00187 
00188       case 'p': PARSEONLY = true;
00189                 break;
00190 
00191       case 'g': NO_FORK = true;
00192                 break;
00193 
00194       case 'L': Verbose("Setting LD_LIBRARY_PATH=%s\n",optarg);
00195                 snprintf(ld_library_path,bufsize-1,"LD_LIBRARY_PATH=%s",optarg);
00196                 putenv(ld_library_path);
00197                 break;
00198 
00199       case 'F':
00200       case '1': ONCE = true;
00201                 NO_FORK = true;
00202                 break;
00203 
00204       default:  Syntax();
00205                 exit(1);
00206 
00207       }
00208    }
00209 
00210 LOGGING = true;                    /* Do output to syslog */
00211 
00212 snprintf(VBUFF,bufsize,"%s/inputs/update.conf",WORKDIR);
00213 MakeDirectoriesFor(VBUFF,'y');
00214 snprintf(VBUFF,bufsize,"%s/bin/cfagent",WORKDIR);
00215 MakeDirectoriesFor(VBUFF,'y');
00216 snprintf(VBUFF,bufsize,"%s/outputs/spooled_reports",WORKDIR);
00217 MakeDirectoriesFor(VBUFF,'y');
00218 
00219 snprintf(VBUFF,bufsize,"%s/inputs",WORKDIR);
00220 chmod(VBUFF,0700); 
00221 snprintf(VBUFF,bufsize,"%s/outputs",WORKDIR);
00222 chmod(VBUFF,0700);
00223 
00224 strncpy(VLOCKDIR,WORKDIR,bufsize-1);
00225 strncpy(VLOGDIR,WORKDIR,bufsize-1);
00226 
00227 VCANONICALFILE = strdup(CanonifyName(VINPUTFILE));
00228 GetNameInfo();
00229 
00230 strcpy(VUQNAME,VSYSNAME.nodename);
00231 }
00232 
00233 
00234 /*******************************************************************/
00235 
00236 void StartServer(argc,argv)
00237 
00238 int argc;
00239 char **argv;
00240 
00241 { int time_to_run = false;
00242   time_t now = time(NULL); 
00243 
00244 if ((!NO_FORK) && (fork() != 0))
00245    {
00246    snprintf(OUTPUT,bufsize*2,"cfexecd starting %.24s\n",ctime(&now));
00247    CfLog(cfinform,OUTPUT,"");
00248    exit(0);
00249    }
00250 
00251 if (!NO_FORK)
00252   {
00253   ActAsDaemon(0);
00254   }
00255 
00256 signal(SIGINT,(void *)ExitCleanly);
00257 signal(SIGTERM,(void *)ExitCleanly);
00258 signal(SIGHUP,SIG_IGN);
00259 signal(SIGPIPE,SIG_IGN);
00260  
00261 umask(077);
00262 
00263 if (ONCE)
00264    {
00265    GetCfStuff();
00266    LocalExec(NULL);
00267    }
00268 else
00269    { char **nargv;
00270      int i;
00271      int pid;
00272 #ifdef HAVE_PTHREAD_H
00273      pthread_t tid;
00274 #endif
00275 
00276    /*
00277     * Append --once option to our arguments for spawned monitor process.
00278     */
00279    nargv = malloc(sizeof(char *) * argc+2);
00280    
00281    for (i = 0; i < argc; i++)
00282       {
00283       nargv[i] = argv[i];
00284       }
00285    
00286    nargv[i++] = strdup("--once");
00287    nargv[i++] = NULL;
00288    
00289    GetCfStuff();
00290    
00291    while (true)
00292       {
00293       time_to_run = ScheduleRun();
00294       
00295       if (time_to_run)
00296          {
00297          if (!GetLock("cfd","exec",exec_ifelapsed,exec_expireafter,VUQNAME,time(NULL)))
00298             {
00299             snprintf(OUTPUT,bufsize*2,"cfexecd: Couldn't get exec lock -- exists or too soon: IfElapsed %d, ExpireAfter %d\n",exec_ifelapsed,exec_expireafter);
00300             CfLog(cfverbose,OUTPUT,"");
00301             continue;
00302             }
00303          
00304          GetCfStuff();
00305          
00306 #ifdef NT 
00307          /*
00308           * Spawn a separate process - spawn will work if the cfexecd binary
00309           * has changed (where cygwin's fork() would fail).
00310           */
00311          
00312          Debug("Spawning %s\n", nargv[0]);
00313          pid = spawnvp((int)_P_NOWAIT, nargv[0], nargv);
00314          if (pid < 1)
00315             {
00316             CfLog(cferror,"Can't spawn run","spawnvp");
00317             }
00318          
00319 #elsif (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD)
00320          
00321          pthread_attr_init(&PTHREADDEFAULTS);
00322          pthread_attr_setdetachstate(&PTHREADDEFAULTS,PTHREAD_CREATE_DETACHED);
00323 
00324 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
00325          pthread_attr_setstacksize(&PTHREADDEFAULTS,(size_t)2048*1024);
00326 #endif
00327 
00328          if (pthread_create(&tid,&PTHREADDEFAULTS,LocalExec,NULL) != 0)
00329             {
00330             CfLog(cferror,"Can't create thread!","pthread_create");
00331             LocalExec(NULL);
00332             }
00333 
00334          pthread_attr_destroy(&PTHREADDEFAULTS);
00335 #else
00336          LocalExec(NULL);        
00337 #endif
00338          
00339          ReleaseCurrentLock();
00340          }
00341       }
00342    }
00343 }
00344 
00345 /*********************************************************************/
00346 /* Level 2                                                           */
00347 /*********************************************************************/
00348 
00349 void Syntax()
00350 
00351 { int i;
00352 
00353 printf("GNU cfengine daemon: scheduler\n%s-%s\n%s\n",PACKAGE,VERSION,COPYRIGHT);
00354 printf("\n");
00355 printf("Options:\n\n");
00356 
00357 for (i=0; CFDOPTIONS[i].name != NULL; i++)
00358    {
00359    printf("--%-20s    (-%c)\n",CFDOPTIONS[i].name,(char)CFDOPTIONS[i].val);
00360    }
00361 
00362 printf("\nBug reports to bug-cfengine@gnu.org (News: gnu.cfengine.bug)\n");
00363 printf("General help to help-cfengine@gnu.org (News: gnu.cfengine.help)\n");
00364 printf("Info & fixes at http://www.iu.hio.no/cfengine\n");
00365 }
00366 
00367 /*******************************************************************/
00368 
00369 void GetCfStuff()
00370 
00371 { FILE *pp;
00372   char cfcom[bufsize];
00373   static char line[bufsize];
00374 
00375 snprintf(cfcom,bufsize-1,"%s/bin/cfagent -z",WORKDIR);
00376  
00377 if ((pp=cfpopen(cfcom,"r")) ==  NULL)
00378    {
00379    CfLog(cferror,"Couldn't start cfengine!","cfpopen");
00380    line[0] = '\0';
00381    return;
00382    }
00383 
00384 line[0] = '\0'; 
00385 fgets(line,bufsize,pp); 
00386 Chop(line); 
00387 
00388 while (strstr(line,":"))
00389    {
00390    line[0] = '\0'; 
00391    fgets(line,bufsize,pp); 
00392    Chop(line);    
00393    }
00394 
00395 if (strstr(line,"No SMTP"))
00396    {
00397    CfLog(cferror,"cfengine defines no SMTP server (not even localhost)","");
00398    CfLog(cferror,"Need: smtpserver = ( ?? ) in control ","");
00399    }
00400 
00401 strcpy(VMAILSERVER,line); 
00402  
00403 Debug("Got cfengine SMTP server as (%s)\n",VMAILSERVER); 
00404 
00405 line[0] = '\0'; 
00406 fgets(line,bufsize,pp); 
00407 Chop(line); 
00408 
00409 if (strlen(line) == 0)
00410    {
00411    CfLog(cferror,"cfengine defines no system administrator address","");
00412    CfLog(cferror,"Need: sysadm = ( ??@?? ) in control ","");
00413    }
00414 
00415 strcpy(MAILTO,line); 
00416 Debug("Got cfengine sysadm variable (%s)\n",MAILTO); 
00417 
00418 line[0] = '\0'; 
00419 fgets(line,bufsize,pp); 
00420 Chop(line); 
00421 strcpy(VFQNAME,line); 
00422 Debug("Got fully qualified name (%s)\n",VFQNAME); 
00423 
00424 line[0] = '\0'; 
00425 fgets(line,bufsize,pp); 
00426 Chop(line); 
00427 strcpy(VIPADDRESS,line); 
00428 Debug("Got IP (%s)\n",VIPADDRESS); 
00429 
00430 if ((ungetc(fgetc(pp), pp)) != '[')
00431    {
00432    line[0] = '\0';
00433    fgets(line,bufsize,pp);
00434    Chop(line);
00435    if (sscanf(line, "%d", &MAXLINES) == 1)
00436       {
00437       Debug("Got max lines (%d)\n", MAXLINES); 
00438       }
00439    else if (strcmp(line, "inf") == 0)
00440       {
00441       Debug("Infinite lines\n");
00442       MAXLINES = INF_LINES;
00443       }
00444    }
00445 
00446 if (MAXLINES == -1)
00447    {
00448    MAXLINES = 100;
00449    Debug("Defaulting to max lines (%d)\n", MAXLINES);
00450    }
00451 
00452 /* Now get scheduling constraints */
00453 
00454 DeleteItemList(SCHEDULE);
00455 SCHEDULE = NULL; 
00456  
00457 while (!feof(pp))
00458    {
00459    line[0] = '\0';
00460    VBUFF[0] = '\0';
00461    fgets(line,bufsize,pp);
00462    sscanf(line,"[%[^]]",VBUFF);
00463 
00464    if (strlen(VBUFF)==0)
00465       {
00466       continue;
00467       }
00468    
00469    if (!IsItemIn(SCHEDULE,VBUFF))
00470       {
00471       AppendItem(&SCHEDULE,VBUFF,NULL);
00472       }
00473    }
00474 
00475 cfpclose(pp);
00476 
00477 if (SCHEDULE == NULL)
00478    {
00479    Verbose("No schedule defined in cfagent.conf, defaulting to Min00_05\n");
00480    AppendItem(&SCHEDULE,"Min00_05",NULL);
00481    }
00482 }
00483 
00484 /*********************************************************************/
00485 
00486 int ScheduleRun()
00487 
00488 { time_t now;
00489   char timekey[64];
00490   struct Item *ip;
00491 
00492 Verbose("Sleeping...\n");
00493 sleep(60);          /* 1 Minute resolution is enough */ 
00494 
00495 now = time(NULL);
00496 
00497 snprintf(timekey,63,"%s",ctime(&now)); 
00498 AddTimeClass(timekey); 
00499 
00500 for (ip = SCHEDULE; ip != NULL; ip = ip->next)
00501    {
00502    Verbose("Checking schedule %s...\n",ip->name);
00503    if (IsDefinedClass(ip->name))
00504       {
00505       Verbose("Waking up the agent at %s ~ %s \n",timekey,ip->name);
00506       DeleteItemList(VHEAP);
00507       VHEAP = NULL;
00508       GetNameInfo();
00509       return true;
00510       }
00511    }
00512 
00513 DeleteItemList(VHEAP);
00514 VHEAP = NULL; 
00515 GetNameInfo();
00516 return false;
00517 }
00518 
00519 /*********************************************************************/
00520 /* Level 3                                                           */
00521 /*********************************************************************/
00522 
00523 void *ExitCleanly()
00524 
00525 {
00526 ReleaseCurrentLock();
00527 closelog();
00528  
00529 exit(0);
00530 }
00531 
00532 /**************************************************************/
00533 
00534 void *LocalExec(dummy)
00535 
00536 void *dummy;
00537 
00538 { FILE *pp; 
00539   char line[bufsize],filename[bufsize],*sp;
00540   char cmd[bufsize];
00541   int print;
00542   time_t starttime = time(NULL);
00543   FILE *fp;
00544 #ifdef HAVE_PTHREAD_SIGMASK
00545  sigset_t sigmask;
00546 
00547 sigemptyset(&sigmask);
00548 pthread_sigmask(SIG_BLOCK,&sigmask,NULL); 
00549 #endif
00550 
00551  
00552 Verbose("------------------------------------------------------------------\n\n");
00553 Verbose("  LocalExec at %s\n",ctime(&starttime));
00554 Verbose("------------------------------------------------------------------\n"); 
00555 
00556 /* Need to make sure we have LD_LIBRARY_PATH here or children will die  */
00557  
00558 snprintf(cmd,bufsize-1,"%s/bin/cfagent",WORKDIR);
00559 snprintf(line,100,CanonifyName(ctime(&starttime)));
00560 snprintf(filename,bufsize-1,"%s/outputs/cf_%s_%s",WORKDIR,CanonifyName(VFQNAME),line);
00561 
00562 
00563 /* What if no more processes? Could sacrifice and exec() - but we need a sentinel */
00564 
00565 if ((fp = fopen(filename,"w")) == NULL)
00566    {
00567    snprintf(OUTPUT,bufsize,"Couldn't open %s\n",filename);
00568    CfLog(cferror,OUTPUT,"fopen");
00569    return NULL;
00570    }
00571  
00572 if ((pp = cfpopen(cmd,"r")) == NULL)
00573    {
00574    snprintf(OUTPUT,bufsize,"Couldn't open pipe to command %s\n",cmd);
00575    CfLog(cferror,OUTPUT,"cfpopen");
00576    return NULL;
00577    }
00578  
00579 while (!feof(pp) && ReadLine(line,bufsize,pp))
00580    {
00581    if (ferror(pp))
00582       {
00583       fflush(pp);
00584       break;
00585       }  
00586    
00587    print = false;
00588       
00589    for (sp = line; *sp != '\0'; sp++)
00590       {
00591       if (! isspace((int)*sp))
00592          {
00593          print = true;
00594          break;
00595          }
00596       }
00597    
00598    if (print)
00599       {
00600       fprintf(fp,"%s\n",line);
00601       
00602       /* If we can't send mail, log to syslog */
00603       
00604       if (strlen(MAILTO) == 0)
00605          {
00606          strcat(line,"\n");
00607          CfLog(cfinform,line,"");
00608          }
00609       
00610       line[0] = '\0';
00611       }
00612    }
00613  
00614 cfpclose(pp);
00615 Debug("Closing fp\n");
00616 fclose(fp);
00617 closelog();
00618   
00619 MailResult(filename,MAILTO);
00620 return NULL; 
00621 }
00622 
00623 /******************************************************************/
00624 /* Level 4                                                        */
00625 /******************************************************************/
00626 
00627 /*
00628  * HvB: Bas van der Vlies
00629  * This function is "stolen" from the checksum.c. Else we have to link so
00630  * many more files with cfexecd. There also some small changes.
00631 */
00632 int FileChecksum(filename,digest,type)
00633 
00634 char *filename,type;
00635 unsigned char digest[EVP_MAX_MD_SIZE+1];
00636 
00637 { FILE *file;
00638   EVP_MD_CTX context;
00639   int len, md_len;
00640   unsigned char buffer[1024];
00641   const EVP_MD *md = NULL;
00642 
00643 Debug2("ChecksumFile(%c,%s)\n",type,filename);
00644 OpenSSL_add_all_digests();
00645 
00646 if ((file = fopen (filename, "rb")) == NULL)
00647    {
00648    printf ("%s can't be opened\n", filename);
00649    }
00650 else
00651    {
00652    switch (type)
00653       {
00654       case 's': md = EVP_get_digestbyname("sha");
00655                 break;
00656       case 'm': md = EVP_get_digestbyname("md5");
00657                 break;
00658       default: FatalError("Software failure in ChecksumFile");
00659       }
00660 
00661    if (!md)
00662       {
00663       return 0;
00664       }
00665    
00666    EVP_DigestInit(&context,md);
00667 
00668    while (len = fread(buffer,1,1024,file))
00669       {
00670       EVP_DigestUpdate(&context,buffer,len);
00671       }
00672 
00673    EVP_DigestFinal(&context,digest,&md_len);
00674 
00675    /* Digest length stored in md_len */
00676    fclose (file);
00677 
00678    return(md_len);
00679    }
00680 
00681 return 0; 
00682 }
00683 
00684 
00685 /*
00686  * HvB: Bas van der Vlies
00687  *  This function compare the current result with the previous run
00688  *  and returns:
00689  *    0 : if the files are the same
00690  *    1 : if the files differ
00691 */
00692 int CompareResult(filename, prev_file)
00693 
00694 char *filename, *prev_file; 
00695 
00696 { int i;
00697   char digest1[EVP_MAX_MD_SIZE+1];
00698   char digest2[EVP_MAX_MD_SIZE+1];
00699   int  md_len1, md_len2;
00700   FILE *fp;
00701 
00702 Verbose("Comparing files  %s with %s\n", prev_file, filename);
00703 
00704 if ((fp=fopen(prev_file,"r")) != NULL)
00705    {
00706    fclose(fp);
00707 
00708    md_len1 = FileChecksum(prev_file, digest1, 'm');
00709    md_len2 = FileChecksum(filename,  digest2, 'm');
00710 
00711    if (md_len1 != md_len2)
00712       {
00713       return(1);
00714       }
00715 
00716    for (i = 0; i < md_len1; i++)
00717       {
00718       if (digest1[i] != digest2[i])
00719          {
00720          /* Current file will now be the previous result */
00721          unlink(prev_file);
00722          if (symlink(filename, prev_file) == -1) 
00723             {
00724             snprintf(OUTPUT,bufsize,"Could not link %s and %s",filename,prev_file);
00725             CfLog(cfinform,OUTPUT,"symlink");
00726             }
00727 
00728          return(1);
00729          }
00730       }
00731 
00732    return(0);
00733    }
00734 else
00735    {
00736    /* no previous file */
00737    if ( symlink(filename, prev_file) == -1 ) 
00738       {
00739       snprintf(OUTPUT,bufsize,"Could not link %s and %s",filename,prev_file);
00740       CfLog(cfinform,OUTPUT,"symlink");
00741       }
00742    return(1);
00743    }
00744 }
00745 
00746 /***********************************************************************/
00747 
00748 void MailResult(file,to)
00749 
00750 char *file,*to;
00751 
00752 { int sd, sent, count = 0;
00753   struct hostent *hp;
00754   struct sockaddr_in raddr;
00755   struct servent *server;
00756   struct stat statbuf;
00757   FILE *fp;
00758 
00759   /* HvB: Bas van der Vlies */
00760   char prev_file[bufsize];
00761 
00762 if ((strlen(VMAILSERVER) == 0) || (strlen(to) == 0))
00763    {
00764    /* Syslog should have done this*/
00765    return;
00766    }
00767   
00768 if (stat(file,&statbuf) == -1)
00769    {
00770    exit(0);
00771    }
00772 
00773 /* HvB: Bas van der Vlies */
00774 snprintf(prev_file,bufsize-1,"%s/outputs/previous",WORKDIR);
00775  
00776 if (statbuf.st_size == 0)
00777    {
00778    unlink(file);
00779 
00780    /* HvB: Bas van der Vlies 
00781     * also remove previous file 
00782    */
00783    if ((fp=fopen(prev_file, "r")) != NULL )
00784       {
00785       fclose(fp);
00786       unlink(prev_file);
00787       }
00788 
00789    Debug("Nothing to report in %s\n",file);
00790    return;
00791    }
00792 
00793 /*
00794  * HvB: Check if the result is the same as the previous run.
00795  *
00796 */
00797 if ( CompareResult(file,prev_file) == 0 ) 
00798    {
00799    Verbose("Previous output is the same as current so do not mail it\n");
00800    return;
00801    }
00802 
00803 if (MAXLINES == 0)
00804    {
00805    Debug("Not mailing: EmailMaxLines was zero\n");
00806    return;
00807    }
00808  
00809 Debug("Mailing results of (%s) to (%s)\n",file,to);
00810  
00811 if (strlen(to) == 0)
00812    {
00813    return;
00814    }
00815 
00816 if ((fp=fopen(file,"r")) == NULL)
00817    {
00818    snprintf(VBUFF,bufsize-1,"Couldn't open file %s",file);
00819    CfLog(cferror,VBUFF,"fopen");
00820    return;
00821    }
00822  
00823  
00824 if ((hp = gethostbyname(VMAILSERVER)) == NULL)
00825    {
00826    printf("Unknown host: %s\n", VMAILSERVER);
00827    printf("Make sure that fully qualified names can be looked up at your site!\n");
00828    printf("i.e. www.gnu.org, not just www. If you use NIS or /etc/hosts\n");
00829    printf("make sure that the full form is registered too as an alias!\n");
00830    return;
00831    }
00832 
00833 if ((server = getservbyname("smtp","tcp")) == NULL)
00834    {
00835    CfLog(cferror,"Unable to lookup smtp service","getservbyname");
00836    return;
00837    }
00838 
00839 bzero(&raddr,sizeof(raddr));
00840 
00841 raddr.sin_port = (unsigned int) server->s_port;
00842 raddr.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
00843 raddr.sin_family = AF_INET;  
00844 
00845 if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)
00846    {
00847    CfLog(cferror,"Couldn't open a socket","socket");
00848    return;
00849    }
00850    
00851 if (connect(sd,(void *) &raddr,sizeof(raddr)) == -1)
00852    {
00853    snprintf(OUTPUT,bufsize*2,"Couldn't connect to host %s\n",VMAILSERVER);
00854    CfLog(cfinform,OUTPUT,"connect");
00855    close(sd);
00856    return;
00857    }
00858 
00859 sprintf(VBUFF,"HELO %s\r\n",VFQNAME); 
00860 Dialogue(sd,VBUFF);
00861 
00862 sprintf(VBUFF,"MAIL FROM: <cfengine@%s>\r\n",VFQNAME);
00863 Dialogue(sd,VBUFF);
00864 
00865 sprintf(VBUFF,"RCPT TO: <%s>\r\n",to);
00866 Dialogue(sd,VBUFF);
00867 
00868 Dialogue(sd,"DATA\r\n"); 
00869 
00870 sprintf(VBUFF,"Subject: (%s/%s)\r\n",VFQNAME,VIPADDRESS); 
00871 sent=send(sd,VBUFF,strlen(VBUFF),0);
00872 sprintf(VBUFF,"To: %s\r\n\r\n",to); 
00873 sent=send(sd,VBUFF,strlen(VBUFF),0);
00874 
00875 while(!feof(fp))
00876    {
00877    VBUFF[0] = '\0';
00878    fgets(VBUFF,bufsize,fp);
00879    if (strlen(VBUFF) > 0)
00880       {
00881       VBUFF[strlen(VBUFF)-1] = '\r';
00882       strcat(VBUFF, "\n");
00883       count++;
00884       sent=send(sd,VBUFF,strlen(VBUFF),0);
00885       }
00886    if ((MAXLINES != INF_LINES) && (count > MAXLINES))
00887       {
00888       sprintf(VBUFF,"\r\n[Mail truncated by cfengine. File is at %s on %s]\r\n",file,VFQNAME);
00889       sent=send(sd,VBUFF,strlen(VBUFF),0);
00890       break;
00891       }
00892    } 
00893 
00894 Dialogue(sd,".\r\n"); 
00895 Dialogue(sd,"QUIT\r\n");
00896 
00897  
00898 fclose(fp);
00899 close(sd); 
00900 Debug("Done sending mail\n");
00901 }
00902 
00903 /******************************************************************/
00904 /* Level 5                                                        */
00905 /******************************************************************/
00906 
00907 void Dialogue(sd,s)
00908 
00909 int sd;
00910 char *s;
00911 
00912 { int sent;
00913   char ch,buf[bufsize];
00914 
00915 snprintf(buf,bufsize-1,s);
00916 sent=send(sd,s,strlen(s),0);
00917 
00918 Debug("SENT(%d)->%s",sent,s);
00919 
00920 while (recv(sd,&ch,1,0))
00921    {
00922    if (ch == '\n' || ch == '\0')
00923       {
00924       break;
00925       }
00926    } 
00927 }
00928 
00929 /******************************************************************/
00930 /*  Dummies                                                       */
00931 /******************************************************************/
00932 
00933 void RotateFiles(name,number)
00934 
00935 char *name;
00936 int number;
00937 
00938 {
00939  /* dummy */
00940 }
00941 
00942 
00943 int RecursiveTidySpecialArea(name,tp,maxrecurse,sb)
00944 
00945 char *name;
00946 struct Tidy *tp;
00947 int maxrecurse;
00948 struct stat *sb;
00949 
00950 {
00951  return true;
00952 }
00953 
00954 
00955 void yyerror(s)
00956 
00957 char *s;
00958 
00959 {
00960  printf("%s\n",s);
00961 }
00962 
00963 /* EOF */
00964 
00965 
00966 

© sourcejam.com 2005-2008