/* should return true if 'to' found */ int LinkFiles(char *from,char *to_tmp, struct Item *inclusions,struct Item *exclusions,struct Item *copy, short nofile,struct Link *ptr) { struct stat buf,savebuf; char to[CF_BUFSIZE], linkbuf[CF_BUFSIZE]; char saved[CF_BUFSIZE],absto[CF_BUFSIZE],*lastnode; struct UidList fakeuid; struct Image ip; char stamp[CF_BUFSIZE]; time_t STAMPNOW; STAMPNOW = time((time_t *)NULL); memset(to,0,CF_BUFSIZE); memset(&ip,0, sizeof(ip)); /* links without a directory reference */ if ((*to_tmp != '/') && (*to_tmp != '.')) { strcpy(to,"./"); } if (strlen(to_tmp)+3 > CF_BUFSIZE) { printf("%s: CF_BUFSIZE boundaries exceeded in LinkFiles(%s->%s)\n", g_vprefix,from,to_tmp); return false; } strcat(to,to_tmp); Debug2("Linkfiles(%s,%s)\n",from,to); for (lastnode = from+strlen(from); *lastnode != '/'; lastnode--) { } lastnode++; if (IgnoredOrExcluded(links,lastnode,inclusions,exclusions)) { Verbose("%s: Skipping non-included pattern %s\n",g_vprefix,from); return true; } if (IsWildItemIn(g_vcopylinks,lastnode) || IsWildItemIn(copy,lastnode)) { fakeuid.uid = CF_SAME_OWNER; fakeuid.next = NULL; ip.plus = CF_SAMEMODE; ip.minus = CF_SAMEMODE; ip.uid = &fakeuid; ip.gid = (struct GidList *) &fakeuid; ip.action = "do"; ip.recurse = 0; ip.type = 't'; ip.defines = ptr->defines; ip.elsedef = ptr->elsedef; ip.backup = true; ip.exclusions = NULL; ip.inclusions = NULL; ip.symlink = NULL; ip.classes = NULL; ip.plus_flags = 0; ip.size = CF_NOSIZE; ip.linktype = 's'; ip.minus_flags = 0; ip.server = strdup("localhost"); Verbose("%s: Link item %s marked for copying instead\n", g_vprefix, from); MakeDirectoriesFor(to,'n'); CheckImage(to,from,&ip); free(ip.server); return true; } /* relative path, must still check if exists */ if (*to != '/') { Debug("Relative link destination detected: %s\n",to); strcpy(absto,AbsLinkPath(from,to)); Debug("Absolute path to relative link = %s, from %s\n",absto,from); } else { strcpy(absto,to); } if (!nofile) { if (stat(absto,&buf) == -1) { /* no error warning, since the higher level routine uses this */ return(false); } } Debug2("Trying to link %s -> %s (%s)\n",from,to,absto); if (lstat(from,&buf) == 0) { if (! S_ISLNK(buf.st_mode) && ! g_enforcelinks) { snprintf(g_output,CF_BUFSIZE*2,"Error linking %s -> %s\n",from,to); CfLog(cfsilent,g_output,""); snprintf(g_output, CF_BUFSIZE*2, "Cannot make link: %s exists and is not a link! " "(uid %d)\n", from, buf.st_uid); CfLog(cfsilent,g_output,""); return(true); } if (S_ISREG(buf.st_mode) && g_enforcelinks) { snprintf(g_output, CF_BUFSIZE*2, "Moving %s to %s%s\n", from, from, CF_SAVED); CfLog(cfsilent,g_output,""); if (g_dontdo) { return true; } saved[0] = '\0'; strcpy(saved,from); sprintf(stamp, "_%d_%s", g_cfstarttime, CanonifyName(ctime(&STAMPNOW))); strcat(saved,stamp); strcat(saved,CF_SAVED); if (rename(from,saved) == -1) { snprintf(g_output, CF_BUFSIZE*2, "Can't rename %s to %s\n", from,saved); CfLog(cferror,g_output,"rename"); return(true); } if (Repository(saved,g_vrepository)) { unlink(saved); } } if (S_ISDIR(buf.st_mode) && g_enforcelinks) { snprintf(g_output,CF_BUFSIZE*2,"Moving directory %s to %s%s.dir\n", from,from,CF_SAVED); CfLog(cfsilent,g_output,""); if (g_dontdo) { return true; } saved[0] = '\0'; strcpy(saved,from); sprintf(stamp, "_%d_%s", g_cfstarttime, CanonifyName(ctime(&STAMPNOW))); strcat(saved,stamp); strcat(saved,CF_SAVED); strcat(saved,".dir"); if (stat(saved,&savebuf) != -1) { snprintf(g_output,CF_BUFSIZE*2, "Couldn't save directory %s, " "since %s exists already\n", from,saved); CfLog(cferror,g_output,""); snprintf(g_output,CF_BUFSIZE*2, "Unable to force link to " "existing directory %s\n",from); CfLog(cferror,g_output,""); return true; } if (rename(from,saved) == -1) { snprintf(g_output, CF_BUFSIZE*2, "Can't rename %s to %s\n", from,saved); CfLog(cferror,g_output,"rename"); return(true); } } } memset(linkbuf,0,CF_BUFSIZE); if (readlink(from,linkbuf,CF_BUFSIZE-1) == -1) { /* link doesn't exist */ if (! MakeDirectoriesFor(from,'n')) { snprintf(g_output,CF_BUFSIZE*2, "Couldn't build directory tree up to %s!\n",from); CfLog(cfsilent,g_output,""); snprintf(g_output,CF_BUFSIZE*2, "One element was a plain file, not a directory!\n"); CfLog(cfsilent,g_output,""); return(true); } } else { int off1 = 0, off2 = 0; DeleteSlash(linkbuf); /* Ignore ./ at beginning */ if (strncmp(linkbuf,"./",2) == 0) { off1 = 2; } if (strncmp(to,"./",2) == 0) { off2 = 2; } if (strcmp(linkbuf+off1,to+off2) != 0) { if (g_enforcelinks) { snprintf(g_output,CF_BUFSIZE*2,"Removing link %s\n",from); CfLog(cfinform,g_output,""); if (!g_dontdo) { if (unlink(from) == -1) { perror("unlink"); return true; } return DoLink(from,to,ptr->defines); } } else { snprintf(g_output,CF_BUFSIZE*2, "Old link %s points somewhere else. Doing nothing!\n", from); CfLog(cfsilent,g_output,""); snprintf(g_output, CF_BUFSIZE*2, "(Link points to %s not %s)\n\n", linkbuf,to); CfLog(cfsilent,g_output,""); return(true); } } else { snprintf(g_output, CF_BUFSIZE*2, "Link (%s->%s) exists.\n", from, to_tmp); CfLog(cfverbose,g_output,""); if (!nofile) { /* Check whether link points somewhere */ KillOldLink(from,ptr->defines); return true; } AddMultipleClasses(ptr->elsedef); return(true); } } return DoLink(from,to,ptr->defines); }
void CheckOptsAndInit(int argc,char **argv) { extern char *optarg; int optindex = 0; char ld_library_path[CF_BUFSIZE]; int c,seed; unsigned char s[16]; ld_library_path[0] = '\0'; Banner("Check options"); NOSPLAY = false; sprintf(VPREFIX, "cfexecd"); openlog(VPREFIX,LOG_PID|LOG_NOWAIT|LOG_ODELAY,LOG_DAEMON); while ((c=getopt_long(argc,argv,"L:d:vhpqFV1g",CFDOPTIONS,&optindex)) != EOF) { switch ((char) c) { case 'd': switch ((optarg==NULL)?3:*optarg) { case '1': D1 = true; break; case '2': D2 = true; break; default: DEBUG = true; break; } NO_FORK = true; VERBOSE = true; printf("cfexecd Debug mode: running in foreground\n"); break; case 'v': VERBOSE = true; break; case 'V': printf("GNU %s-%s daemon\n%s\n",PACKAGE,VERSION,COPYRIGHT); printf("This program is covered by the GNU Public License and may be\n"); printf("copied free of charge. No warrenty is implied.\n\n"); exit(0); break; case 'q': NOSPLAY = true; break; case 'p': PARSEONLY = true; break; case 'g': NO_FORK = true; break; case 'L': snprintf(ld_library_path,CF_BUFSIZE-1,"LD_LIBRARY_PATH=%s",optarg); if (putenv(strdup(ld_library_path)) != 0) { } break; case 'F': case '1': ONCE = true; NO_FORK = true; break; case 'h': Syntax(); exit(1); break; /* never reached.... */ default: Syntax(); exit(1); } } LOGGING = true; /* Do output to syslog */ /* XXX Initialize workdir for non privileged users */ strcpy(CFWORKDIR,WORKDIR); #ifndef NT if (getuid() > 0) { char *homedir; if ((homedir = getenv("HOME")) != NULL) { strcpy(CFWORKDIR,homedir); strcat(CFWORKDIR,"/.cfagent"); } } #endif snprintf(VBUFF,CF_BUFSIZE,"%s/inputs/update.conf",CFWORKDIR); MakeDirectoriesFor(VBUFF,'y'); snprintf(VBUFF,CF_BUFSIZE,"%s/bin/cfagent -D from_cfexecd",CFWORKDIR); MakeDirectoriesFor(VBUFF,'y'); snprintf(VBUFF,CF_BUFSIZE,"%s/outputs/spooled_reports",CFWORKDIR); MakeDirectoriesFor(VBUFF,'y'); snprintf(VBUFF,CF_BUFSIZE,"%s/inputs",CFWORKDIR); chmod(VBUFF,0700); snprintf(VBUFF,CF_BUFSIZE,"%s/outputs",CFWORKDIR); chmod(VBUFF,0700); strncpy(VLOCKDIR,CFWORKDIR,CF_BUFSIZE-1); strncpy(VLOGDIR,CFWORKDIR,CF_BUFSIZE-1); VCANONICALFILE = strdup(CanonifyName(VINPUTFILE)); GetCfStuff(); MAILTO[0] = '\0'; MAILFROM[0] = '\0'; VIPADDRESS[0] = '\0'; VMAILSERVER[0] = '\0'; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); CheckWorkDirectories(); RandomSeed(); RAND_bytes(s,16); s[15] = '\0'; seed = ElfHash(s); srand48((long)seed); }