int read_some_events(struct thread_info *t) { struct io_unit *event_io; struct io_event *event; int nr; int i; int min_nr = io_iter; struct timeval stop_time; if (t->num_global_pending < io_iter) min_nr = t->num_global_pending; #ifdef NEW_GETEVENTS nr = io_getevents(t->io_ctx, min_nr, t->num_global_events, t->events,NULL); #else nr = io_getevents(t->io_ctx, t->num_global_events, t->events, NULL); #endif if (nr <= 0) return nr; gettimeofday(&stop_time, NULL); for (i = 0 ; i < nr ; i++) { event = t->events + i; event_io = (struct io_unit *)((unsigned long)event->obj); finish_io(t, event_io, event->res, &stop_time); } return nr; }
/* * wait for all pending requests for this io operation to finish */ static int io_oper_wait(struct thread_info *t, struct io_oper *oper) { struct io_event event; struct io_unit *event_io; if (oper == NULL) { return 0; } if (oper->num_pending == 0) goto done; /* this func is not speed sensitive, no need to go wild reading * more than one event at a time */ #ifdef NEW_GETEVENTS while(io_getevents(t->io_ctx, 1, 1, &event, NULL) > 0) { #else while(io_getevents(t->io_ctx, 1, &event, NULL) > 0) { #endif struct timeval tv_now; event_io = (struct io_unit *)((unsigned long)event.obj); gettimeofday(&tv_now, NULL); finish_io(t, event_io, event.res, &tv_now); if (oper->num_pending == 0) break; } done: if (oper->num_err) { fprintf(stderr, "%u errors on oper, last %u\n", oper->num_err, oper->last_err); } return 0; } off_t random_byte_offset(struct io_oper *oper) { off_t num; off_t rand_byte = oper->start; off_t range; off_t offset = 1; range = (oper->end - oper->start) / (1024 * 1024); if ((page_size_mask+1) > (1024 * 1024)) offset = (page_size_mask+1) / (1024 * 1024); if (range < offset) range = 0; else range -= offset; /* find a random mb offset */ num = 1 + (int)((double)range * rand() / (RAND_MAX + 1.0 )); rand_byte += num * 1024 * 1024; /* find a random byte offset */ num = 1 + (int)((double)(1024 * 1024) * rand() / (RAND_MAX + 1.0)); /* page align */ num = (num + page_size_mask) & ~page_size_mask; rand_byte += num; if (rand_byte + oper->reclen > oper->end) { rand_byte -= oper->reclen; } return rand_byte; }
int main(int argc,char **argv) { URL *Url; URL **list,*refresh; int j; if(argc==1) {fprintf(stderr,"usage: test-doc URL < contents-of-url\n");return(1);} StderrLevel=ExtraDebug; InitErrorHandler("test-doc",0,1); InitConfigurationFile("./wwwoffle.conf"); init_io(STDERR_FILENO); if(ReadConfigurationFile(STDERR_FILENO)) PrintMessage(Fatal,"Error in configuration file 'wwwoffle.conf'."); finish_io(STDERR_FILENO); Url=SplitURL(argv[1]); init_io(0); ParseDocument(0,Url,1); if((refresh=GetReference(RefMetaRefresh))) printf("Refresh = %s\n",refresh->file); if((list=GetReferences(RefStyleSheet))) for(j=0;list[j];j++) printf("StyleSheet = %s\n",list[j]->file); if((list=GetReferences(RefImage))) for(j=0;list[j];j++) printf("Image = %s\n",list[j]->file); if((list=GetReferences(RefFrame))) for(j=0;list[j];j++) printf("Frame = %s\n",list[j]->file); if((list=GetReferences(RefScript))) for(j=0;list[j];j++) printf("Script = %s\n",list[j]->file); if((list=GetReferences(RefObject))) for(j=0;list[j];j++) printf("Object = %s\n",list[j]->file); if((list=GetReferences(RefInlineObject))) for(j=0;list[j];j++) printf("InlineObject = %s\n",list[j]->file); if((list=GetReferences(RefLink))) for(j=0;list[j];j++) printf("Link = %s\n",list[j]->file); FreeURL(Url); finish_io(0); return(0); }
void RequestMonitoredPages(void) { DIR *dir; struct dirent* ent; /* Open the monitor subdirectory. */ if(chdir("monitor")) {PrintMessage(Warning,"Cannot change to directory 'monitor'; [%!s] no files monitored.");return;} dir=opendir("."); if(!dir) {PrintMessage(Warning,"Cannot open directory 'monitor'; [%!s] no files monitored.");ChangeBackToSpoolDir();return;} ent=readdir(dir); if(!ent) {PrintMessage(Warning,"Cannot read directory 'monitor'; [%!s] no files monitored.");closedir(dir);ChangeBackToSpoolDir();return;} /* Scan through all of the files. */ do { struct stat buf; if(ent->d_name[0]=='.' && (ent->d_name[1]==0 || (ent->d_name[1]=='.' && ent->d_name[2]==0))) continue; /* skip . & .. */ if(stat(ent->d_name,&buf)) {PrintMessage(Inform,"Cannot stat file 'monitor/%s'; [%!s] race condition?",ent->d_name);return;} else if(S_ISREG(buf.st_mode) && *ent->d_name=='O') { URL *Url=FileNameToURL(ent->d_name); int last,next; ChangeBackToSpoolDir(); if(!Url) continue; MonitorTimes(Url,&last,&next); PrintMessage(Debug,"Monitoring '%s' last=%dh next=%dh => %s",Url->name,last,next,next?"No":"Yes"); chdir("monitor"); if(next==0) { int ifd=open(ent->d_name,O_RDONLY|O_BINARY); if(ifd==-1) PrintMessage(Warning,"Cannot open monitored file 'monitor/%s' to read; [%!s].",ent->d_name); else { int ofd; init_io(ifd); ChangeBackToSpoolDir(); ofd=OpenNewOutgoingSpoolFile(); if(ofd==-1) PrintMessage(Warning,"Cannot open outgoing spool file for monitored URL '%s'; [%!s].",Url->name); else { char *contents=(char*)malloc(buf.st_size+1); init_io(ofd); read_data(ifd,contents,buf.st_size); if(write_data(ofd,contents,buf.st_size)==-1) PrintMessage(Warning,"Cannot write to outgoing file; disk full?"); finish_io(ofd); CloseNewOutgoingSpoolFile(ofd,Url); free(contents); } chdir("monitor"); finish_io(ifd); close(ifd); if(utime(URLToFileName(Url,'M',0),NULL)) PrintMessage(Warning,"Cannot change timestamp of monitored file 'monitor/%s'; [%!s].",URLToFileName(Url,'M',0)); } } FreeURL(Url); } } while((ent=readdir(dir))); ChangeBackToSpoolDir(); closedir(dir); }
static void MonitorFormParse(int fd,URL *Url,char *request_args,Body *request_body) { int i,mfd=-1; char **args,*url=NULL; URL *monUrl; char mofy[13]="NNNNNNNNNNNN",*dofm=NULL,dofw[8]="NNNNNNN",*hofd=NULL; char MofY[13],DofM[32],DofW[8],HofD[25]; if(!request_args && !request_body) { HTMLMessage(fd,404,"WWWOFFLE Monitor Form Error",NULL,"MonitorFormError", "body",NULL, NULL); return; } if(request_body) { char *form=URLRecodeFormArgs(request_body->content); args=SplitFormArgs(form); free(form); } else args=SplitFormArgs(request_args); for(i=0;args[i];i++) { if(!strncmp("url=",args[i],(size_t)4)) url=TrimArgs(URLDecodeFormArgs(args[i]+4)); else if(!strncmp("mofy1=",args[i],(size_t)6)) mofy[0]=args[i][6]; else if(!strncmp("mofy2=",args[i],(size_t)6)) mofy[1]=args[i][6]; else if(!strncmp("mofy3=",args[i],(size_t)6)) mofy[2]=args[i][6]; else if(!strncmp("mofy4=",args[i],6)) mofy[3]=args[i][6]; else if(!strncmp("mofy5=",args[i],(size_t)6)) mofy[4]=args[i][6]; else if(!strncmp("mofy6=",args[i],(size_t)6)) mofy[5]=args[i][6]; else if(!strncmp("mofy7=",args[i],(size_t)6)) mofy[6]=args[i][6]; else if(!strncmp("mofy8=",args[i],(size_t)6)) mofy[7]=args[i][6]; else if(!strncmp("mofy9=",args[i],(size_t)6)) mofy[8]=args[i][6]; else if(!strncmp("mofy10=",args[i],(size_t)7)) mofy[9]=args[i][7]; else if(!strncmp("mofy11=",args[i],(size_t)7)) mofy[10]=args[i][7]; else if(!strncmp("mofy12=",args[i],(size_t)7)) mofy[11]=args[i][7]; else if(!strncmp("dofm=",args[i],(size_t)5)) dofm=args[i]+5; else if(!strncmp("dofw0=",args[i],(size_t)6)) dofw[0]=args[i][6]; else if(!strncmp("dofw1=",args[i],(size_t)6)) dofw[1]=args[i][6]; else if(!strncmp("dofw2=",args[i],(size_t)6)) dofw[2]=args[i][6]; else if(!strncmp("dofw3=",args[i],(size_t)6)) dofw[3]=args[i][6]; else if(!strncmp("dofw4=",args[i],(size_t)6)) dofw[4]=args[i][6]; else if(!strncmp("dofw5=",args[i],(size_t)6)) dofw[5]=args[i][6]; else if(!strncmp("dofw6=",args[i],(size_t)6)) dofw[6]=args[i][6]; else if(!strncmp("hofd=",args[i],(size_t)5)) hofd=args[i]+5; else PrintMessage(Warning,"Unexpected argument '%s' seen decoding form data for URL '%s'.",args[i],Url->name); } if(url==NULL || *url==0) { HTMLMessage(fd,404,"WWWOFFLE Monitor Form Error",NULL,"MonitorFormError", "body",request_body?request_body->content:request_args, NULL); if(url) free(url); free(args[0]); free(args); return; } monUrl=SplitURL(url); free(url); /* Parse the requested time */ strcpy(MofY,"000000000000"); for(i=0;i<12;i++) if(mofy[i]=='Y') MofY[i]='1'; if(!dofm || !*dofm) strcpy(DofM,"1111111111111111111111111111111"); else { int d,any=0,range=0,lastd=0; char *p=dofm; strcpy(DofM,"0000000000000000000000000000000"); while(*p) { while(*p && !isdigit(*p)) { if(*p=='*') { strcpy(DofM,"1111111111111111111111111111111"); any=1; } if(*p=='-') range=1; p++; } if(!*p) break; d=atoi(p)-1; if(range) { if(d>30) d=30; for(;lastd<=d;lastd++) DofM[lastd]='1'; range=0; any++; } else if(d>=0 && d<31) { DofM[d]='1'; any++; lastd=d; } while(isdigit(*p)) p++; } if(range) for(;lastd<=30;lastd++) DofM[lastd]='1'; else if(!any) strcpy(DofM,"1111111111111111111111111111111"); } strcpy(DofW,"0000000"); for(i=0;i<7;i++) if(dofw[i]=='Y') DofW[i]='1'; if(!hofd || !*hofd) strcpy(HofD,"100000000000000000000000"); else { int h,any=0,range=0,lasth=0; char *p=hofd; strcpy(HofD,"000000000000000000000000"); while(*p) { while(*p && !isdigit(*p)) { if(*p=='*') { strcpy(HofD,"111111111111111111111111"); any=1; } if(*p=='-') range=1; p++; } if(!*p) break; h=atoi(p); if(range) { if(h>23) h=23; for(;lasth<=h;lasth++) HofD[lasth]='1'; range=0; any++; } else if(h>=0 && h<24) { HofD[h]='1'; any++; lasth=h; } while(isdigit(*p)) p++; } if(range) for(;lasth<=23;lasth++) HofD[lasth]='1'; else if(!any) strcpy(HofD,"100000000000000000000000"); } mfd=CreateMonitorSpoolFile(monUrl,MofY,DofM,DofW,HofD); if(mfd==-1) HTMLMessage(fd,500,"WWWOFFLE Server Error",NULL,"ServerError", "error","Cannot open file to store monitor request", NULL); else { Header *new_request_head=RequestURL(monUrl,NULL); char *head=HeaderString(new_request_head); init_io(mfd); write_string(mfd,head); finish_io(mfd); close(mfd); HTMLMessage(fd,200,"WWWOFFLE Monitor Will Get",NULL,"MonitorWillGet", "url",monUrl->name, NULL); free(head); FreeHeader(new_request_head); } free(args[0]); free(args); FreeURL(monUrl); }
int main(int argc, char** argv) { int i; int err; struct stat buf; int uid,gid; /* Parse the command line options */ for(i=1;i<argc;i++) { if(!strcmp(argv[i],"-h") || !strcmp(argv[i],"--help")) usage(1); if(!strcmp(argv[i],"--version")) usage(2); if(!strcmp(argv[i],"-d")) { detached=0; if(i<(argc-1) && isdigit(argv[i+1][0])) { StderrLevel=Fatal+1-atoi(argv[++i]); if(StderrLevel<0 || StderrLevel>Fatal) {fprintf(stderr,"wwwoffled: The '-d' option requires a number between 0 and %d.\n",Fatal+1); exit(1);} } continue; } if(!strcmp(argv[i],"-l")) { if(++i>=argc) {fprintf(stderr,"wwwoffled: The '-l' option requires a filename.\n"); exit(1);} if(argv[i][0]!='/') {fprintf(stderr,"wwwoffled: The '-l' option requires an absolute pathname.\n"); exit(1);} log_file=argv[i]; continue; } if(!strcmp(argv[i],"-p")) { print_pid=1; continue; } if(!strcmp(argv[i],"-f")) { nofork=1; detached=0; continue; } if(!strcmp(argv[i],"-c")) { if(++i>=argc) {fprintf(stderr,"wwwoffled: The '-c' option requires a filename.\n"); exit(1);} config_file=argv[i]; continue; } fprintf(stderr,"wwwoffled: Unknown option '%s'.\n",argv[i]); exit(1); } /* Combination options */ if(log_file) { if(nofork) log_file=NULL; /* -f overrides -l */ else detached=1; /* -l overrides -d */ if(StderrLevel==-1) StderrLevel=Inform; /* -l sets log level if no -d */ } /* Initialise things. */ for(i=0;i<MAX_FETCH_SERVERS;i++) fetch_pids[i]=0; for(i=0;i<MAX_SERVERS;i++) server_pids[i]=0; if(log_file) OpenErrorLog(log_file); InitErrorHandler("wwwoffled",0,1); /* use stderr and not syslog to start with. */ /* Read the configuration file. */ InitConfigurationFile(config_file); init_io(STDERR_FILENO); if(ReadConfigurationFile(STDERR_FILENO)) PrintMessage(Fatal,"Error in configuration file '%s'.",ConfigurationFileName()); finish_io(STDERR_FILENO); InitErrorHandler("wwwoffled",ConfigInteger(UseSyslog),1); /* enable syslog if requested. */ /* Print a startup message. */ #if USE_IPV6 #define IPV6_STRING "with ipv6" #else #define IPV6_STRING "without ipv6" #endif #define ZLIB_STRING "with zlib" #define GNUTLS_STRING "with gnutls" PrintMessage(Important,"WWWOFFLE Demon Version %s (%s,%s,%s) started.",WWWOFFLE_VERSION,IPV6_STRING,ZLIB_STRING,GNUTLS_STRING); PrintMessage(Inform,"WWWOFFLE Read Configuration File '%s'.",ConfigurationFileName()); /* Change the user and group. */ gid=ConfigInteger(WWWOFFLE_Gid); uid=ConfigInteger(WWWOFFLE_Uid); if(uid!=-1) seteuid(0); if(log_file && (uid!=-1 || gid!=-1)) chown(log_file,(uid_t)uid,(gid_t)gid); if(gid!=-1) { #if HAVE_SETGROUPS if(getuid()==0 || geteuid()==0) if(setgroups(0,NULL)<0) PrintMessage(Fatal,"Cannot clear supplementary group list [%!s]."); #endif #if HAVE_SETRESGID if(setresgid((gid_t)gid,(gid_t)gid,(gid_t)gid)<0) PrintMessage(Fatal,"Cannot set real/effective/saved group id to %d [%!s].",gid); #else if(geteuid()==0) { if(setgid((gid_t)gid)<0) PrintMessage(Fatal,"Cannot set group id to %d [%!s].",gid); } else { #if HAVE_SETREGID if(setregid(getegid(),(gid_t)gid)<0) PrintMessage(Fatal,"Cannot set effective group id to %d [%!s].",gid); if(setregid((gid_t)gid,(gid_t)~1)<0) PrintMessage(Fatal,"Cannot set real group id to %d [%!s].",gid); #else PrintMessage(Fatal,"Must be root to totally change group id."); #endif } #endif } if(uid!=-1) { #if HAVE_SETRESUID if(setresuid((uid_t)uid,(uid_t)uid,(uid_t)uid)<0) PrintMessage(Fatal,"Cannot set real/effective/saved user id to %d [%!s].",uid); #else if(geteuid()==0) { if(setuid((uid_t)uid)<0) PrintMessage(Fatal,"Cannot set user id to %d [%!s].",uid); } else { #if HAVE_SETREUID if(setreuid(geteuid(),(uid_t)uid)<0) PrintMessage(Fatal,"Cannot set effective user id to %d [%!s].",uid); if(setreuid((uid_t)uid,(uid_t)~1)<0) PrintMessage(Fatal,"Cannot set real user id to %d [%!s].",uid); #else PrintMessage(Fatal,"Must be root to totally change user id."); #endif } #endif } if(uid!=-1 || gid!=-1) PrintMessage(Inform,"Running with uid=%d, gid=%d.",geteuid(),getegid()); if(geteuid()==0 || getegid()==0) PrintMessage(Warning,"Running with root user or group privileges is not recommended."); /* Create, Change to and open the spool directory. */ umask(0); if(stat(ConfigString(SpoolDir),&buf)) { err=mkdir(ConfigString(SpoolDir),(mode_t)ConfigInteger(DirPerm)); if(err==-1 && errno!=EEXIST) PrintMessage(Fatal,"Cannot create spool directory %s [%!s].",ConfigString(SpoolDir)); stat(ConfigString(SpoolDir),&buf); } if(!S_ISDIR(buf.st_mode)) PrintMessage(Fatal,"The spool directory %s is not a directory.",SpoolDir); err=ChangeToSpoolDir(ConfigString(SpoolDir)); if(err==-1) PrintMessage(Fatal,"Cannot change to spool directory %s [%!s].",ConfigString(SpoolDir)); /* Bind the HTTP proxy socket(s). */ #if USE_IPV6 if(ConfigString(Bind_IPv6)) { http_fd[1]=OpenServerSocket(ConfigString(Bind_IPv6),ConfigInteger(HTTP_Port)); if(http_fd[1]==-1) PrintMessage(Fatal,"Cannot create HTTP IPv6 server socket."); } #endif if(ConfigString(Bind_IPv4)) { http_fd[0]=OpenServerSocket(ConfigString(Bind_IPv4),ConfigInteger(HTTP_Port)); if(http_fd[0]==-1) { #if USE_IPV6 if(http_fd[1]!=-1 && /* PS 2003-01-13 redundant? If IPv6 is listening to 0 then it doesn't matter what address IPv4 is listening to... (at least on linux?) */ /* ConfigString(Bind_IPv4) && !strcmp(ConfigString(Bind_IPv4),"0.0.0.0") && */ ConfigString(Bind_IPv6) && !strcmp(ConfigString(Bind_IPv6),"[0:0:0:0:0:0:0:0]")) PrintMessage(Warning,"Cannot create HTTP IPv4 server socket (but the IPv6 one might accept IPv4 connections)."); else PrintMessage(Fatal,"Cannot create HTTP IPv4 server socket."); #else PrintMessage(Fatal,"Cannot create HTTP server socket."); #endif } } if(http_fd[0]==-1 && http_fd[1]==-1) { #if USE_IPV6 PrintMessage(Fatal,"The IPv4 and IPv6 HTTP sockets were not bound; are they disabled in the config file?"); #else PrintMessage(Fatal,"The HTTP socket was not bound; is it disabled in the config file?"); #endif } /* Bind the HTTPS socket(s). */ if(LoadRootCredentials()) { PrintMessage(Warning,"Failed to read (or create if needed) the WWWOFFLE root certificates."); } if(LoadTrustedCertificates()) { PrintMessage(Warning,"Failed to read in any trusted certificates."); } #if USE_IPV6 if(ConfigString(Bind_IPv6)) { https_fd[1]=OpenServerSocket(ConfigString(Bind_IPv6),ConfigInteger(HTTPS_Port)); if(https_fd[1]==-1) PrintMessage(Fatal,"Cannot create HTTPS IPv6 server socket."); } #endif if(ConfigString(Bind_IPv4)) { https_fd[0]=OpenServerSocket(ConfigString(Bind_IPv4),ConfigInteger(HTTPS_Port)); if(https_fd[0]==-1) { #if USE_IPV6 if(https_fd[1]!=-1 && ConfigString(Bind_IPv4) && !strcmp(ConfigString(Bind_IPv4),"0.0.0.0") && ConfigString(Bind_IPv6) && !strcmp(ConfigString(Bind_IPv6),"[0:0:0:0:0:0:0:0]")) PrintMessage(Warning,"Cannot create HTTPS IPv4 server socket (but the IPv6 one might accept IPv4 connections)."); else PrintMessage(Fatal,"Cannot create HTTPS IPv4 server socket."); #else PrintMessage(Fatal,"Cannot create HTTPS server socket."); #endif } } if(https_fd[0]==-1 && https_fd[1]==-1) { #if USE_IPV6 PrintMessage(Fatal,"The IPv4 and IPv6 HTTPS sockets were not bound; are they disabled in the config file?"); #else PrintMessage(Fatal,"The HTTPS socket was not bound; is it disabled in the config file?"); #endif } /* Bind the WWWOFFLE control socket(s). */ #if USE_IPV6 if(ConfigString(Bind_IPv6)) { wwwoffle_fd[1]=OpenServerSocket(ConfigString(Bind_IPv6),ConfigInteger(WWWOFFLE_Port)); if(wwwoffle_fd[1]==-1) PrintMessage(Fatal,"Cannot create WWWOFFLE IPv6 server socket."); } #endif if(ConfigString(Bind_IPv4)) { wwwoffle_fd[0]=OpenServerSocket(ConfigString(Bind_IPv4),ConfigInteger(WWWOFFLE_Port)); if(wwwoffle_fd[0]==-1) { #if USE_IPV6 if(wwwoffle_fd[1]!=-1 && ConfigString(Bind_IPv4) && !strcmp(ConfigString(Bind_IPv4),"0.0.0.0") && ConfigString(Bind_IPv6) && !strcmp(ConfigString(Bind_IPv6),"[0:0:0:0:0:0:0:0]")) { PrintMessage(Warning,"Cannot create WWWOFFLE IPv4 server socket (but the IPv6 one might accept IPv4 connections)."); PrintMessage(Warning,"Consider adding \"bind-ipv4 = none\" to wwwoffle.conf if using IPv6."); } else PrintMessage(Fatal,"Cannot create WWWOFFLE IPv4 server socket."); #else PrintMessage(Fatal,"Cannot create WWWOFFLE server socket."); #endif } } if(wwwoffle_fd[0]==-1 && wwwoffle_fd[1]==-1) { #if USE_IPV6 PrintMessage(Fatal,"The IPv4 and IPv6 WWWOFFLE sockets were not bound; are they disabled in the config file?"); #else PrintMessage(Fatal,"The WWWOFFLE socket was not bound; is it disabled in the config file?"); #endif } /* Detach from terminal */ if(detached) { demoninit(); PrintMessage(Important,"Detached from terminal and changed pid to %d.",getpid()); if(log_file) InitErrorHandler("wwwoffled",-1,-1); /* pid changes after detaching, keep stderr as was. */ else InitErrorHandler("wwwoffled",-1, 0); /* pid changes after detaching, disable stderr. */ if(!log_file) close(STDERR_FILENO); } close(STDIN_FILENO); close(STDOUT_FILENO); install_sighandlers(); max_servers=ConfigInteger(MaxServers); max_fetch_servers=ConfigInteger(MaxFetchServers); /* Loop around waiting for connections. */ PrintMessage(Inform,"WWWOFFLE Ready to accept connections."); do { struct timeval tv; fd_set readfd; int nfds=0,nfd=0; FD_ZERO(&readfd); #if USE_IPV6 for(nfd=0;nfd<=1;nfd++) { #endif if(http_fd[nfd]>=nfds) nfds=http_fd[nfd]+1; if(https_fd[nfd]>=nfds) nfds=https_fd[nfd]+1; if(wwwoffle_fd[nfd]>=nfds) nfds=wwwoffle_fd[nfd]+1; if(n_servers<max_servers) { if(http_fd[nfd]!=-1) FD_SET(http_fd[nfd],&readfd); if(https_fd[nfd]!=-1) FD_SET(https_fd[nfd],&readfd); } if(wwwoffle_fd[nfd]!=-1) FD_SET(wwwoffle_fd[nfd],&readfd); #if USE_IPV6 } #endif tv.tv_sec=10; tv.tv_usec=0; if(select(nfds,&readfd,NULL,NULL,&tv)!=-1) { #if USE_IPV6 for(nfd=0;nfd<=1;nfd++) { #endif if(wwwoffle_fd[nfd]!=-1 && FD_ISSET(wwwoffle_fd[nfd],&readfd)) { char *host,*ip; int port,client; client=AcceptConnect(wwwoffle_fd[nfd]); if(client>=0) { init_io(client); configure_io_timeout(client,ConfigInteger(SocketTimeout),ConfigInteger(SocketTimeout)); if(SocketRemoteName(client,&host,&ip,&port)) { finish_io(client); CloseSocket(client); } else { char *canonical_ip=CanonicaliseHost(ip); if(IsAllowedConnectHost(host) || IsAllowedConnectHost(canonical_ip)) { PrintMessage(Important,"WWWOFFLE Connection from host %s (%s).",host,canonical_ip); /* Used in audit-usage.pl */ CommandConnect(client); if(fetch_fd!=client) { finish_io(client); CloseSocket(client); } } else { PrintMessage(Warning,"WWWOFFLE Connection rejected from host %s (%s).",host,canonical_ip); /* Used in audit-usage.pl */ finish_io(client); CloseSocket(client); } free(canonical_ip); } } } if(http_fd[nfd]!=-1 && FD_ISSET(http_fd[nfd],&readfd)) { char *host,*ip; int port,client; client=AcceptConnect(http_fd[nfd]); if(client>=0) { init_io(client); configure_io_timeout(client,ConfigInteger(SocketTimeout),ConfigInteger(SocketTimeout)); if(!SocketRemoteName(client,&host,&ip,&port)) { char *canonical_ip=CanonicaliseHost(ip); if(IsAllowedConnectHost(host) || IsAllowedConnectHost(canonical_ip)) { PrintMessage(Inform,"HTTP Proxy connection from host %s (%s).",host,canonical_ip); /* Used in audit-usage.pl */ ForkServer(client); } else PrintMessage(Warning,"HTTP Proxy connection rejected from host %s (%s).",host,canonical_ip); /* Used in audit-usage.pl */ free(canonical_ip); } if(nofork) got_sigexit=1; if(!nofork) { finish_io(client); CloseSocket(client); } } } if(https_fd[nfd]!=-1 && FD_ISSET(https_fd[nfd],&readfd)) { char *host,*ip; int port,client; client=AcceptConnect(https_fd[nfd]); if(client>=0) { init_io(client); configure_io_timeout(client,ConfigInteger(SocketTimeout),ConfigInteger(SocketTimeout)); if(!SocketRemoteName(client,&host,&ip,&port)) { char *canonical_ip=CanonicaliseHost(ip); if(IsAllowedConnectHost(host) || IsAllowedConnectHost(canonical_ip)) { PrintMessage(Inform,"HTTPS Proxy connection from host %s (%s).",host,canonical_ip); /* Used in audit-usage.pl */ ForkServer(client); } else PrintMessage(Warning,"HTTPS Proxy connection rejected from host %s (%s).",host,canonical_ip); /* Used in audit-usage.pl */ free(canonical_ip); } if(nofork) got_sigexit=1; if(!nofork) { finish_io(client); CloseSocket(client); } } } #if USE_IPV6 } #endif } if(got_sighup) { got_sighup=0; PrintMessage(Important,"SIGHUP signalled."); if(log_file) { PrintMessage(Important,"Closing and opening log file."); OpenErrorLog(log_file); } PrintMessage(Important,"WWWOFFLE Re-reading Configuration File."); if(ReadConfigurationFile(-1)) PrintMessage(Warning,"Error in configuration file; keeping old values."); PrintMessage(Important,"WWWOFFLE Finished Re-reading Configuration File."); } if(got_sigchld) { int pid, status; int isserver=0; /* To avoid race conditions, reset the flag before fetching the status */ got_sigchld=0; while((pid=waitpid(-1,&status,WNOHANG))>0) { int i; int exitval=0; if(WIFEXITED(status)) exitval=WEXITSTATUS(status); else if(WIFSIGNALED(status)) exitval=-WTERMSIG(status); if(purging) if(purge_pid==pid) { if(exitval>=0) PrintMessage(Inform,"Purge process exited with status %d (pid=%d).",exitval,pid); else PrintMessage(Important,"Purge process terminated by signal %d (pid=%d).",-exitval,pid); purging=0; } for(i=0;i<max_servers;i++) if(server_pids[i]==pid) { n_servers--; server_pids[i]=0; isserver=1; if(exitval>=0) PrintMessage(Inform,"Child wwwoffles exited with status %d (pid=%d).",exitval,pid); else PrintMessage(Important,"Child wwwoffles terminated by signal %d (pid=%d).",-exitval,pid); break; } /* Check if the child that terminated is one of the fetching wwwoffles */ for(i=0;i<max_fetch_servers;i++) if(fetch_pids[i]==pid) { n_fetch_servers--; fetch_pids[i]=0; break; } if(exitval==3) fetching=0; if(exitval==4 && online!=0) fetching=1; if(online==0) fetching=0; } if(isserver) PrintMessage(Debug,"Currently running: %d servers total, %d fetchers.",n_servers,n_fetch_servers); } /* The select timed out or we got a signal. If we are currently fetching, start fetch servers to look for jobs in the spool directory. */ while(fetching && n_fetch_servers<max_fetch_servers && n_servers<max_servers) ForkServer(fetch_fd); if(fetch_fd!=-1 && !fetching && n_fetch_servers==0) { write_string(fetch_fd,"WWWOFFLE No more to fetch.\n"); finish_io(fetch_fd); CloseSocket(fetch_fd); fetch_fd=-1; PrintMessage(Important,"WWWOFFLE Fetch finished."); ForkRunModeScript(ConfigString(RunFetch),"fetch","stop",-1); } } while(!got_sigexit); /* Close down and exit. */ /* These four sockets don't need finish_io() calling because they never had init_io() called, they are just bound to a port listening. */ if(http_fd[0]!=-1) CloseSocket(http_fd[0]); if(http_fd[1]!=-1) CloseSocket(http_fd[1]); if(wwwoffle_fd[0]!=-1) CloseSocket(wwwoffle_fd[0]); if(wwwoffle_fd[1]!=-1) CloseSocket(wwwoffle_fd[1]); if(!nofork) { if(n_servers) PrintMessage(Important,"Exit signalled - waiting for %d child wwwoffles servers.",n_servers); else PrintMessage(Important,"Exit signalled."); } while(n_servers) { int i; int pid,status,exitval=0; while((pid=waitpid(-1,&status,0))>0) { if(WIFEXITED(status)) exitval=WEXITSTATUS(status); else if(WIFSIGNALED(status)) exitval=-WTERMSIG(status); for(i=0;i<max_servers;i++) if(server_pids[i]==pid) { n_servers--; server_pids[i]=0; if(exitval>=0) PrintMessage(Inform,"Child wwwoffles exited with status %d (pid=%d).",exitval,pid); else PrintMessage(Important,"Child wwwoffles terminated by signal %d (pid=%d).",-exitval,pid); break; } if(purging) if(purge_pid==pid) { if(exitval>=0) PrintMessage(Inform,"Purge process exited with status %d (pid=%d).",exitval,pid); else PrintMessage(Important,"Purge process terminated by signal %d (pid=%d).",-exitval,pid); purging=0; } } } PrintMessage(Important,"Exiting."); FinishConfigurationFile(); FreeLoadedCredentials(); return(0); }