예제 #1
0
파일: exef.c 프로젝트: rmblair/tecoc
static DEFAULT ExeFD()			/* execute an FD command */
{
	DBGFEN(1,"ExeFD",NULL);

/*
 * The command m,nFD is illegal: the user should use m,nFB
 */

	if (CmdMod & MARGIS) {			/* if it's m,nFD */
		ErrStr(ERR_ILL, "m,nFD");	/* illegal command "m,nFD" */
		DBGFEX(1,DbgFNm,"FAILURE");
		return FAILURE;
	}

	if (CmdMod & DCOLON) {			/* if it's ::FD */
		ErrStr(ERR_ILL, "::FD");	/* illegal command "::FD" */
		DBGFEX(1,DbgFNm,"FAILURE");
		return FAILURE;
	}

	SrcTyp = S_SEARCH;
	if (Search(FALSE) == FAILURE) {
		DBGFEX(1,DbgFNm,"FAILURE");
		return FAILURE;
	}

	if (Matchd) {				/* if successful search */
		GapBeg += RefLen;		/* delete found string */
	}

	CmdMod = '\0';				/* clear modifiers flags */

	DBGFEX(1,DbgFNm,"SUCCESS");
	return SUCCESS;
}
예제 #2
0
파일: exef.c 프로젝트: rmblair/tecoc
static DEFAULT ExeFUn()				/* execute an F_ command */
{
	DBGFEN(1,"ExeFUn",NULL);

/*
 * The command m,nF_ is illegal: the user should use m,nFC
 */


	if (CmdMod & MARGIS) {			/* if it's m,nF_ */
		ErrStr(ERR_ILL, "m,nF_");	/* illegal command "m,nF_" */
		DBGFEX(1,DbgFNm,"FAILURE");
		return FAILURE;
	}

	if (CmdMod & DCOLON) {			/* if it's ::F_ */
		ErrStr(ERR_ILL, "::F_");	/* illegal command "::F_" */
		DBGFEX(1,DbgFNm,"FAILURE");
		return FAILURE;
	}

	SrcTyp = U_SEARCH;

	if (Replac() == FAILURE) {
		DBGFEX(1,DbgFNm,"FAILURE");
		return FAILURE;
	}

	CmdMod = '\0';				/* clear modifiers flags */

	DBGFEX(1,DbgFNm,"SUCCESS");
	return SUCCESS;
}
예제 #3
0
파일: exef.c 프로젝트: rmblair/tecoc
static DEFAULT ExeFS()			/* execute an FS command */
{
	DBGFEN(1,"ExeFS",NULL);

/*
 * The command m,nFS is illegal: the user should use m,nFC
 */

	if (CmdMod & MARGIS) {			/* if it's m,nFS */
		ErrStr(ERR_ILL, "m,nFS");	/* illegal command "m,nFS" */
		DBGFEX(1,DbgFNm,"FAILURE");
		return FAILURE;
	}

/*
 * If it's ::FStext$,  it's a compare,  not a search.  The text argument is
 * compared to the characters immediately following the character pointer.
 * It returns -1 if the strings match, else 0.  A ::FStext$ command is
 * equivalent to a .,.+1:FCtext$ command, so that's the way it's implemented.
 */

	if (CmdMod & DCOLON) {			/* if it's ::FS */
		if (CmdMod & MARGIS) {		/* if it's m,n::FS */
			ErrStr(ERR_ILL, "m,n::FS");
			DBGFEX(1,DbgFNm,"FAILURE");
			return FAILURE;
		}
		if (EStTop > EStBot) {		/* if it's n::FS */
			ErrStr(ERR_ILL, "n::FS");
			DBGFEX(1,DbgFNm,"FAILURE");
			return FAILURE;
		}
		if (GapEnd == EBfEnd) {		/* if nothing to search */
			CmdMod = '\0';		/* clear modifiers flags */
			DBGFEX(1,DbgFNm,"PushEx(0)");
			return PushEx(0L,OPERAND);
		}
		CmdMod &= ~DCOLON;		/* clear double-colon bit */
		CmdMod |= COLON;		/* set colon bit */
		CmdMod |= MARGIS;		/* set m defined bit */
		MArgmt = GapBeg - EBfBeg;	/* set m */
		if (PushEx((LONG)((GapBeg-EBfBeg)+1),OPERAND) == FAILURE) {
			DBGFEX(1,DbgFNm,"FAILURE, PushEx() failed");
			return FAILURE;
		}
		DBGFEX(1,DbgFNm,"ExeFC()");
		return ExeFC();			/* execute FC command */
	}

	SrcTyp = S_SEARCH;
	if (Replac() == FAILURE) {
		DBGFEX(1,DbgFNm,"FAILURE, Replac() failed");
		return FAILURE;
	}

	CmdMod = '\0';				/* clear modifiers flags */

	DBGFEX(1,DbgFNm,"SUCCESS");
	return SUCCESS;
}
예제 #4
0
파일: exef.c 프로젝트: rmblair/tecoc
static DEFAULT ExeFK()			/* execute an FK command */
{
	DBGFEN(1,"ExeFK",NULL);

	if (CmdMod & MARGIS) {			/* if it's m,nFK */
		ErrStr(ERR_ILL, "m,nFK");	/* illegal command "m,nFK" */
		DBGFEX(1,DbgFNm,"FAILURE");
		return FAILURE;
	}

	if (CmdMod & DCOLON) {			/* if it's ::FK */
		ErrStr(ERR_ILL, "::FK");	/* illegal command "::FK" */
		DBGFEX(1,DbgFNm,"FAILURE");
		return FAILURE;
	}

	SrcTyp = FK_SEARCH;

	if (Search(FALSE) == FAILURE) {
		DBGFEX(1,DbgFNm,"FAILURE");
		return FAILURE;
	}

	CmdMod = '\0';				/* clear modifiers flags */

	DBGFEX(1,DbgFNm,"SUCCESS");
	return SUCCESS;
}
예제 #5
0
파일: getara.c 프로젝트: rmblair/tecoc
DEFAULT GetAra()		/* get m,n addresses */
{
	LONG	TmpLng;

#if DEBUGGING
	static char *DbgFNm = "GetAra";
	sprintf(DbgSBf,"MArgmt = %ld, NArgmt = %ld", MArgmt, NArgmt);
	DbgFEn(4,DbgFNm,DbgSBf);
#endif

	if (MArgmt < 0) {			/* if negative m */
		ErrMsg(ERR_NCA);		/* negative argument to , */
		DBGFEX(4,DbgFNm,"FAILURE, negative m");
		return FAILURE;
	}

	if (NArgmt < 0)	{			/* if negative n */
		ErrStr(ERR_POP, ErrTxt);	/* POP = pointer off page */
		DBGFEX(4,DbgFNm,"FAILURE, negative n");
		return FAILURE;
	}

	if (MArgmt > NArgmt) {			/* if wrong order */
		TmpLng = NArgmt;
		NArgmt = MArgmt;
		MArgmt = TmpLng;
	}

	AraBeg = EBfBeg + MArgmt;		/* compute area beginning */
	if (AraBeg > GapBeg-1) {		/* if past start of gap */
		AraBeg += (GapEnd-GapBeg) + 1;	/* correct for gap */
	}

	AraEnd = (EBfBeg + NArgmt) - 1;		/* compute area end */
	if (AraEnd > GapBeg-1) {		/* if before end of gap */
		AraEnd += (GapEnd-GapBeg) + 1;	/* correct for gap */
	}

	if ((AraBeg > EBfEnd) ||		/* if m or n too large */
	    (AraEnd > EBfEnd)) {
		ErrStr(ERR_POP, ErrTxt);	/* POP = pointer off page */
		DBGFEX(4,DbgFNm,"FAILURE");
		return FAILURE;
	}

#if DEBUGGING
	sprintf(DbgSBf,"SUCCESS, AraBeg = %ld, AraEnd = %ld",
		Zcp2ul(AraBeg), Zcp2ul(AraEnd));
	DbgFEx(4,DbgFNm,DbgSBf);
#endif
	return SUCCESS;
}
예제 #6
0
PulseSignalHeader &
PulseClusterer::getNth(int idx)
{
	if (!isComplete())
		Fatal(666);
	if (idx < 0 || idx > (int) clusterList.size()) {
		ErrStr(idx, "index");
		ErrStr(clusterList.size(), "pd clusters");
		ErrStr(parent->getCount(), "supercluster count");
		Fatal(666);
	}
	return *clusterList[idx];
}
예제 #7
0
파일: error.cpp 프로젝트: NotFound/Blassic
std::ostream & operator << (std::ostream & os, const BlError & bl)
{
	os << ErrStr (bl.err);
	const BlLineNumber line= bl.getpos ().getnum ();
	if (line != LineDirectCommand)
		os << " in " << line;
	//os << '\n';
	return os;
}
예제 #8
0
파일: exef.c 프로젝트: rmblair/tecoc
static DEFAULT ExeFC()			/* execute an FC command */
{
	DBGFEN(1,"ExeFC",NULL);

	if (CmdMod & DCOLON) {			/* if it's ::FC */
		ErrStr(ERR_ILL, "::FC");	/* illegal command "::FC" */
		DBGFEX(1,DbgFNm,"FAILURE");
		return FAILURE;
	}

	SrcTyp = FB_SEARCH;
	if (Replac() == FAILURE) {
		DBGFEX(1,DbgFNm,"FAILURE");
		return FAILURE;
	}

	CmdMod = '\0';				/* clear modifiers flags */

	DBGFEX(1,DbgFNm,"SUCCESS");
	return SUCCESS;
}
예제 #9
0
/********************************************************************************************

>	HRESULT Error::GetRalphError()

	Author:		Chris_Snook (Xara Group Ltd) <*****@*****.**>
	Created:	23/05/94
	Purpose:	ERROR1 - No local reporting -pass the mapped Error code to the harness
				ERROR2 - Report the Error locally - don't pass to handler 
				ERROR3 - Report as ERROR2's - won't occur in retails - 

********************************************************************************************/
HRESULT Error::GetRalphError()
{
	
	UINT32 Err = Error::GetRalphErrorNumber();
	wxString ErrStr( Error::GetErrorString() );
	HRESULT hr = S_OK;

	// ERROR2's 3's
	if(Err==0)
	{
		if(!ErrStr.IsEmpty())
		{
#if defined(_DEBUG) && defined(__WXMSW__)
			MessageBox(NULL,ErrStr,_T("Error"),MB_OK);
#endif
			// make sure we clear ERROR2's 'cause we report them now
			Error::ClearError();
		}	
	}

	//ERROR1
	if(Err!=0)
	{
		// Do Mapping
		hr = ErrIDToHRESULT(Err);
	
	}
	// ERROR 2's 3's
	if(Err==0)
	{
		if(!ErrStr.IsEmpty())
		   hr = RALPH_E_INTERNAL;
	}
	
	return hr;
}
예제 #10
0
//
// routine: receive and send on incoming messages
//
// Notes:
//		No analysis of the message is performed - that is left
//		to the command processor task.  Instead, the local copy
//		of the header
//		is demarshalled to determined whether or not there
//		is associated data; if there is, space is allocated to
//		contain it.
void *
SseInputTask::routine()
{
    extractArgs();

    Timer timer;
    if (cmdArgs->noSSE()) {
        processIpFromFile();
        while (1)
            timer.sleep(3000);
    };

    // run forever, waiting for messages from the SSE
    bool stopIssued = false;
    bool done = false;
    uint32_t lastCode = MESSAGE_CODE_UNINIT;
    int32_t lastLen = 0;
    uint32_t lastTime = 0;
    while (!done) {
        // if there's no connection, request that it be
        // established, then wait for that to happen
        if (!sse->isConnected()) {
            requestConnection();
            while (!sse->isConnected())
                timer.sleep(3000);
        }
        stopIssued = false;

        // got a connection - wait for data to come in
        SseInterfaceHeader hdr;
        Error err = sse->recv((void *) &hdr, sizeof(hdr));
        if (err) {
            switch (err) {
            case EAGAIN:
            case EINTR:
            case ENOTCONN:
            case ECONNRESET:
                stopAllActivities(stopIssued);
                continue;
            default:
                Fatal(err);
                break;
            }
        }
        // demarshall the header
        hdr.demarshall();

        if (cmdArgs->logSseMessages()) {
            LogWarning(ERR_NE, hdr.activityId,
                       "bad msg from Sse, code = %d, len = %d", hdr.code,
                       hdr.dataLength);
        }

        // allocate a message to hold the incoming message
        Msg *msg = msgList->alloc();
        msg->setHeader(hdr);
        msg->setUnit((sonata_lib::Unit) UnitSse);

        // if there's data associated with the message,
        // allocate space and retrieve it, demarshall it
        // based on the message type,
        // then send it on to the command processor
        void *data = 0;
        int32_t len = hdr.dataLength;
        timeval tv;
        gettimeofday(&tv, NULL);
        if (len > 10000) {
            LogWarning(ERR_NE, hdr.activityId,
                       "msg code = %d, len = %d, t = %u, last msg = %d, last len = %d, last t = %u",
                       hdr.code, len, tv.tv_sec, lastCode, lastLen, lastTime);
            Timer t;
            t.sleep(100);
        }
        else {
            lastCode = hdr.code;
            lastLen = len;
            lastTime = tv.tv_sec;
        }
        if (len) {
            MemBlk *blk = partitionSet->alloc(len);
            Assert(blk);
            if (!blk)
                Fatal(ERR_MAF);
            data = blk->getData();
            err = sse->recv(data, len);
            if (err) {
                switch (err) {
                case EAGAIN:
                case EINTR:
                case ENOTCONN:
                case ECONNRESET:
                    blk->free();
                    Assert(msgList->free(msg));
                    stopAllActivities(stopIssued);
                    continue;
                default:
                    Fatal(err);
                    break;
                }
            }
            msg->setData(data, len, blk);
        }

        // demarshall the data of the message depending on
        // the message type
        switch (hdr.code) {
        case REQUEST_INTRINSICS:
            break;
        case CONFIGURE_DX:
            (static_cast<DxConfiguration *> (data))->demarshall();
            break;

        case PERM_RFI_MASK:
        case BIRDIE_MASK:
        case RCVR_BIRDIE_MASK:
        case TEST_SIGNAL_MASK:
            demarshallFrequencyMask(data);
            break;
        case RECENT_RFI_MASK:
            demarshallRecentRFIMask(data);
            break;
        case REQUEST_DX_STATUS:
            break;
        case SEND_DX_ACTIVITY_PARAMETERS:
            (static_cast<DxActivityParameters *> (data))->demarshall();
            break;
        case DX_SCIENCE_DATA_REQUEST:
            (static_cast<DxScienceDataRequest *> (data))->demarshall();
            break;
#ifdef notdef
        case SEND_DOPPLER_PARAMETERS:
            (static_cast<DopplerParameters *> (data))->demarshall();
            break;
#endif
        case BEGIN_SENDING_FOLLOW_UP_SIGNALS:
            (static_cast<Count *> (data))->demarshall();
            break;
        case SEND_FOLLOW_UP_CW_SIGNAL:
            (static_cast<FollowUpCwSignal *> (data))->demarshall();
            break;
        case SEND_FOLLOW_UP_PULSE_SIGNAL:
            (static_cast<FollowUpPulseSignal *> (data))->demarshall();
            break;
        case DONE_SENDING_FOLLOW_UP_SIGNALS:
            break;
        case START_TIME:
            (static_cast<StartActivity *> (data))->demarshall();
            break;
        case BEGIN_SENDING_CANDIDATES:
            (static_cast<Count *> (data))->demarshall();
            break;
        case SEND_CANDIDATE_CW_POWER_SIGNAL:
            (static_cast<CwPowerSignal *> (data))->demarshall();
            break;
        case SEND_CANDIDATE_PULSE_SIGNAL:
            demarshallPulseSignal(data);
            break;
        case DONE_SENDING_CANDIDATES:
            break;
        case BEGIN_SENDING_CW_COHERENT_SIGNALS:
            break;
        case SEND_CW_COHERENT_SIGNAL:
            (static_cast<CwCoherentSignal *> (data))->demarshall();
            break;
        case DONE_SENDING_CW_COHERENT_SIGNALS:
            break;
        case REQUEST_ARCHIVE_DATA:
            (static_cast<ArchiveRequest *> (data))->demarshall();
            break;
        case DISCARD_ARCHIVE_DATA:
            (static_cast<ArchiveRequest *> (data))->demarshall();
            break;
        // the following commands arrive with no data
        case STOP_DX_ACTIVITY:
        case SHUTDOWN_DX:
        case RESTART_DX:
            Debug(DEBUG_CONTROL, hdr.activityId,
                  "STOP_DX_ACTIVITY, act");
            break;
        default:
            LogError(ERR_IMT, hdr.activityId, "activity %d, type %d",
                     hdr.activityId, hdr.code);
            Err(ERR_IMT);
            ErrStr(hdr.code, "msg code");
            Assert(msgList->free(msg));
            continue;
        }

        // at this point, the entire marshalled message is in
        // a generic Msg; send the message on for processing,
        // then go back to waiting
        cmdQ->send(msg);
    }
    return (0);
}
예제 #11
0
// program entry point
int main(int argc, char *argv[])
{
	is_daemonised = false;
	bool nodaemon = false;
	bool needreset = false;
	std::string configfile(__CONFFILE);
	srand(time(NULL));
	int rc;

	openlog("dansguardian", LOG_PID | LOG_CONS, LOG_USER);

#ifdef DGDEBUG
	std::cout << "Running in debug mode..." << std::endl;
#endif

#ifdef __BENCHMARK
	char benchmark = '\0';
#endif

	for (int i = 1; i < argc; i++) {
		if (argv[i][0] == '-') {
			for (unsigned int j = 1; j < strlen(argv[i]); j++) {
				char option = argv[i][j];
				bool dobreak = false;
				switch (option) {
				case 'q':
					read_config(configfile.c_str(), 0);
					return sysv_kill(o.pid_filename);
				case 'Q':
					read_config(configfile.c_str(), 0);
					sysv_kill(o.pid_filename, false);
					// give the old process time to die
					while(sysv_amirunning(o.pid_filename))
						sleep(1);
					unlink(o.pid_filename.c_str());
					unlink(o.ipc_filename.c_str());
					unlink(o.urlipc_filename.c_str());
					// remember to reset config before continuing
					needreset = true;
					break;
				case 's':
					read_config(configfile.c_str(), 0);
					return sysv_showpid(o.pid_filename);
				case 'r':
					read_config(configfile.c_str(), 0);
					return sysv_hup(o.pid_filename);
				case 'g':
					read_config(configfile.c_str(), 0);
					return sysv_usr1(o.pid_filename);
				case 'v':
					std::cout << "DansGuardian " << PACKAGE_VERSION << std::endl << std::endl
						<< "Built with: " << DG_CONFIGURE_OPTIONS << std::endl;
					return 0;
				case 'N':
					nodaemon = true;
					break;
				case 'c':
					if ((i+1) < argc) {
						configfile = argv[i+1];
						dobreak = true;  // broken-ness of this option reported by Jason Gauthier 2006-03-09
					} else {
						std::cerr << "No config file specified!" << std::endl;
						return 1;
					}
					break;
				case 'h':
					std::cout << "Usage: " << argv[0] << " [{-c ConfigFileName|-v|-P|-h|-N|-q|-s|-r|-g}]" << std::endl;
					std::cout << "  -v gives the version number and build options." << std::endl;
					std::cout << "  -h gives this message." << std::endl;
					std::cout << "  -c allows you to specify a different configuration file location." << std::endl;
					std::cout << "  -N Do not go into the background." << std::endl;
					std::cout << "  -q causes DansGuardian to kill any running copy." << std::endl;
					std::cout << "  -Q kill any running copy AND start a new one with current options." << std::endl;
					std::cout << "  -s shows the parent process PID and exits." << std::endl;
					std::cout << "  -r closes all connections and reloads config files by issuing a HUP," << std::endl;
					std::cout << "     but this does not reset the maxchildren option (amongst others)." << std::endl;
					std::cout << "  -g gently restarts by not closing all current connections; only reloads" << std::endl
						<< "     filter group config files. (Issues a USR1)" << std::endl;
#ifdef __BENCHMARK
					std::cout << "  --bs benchmark searching filter group 1's bannedsitelist" << std::endl;
					std::cout << "  --bu benchmark searching filter group 1's bannedurllist" << std::endl;
					std::cout << "  --bp benchmark searching filter group 1's phrase lists" << std::endl;
					std::cout << "  --bn benchmark filter group 1's NaughtyFilter in its entirety" << std::endl;
#endif
					return 0;
#ifdef __BENCHMARK
				case '-':
					if (strlen(argv[i]) != 4) {
						std::cerr << "Invalid benchmark option" << std::endl;
						return 1;
					}
					benchmark = argv[i][3];
					dobreak = true;
					break;
#endif
				}
				if (dobreak) break; // skip to the next argument
			}
		}
	}

	// Set current locale for proper character conversion
	setlocale(LC_ALL, "");

	if (needreset) {
		o.reset();
	}
	
	read_config(configfile.c_str(), 2);

#ifdef __BENCHMARK
	// run benchmarks instead of starting the daemon
	if (benchmark) {
		std::string results;
		char* found;
		struct tms then, now;
		std::string line;
		std::deque<String*> lines;
		while (!std::cin.eof()) {
			std::getline(std::cin, line);
			String* strline = new String(line);
			lines.push_back(strline);
		}
		String* strline = NULL;
		times(&then);
		switch (benchmark) {
		case 's':
			// bannedsitelist
			while (!lines.empty()) {
				strline = lines.back();
				lines.pop_back();
				if ((found = o.fg[0]->inBannedSiteList(*strline))) {
					results += found;
					results += '\n';
				}
				delete strline;
			}
			break;
		case 'u':
			// bannedurllist
			while (!lines.empty()) {
				strline = lines.back();
				lines.pop_back();
				if ((found = o.fg[0]->inBannedURLList(*strline))) {
					results += found;
					results += '\n';
				}
				delete strline;
			}
			break;
		case 'p': {
				// phraselists
				std::deque<unsigned int> found;
				std::string file;
				while (!lines.empty()) {
					strline = lines.back();
					lines.pop_back();
					file += strline->toCharArray();
					delete strline;
				}
				char cfile[file.length() + 129];
				memcpy(cfile, file.c_str(), sizeof(char)*file.length());
				o.lm.l[o.fg[0]->banned_phrase_list]->graphSearch(found, cfile, file.length());
				for (std::deque<unsigned int>::iterator i = found.begin(); i != found.end(); i++) {
					results += o.lm.l[o.fg[0]->banned_phrase_list]->getItemAtInt(*i);
					results += '\n';
				}
			}
			break;
		case 'n': {
				// NaughtyFilter
				std::string file;
				NaughtyFilter n;
				while (!lines.empty()) {
					strline = lines.back();
					lines.pop_back();
					file += strline->toCharArray();
					delete strline;
				}
				DataBuffer d(file.c_str(), file.length());
				String f;
				n.checkme(&d, f, f);
				std::cout << n.isItNaughty << std::endl << n.whatIsNaughty << std::endl << n.whatIsNaughtyLog << std::endl << n.whatIsNaughtyCategories << std::endl;
			}
			break;
		default:
			std::cerr << "Invalid benchmark option" << std::endl;
			return 1;
		}
		times(&now);
		std::cout << results << std::endl << "time: " << now.tms_utime - then.tms_utime << std::endl;
		return 0;
	}
#endif

	if (sysv_amirunning(o.pid_filename)) {
		syslog(LOG_ERR, "%s", "I seem to be running already!");
		std::cerr << "I seem to be running already!" << std::endl;
		return 1;  // can't have two copies running!!
	}

	if (nodaemon) {
		o.no_daemon = 1;
	}

	if ((o.max_children + 6) > FD_SETSIZE) {
		syslog(LOG_ERR, "%s", "maxchildren option in dansguardian.conf has a value too high.");
		std::cerr << "maxchildren option in dansguardian.conf has a value too high." << std::endl;
		std::cerr << "Dammit Jim, I'm a filtering proxy, not a rabbit." << std::endl;
		return 1;  // we can't have rampant proccesses can we?
	}

	unsigned int rootuid;  // prepare a struct for use later
	rootuid = geteuid();
	o.root_user = rootuid;

	struct passwd *st;  // prepare a struct
	struct group *sg;

	// "daemongroup" option exists, but never used to be honoured. this is now
	// an important feature, however, because we need to be able to create temp
	// files with suitable permissions for scanning by AV daemons - we do this
	// by becoming a member of a specified AV group and setting group read perms
	if ((sg = getgrnam(o.daemon_group_name.c_str())) != 0) {
		o.proxy_group = sg->gr_gid;
	} else {
		syslog(LOG_ERR, "Unable to getgrnam(): %s", ErrStr().c_str());
		std::cerr << "Unable to getgrnam(): " << ErrStr() << std::endl;
		return 1;
	}

	if ((st = getpwnam(o.daemon_user_name.c_str())) != 0) {	// find uid for proxy user
		o.proxy_user = st->pw_uid;

		rc = setgid(o.proxy_group);  // change to rights of proxy user group
		// i.e. low - for security
		if (rc == -1) {
			syslog(LOG_ERR, "%s", "Unable to setgid()");
			std::cerr << "Unable to setgid()" << std::endl;
			return 1;  // setgid failed for some reason so exit with error
		}
#ifdef HAVE_SETREUID
		rc = setreuid((uid_t) - 1, st->pw_uid);
#else
		rc = seteuid(o.proxy_user);  // need to be euid so can su back
		// (yes it negates but no choice)
#endif
		if (rc == -1) {
			syslog(LOG_ERR, "Unable to seteuid()");
			std::cerr << "Unable to seteuid()" << std::endl;
			return 1;  // seteuid failed for some reason so exit with error
		}
	} else {
		syslog(LOG_ERR, "Unable to getpwnam() - does the proxy user exist?");
		std::cerr << "Unable to getpwnam() - does the proxy user exist?" << std::endl;
		std::cerr << "Proxy user looking for is '" << o.daemon_user_name << "'" << std::endl;
		return 1;  // was unable to lockup the user id from passwd
		// for some reason, so exit with error
	}

	if (!o.no_logger && !o.log_syslog) {
		std::ofstream logfiletest(o.log_location.c_str(), std::ios::app);
		if (logfiletest.fail()) {
			syslog(LOG_ERR, "Error opening/creating log file. (check ownership and access rights).");
			std::cout << "Error opening/creating log file. (check ownership and access rights)." << std::endl;
			std::cout << "I am running as " << o.daemon_user_name << " and I am trying to open " << o.log_location << std::endl;
			return 1;  // opening the log file for writing failed
		}
		logfiletest.close();
	}

	urldecode_re.comp("%[0-9a-fA-F][0-9a-fA-F]");  // regexp for url decoding

#ifdef HAVE_PCRE
	// todo: these only work with PCRE enabled (non-greedy matching).
	// change them, or make them a feature for which you need PCRE?
	absurl_re.comp("[\"'](http|ftp)://.*?[\"']");  // find absolute URLs in quotes
	relurl_re.comp("(href|src)\\s*=\\s*[\"'].*?[\"']");  // find relative URLs in quotes
#endif

	// this is no longer a class, but the comment has been retained for historical reasons. PRA 03-10-2005
	//FatController f;  // Thomas The Tank Engine

	while (true) {
		rc = fc_controlit();
		// its a little messy, but I wanted to split
		// all the ground work and non-daemon stuff
		// away from the daemon class
		// However the line is not so fine.
		if (rc == 2) {

			// In order to re-read the conf files and create cache files
			// we need to become root user again

#ifdef HAVE_SETREUID
			rc = setreuid((uid_t) - 1, rootuid);
#else
			rc = seteuid(rootuid);
#endif
			if (rc == -1) {
				syslog(LOG_ERR, "%s", "Unable to seteuid() to read conf files.");
#ifdef DGDEBUG
				std::cerr << "Unable to seteuid() to read conf files." << std::endl;
#endif
				return 1;
			}
#ifdef DGDEBUG
			std::cout << "About to re-read conf file." << std::endl;
#endif
			o.reset();
			if (!o.read(configfile.c_str(), 2)) {
				syslog(LOG_ERR, "%s", "Error re-parsing the dansguardian.conf file or other DansGuardian configuration files");
#ifdef DGDEBUG
				std::cerr << "Error re-parsing the dansguardian.conf file or other DansGuardian configuration files" << std::endl;
#endif
				return 1;
				// OptionContainer class had an error reading the conf or
				// other files so exit with error
			}
#ifdef DGDEBUG
			std::cout << "conf file read." << std::endl;
#endif

			if (nodaemon) {
				o.no_daemon = 1;
			}

			while (waitpid(-1, NULL, WNOHANG) > 0) {
			}	// mop up defunts

#ifdef HAVE_SETREUID
			rc = setreuid((uid_t) - 1, st->pw_uid);
#else
			rc = seteuid(st->pw_uid);  // become low priv again
#endif

			if (rc == -1) {
				syslog(LOG_ERR, "%s", "Unable to re-seteuid()");
#ifdef DGDEBUG
				std::cerr << "Unable to re-seteuid()" << std::endl;
#endif
				return 1;  // seteuid failed for some reason so exit with error
			}
			continue;
		}

		if (rc > 0) {
			if (!is_daemonised) {
				std::cerr << "Exiting with error" << std::endl;
			}
			syslog(LOG_ERR, "%s", "Exiting with error");
			return rc;  // exit returning the error number
		}
		return 0;  // exit without error
	}
}