home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 52
/
Amiga_Dream_52.iso
/
Linux
/
Magazine
/
wwwoffle-2.1.tar.gz
/
wwwoffle-2.1
/
wwwoffles.c
< prev
Wrap
C/C++ Source or Header
|
1998-03-02
|
27KB
|
953 lines
/***************************************
$Header: /home/amb/wwwoffle/RCS/wwwoffles.c 2.48 1998/03/02 15:06:00 amb Exp $
WWWOFFLE - World Wide Web Offline Explorer - Version 2.1.
A server to fetch the required pages.
******************/ /******************
Written by Andrew M. Bishop
This file Copyright 1996,97,98 Andrew M. Bishop
It may be distributed under the GNU Public License, version 2, or
any higher version. See section COPYING of the GNU Public license
for conditions under which this file may be redistributed.
***************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include "wwwoffle.h"
#include "misc.h"
#include "proto.h"
#include "config.h"
#include "sockets.h"
#include "errors.h"
static void uninstall_sighandlers(void);
/*+ The mode of operation of the server. +*/
typedef enum _Mode
{
None, /*+ Undecided. +*/
Real, /*+ From server host to cache and client. +*/
RealNoCache, /*+ From server host to client. +*/
RealRefresh, /*+ Refresh the page, forced from index. +*/
SpoolOrReal, /*+ From server host to cache and client but only if not already cached. +*/
Fetch, /*+ From server host to cache. +*/
Spool, /*+ From cache to client. +*/
SpoolGet, /*+ Not in cache so record request in outgoing. +*/
SpoolWillGet, /*+ Not in cache but is in outgoing. +*/
SpoolRefresh, /*+ Refresh the page, forced from index. +*/
SpoolPragma /*+ Refresh the page, forced from browser by 'Pragma: no-cache'. +*/
}
Mode;
/*++++++++++++++++++++++++++++++++++++++
The main server program.
int wwwoffles Returns the exit status.
int online Whether the demon is online or not.
int browser Set to true if there is a browser.
int client The file descriptor of the client.
++++++++++++++++++++++++++++++++++++++*/
int wwwoffles(int online,int browser,int client)
{
int outgoing=-1,spool=-1;
int fetch_again=0;
char *mirrorProto=NULL,*mirrorHost=NULL;
char *request_head,*request_body;
char *reply_head,*reply_body;
int reply_status=-1;
char *url;
URL *Url;
Mode mode=None;
int lasttime_exists=0,spool_exists=0;
/* Initialise things. */
uninstall_sighandlers();
InitErrorHandler("wwwoffles",-1,-1); /* change name nothing else */
if(online==1 && browser)
mode=Real;
else if(online==1 && !browser)
mode=Fetch;
else if(online==-1 && browser)
mode=SpoolOrReal;
else if(!online && browser)
mode=Spool;
else
{
if(client!=-1)
ServerError(client,"Started server in illegal mode, seek help.");
PrintMessage(Fatal,"Started in a mode that is not allowed (online=%d, browser=%d).",online,browser);
}
/* Set up the client file. */
if(client<0 && mode!=Fetch)
{PrintMessage(Warning,"Cannot use client file descriptor %d.",client);exit(1);}
/* Set up the outgoing file. */
if(mode==Fetch)
{
outgoing=OpenOutgoingSpoolFile(1);
init_buffer(outgoing);
if(outgoing==-1)
{PrintMessage(Inform,"No more outgoing requests.");exit(3);}
}
/* Get the URL from the request. */
if(mode==Real || mode==Spool || mode==SpoolOrReal)
url=ParseRequest(client,&request_head,&request_body);
else /* mode==Fetch */
url=ParseRequest(outgoing,&request_head,&request_body);
if(!url)
{
if(mode!=Fetch)
ServerError(client,request_head?"Cannot parse the HTTP request":"The HTTP request was empty");
PrintMessage(Warning,"Could not parse HTTP request (%s).",request_head?"Parse error":"Empty request");
exit(1);
}
PrintMessage(Inform,"URL='%s'.",url);
Url=SplitURL(url);
PrintMessage(Debug,"proto='%s'; host='%s'; path='%s'; args='%s'.",Url->proto,Url->host,Url->path,Url->args);
if(!Url->Protocol)
{
if(mode==Real || mode==Spool || mode==SpoolOrReal)
IllegalProto(client,Url->name,Url->proto);
PrintMessage(Inform,"The protocol '%s' is not available.",Url);
exit(1);
}
if(Url->user)
{
if(mode==Real || mode==Spool || mode==SpoolOrReal)
PasswordDisallowed(client,Url);
PrintMessage(Inform,"URLs with username and password are not allowed.",Url->proto);
exit(1);
}
/* Change the mode based on the URL as required. */
/* (At this point mode is Spool, Real, SpoolOrReal or Fetch only.) */
if(IsNotGot(Url->proto,Url->host,Url->path))
{
char* colon=strchr(Url->host,':');
if(colon) *colon=0;
if(mode==Real || mode==Spool || mode==SpoolOrReal)
RemoteHostError(client,Url,"is on the list of hosts and paths not to get.",0,0);
PrintMessage(Inform,"The server '%s://%s' and/or path '%s' is on the list not to get.",Url->proto,Url->host,Url->path);
exit(0);
}
if(Url->local)
{
int newurl=0;
if(!strncmp("/refresh",Url->path,8))
{
url=RefreshPage(client,Url->path,Url->args,Url->name,request_body,online);
if(url==(char*)1)
newurl=-1;
else if(url)
{
FreeURL(Url);
Url=SplitURL(url);
if(Url->args && *Url->args=='!')
{
PrintMessage(Inform,"It is not possible to refresh a URL that was posted.");
if(mode!=Fetch)
CantRefreshPosted(client,Url);
exit(0);
}
else if(!*Url->host || IsLocalNetHost(Url->host))
mode=RealNoCache;
else if(mode==Real || mode==SpoolOrReal)
{
mode=RealRefresh;
DeleteWebpageSpoolFile(Url,0);
}
else if(mode==Spool)
{
if(ExistsWebpageSpoolFile(Url))
mode=SpoolRefresh;
else
if(ExistsOutgoingSpoolFile(Url))
mode=SpoolWillGet;
else
mode=SpoolGet;
}
newurl=1;
}
}
else if(mode==Fetch)
PrintMessage(Inform,"The request to fetch a page from the local host is ignored.");
else if(!strcmp(Url->path,"/") && !Url->args)
WelcomePage(client);
else if(!strncmp("/index/",Url->path,7))
IndexPage(client,&Url->path[7],Url->args);
else if(!strncmp("/control/",Url->path,9))
ControlPage(client,&Url->path[9],Url->args,request_head,request_body);
else if(!strncmp("/monitor",Url->path,8))
MonitorPage(client,Url->path,Url->args,request_body);
else
{
int i;
for(i=0;i<NProtocols;i++)
if(!strncmp(Protocols[i].name,Url->pathp+1,strlen(Protocols[i].name)) &&
Url->pathp[strlen(Protocols[i].name)+1]=='/')
{
url=(char*)malloc(strlen(Url->pathp)+4);
Url->pathp[strlen(Protocols[i].name)+1]=0;
sprintf(url,"%s://%s",Url->pathp+1,&Url->pathp[strlen(Protocols[i].name)+2]);
Url->pathp[strlen(Protocols[i].name)+1]='/';
newurl=1;
break;
}
if(!newurl)
IllegalPage(client,Url->pathp);
FreeURL(Url);
Url=SplitURL(url);
}
if(!newurl)
exit(0);
else if(newurl==-1)
exit(4);
PrintMessage(Inform,"new URL='%s'.",url);
PrintMessage(Debug,"new proto='%s'; host='%s'; path='%s'; args='%s'.",Url->proto,Url->host,Url->path,Url->args);
if(!Url->Protocol)
{
if(mode==Real || mode==Spool || mode==SpoolOrReal)
IllegalProto(client,Url->name,Url->proto);
PrintMessage(Inform,"The protocol '%s' is not available.",Url->proto);
exit(1);
}
}
if(IsMirrored(Url->proto,Url->host,&mirrorProto,&mirrorHost))
{
char *newurl=(char*)malloc(strlen(mirrorProto)+strlen(mirrorHost)+strlen(Url->pathp)+8);
sprintf(newurl,"%s://%s%s",mirrorProto,mirrorHost,Url->pathp);
url=newurl;
FreeURL(Url);
Url=SplitURL(url);
PrintMessage(Inform,"mirrored URL='%s'.",url);
PrintMessage(Debug,"mirrored proto='%s'; host='%s'; path='%s'; args='%s'.",Url->proto,Url->host,Url->path,Url->args);
if(!Url->Protocol)
{
if(mode==Real || mode==Spool || mode==SpoolOrReal)
IllegalProto(client,Url->name,Url->proto);
PrintMessage(Inform,"The protocol '%s' is not available.",Url->proto);
exit(1);
}
}
if(IsLocalNetHost(Url->host))
{
if(mode==Real || mode==Spool || mode==SpoolOrReal)
mode=RealNoCache;
else
{
PrintMessage(Inform,"The request to fetch a page from the local network host '%s' is ignored.",Url->host);
exit(0);
}
}
else if((mode==Real || mode==SpoolOrReal) && IsNotCached(Url->proto,Url->host,Url->path))
{
mode=RealNoCache;
}
if(!strncasecmp(request_head,"POST",4))
{
if(mode==Spool)
mode=SpoolGet;
}
else if(Url->args && *Url->args=='!')
{
if(mode==Real || mode==SpoolOrReal)
mode=Spool;
else if(mode==Fetch)
{
PrintMessage(Inform,"It is not possible to fetch a URL that was posted.");
exit(0);
}
}
if(strstr(request_head,"\nIf-Modified-Since:"))
{
char *bol=strstr(request_head,"\nIf-Modified-Since:")+1,*eol=strchr(bol,'\n');
*eol++=0;
if(mode==Spool || mode==SpoolOrReal)
{
spool=OpenWebpageSpoolFile(1,Url);
if(spool!=-1)
{
struct stat buf;
long since;
buf.st_mtime=time(NULL)+1;
fstat(spool,&buf);
since=DateToTimeT(bol+19);
close(spool);
if(since>buf.st_mtime)
{NotModified(client);exit(0);}
}
}
while(*eol)
*bol++=*eol++;
*bol=0;
}
spool_exists=ExistsWebpageSpoolFile(Url);
if(PragmaNoCache && strstr(request_head,"\nPragma: no-cache"))
{
if(mode==Spool || mode==SpoolGet)
{
if(spool_exists)
mode=SpoolPragma;
else
if(ExistsOutgoingSpoolFile(Url))
mode=SpoolWillGet;
else
mode=SpoolGet;
}
else if(mode==SpoolOrReal)
mode=Real;
/* (mode==Fetch || mode==Real) are left unchanged, not modified as below. */
}
else if(mode==Spool && !spool_exists)
{
if(ExistsOutgoingSpoolFile(Url))
mode=SpoolWillGet;
else
mode=SpoolGet;
}
else if(mode==Fetch && spool_exists)
{
spool=OpenWebpageSpoolFile(1,Url);
init_buffer(spool);
if(RequestChanges(spool,&request_head)==1)
TouchWebpageSpoolFile(Url);
else
exit(0);
close(spool);
}
else if(mode==Real && spool_exists)
{
spool=OpenWebpageSpoolFile(1,Url);
init_buffer(spool);
if(RequestChanged>=0 && RequestChanges(spool,&request_head)==1)
TouchWebpageSpoolFile(Url);
else
mode=Spool;
close(spool);
}
else if(mode==SpoolOrReal)
{
if(spool_exists)
mode=Spool;
else
mode=Real;
}
/* Create the last time file. */
if(mode==Real || mode==Fetch)
lasttime_exists=CreateLastTimeSpoolFile(Url);
/* Set up the file descriptor for the spool file. */
if(mode==Real || mode==Fetch)
{
spool=OpenWebpageSpoolFile(0,Url);
init_buffer(spool); /* may be read if Real changes to Spool later. */
if(spool==-1)
{
if(mode==Real)
ServerError(client,"Cannot open the spooled web page to write.");
PrintMessage(Warning,"Cannot open the spooled web page to write.");
exit(1);
}
if(spool_exists)
CreateBackupWebpageSpoolFile(Url,spool);
}
else if(mode==Spool || mode==SpoolPragma)
{
spool=OpenWebpageSpoolFile(1,Url);
init_buffer(spool);
if(spool==-1)
{
ServerError(client,"Cannot open the spooled web page to read.");
PrintMessage(Warning,"Cannot open the spooled web page to read.");
exit(1);
}
}
/* Set up the outgoing file. */
if((mode==SpoolGet || mode==SpoolRefresh || mode==SpoolPragma) && OfflineRequests)
{
outgoing=OpenOutgoingSpoolFile(0);
if(outgoing==-1)
{
ServerError(client,"Cannot open the outgoing request to write.");
PrintMessage(Warning,"Cannot open the outgoing request to write.");
exit(1);
}
}
/* Open the connection to the server host. */
if(mode==Real || mode==RealNoCache || mode==Fetch)
{
char *err=(Url->Protocol->open)(Url);
if(err)
{
if(mode==Fetch || mode==Real)
{
lseek(spool,0,SEEK_SET);
ftruncate(spool,0);
RemoteHostError(spool,Url,err,1,spool_exists);
}
if(mode==Real || mode==RealNoCache)
RemoteHostError(client,Url,err,0,spool_exists);
exit(1);
}
}
/* Modify the header (Censor / Cannonicalise URL / POST / HTTP-1.1 etc). */
if(mode==Real || mode==RealNoCache || mode==Fetch || mode==SpoolGet || mode==SpoolRefresh || mode==SpoolPragma)
request_head=ModifyRequest(Url,request_head);
/* Write request to remote server or outgoing file. */
if(mode==Real || mode==RealNoCache || mode==Fetch)
{
char *err=(Url->Protocol->request)(Url,request_head,request_body);
if(err)
{
if(mode==Real || mode==Fetch)
{
lseek(spool,0,SEEK_SET);
ftruncate(spool,0);
RemoteHostError(spool,Url,err,1,spool_exists);
}
if(mode==Real || mode==RealNoCache)
RemoteHostError(client,Url,err,0,spool_exists);
else if(mode==Fetch && client!=-1)
write_formatted(client,"Fetching %s [Server Connection Error]\n",Url->name);
exit(1);
}
}
else if((mode==SpoolGet || mode==SpoolRefresh || mode==SpoolPragma) && OfflineRequests)
{
int err=write_string(outgoing,request_head);
if(err==-1)
{
ServerError(client,"Cannot write the outgoing request.");
PrintMessage(Warning,"Cannot write the outgoing request.");
exit(1);
}
if(request_body)
write_string(outgoing,request_body);
}
/* Parse the reply */
if(mode==Real || mode==RealNoCache || mode==Fetch)
{
reply_status=ParseReply(Url,&reply_head);
if(!reply_head)
{
if(mode==Real || mode==Fetch)
{
lseek(spool,0,SEEK_SET);
ftruncate(spool,0);
RemoteHostError(spool,Url,"the server timed out before sending the reply.",1,spool_exists);
}
if(mode==Real || mode==RealNoCache)
RemoteHostError(client,Url,"the server timed out before sending the reply.",0,spool_exists);
else if(mode==Fetch && client!=-1)
write_formatted(client,"Fetching %s [Server Reply Error]\n",Url->name);
PrintMessage(Warning,"Timed out reading the reply.");
exit(1);
}
if(mode==Fetch && (reply_status==301 || reply_status==302))
{
char *new_url=MovedLocation(Url,reply_head);
if(client!=-1)
write_formatted(client,"Fetching %s [Page Moved]\n",Url->name);
if(!new_url)
PrintMessage(Warning,"Cannot parse the reply for the new location.");
else
{
char *new_request=RequestURL(new_url,Url->name);
int new_outgoing=OpenOutgoingSpoolFile(0);
PrintMessage(Inform,"This URL has been moved to %s.",new_url);
if(new_outgoing==-1)
PrintMessage(Warning,"Cannot open the new outgoing request to write.");
else
{
URL *new_Url=SplitURL(new_url);
write_string(new_outgoing,new_request);
CloseOutgoingSpoolFile(new_outgoing,new_Url);
FreeURL(new_Url);
fetch_again++;
}
free(new_request);
free(new_url);
}
}
else if(reply_status==304)
{
PrintMessage(Inform,"Server page is not newer than the one in cache.");
if((mode==Fetch || mode==Real) && !lasttime_exists)
DeleteLastTimeSpoolFile(Url);
if(mode==Fetch)
{
if(client!=-1)
write_formatted(client,"Fetching %s [Page Unchanged]\n",Url->name);
if(spool_exists)
DeleteBackupWebpageSpoolFile(Url);
exit(0);
}
else if(mode==Real)
{
mode=Spool;
if(spool_exists)
DeleteBackupWebpageSpoolFile(Url);
}
}
else if(mode==Fetch && client!=-1)
write_formatted(client,"Fetching %s\n",Url->name);
}
else
reply_head=NULL;
reply_body=(char*)malloc(257);
/* Close the outgoing file if any. */
if(outgoing>=0)
{
if(mode==Fetch)
close(outgoing);
if(mode==SpoolGet || mode==SpoolRefresh || mode==SpoolPragma)
CloseOutgoingSpoolFile(outgoing,Url);
}
/* Process the request. */
if(mode==Real || mode==RealNoCache)
{
int n=strlen(reply_head),err=0;
if(mode==Real)
write_data(spool,reply_head,n);
err=write_data(client,reply_head,n);
while(err!=-1 && (n=(Url->Protocol->readbody)(reply_body,256))>0)
{
if(mode==Real)
write_data(spool,reply_body,n);
err=write_data(client,reply_body,n);
}
if(mode==Real)
if(err==-1 || n<0)
{
lseek(spool,0,SEEK_SET);
ftruncate(spool,0);
if(err==-1)
{
RemoteHostError(spool,Url,"the connection was closed by the client during the transfer.",1,spool_exists);
PrintMessage(Warning,"Error writing to client [%!s]; client disconnected?.");
exit(1);
}
else
{
RemoteHostError(spool,Url,"the server timed out during the transfer.",1,spool_exists);
PrintMessage(Warning,"Timed out while reading from remote host.");
exit(1);
}
}
else
{
int tell=lseek(spool,0,SEEK_CUR);
if(tell!=-1)
ftruncate(spool,tell);
if(spool_exists)
DeleteBackupWebpageSpoolFile(Url);
}
}
else if(mode==Fetch)
{
int n=strlen(reply_head);
write_data(spool,reply_head,n);
while((n=(Url->Protocol->readbody)(reply_body,256))>0)
write_data(spool,reply_body,n);
if(n<0)
{
lseek(spool,0,SEEK_SET);
ftruncate(spool,0);
RemoteHostError(spool,Url,"the server timed out during the transfer.",1,spool_exists);
PrintMessage(Warning,"Timed out while reading from remote host.");
exit(1);
}
else
{
int tell=lseek(spool,0,SEEK_CUR);
if(tell!=-1)
ftruncate(spool,tell);
if(spool_exists)
DeleteBackupWebpageSpoolFile(Url);
}
if(reply_status>=200 && reply_status<400)
{
lseek(spool,0,SEEK_SET);
init_buffer(spool);
if(ParseHTML(spool,Url,0))
{
char **list,*refresh;
if((refresh=MetaRefresh()))
{
char *new_request=RequestURL(refresh,Url->name);
int new_outgoing=OpenOutgoingSpoolFile(0);
PrintMessage(Debug,"Meta-Refresh=%s",refresh);
if(new_outgoing==-1)
PrintMessage(Warning,"Cannot open the new outgoing request to write.");
else
{
URL *ref_Url=SplitURL(refresh);
write_string(new_outgoing,new_request);
CloseOutgoingSpoolFile(new_outgoing,ref_Url);
FreeURL(ref_Url);
fetch_again++;
}
free(new_request);
free(refresh);
}
if(FetchImages && (list=ListImages()))
for(n=0;list[n];n++)
{
char *new_request=RequestURL(list[n],Url->name);
int new_outgoing=OpenOutgoingSpoolFile(0);
PrintMessage(Debug,"Image=%s",list[n]);
if(new_outgoing==-1)
PrintMessage(Warning,"Cannot open the new outgoing request to write.");
else
{
URL *new_Url=SplitURL(list[n]);
write_string(new_outgoing,new_request);
CloseOutgoingSpoolFile(new_outgoing,new_Url);
FreeURL(new_Url);
fetch_again++;
}
free(new_request);
}
if(FetchFrames && (list=ListFrames()))
for(n=0;list[n];n++)
{
char *new_request=RequestURL(list[n],Url->name);
int new_outgoing=OpenOutgoingSpoolFile(0);
PrintMessage(Debug,"Frame=%s",list[n]);
if(new_outgoing==-1)
PrintMessage(Warning,"Cannot open the new outgoing request to write.");
else
{
URL *new_Url=SplitURL(list[n]);
write_string(new_outgoing,new_request);
CloseOutgoingSpoolFile(new_outgoing,new_Url);
FreeURL(new_Url);
fetch_again++;
}
free(new_request);
}
}
}
}
else if(mode==Spool || mode==SpoolPragma)
{
struct stat buf;
char *head="HTTP/1.0 503 WWWOFFLE Remote Host Error\r\n"; /* This line must not be changed (see messages.c). */
int n=read_data(spool,reply_body,64);
if(!strncmp(reply_body,head,strlen(head)) || (!fstat(spool,&buf) && buf.st_size==0))
{
DeleteWebpageSpoolFile(Url,0);
RestoreBackupWebpageSpoolFile(Url);
}
if(AddInfoRefresh)
{
struct stat buf;
lseek(spool,0,SEEK_SET);
init_buffer(spool);
if(ParseHTML(spool,Url,0) && !fstat(spool,&buf))
{
time_t t_ago=time(NULL)-buf.st_mtime;
int position=GetHTMLEnd();
char *date=RFC822Date(buf.st_mtime,0),ago[24],*localhost=GetLocalHost(1);
char *refresh=(char*)malloc(4*strlen(Url->name)+4*strlen(localhost)+256);
char *index=(char*)malloc(strlen(Url->name)+strlen(localhost)+64);
char *msg=(char*)malloc(strlen(date)+5*strlen(Url->name)+5*strlen(localhost)+320);
if(t_ago<0)
sprintf(ago,"in the future");
else if(t_ago<3600)
sprintf(ago,"%ld min%s ago",t_ago/60,t_ago/60==1?"":"s");
else if(t_ago<(24*3600))
sprintf(ago,"%ld hour%s ago",t_ago/3600,t_ago/3600==1?"":"s");
else if(t_ago<(14*24*3600))
sprintf(ago,"%ld day%s ago",t_ago/(24*3600),t_ago/(24*3600)==1?"":"s");
else if(t_ago<(30*24*3600))
sprintf(ago,"%ld week%s ago",t_ago/(7*24*3600),t_ago/(7*24*3600)==1?"":"s");
else
sprintf(ago,"%ld month%s ago",t_ago/(30*24*3600),t_ago/(30*24*3600)==1?"":"s");
if(Url->args && *Url->args=='!')
sprintf(refresh,"[<a href=\"http://%s/control/delete?url=%s\">Delete</a>"
"|Refresh:"
"Options|"
"Monitor]",
localhost,Url->name);
else
sprintf(refresh,"[<a href=\"http://%s/control/delete?url=%s\">Delete</a>"
"|<a href=\"http://%s/refresh/%s/%s\">Refresh</a>:"
"<a href=\"http://%s/refresh/?%s\">Options</a>|"
"<a href=\"http://%s/monitor/?%s\">Monitor</a>]",
localhost,Url->name,
localhost,Url->proto,Url->hostp,
localhost,Url->name,
localhost,Url->name);
sprintf(index,"[<a href=\"http://%s/index/%s/%s/?none\">Index</a>]",
localhost,Url->proto,Url->host);
sprintf(msg,"\n"
"<hr>\n"
"<p align=center>\n"
"WWWOFFLE - %s (%s) - %s - %s - WWWOFFLE\n"
"</p>\n"
"<hr>\n",
date,ago,refresh,index);
lseek(spool,0,SEEK_SET);
init_buffer(spool);
while((reply_head=read_line(spool,reply_head)))
{
if(!strncmp(reply_head,"Content-Length:",15))
sprintf(reply_head,"Content-Length: %d\r\n",atoi(&reply_head[16])+strlen(msg));
write_string(client,reply_head);
if(reply_head[0]=='\r' || reply_head[0]=='\n')
break;
}
while(position>0 && (n=read_data(spool,reply_body,position>256?256:position))>0)
{
write_data(client,reply_body,n);
position-=n;
}
write_string(client,msg);
while((n=read_data(spool,reply_body,256))>0)
write_data(client,reply_body,n);
free(localhost);
free(refresh);
free(index);
free(msg);
}
else
{
lseek(spool,0,SEEK_SET);
init_buffer(spool);
while((n=read_data(spool,reply_body,256))>0)
write_data(client,reply_body,n);
}
}
else
do
{
write_data(client,reply_body,n);
}
while((n=read_data(spool,reply_body,256))>0);
}
else if(mode==SpoolGet)
{
if(OfflineRequests)
WillGetURL(client,Url,0);
else
RefusedRequest(client,Url);
}
else if(mode==SpoolWillGet)
{
WillGetURL(client,Url,1);
}
else if(mode==RealRefresh || mode==SpoolRefresh)
{
RefreshRedirect(client,Url);
}
/* Close down and exit. */
if(mode==Real && ExistsOutgoingSpoolFile(Url))
DeleteOutgoingSpoolFile(Url);
if(mode==Real || mode==RealNoCache || mode==Fetch)
(Url->Protocol->close)();
if(spool>=0)
close(spool);
if(request_head)
free(request_head);
if(request_body)
free(request_body);
if(reply_head)
free(reply_head);
if(reply_body)
free(reply_body);
if(client>=0)
CloseSocket(client);
if(fetch_again)
return(4);
else
return(0);
}
/*++++++++++++++++++++++++++++++++++++++
Uninstall the signal handlers.
++++++++++++++++++++++++++++++++++++++*/
static void uninstall_sighandlers(void)
{
struct sigaction action;
/* SIGCHLD */
action.sa_handler = SIG_DFL;
sigemptyset (&action.sa_mask);
action.sa_flags = 0;
if(sigaction(SIGCHLD, &action, NULL) != 0)
PrintMessage(Warning, "Cannot uninstall SIGCHLD handler.");
/* SIGINT, SIGQUIT, SIGTERM */
action.sa_handler = SIG_DFL;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
if(sigaction(SIGINT, &action, NULL) != 0)
PrintMessage(Warning, "Cannot uninstall SIGINT handler.");
if(sigaction(SIGQUIT, &action, NULL) != 0)
PrintMessage(Warning, "Cannot uninstall SIGQUIT handler.");
if(sigaction(SIGTERM, &action, NULL) != 0)
PrintMessage(Warning, "Cannot uninstall SIGTERM handler.");
/* SIGHUP */
action.sa_handler = SIG_DFL;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
if(sigaction(SIGHUP, &action, NULL) != 0)
PrintMessage(Warning, "Cannot uninstall SIGHUP handler.");
/* SIGPIPE */
action.sa_handler = SIG_IGN;
sigemptyset (&action.sa_mask);
action.sa_flags = 0;
if(sigaction(SIGPIPE, &action, NULL) != 0)
PrintMessage(Warning, "Cannot ignore SIGPIPE.");
}