Exemple #1
0
static void test_get_process_cmdline_harder(void) {
        char path[] = "/tmp/test-cmdlineXXXXXX";
        _cleanup_close_ int fd = -1;
        _cleanup_free_ char *line = NULL;
        pid_t pid;

        if (geteuid() != 0)
                return;

#ifdef HAVE_VALGRIND_VALGRIND_H
        /* valgrind patches open(/proc//cmdline)
         * so, test_get_process_cmdline_harder fails always
         * See https://github.com/systemd/systemd/pull/3555#issuecomment-226564908 */
        if (RUNNING_ON_VALGRIND)
                return;
#endif

        pid = fork();
        if (pid > 0) {
                siginfo_t si;

                (void) wait_for_terminate(pid, &si);

                assert_se(si.si_code == CLD_EXITED);
                assert_se(si.si_status == 0);

                return;
        }

        assert_se(pid == 0);
        assert_se(unshare(CLONE_NEWNS) >= 0);

        fd = mkostemp(path, O_CLOEXEC);
        assert_se(fd >= 0);
        assert_se(mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) >= 0);
        assert_se(unlink(path) >= 0);

        assert_se(prctl(PR_SET_NAME, "testa") >= 0);

        assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);

        assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
        assert_se(streq(line, "[testa]"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 1, true, &line) >= 0);
        assert_se(streq(line, ""));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 2, true, &line) >= 0);
        assert_se(streq(line, "["));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 3, true, &line) >= 0);
        assert_se(streq(line, "[."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 4, true, &line) >= 0);
        assert_se(streq(line, "[.."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 5, true, &line) >= 0);
        assert_se(streq(line, "[..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 6, true, &line) >= 0);
        assert_se(streq(line, "[...]"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 7, true, &line) >= 0);
        assert_se(streq(line, "[t...]"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 8, true, &line) >= 0);
        assert_se(streq(line, "[testa]"));
        line = mfree(line);

        assert_se(write(fd, "\0\0\0\0\0\0\0\0\0", 10) == 10);

        assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);

        assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
        assert_se(streq(line, "[testa]"));
        line = mfree(line);

        assert_se(write(fd, "foo\0bar\0\0\0\0\0", 10) == 10);

        assert_se(get_process_cmdline(getpid(), 0, false, &line) >= 0);
        assert_se(streq(line, "foo bar"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
        assert_se(streq(line, "foo bar"));
        line = mfree(line);

        assert_se(write(fd, "quux", 4) == 4);
        assert_se(get_process_cmdline(getpid(), 0, false, &line) >= 0);
        assert_se(streq(line, "foo bar quux"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
        assert_se(streq(line, "foo bar quux"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 1, true, &line) >= 0);
        assert_se(streq(line, ""));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 2, true, &line) >= 0);
        assert_se(streq(line, "."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 3, true, &line) >= 0);
        assert_se(streq(line, ".."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 4, true, &line) >= 0);
        assert_se(streq(line, "..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 5, true, &line) >= 0);
        assert_se(streq(line, "f..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 6, true, &line) >= 0);
        assert_se(streq(line, "fo..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 7, true, &line) >= 0);
        assert_se(streq(line, "foo..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 8, true, &line) >= 0);
        assert_se(streq(line, "foo..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 9, true, &line) >= 0);
        assert_se(streq(line, "foo b..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 10, true, &line) >= 0);
        assert_se(streq(line, "foo ba..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 11, true, &line) >= 0);
        assert_se(streq(line, "foo bar..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 12, true, &line) >= 0);
        assert_se(streq(line, "foo bar..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 13, true, &line) >= 0);
        assert_se(streq(line, "foo bar quux"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 14, true, &line) >= 0);
        assert_se(streq(line, "foo bar quux"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 1000, true, &line) >= 0);
        assert_se(streq(line, "foo bar quux"));
        line = mfree(line);

        assert_se(ftruncate(fd, 0) >= 0);
        assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);

        assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);

        assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
        assert_se(streq(line, "[aaaa bbbb cccc]"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 10, true, &line) >= 0);
        assert_se(streq(line, "[aaaa...]"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 11, true, &line) >= 0);
        assert_se(streq(line, "[aaaa...]"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid(), 12, true, &line) >= 0);
        assert_se(streq(line, "[aaaa b...]"));
        line = mfree(line);

        safe_close(fd);
        _exit(0);
}
Exemple #2
0
static void test_config_parse_rlimit(void) {
        struct rlimit * rl[_RLIMIT_MAX] = {};

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_NOFILE]);
        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_NOFILE]);
        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_NOFILE]);
        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_NOFILE]);
        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);

        rl[RLIMIT_NOFILE]->rlim_cur = 10;
        rl[RLIMIT_NOFILE]->rlim_max = 20;

        /* Invalid values don't change rl */
        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_NOFILE]);
        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_NOFILE]);
        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_NOFILE]);
        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_NOFILE]);
        assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
        assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);

        rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_CPU]);
        assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
        assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_CPU]);
        assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
        assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_CPU]);
        assert_se(rl[RLIMIT_CPU]->rlim_cur == 40);
        assert_se(rl[RLIMIT_CPU]->rlim_max == 60);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_CPU]);
        assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
        assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_CPU]);
        assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
        assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);

        rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_RTTIME]);
        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_RTTIME]);
        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
        assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_RTTIME]);
        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_RTTIME]);
        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
        assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_RTTIME]);
        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_RTTIME]);
        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);

        assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
        assert_se(rl[RLIMIT_RTTIME]);
        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
        assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);

        rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]);
}
Exemple #3
0
static int set_machine_info(Context *c, sd_bus_message *m, int prop, sd_bus_message_handler_t cb, sd_bus_error *error) {
        int interactive;
        const char *name;
        int r;

        assert(c);
        assert(m);

        r = sd_bus_message_read(m, "sb", &name, &interactive);
        if (r < 0)
                return r;

        if (isempty(name))
                name = NULL;

        if (streq_ptr(name, c->data[prop]))
                return sd_bus_reply_method_return(m, NULL);

        /* Since the pretty hostname should always be changed at the
         * same time as the static one, use the same policy action for
         * both... */

        r = bus_verify_polkit_async(
                        m,
                        CAP_SYS_ADMIN,
                        prop == PROP_PRETTY_HOSTNAME ? "org.freedesktop.hostname1.set-static-hostname" : "org.freedesktop.hostname1.set-machine-info",
                        NULL,
                        interactive,
                        UID_INVALID,
                        &c->polkit_registry,
                        error);
        if (r < 0)
                return r;
        if (r == 0)
                return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */

        if (isempty(name)) {
                c->data[prop] = mfree(c->data[prop]);
        } else {
                char *h;

                /* The icon name might ultimately be used as file
                 * name, so better be safe than sorry */

                if (prop == PROP_ICON_NAME && !filename_is_valid(name))
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid icon name '%s'", name);
                if (prop == PROP_PRETTY_HOSTNAME && string_has_cc(name, NULL))
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid pretty host name '%s'", name);
                if (prop == PROP_CHASSIS && !valid_chassis(name))
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid chassis '%s'", name);
                if (prop == PROP_DEPLOYMENT && !valid_deployment(name))
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid deployment '%s'", name);
                if (prop == PROP_LOCATION && string_has_cc(name, NULL))
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid location '%s'", name);

                h = strdup(name);
                if (!h)
                        return -ENOMEM;

                free(c->data[prop]);
                c->data[prop] = h;
        }

        r = context_write_data_machine_info(c);
        if (r < 0) {
                log_error_errno(r, "Failed to write machine info: %m");
                return sd_bus_error_set_errnof(error, r, "Failed to write machine info: %s", strerror(-r));
        }

        log_info("Changed %s to '%s'",
                 prop == PROP_PRETTY_HOSTNAME ? "pretty host name" :
                 prop == PROP_DEPLOYMENT ? "deployment" :
                 prop == PROP_LOCATION ? "location" :
                 prop == PROP_CHASSIS ? "chassis" : "icon name", strna(c->data[prop]));

        (void) sd_bus_emit_properties_changed(
                        sd_bus_message_get_bus(m),
                        "/org/freedesktop/hostname1",
                        "org.freedesktop.hostname1",
                        prop == PROP_PRETTY_HOSTNAME ? "PrettyHostname" :
                        prop == PROP_DEPLOYMENT ? "Deployment" :
                        prop == PROP_LOCATION ? "Location" :
                        prop == PROP_CHASSIS ? "Chassis" : "IconName" , NULL);

        return sd_bus_reply_method_return(m, NULL);
}
// returns false and sets g_errno on error
bool Title::setTitle ( Xml *xml, Words *words, int32_t maxTitleLen, Query *query,
                       LinkInfo *linkInfo, Url *firstUrl, const char *filteredRootTitleBuf, int32_t filteredRootTitleBufSize,
                       uint8_t contentType, uint8_t langId, int32_t niceness ) {
	// make Msg20.cpp faster if it is just has
	// Msg20Request::m_setForLinkInfo set to true, no need to extricate a title.
	if ( maxTitleLen <= 0 ) {
		return true;
	}

	m_niceness = niceness;
	m_maxTitleLen = maxTitleLen;

	// if this is too big the "first line" algo can be huge!!!
	// and really slow everything way down with a huge title candidate
	int32_t maxTitleWords = 128;

	// assume no title
	reset();

	int32_t NW = words->getNumWords();

	//
	// now get all the candidates
	//

	// . allow up to 100 title CANDIDATES
	// . "as" is the word # of the first word in the candidate
	// . "bs" is the word # of the last word IN the candidate PLUS ONE
	int32_t n = 0;
	int32_t as[MAX_TIT_CANDIDATES];
	int32_t bs[MAX_TIT_CANDIDATES];
	float scores[MAX_TIT_CANDIDATES];
	Words *cptrs[MAX_TIT_CANDIDATES];
	int32_t types[MAX_TIT_CANDIDATES];
	int32_t parent[MAX_TIT_CANDIDATES];

	// record the scoring algos effects
	float  baseScore        [MAX_TIT_CANDIDATES];
	float  noCapsBoost      [MAX_TIT_CANDIDATES];
	float  qtermsBoost      [MAX_TIT_CANDIDATES];
	float  inCommonCandBoost[MAX_TIT_CANDIDATES];

	// reset these
	for ( int32_t i = 0 ; i < MAX_TIT_CANDIDATES ; i++ ) {
		// assume no parent
		parent[i] = -1;
	}

	// xml and words class for each link info, rss item
	Xml   tx[MAX_TIT_CANDIDATES];
	Words tw[MAX_TIT_CANDIDATES];
	int32_t  ti = 0;

	// restrict how many link texts and rss blobs we check for titles
	// because title recs like www.google.com have hundreds and can
	// really slow things down to like 50ms for title generation
	int32_t kcount = 0;
	int32_t rcount = 0;

	//int64_t x = gettimeofdayInMilliseconds();

	// . get every link text
	// . TODO: repeat for linkInfo2, the imported link text
	for ( Inlink *k = NULL; linkInfo && (k = linkInfo->getNextInlink(k)) ; ) {
		// breathe
		QUICKPOLL(m_niceness);
		// fast skip check for link text
		if ( k->size_linkText >= 3 && ++kcount >= 20 ) continue;
		// fast skip check for rss item
		if ( k->size_rssItem > 10 && ++rcount >= 20 ) continue;

		// set Url
		Url u;
		u.set( k->getUrl(), k->size_urlBuf );

		// is it the same host as us?
		bool sh = true;

		// skip if not from same host and should be
		if ( firstUrl->getHostLen() != u.getHostLen() ) {
			sh = false;
		}

		// skip if not from same host and should be
		if ( strncmp( firstUrl->getHost(), u.getHost(), u.getHostLen() ) ) {
			sh = false;
		}

		// get the link text
		if ( k->size_linkText >= 3 ) {
			char *p    = k->getLinkText();
			int32_t  plen = k->size_linkText - 1;
			if ( ! verifyUtf8 ( p , plen ) ) {
				log("title: set4 bad link text from url=%s", k->getUrl());
				continue;
			}

			// now the words.
			if ( !tw[ti].set( k->getLinkText(), k->size_linkText - 1, true, 0 ) ) {
				return false;
			}

			// set the bookends, it is the whole thing
			cptrs   [n] = &tw[ti];
			as      [n] = 0;
			bs      [n] = tw[ti].getNumWords();
			// score higher if same host
			if ( sh ) scores[n] = 1.05;
			// do not count so high if remote!
			else      scores[n] = 0.80;
			// set the type
			if ( sh ) types [n] = TT_LINKTEXTLOCAL;
			else      types [n] = TT_LINKTEXTREMOTE;
			// another candidate
			n++;
			// use xml and words
			ti++;
			// break out if too many already. save some for below.
			if ( n + 30 >= MAX_TIT_CANDIDATES ) break;
		}
		// get the rss item
		if ( k->size_rssItem <= 10 ) continue;
		// . returns false and sets g_errno on error
		// . use a 0 for niceness
		if ( ! k->setXmlFromRSS ( &tx[ti] , 0 ) ) return false;
		// get the word range
		int32_t tslen;
		bool isHtmlEnc;
		char *ts = tx[ti].getRSSTitle ( &tslen , &isHtmlEnc );
		// skip if not in the rss
		if ( ! ts ) continue;
		// skip if empty
		if ( tslen <= 0 ) continue;
		// now set words to that
		if ( !tw[ti].set( ts, tslen, true, 0 ) ) {
			return false;
		}

		// point to that
		cptrs   [n] = &tw[ti];
		as      [n] = 0;
		bs      [n] = tw[ti].getNumWords();
		// increment since we are using it
		ti++;
		// base score for rss title
		if ( sh ) scores[n] = 5.0;
		// if not same host, treat like link text
		else      scores[n] = 2.0;
		// set the type
		if ( sh ) types [n] = TT_RSSITEMLOCAL;
		else      types [n] = TT_RSSITEMREMOTE;
		// advance
		n++;
		// break out if too many already. save some for below.
		if ( n + 30 >= MAX_TIT_CANDIDATES ) break;
	}

	//logf(LOG_DEBUG,"title: took1=%" PRId64,gettimeofdayInMilliseconds()-x);
	//x = gettimeofdayInMilliseconds();

	// . set the flags array
	// . indicates what words are in title candidates already, but
	//   that is set below
	// . up here we set words that are not allowed to be in candidates,
	//   like words that are in a link that is not a self link
	// . alloc for it
	char *flags = NULL;
	char localBuf[10000];

	int32_t  need = words->getNumWords();
	if ( need <= 10000 ) {
		flags = (char *)localBuf;
	} else {
		flags = (char *)mmalloc(need,"TITLEflags");
	}

	if ( ! flags ) {
		return false;
	}

	// clear it
	memset ( flags , 0 , need );

	// check tags in body
	nodeid_t *tids = words->getTagIds();

	// scan to set link text flags
	// loop over all "words" in the html body
	char inLink   = false;
	char selfLink = false;
	for ( int32_t i = 0 ; i < NW ; i++ ) {
		// breathe
		QUICKPOLL(m_niceness);

		// if in a link that is not self link, cannot be in a candidate
		if ( inLink && ! selfLink ) {
			flags[i] |= 0x02;
		}

		// out of a link
		if ( tids[i] == (TAG_A | BACKBIT) ) {
			inLink = false;
		}

		// if not start of <a> tag, skip it
		if ( tids[i] != TAG_A ) {
			continue;
		}

		// flag it
		inLink = true;

		// get the node in the xml
		int32_t xn = words->getNodes()[i];

		// is it a self link?
		int32_t len;
		char *link = xml->getString(xn,"href",&len);

		// . set the url class to this
		// . TODO: use the base url in the doc
		Url u;
		u.set( link, len, true, false );

		// compare
		selfLink = u.equals ( firstUrl );

		// skip if not selfLink
		if ( ! selfLink ) {
			continue;
		}

		// if it is a selflink , check for an "onClick" tag in the
		// anchor tag to fix that Mixx issue for:
		// http://www.npr.org/templates/story/story.php?storyId=5417137

		int32_t  oclen;
		char *oc = xml->getString(xn,"onclick",&oclen);

		if ( ! oc ) {
			oc = xml->getString(xn,"onClick",&oclen);
		}

		// assume not a self link if we see that...
		if ( oc ) {
			selfLink = false;
		}

		// if this <a href> link has a "title" attribute, use that
		// instead! that thing is solid gold.
		int32_t  atlen;
		char *atitle = xml->getString(xn,"title",&atlen);

		// stop and use that, this thing is gold!
		if ( ! atitle || atlen <= 0 ) {
			continue;
		}

		// craziness? ignore it...
		if ( atlen > 400 ) {
			continue;
		}

		// if it contains permanent, permalink or share, ignore it!
		if ( strncasestr ( atitle, "permalink", atlen ) ||
		     strncasestr ( atitle,"permanent", atlen) ||
		     strncasestr ( atitle,"share", atlen) ) {
			continue;
		}

		// do not count the link text as viable
		selfLink = false;

		// aw, dammit
		if ( ti >= MAX_TIT_CANDIDATES ) {
			continue;
		}

		// other dammit
		if ( n >= MAX_TIT_CANDIDATES ) {
			break;
		}

		// ok, process it
		if ( ! tw[ti].set ( atitle, atlen, true, 0 )) {
			return false;
		}

		// set the bookends, it is the whole thing
		cptrs   [n] = &tw[ti];
		as      [n] = 0;
		bs      [n] = tw[ti].getNumWords();
		scores  [n] = 3.0; // not ALWAYS solid gold!
		types   [n] = TT_TITLEATT;

		// we are using the words class
		ti++;

		// advance
		n++;

		// break out if too many already. save some for below.
		if ( n + 20 >= MAX_TIT_CANDIDATES ) {
			break;
		}
	}

	//logf(LOG_DEBUG,"title: took2=%" PRId64,gettimeofdayInMilliseconds()-x);
	//x = gettimeofdayInMilliseconds();

	//int64_t *wids = WW->getWordIds();
	// . find the last positive scoring guy
	// . do not consider title candidates after "r" if "r" is non-zero
	// . FIXES http://larvatusprodeo.net/2009/01/07/partisanship-politics-and-participation/

	// the candidate # of the title tag
	int32_t tti = -1;

	// allow up to 4 tags from each type
	char table[512];

	// sanity check
	if ( getNumXmlNodes() > 512 ) { char *xx=NULL;*xx=0; }

	// clear table counts
	memset ( table , 0 , 512 );

	// the first word
	char *wstart = NULL;
	if ( NW > 0 ) {
		wstart = words->getWord(0);
	}

	// loop over all "words" in the html body
	for ( int32_t i = 0 ; i < NW ; i++ ) {
		// come back up here if we encounter another "title-ish" tag
		// within our first alleged "title-ish" tag
	subloop:
		// stop after 30k of text
		if ( words->getWord(i) - wstart > 200000 ) {
			break; // 1106
		}

		// get the tag id minus the back tag bit
		nodeid_t tid = tids[i] & BACKBITCOMP;


		// pen up and pen down for these comment like tags
		if ( tid == TAG_SCRIPT || tid == TAG_STYLE ) {
			// ignore "titles" in script or style tags
			if ( ! (tids[i] & BACKBIT) ) {
				continue;
			}
		}

		/// @todo ALC we should allow more tags than just title/link
		// skip if not a good tag.
		if (tid != TAG_TITLE && tid != TAG_A) {
			continue;
		}

		// must NOT be a back tag
		if ( tids[i] & BACKBIT ) {
			continue;
		}

		// skip if we hit our limit
		if ( table[tid] >= 4 ) {
			continue;
		}

		// skip over tag/word #i
		i++;

		// no words in links, unless it is a self link
		if ( i < NW && (flags[i] & 0x02) ) {
			continue;
		}

		// the start should be here
		int32_t start = -1;

		// do not go too far
		int32_t max = i + 200;

		// find the corresponding back tag for it
		for (  ; i < NW && i < max ; i++ ) {
			// hey we got it, BUT we got no alnum word first
			// so the thing was empty, so loop back to subloop
			if ( (tids[i] & BACKBITCOMP) == tid  &&   
			     (tids[i] & BACKBIT    ) && 
			     start == -1 ) {
				goto subloop;
			}

			// if we hit another title-ish tag, loop back up
			if ( (tids[i] & BACKBITCOMP) == TAG_TITLE || (tids[i] & BACKBITCOMP) == TAG_A ) {
				// if no alnum text, restart at the top
				if ( start == -1 ) {
					goto subloop;
				}

				// otherwise, break out and see if title works
				break;
			}

			// if we hit a breaking tag...
			if ( isBreakingTagId ( tids[i] & BACKBITCOMP ) &&
			     // do not consider <span> tags breaking for 
			     // our purposes. i saw a <h1><span> setup before.
			     tids[i] != TAG_SPAN ) {
				break;
			}

			// skip if not alnum word
			if ( ! words->isAlnum(i) ) {
				continue;
			}

			// if we hit an alnum word, break out
			if ( start == -1 ) {
				start = i;
			}
		}

		// if no start was found, must have had a 0 score in there
		if ( start == -1 ) {
			continue;
		}

		// if we exhausted the doc, we are done
		if ( i >= NW ) {
			break;
		}

		// skip if way too big!
		if ( i >= max ) {
			continue;
		}

		// if was too long do not consider a title
		if ( i - start > 300 ) {
			continue;
		}

		// . skip if too many bytes
		// . this does not include the length of word #i, but #(i-1)
		if ( words->getStringSize ( start , i ) > 1000 ) {
			continue;
		}

		// when using pdftohtml, the title tag is the filename when PDF property does not have title tag
		if ( tid == TAG_TITLE && contentType == CT_PDF ) {
			// skip if title == '/in.[0-9]*'
			char* title_start = words->getWord(start);
			char* title_end = words->getWord(i);
			size_t title_size = title_end - title_start;
			const char* result = strnstr( title_start, "/in.", title_size );
			if (result != NULL) {
				char* endp = NULL;
				// do some further verification to avoid screwing up title
				if ((strtoll(result + 4, &endp, 10) > 0) && (endp == title_end)) {
					continue;
				}
			}
		}

		// count it
		table[tid]++;

		// max it out if we are positive scoring. stop after the
		// first positive scoring guy in a section. this might
		// hurt the "Hamlet" thing though...

		// store a point to the title tag guy. Msg20.cpp needs this
		// because the zak's proximity algo uses it in Summary.cpp
		// and in Msg20.cpp

		// only get the first one! often the 2nd on is in an iframe!! which we now expand into here.
		if ( tid == TAG_TITLE && m_titleTagStart == -1 ) {
			m_titleTagStart = start;
			m_titleTagEnd   = i;

			// save the candidate # because we always use this
			// as the title if we are a root
			if ( tti < 0 ) {
				tti = n;
			}
		}

		// point to words class of the body that was passed in to us
		cptrs[n] = words;
		as[n] = start;
		bs[n] = i;
		if ( tid == TAG_B ) {
			types[n] = TT_BOLDTAG;
			scores[n] = 1.0;
		} else if ( tid == TAG_H1 ) {
			types[n] = TT_HTAG;
			scores[n] = 1.8;
		} else if ( tid == TAG_H2 ) {
			types[n] = TT_HTAG;
			scores[n] = 1.7;
		} else if ( tid == TAG_H3 ) {
			types[n] = TT_HTAG;
			scores[n] = 1.6;
		} else if ( tid == TAG_TITLE ) {
			types[n] = TT_TITLETAG;
			scores[n] = 3.0;
		} else if ( tid == TAG_DIV ) {
			types[n] = TT_DIVTAG;
			scores[n] = 1.0;
		} else if ( tid == TAG_TD ) {
			types[n] = TT_TDTAG;
			scores[n] = 1.0;
		} else if ( tid == TAG_P ) {
			types[n] = TT_PTAG;
			scores[n] = 1.0;
		} else if ( tid == TAG_FONT ) {
			types[n] = TT_FONTTAG;
			scores[n] = 1.0;
		} else if ( tid == TAG_A ) {
			types[n] = TT_ATAG;
			// . self link is very powerful BUT
			//   http://www.npr.org/templates/story/story.php?storyId=5417137
			//   doesn't use it right! so use
			//   1.3 instead of 3.0. that has an "onClick" thing in the
			//   <a> tag, so check for that!
			// this was bad for
			// http://www.spiritualwoman.net/?cat=191
			// so i am demoting from 3.0 to 1.5
			scores[n] = 1.5;
		}

		// count it
		n++;

		// start loop over at tag #i, for loop does an i++, so negate
		// that so this will work
		i--;

		// break out if too many already. save some for below.
		if ( n + 10 >= MAX_TIT_CANDIDATES ) {
			break;
		}
	}

	//logf(LOG_DEBUG,"title: took3=%" PRId64,gettimeofdayInMilliseconds()-x);
	//x = gettimeofdayInMilliseconds();

	// to handle text documents, throw in the first line of text
	// as a title candidate, just make the score really low
	bool textDoc = (contentType == CT_UNKNOWN || contentType == CT_TEXT);

	if (textDoc) {
		// make "i" point to first alphabetical word in the document
		int32_t i ;

		for ( i = 0 ; i < NW && !words->isAlpha(i) ; i++);

		// if we got a first alphabetical word, then assume that to be the start of our title
		if ( i < NW && n < MAX_TIT_CANDIDATES ) {
			// first word in title is "t0"
			int32_t t0 = i;
			// find end of first line
			int32_t numWords = 0;

			// set i to the end now. we MUST find a \n to terminate the
			// title, otherwise we will not have a valid title
			while (i < NW && numWords < maxTitleWords && (words->isAlnum(i) || !words->hasChar(i, '\n'))) {
				if(words->isAlnum(i)) {
					numWords++;
				}

				++i;
			}

			// "t1" is the end
			int32_t t1 = -1;

			// we must have found our \n in order to set "t1"
			if (i <= NW && numWords < maxTitleWords ) {
				t1 = i;
			}

			// set the ptrs
			cptrs   [n] =  words;

			// this is the last resort i guess...
			scores  [n] =  0.5;
			types   [n] =  TT_FIRSTLINE;
			as      [n] =  t0;
			bs      [n] =  t1;

			// add it as a candidate if t0 and t1 were valid
			if (t0 >= 0 && t1 > t0) {
				n++;
			}
		}
	}

	//logf(LOG_DEBUG,"title: took4=%" PRId64,gettimeofdayInMilliseconds()-x);
	//x = gettimeofdayInMilliseconds();

	{
		// now add the last url path to contain underscores or hyphens
		char *pstart = firstUrl->getPath();

		// get first url
		Url *fu = firstUrl;

		// start at the end
		char *p = fu->getUrl() + fu->getUrlLen();

		// end pointer
		char *pend = NULL;

		// come up here for each path component
		while ( p >= pstart ) {
			// save end
			pend = p;

			// skip over /
			if ( *p == '/' ) {
				p--;
			}

			// now go back to next /
			int32_t count = 0;
			for ( ; p >= pstart && *p !='/' ; p-- ) {
				if ( *p == '_' || *p == '-' ) {
					count++;
				}
			}

			// did we get it?
			if ( count > 0 ) {
				break;
			}
		}

		// did we get any?
		if ( p > pstart && n < MAX_TIT_CANDIDATES ) {
			// now set words to that
			if ( ! tw[ti].set ( p, (pend - p), true, 0 )) {
				return false;
			}

			// point to that
			cptrs   [n] = &tw[ti];
			as      [n] = 0;
			bs      [n] = tw[ti].getNumWords();
			scores  [n] = 1.0;
			types   [n] = TT_URLPATH;

			// increment since we are using it
			ti++;

			// advance
			n++;
		}
	}

	// save old n
	int32_t oldn = n;

	// . do not split titles if we are a root url maps.yahoo.com was getting "Maps" for the title
	if ( firstUrl->isRoot() ) {
		oldn = -2;
	}

	// point to list of \0 separated titles
	const char *rootTitleBuf    = NULL;
	const char *rootTitleBufEnd = NULL;

	// get the root title if we are not root!
	if (filteredRootTitleBuf) {
#ifdef _VALGRIND_
		VALGRIND_CHECK_MEM_IS_DEFINED(filteredRootTitleBuf,filteredRootTitleBufSize);
#endif
		// point to list of \0 separated titles
		rootTitleBuf    = filteredRootTitleBuf;
		rootTitleBufEnd =  filteredRootTitleBuf + filteredRootTitleBufSize;
	}

	{
		Matches m;
		if ( rootTitleBuf && query ) {
			m.setQuery ( query );
		}

		// convert into an array
		int32_t nr = 0;
		const char *pr = rootTitleBuf;
		const char *rootTitles[20];
		int32_t  rootTitleLens[20];

		// loop over each root title segment
		for ( ; pr && pr < rootTitleBufEnd ; pr += strnlen(pr,rootTitleBufEnd-pr) + 1 ) {
			// if we had a query...
			if ( query ) {
				// reset it
				m.reset();

				// see if root title segment has query terms in it
				m.addMatches ( const_cast<char*>(pr), strnlen(pr,rootTitleBufEnd-pr), MF_TITLEGEN, m_niceness );

				// if matches query, do NOT add it, we only add it for
				// removing from the title of the page...
				if ( m.getNumMatches() ) {
					continue;
				}
			}
			// point to it. it should start with an alnum already
			// since it is the "filtered" list of root titles...
			// if not, fix it in xmldoc then.
			rootTitles   [nr] = pr;
			rootTitleLens[nr] = gbstrlen(pr);
			// advance
			nr++;
			// no breaching
			if ( nr >= 20 ) break;
		}

		// now split up candidates in children candidates by tokenizing
		// using :, | and - as delimters.
		// the hyphen must have a space on at least one side, so "cd-rom" does
		// not create a pair of tokens...
		// FIX: for the title:
		// Best Careers 2009: Librarian - US News and World Report
		// we need to recognize "Best Careers 2009: Librarian" as a subtitle
		// otherwise we don't get it as the title. so my question is are we
		// going to have to do all the permutations at some point? for now
		// let's just add in pairs...
		for ( int32_t i = 0 ; i < oldn && n + 3 < MAX_TIT_CANDIDATES ; i++ ) {
			// stop if no root title segments
			if ( nr <= 0 ) break;
			// get the word info
			Words *w = cptrs[i];
			int32_t   a = as[i];
			int32_t   b = bs[i];
			// init
			int32_t lasta = a;
			char prev  = false;
			// char length in bytes
			//int32_t charlen = 1;
			// see how many we add
			int32_t added = 0;
			char *skipTo = NULL;
			bool qualified = true;
			// . scan the words looking for a token
			// . sometimes the candidates end in ": " so put in "k < b-1"
			// . made this from k<b-1 to k<b to fix
			//   "Hot Tub Time Machine (2010) - IMDb" to strip IMDb
			for ( int32_t k = a ; k < b && n + 3 < MAX_TIT_CANDIDATES; k++){
				// get word
				char *wp = w->getWord(k);
				// skip if not alnum
				if ( ! w->isAlnum(k) ) {
					// in order for next alnum word to
					// qualify for "clipping" if it matches
					// the root title, there has to be more
					// than just spaces here, some punct.
					// otherwise title
					// "T. D. Jakes: Biography from Answers.com"
					// becomes
					// "T. D. Jakes: Biography from"
					qualified=isWordQualified(wp,w->getWordLen(k));
					continue;
				}
				// gotta be qualified!
				if ( ! qualified ) continue;
				// skip if in root title
				if ( skipTo && wp < skipTo ) continue;
				// does this match any root page title segments?
				int32_t j;
				for ( j = 0 ; j < nr ; j++ ) {
					// . compare to root title
					// . break out if we matched!
					if ( ! strncmp( wp, rootTitles[j], rootTitleLens[j] ) ) {
						break;
					}
				}

				// if we did not match a root title segment,
				// keep on chugging
				if ( j >= nr ) continue;
				// . we got a root title match!
				// . skip over
				skipTo = wp + rootTitleLens[j];
				// must land on qualified punct then!!
				int32_t e = k+1;
				for ( ; e<b && w->getWord(e)<skipTo ; e++ );
				// ok, word #e must be a qualified punct
				if ( e<b &&
				     ! isWordQualified(w->getWord(e),w->getWordLen(e)))
					// assume no match then!!
					continue;
				// if we had a previous guy, reset the end of the
				// previous candidate
				if ( prev ) {
					bs[n-2] = k;
					bs[n-1] = k;
				}
				// . ok, we got two more candidates
				// . well, only one more if this is not the 1st time
				if ( ! prev ) {
					cptrs   [n] = cptrs   [i];
					scores  [n] = scores  [i];
					types   [n] = types   [i];
					as      [n] = lasta;
					bs      [n] = k;
					parent  [n] = i;
					n++;
					added++;
				}
				// the 2nd one
				cptrs   [n] = cptrs   [i];
				scores  [n] = scores  [i];
				types   [n] = types   [i];
				as      [n] = e + 1;
				bs      [n] = bs      [i];
				parent  [n] = i;
				n++;
				added++;

				// now add in the last pair as a whole token
				cptrs   [n] = cptrs   [i];
				scores  [n] = scores  [i];
				types   [n] = types   [i];
				as      [n] = lasta;
				bs      [n] = bs      [i];
				parent  [n] = i;
				n++;
				added++;

				// nuke the current candidate then since it got
				// split up to not contain the root title...
				//cptrs[i] = NULL;

				// update this
				lasta = k+1;

				// if we encounter another delimeter we will have to revise bs[n-1], so note that
				prev = true;
			}

			// nuke the current candidate then since it got
			// split up to not contain the root title...
			if ( added ) {
				scores[i] = 0.001;
				//cptrs[i] = NULL;
			}

			// erase the pair if that there was only one token
			if ( added == 3 ) n--;
		}
	}

	for ( int32_t i = 0 ; i < n ; i++ ) baseScore[i] = scores[i];
	
	//
	// . now punish by 0.85 for every lower case non-stop word it has
	// . reward by 1.1 if has a non-stopword in the query
	//
	for ( int32_t i = 0 ; i < n ; i++ ) {
		// point to the words
		Words *w = cptrs[i];

		// skip if got nuked above
		if ( ! w ) {
			continue;
		}

		// the word ptrs
		char **wptrs = w->getWordPtrs();

		// skip if empty
		if ( w->getNumWords() <= 0 ) {
			continue;
		}

		// get the word boundaries
		int32_t a = as[i];
		int32_t b = bs[i];

		// record the boosts
		float ncb = 1.0;
		float qtb = 1.0;

		// a flag
		char uncapped = false;

		// scan the words in this title candidate
		for ( int32_t j = a ; j < b ; j++ ) {
			// skip stop words
			if ( w->isQueryStopWord( j, langId ) ) {
				continue;
			}

			// punish if uncapitalized non-stopword
			if ( ! w->isCapitalized(j) ) {
				uncapped = true;
			}

			// skip if no query
			if ( ! query ) {
				continue;
			}

			int64_t wid = w->getWordId(j);

			// reward if in the query
			if ( query->getWordNum(wid) >= 0 ) {
				qtb       *= 1.5;
				scores[i] *= 1.5;
			}
		}

		// . only punish once if missing a capitalized word hurts us for:
		//   http://content-uk.cricinfo.com/ausvrsa2008_09/engine/current/match/351682.html
		if ( uncapped ) {
			ncb *= 1.00;
			scores[i] *= 1.00;
		}

		// punish if a http:// title thingy
		char *s = wptrs[a];
		int32_t size = w->getStringSize(a,b);
		if ( size > 9 && memcmp("http://", s, 7) == 0 ) {
			ncb *= .10;
		}
		if ( size > 14 && memcmp("h\0t\0t\0p\0:\0/\0/", s, 14) == 0 ) {
			ncb *= .10;
		}

		// set these guys
		scores[i] *= ncb;

		noCapsBoost[i]  = ncb;
		qtermsBoost[i]  = qtb;
	}

	// . now compare each candidate to the other candidates
	// . give a boost if matches
	for ( int32_t i = 0 ; i < n ; i++ ) {
		// point to the words
		Words *w1 = cptrs[i];

		// skip if got nuked above
		if ( ! w1 ) {
			continue;
		}

		int32_t a1 = as[i];
		int32_t b1 = bs[i];

		// reset some flags
		char localFlag1 = 0;
		char localFlag2 = 0;

		// record the boost
		float iccb = 1.0;

		// total boost
		float total = 1.0;

		// to each other candidate
		for ( int32_t j = 0 ; j < n ; j++ ) {
			// not to ourselves
			if ( j == i ) {
				continue;
			}

			// or our derivatives
			if ( parent[j] == i ) {
				continue;
			}

			// or derivates to their parent
			if ( parent[i] == j ) {
				continue;
			}

			// only check parents now. do not check kids.
			// this was only for when doing percent contained
			// not getSimilarity() per se
			//if ( parent[j] != -1 ) continue;

			// TODO: do not accumulate boosts from a parent
			// and its kids, subtitles...
			//
			// do not compare type X to type Y
			if ( types[i] == TT_TITLETAG ) {
				if ( types[j] == TT_TITLETAG ) {
					continue;
				}
			}

			// do not compare a div candidate to another div cand
			// http://friendfeed.com/foxiewire?start=30
			// likewise, a TD to another TD
			// http://content-uk.cricinfo.com/ausvrsa2008_09/engine/match/351681.html
			// ... etc.
			if ( types[i] == TT_BOLDTAG ||
			     types[i] == TT_HTAG    ||
			     types[i] == TT_DIVTAG  ||
			     types[i] == TT_TDTAG   ||
			     types[i] == TT_FONTTAG    ) {
				if ( types[j] == types[i] ) continue;
			}
			// . do not compare one kid to another kid
			// . i.e. if we got "x | y" as a title and "x | z"
			//   as a link text, it will emphasize "x" too much
			//   http://content-uk.cricinfo.com/ausvrsa2008_09/engine/current/match/351682.html
			if ( parent[j] != -1 && parent[i] != -1 ) continue;

			// . body type tags are mostly mutually exclusive
			// . for the legacy.com url mentioned below, we have
			//   good stuff in <td> tags, so this hurts us...
			// . but for the sake of 
			//   http://larvatusprodeo.net/2009/01/07/partisanship-politics-and-participation/
			//   i put bold tags back

			if ( types[i] == TT_LINKTEXTLOCAL ) {
				if ( types[j] == TT_LINKTEXTLOCAL ) continue;
			}
			if ( types[i] == TT_RSSITEMLOCAL ) {
				if ( types[j] == TT_RSSITEMLOCAL ) continue;
			}

			// only compare to one local link text for each i
			if ( types[j] == TT_LINKTEXTLOCAL && localFlag1 ) {
				continue;
			}
			if ( types[j] == TT_RSSITEMLOCAL  && localFlag2 ) {
				continue;
			}
			if ( types[j] == TT_LINKTEXTLOCAL ) {
				localFlag1 = 1;
			}
			if ( types[j] == TT_RSSITEMLOCAL  ) {
				localFlag2 = 1;
			}

			// not link title attr to link title attr either
			// fixes http://www.spiritualwoman.net/?cat=191
			if ( types[i] == TT_TITLEATT &&
			     types[j] == TT_TITLEATT )
				continue;

			// get our words
			Words *w2 = cptrs[j];

			// skip if got nuked above
			if ( ! w2 ) continue;
			int32_t   a2 = as   [j];
			int32_t   b2 = bs   [j];

			// how similar is title #i to title #j ?
			float fp = getSimilarity ( w2 , a2 , b2 , w1 , a1 , b1 );

			// error?
			if ( fp == -1.0 ) return false;

			// custom boosting...
			float boost = 1.0;
			if      ( fp >= .95 ) boost = 3.0;
			else if ( fp >= .90 ) boost = 2.0;
			else if ( fp >= .85 ) boost = 1.5;
			else if ( fp >= .80 ) boost = 1.4;
			else if ( fp >= .75 ) boost = 1.3;
			else if ( fp >= .70 ) boost = 1.2;
			else if ( fp >= .60 ) boost = 1.1;
			else if ( fp >= .50 ) boost = 1.08;
			else if ( fp >= .40 ) boost = 1.04;

			// limit total
			total *= boost;
			if ( total > 100.0 ) break;
			// if you are matching the url path, that is pretty 
			// good so give more!
			// actually, that would hurt:
			// http://michellemalkin.com/2008/12/29/gag-worthy/

			// custom boosting!
			if ( fp > 0.0 && g_conf.m_logDebugTitle )
				logf(LOG_DEBUG,"title: i=%" PRId32" j=%" PRId32" fp=%.02f "
				     "b=%.02f", i,j,fp,boost);
			// apply it
			scores[i] *= boost;

			iccb      *= boost;
		}

		inCommonCandBoost[i] = iccb;
	}

	//logf(LOG_DEBUG,"title: took7=%" PRId64,gettimeofdayInMilliseconds()-x);
	//x = gettimeofdayInMilliseconds();


	// loop over all n candidates
	for ( int32_t i = 0 ; i < n ; i++ ) {
		// skip if not in the document body
		if ( cptrs[i] != words ) continue;
		// point to the words
		int32_t       a1    = as   [i];
		int32_t       b1    = bs   [i];

		// . loop through this candidates words
		// . TODO: use memset here?
		for ( int32_t j = a1 ; j <= b1 && j < NW ; j++ ) {
			// flag it
			flags[j] |= 0x01;
		}
	}

	// free our stuff
	if ( flags!=localBuf ) {
		mfree (flags, need, "TITLEflags");
	}

	// now get the highest scoring candidate title
	float max    = -1.0;
	int32_t  winner = -1;
	for ( int32_t i = 0 ; i < n ; i++ ) {
		// skip if got nuked
		if ( ! cptrs[i] ) {
			continue;
		}

		if ( winner != -1 && scores[i] <= max ) {
			continue;
		}

		// url path's cannot be titles in and of themselves
		if ( types[i] == TT_URLPATH ) {
			continue;
		}

		// skip if empty basically, like if title was exact
		// copy of root, then the whole thing got nuked and
		// some empty string added, where a > b
		if ( as[i] >= bs[i] ) {
			continue;
		}

		// got one
		max = scores[i];

		// save it
		winner = i;
	}

	// if we are a root, always pick the title tag as the title
	if ( oldn == -2 && tti >= 0 ) {
		winner = tti;
	}

	// if no winner, all done. no title
	if ( winner == -1 ) {
		// last resort use file name
		if ((contentType == CT_PDF) && (firstUrl->getFilenameLen() != 0)) {
			Words w;
			w.set(firstUrl->getFilename(), firstUrl->getFilenameLen(), true);
			if (!copyTitle(&w, 0, w.getNumWords())) {
				return false;
			}
		}
		return true;
	}

	// point to the words class of the winner
	Words *w = cptrs[winner];
	// skip if got nuked above
	if ( ! w ) { char *xx=NULL;*xx=0; }

	// need to make our own Pos class if title not from body
	Pos  tp;
	if ( w != words ) {
		// set "Scores" ptr to NULL. we assume all are positive scores
		if ( ! tp.set ( w ) ) {
			return false;
		}
	}

	// the string ranges from word #a up to and including word #b
	int32_t a = as[winner];
	int32_t b = bs[winner];
	// sanity check
	if ( a < 0 || b > w->getNumWords() ) { char*xx=NULL;*xx=0; }

	// save the title
	if ( ! copyTitle(w, a, b) ) {
		return false;
	}

	/*
	// debug logging
	SafeBuf sb;
	SafeBuf *pbuf = &sb;

	log("title: candidates for %s",xd->getFirstUrl()->getUrl() );

	pbuf->safePrintf("<div stype=\"border:1px solid black\">");
	pbuf->safePrintf("<b>***Finding Title***</b><br>\n");

	pbuf->safePrintf("<table cellpadding=5 border=2><tr>"
			 "<td colspan=20><center><b>Title Generation</b>"
			 "</center></td>"
			 "</tr>\n<tr>"
			 "<td>#</td>"
			 "<td>type</td>"
			 "<td>parent</td>"
			 "<td>base score</td>"
			 "<td>format penalty</td>"
			 "<td>query term boost</td>"
			 "<td>candidate intersection boost</td>"
			 "<td>FINAL SCORE</td>"
			 "<td>title</td>"
			 "</tr>\n" );
			 

	// print out all candidates
	for ( int32_t i = 0 ; i < n ; i++ ) {
		char *ts = "unknown";
		if ( types[i] == TT_LINKTEXTLOCAL  ) ts = "local inlink text";
		if ( types[i] == TT_LINKTEXTREMOTE ) ts = "remote inlink text";
		if ( types[i] == TT_RSSITEMLOCAL   ) ts = "local rss title";
		if ( types[i] == TT_RSSITEMREMOTE  ) ts = "remote rss title";
		if ( types[i] == TT_BOLDTAG        ) ts = "bold tag";
		if ( types[i] == TT_HTAG           ) ts = "header tag";
		if ( types[i] == TT_TITLETAG       ) ts = "title tag";
		if ( types[i] == TT_FIRSTLINE      ) ts = "first line in text";
		if ( types[i] == TT_FONTTAG        ) ts = "font tag";
		if ( types[i] == TT_ATAG           ) ts = "anchor tag";
		if ( types[i] == TT_DIVTAG         ) ts = "div tag";
		if ( types[i] == TT_TDTAG          ) ts = "td tag";
		if ( types[i] == TT_PTAG           ) ts = "p tag";
		if ( types[i] == TT_URLPATH        ) ts = "url path";
		if ( types[i] == TT_TITLEATT       ) ts = "title attribute";
		// get the title
		pbuf->safePrintf(
				 "<tr>"
				 "<td>#%" PRId32"</td>"
				 "<td><nobr>%s</nobr></td>"
				 "<td>%" PRId32"</td>"
				 "<td>%0.2f</td>" // baseScore
				 "<td>%0.2f</td>"
				 "<td>%0.2f</td>"
				 "<td>%0.2f</td>"
				 "<td>%0.2f</td>"
				 "<td>",
				 i,
				 ts ,
				 parent[i],
				 baseScore[i],
				 noCapsBoost[i],
				 qtermsBoost[i],
				 inCommonCandBoost[i],
				 scores[i]);
		// ptrs
		Words *w = cptrs[i];
		int32_t   a = as[i];
		int32_t   b = bs[i];
		// skip if no words
		if ( w->getNumWords() <= 0 ) continue;
		// the word ptrs
		char **wptrs = w->getWordPtrs();
		// string ptrs
		char *ptr  = wptrs[a];//w->getWord(a);
		int32_t  size = w->getStringSize(a,b);
		// it is utf8
		pbuf->safeMemcpy ( ptr , size );
		// end the line
		pbuf->safePrintf("</td></tr>\n");
	}

	pbuf->safePrintf("</table>\n<br>\n");

	// log these for now
	log("title: %s",sb.getBufStart());
	*/

	return true;

}
// . but now that we may get a list remotely to fix data corruption,
//   this may indeed block
bool Msg3::doneScanning ( ) {
	QUICKPOLL(m_niceness);
	// . did we have any error on any scan?
	// . if so, repeat ALL of the scans
	g_errno = m_errno;
	// 2 retry is the default
	int32_t max = 2;
	// see if explicitly provided by the caller
	if ( m_maxRetries >= 0 ) max = m_maxRetries;
	// now use -1 (no max) as the default no matter what
	max = -1;
	// ENOMEM is particulary contagious, so watch out with it...
	if ( g_errno == ENOMEM && m_maxRetries == -1 ) max = 0;
	// msg0 sets maxRetries to 2, don't let max stay set to -1
	if ( g_errno == ENOMEM && m_maxRetries != -1 ) max = m_maxRetries;
	// when thread cannot alloc enough read buf it keeps the read buf
	// set to NULL and BigFile.cpp sets g_errno to EBUFTOOSMALL
	if ( g_errno == EBUFTOOSMALL && m_maxRetries == -1 ) max = 0;
	// msg0 sets maxRetries to 2, don't let max stay set to -1
	if ( g_errno == EBUFTOOSMALL && m_maxRetries != -1 ) max = m_maxRetries;
	// . if no thread slots available, that hogs up serious memory.
	//   the size of Msg3 is 82k, so having just 5000 of them is 430MB.
	// . i just made Msg3 alloc mem when it needs more than about 2k
	//   so this problem is greatly reduced, therefore let's keep 
	//   retrying... forever if no thread slots in thread queue since
	//   we become the thread queue in a way.
	if ( g_errno == ENOTHREADSLOTS ) max = -1;
	// this is set above if the map has the same consecutive key repeated
	// and the read is enormous
	if ( g_errno == ECORRUPTDATA ) max = 0;
	// usually bad disk failures, don't retry those forever
	//if ( g_errno == EIO ) max = 3;
        // no, now our hitachis return these even when they're good so
	// we have to keep retrying forever
	if ( g_errno == EIO ) max = -1;
	// count these so we do not take drives offline just because
	// kernel ring buffer complains...
	if ( g_errno == EIO ) g_numIOErrors++;
	// bail early on high priority reads for these errors
	if ( g_errno == EDISKSTUCK && m_niceness == 0 ) max = 0;
	if ( g_errno == EIO        && m_niceness == 0 ) max = 0;

	// how does this happen? we should never bail out on a low priority
	// disk read... we just wait for it to complete...
	if ( g_errno == EDISKSTUCK && m_niceness != 0 ) { char *xx=NULL;*xx=0;}

	// on I/O, give up at call it corrupt after a while. some hitachis
	// have I/O errros on little spots, like gk88, maybe we can fix him
	if ( g_errno == EIO && m_retryNum >= 5 ) {
		m_errno = ECORRUPTDATA;
		m_hadCorruption = true;
		// do not do any retries any more
		max = 0;
	}

	// convert m_errno to ECORRUPTDATA if it is EBUFTOOSMALL and the
	// max of the bytesToRead are over 500MB.
	// if bytesToRead was ludicrous, then assume that the data file
	// was corrupted, the map was regenerated and it patched
	// over the corrupted bits which were 500MB or more in size.
	// we cannot practically allocate that much, so let's just
	// give back an empty buffer. treat it like corruption...
	// the way it patches is to store the same key over all the corrupted
	// pages, which can get pretty big. so if you read a range with that
	// key you will be hurting!!
	// this may be the same scenario as when the rdbmap has consecutive
	// same keys. see above where we set m_errno to ECORRUPTDATA...
	if ( g_errno == EBUFTOOSMALL ) { 
		int32_t biggest = 0;
		for ( int32_t i = 0 ; i < m_numFileNums ; i++ ) {
			if ( m_scans[i].m_bytesToRead < biggest ) continue;
			biggest = m_scans[i].m_bytesToRead;
		}
		if ( biggest > 500000000 ) {
			log("db: Max read size was %" PRId32" > 500000000. Assuming "
			    "corrupt data in data file.",biggest);
			m_errno = ECORRUPTDATA;
			m_hadCorruption = true;
			// do not do any retries on this, the read was > 500MB
			max = 0;
		}
	}

	// if shutting down gb then limit to 20 so we can shutdown because
	// it can't shutdown until all threads are out of the queue i think
	if ( g_process.m_mode == EXIT_MODE && max < 0 ) {
		//log("msg3: forcing retries to 0 because shutting down");
		max = 0;
	}

	// get base, returns NULL and sets g_errno to ENOCOLLREC on error
	RdbBase *base = getRdbBase( m_rdbId, m_collnum );
	if ( ! base ) {
		return true;
	}

	// this really slows things down because it blocks the cpu so
	// leave it out for now
#ifdef GBSANITYCHECK
	// check for corruption here, do not do it again in Msg5 if we pass
	if ( ! g_errno ) { // && g_conf.m_doErrorCorrection ) {
		int32_t i;
		for ( i = 0 ; i < m_numFileNums ; i++ )
			if ( ! m_lists[i].checkList_r ( false, false ) ) break;
		if ( i < m_numFileNums ) {
			g_errno = ECORRUPTDATA;
			m_errno = ECORRUPTDATA;
			max     = g_conf.m_corruptRetries; // try 100 times
			log("db: Encountered corrupt list in file %s.",
			    base->getFile(m_fileNums[i])->getFilename());
		}
		else
			m_listsChecked = true;
	}
#endif

	// try to fix this error i've seen
	if ( g_errno == EBADENGINEER && max == -1 )
		max = 100;

	// . if we had a ETRYAGAIN error, then try again now
	// . it usually means the whole file or a part of it was deleted 
	//   before we could finish reading it, so we should re-read all now
	// . RdbMerge deletes BigFiles after it merges them and also chops
	//   off file heads
	// . now that we have threads i'd imagine we'd get EBADFD or something
	// . i've also seen "illegal seek" as well
	if ( m_errno && (m_retryNum < max || max < 0) &&
	     // this will complete in due time, we can't call a sleep wrapper
	     // on it because the read is really still pending...
	     m_errno != EDISKSTUCK ) {
		// print the error
		static time_t s_time  = 0;
		time_t now = getTime();
		if ( now - s_time > 5 || g_errno != ENOTHREADSLOTS ) {
			log("net: Had error reading %s: %s. Retrying. "
			    "(retry #%" PRId32")", 
			    base->m_dbname,mstrerror(m_errno) , m_retryNum );
			s_time = now;
		}
		// send email alert if in an infinite loop, but don't send
		// more than once every 2 hours
		static int32_t s_lastSendTime = 0;
		if ( m_retryNum == 100 && getTime() - s_lastSendTime > 3600*2){
			// remove this for now it is going off all the time
			//g_pingServer.sendEmail(NULL,//g_hostdb.getMyHost(),
			//		       "100 read retries",true);
			s_lastSendTime = getTime();
		}
		// clear g_errno cuz we should for call to readList()
		g_errno = 0;
		// free the list buffer since if we have 1000 Msg3s retrying
		// it will totally use all of our memory
		for ( int32_t i = 0 ; i < m_numChunks ; i++ ) 
			m_lists[i].destructor();
		// count retries
		m_retryNum++;
		// backoff scheme, wait 100ms more each time
		int32_t wait ;
		if ( m_retryNum == 1 ) wait = 10;
		else                   wait = 200 * m_retryNum;
		// . don't wait more than 10 secs between tries
		// . i've seen gf0 and gf16 get mega saturated
		if ( wait > 10000 ) wait = 10000;
		// wait 500 ms
		if ( g_loop.registerSleepCallback ( wait  , // ms
						    this  ,
						    doneSleepingWrapper3,
						    m_niceness))
			return false;
		// otherwise, registration failed
		log(
		    "net: Failed to register sleep callback for retry. "
		    "Abandoning read. This is bad.");
		// return, g_errno should be set
		g_errno = EBUFTOOSMALL;
		m_errno = EBUFTOOSMALL;
		return true;
	}

	// if we got an error and should not retry any more then give up
	if ( g_errno ) {
		log(
		    "net: Had error reading %s: %s. Giving up after %" PRId32" "
		    "retries.",
		    base->m_dbname,mstrerror(g_errno) , m_retryNum );
		return true;
	}

	// note it if the retry finally worked
	if ( m_retryNum > 0 ) 
		log(LOG_INFO,"disk: Read succeeded after retrying %" PRId32" times.",
		    (int32_t)m_retryNum);

	// count total bytes for logging
	int32_t count = 0;
	// . constrain all lists to make merging easier
	// . if we have only one list, then that's nice cuz the constrain
	//   will allow us to send it right away w/ zero copying
	// . if we have only 1 list, it won't be merged into a final list,
	//   that is, we'll just set m_list = &m_lists[i]
	for ( int32_t i = 0 ; i < m_numFileNums ; i++ ) {
		QUICKPOLL(m_niceness);
		// count total bytes for logging
		count += m_lists[i].getListSize();
		// . hint offset is relative to the offset of first key we read
		// . if that key was only 6 bytes RdbScan shift the list buf
		//   down 6 bytes to make the first key 12 bytes... a 
		//   requirement for all RdbLists
		// . don't inc it, though, if it was 0, pointing to the start
		//   of the list because our shift won't affect that
		if ( m_scans[i].m_shifted == 6 && m_hintOffsets[i] > 0 ) 
			m_hintOffsets[i] += 6;
		// posdb double compression
		if ( m_scans[i].m_shifted == 12 && m_hintOffsets[i] > 0 ) 
			m_hintOffsets[i] += 12;
		// . don't constrain on minRecSizes here because it may
		//   make our endKey smaller, which will cause problems
		//   when Msg5 merges these lists.
		// . If all lists have different endKeys RdbList's merge
		//   chooses the min and will merge in recs beyond that
		//   causing a bad list BECAUSE we don't check to make
		//   sure that recs we are adding are below the endKey
		// . if we only read from one file then constrain based 
		//   on minRecSizes so we can send the list back w/o merging
		//   OR if just merging with RdbTree's list
		int32_t mrs ;
		// . constrain to m_minRecSizesOrig, not m_minRecSizes cuz 
		//   that  could be adjusted by compensateForNegativeRecs()
		// . but, really, they should be the same if we only read from
		//   the root file
		if ( m_numFileNums == 1 ) mrs = m_minRecSizesOrig;
		else                      mrs = -1;
		// . this returns false and sets g_errno on error
		// . like if data is corrupt
		BigFile *ff = base->getFile(m_fileNums[i]);
		// if we did a merge really quick and delete one of the 
		// files we were reading, i've seen 'ff' be NULL
		char *filename = "lostfilename";
		if ( ff ) filename = ff->getFilename();

		// compute cache info
		RdbCache *rpc = getDiskPageCache ( m_rdbId );
		if ( ! m_allowPageCache ) rpc = NULL;
		int64_t vfd ;
		if ( ff ) vfd = ff->getVfd();
		key192_t ck ;
		if ( ff )
			ck = makeCacheKey ( vfd ,
					    m_scans[i].m_offset ,
					    m_scans[i].m_bytesToRead );
		if ( m_validateCache && ff && rpc && vfd != -1 ) {
			bool inCache;
			char *rec; int32_t recSize;
			inCache = rpc->getRecord ( (collnum_t)0 , // collnum
						   (char *)&ck , 
						   &rec , 
						   &recSize ,
						   true , // copy?
						   -1 , // maxAge, none 
						   true ); // inccounts?
			if ( inCache && 
			     // 1st byte is RdbScan::m_shifted
			     ( m_lists[i].m_listSize != recSize-1 ||
			       memcmp ( m_lists[i].m_list , rec+1,recSize-1) ||
			       *rec != m_scans[i].m_shifted ) ) {
				log("msg3: cache did not validate");
				char *xx=NULL;*xx=0;
			}
			mfree ( rec , recSize , "vca" );
		}


		///////
		//
		// STORE IN PAGE CACHE
		//
		///////
		// store what we read in the cache. don't bother storing
		// if it was a retry, just in case something strange happened.
		// store pre-constrain call is more efficient.
		if ( m_retryNum<=0 && ff && rpc && vfd != -1 &&
		     ! m_scans[i].m_inPageCache )
			rpc->addRecord ( (collnum_t)0 , // collnum
					 (char *)&ck , 
					 // rec1 is this little thingy
					 &m_scans[i].m_shifted,
					 1,
					 // rec2
					 m_lists[i].getList() ,
					 m_lists[i].getListSize() ,
					 0 ); // timestamp. 0 = now

		QUICKPOLL(m_niceness);

		// if from our 'page' cache, no need to constrain
		if ( ! m_lists[i].constrain ( m_startKey       ,
					      m_constrainKey   , // m_endKey
					      mrs           , // m_minRecSizes
					      m_hintOffsets[i] ,
					      //m_hintKeys   [i] ,
					      &m_hintKeys   [i*m_ks] ,
					      filename,//ff->getFilename() ,
					      m_niceness ) ) {
			log("net: Had error while constraining list read from "
			    "%s: %s/%s. vfd=%" PRId32" parts=%" PRId32". "
			    "This is likely caused by corrupted "
			    "data on disk.", 
			    mstrerror(g_errno), ff->getDir(),
			    ff->getFilename(), ff->m_vfd , 
			    (int32_t)ff->m_numParts );
			continue;
		}
	}

	// print the time
	if ( g_conf.m_logTimingDb ) {
		int64_t now = gettimeofdayInMilliseconds();
		int64_t took = now - m_startTime;
		log(LOG_TIMING,
		    "net: Took %" PRId64" ms to read %" PRId32" lists of %" PRId32" bytes total"
		     " from %s (niceness=%" PRId32").",
		     took,m_numFileNums,count,base->m_dbname,m_niceness);
	}
	return true;
}
Exemple #6
0
static void raw_pull_job_on_finished(PullJob *j) {
        RawPull *i;
        int r;

        assert(j);
        assert(j->userdata);

        i = j->userdata;
        if (j == i->roothash_job) {
                if (j->error != 0)
                        log_info_errno(j->error, "Root hash file could not be retrieved, proceeding without.");
        } else if (j == i->settings_job) {
                if (j->error != 0)
                        log_info_errno(j->error, "Settings file could not be retrieved, proceeding without.");
        } else if (j->error != 0 && j != i->signature_job) {
                if (j == i->checksum_job)
                        log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)");
                else
                        log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)");

                r = j->error;
                goto finish;
        }

        /* This is invoked if either the download completed
         * successfully, or the download was skipped because we
         * already have the etag. In this case ->etag_exists is
         * true.
         *
         * We only do something when we got all three files */

        if (!raw_pull_is_done(i))
                return;

        if (i->signature_job && i->checksum_job->style == VERIFICATION_PER_DIRECTORY && i->signature_job->error != 0) {
                log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");

                r = i->signature_job->error;
                goto finish;
        }

        if (i->roothash_job)
                i->roothash_job->disk_fd = safe_close(i->roothash_job->disk_fd);
        if (i->settings_job)
                i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd);

        r = raw_pull_determine_path(i, ".raw", &i->final_path);
        if (r < 0)
                goto finish;

        if (!i->raw_job->etag_exists) {
                /* This is a new download, verify it, and move it into place */
                assert(i->raw_job->disk_fd >= 0);

                raw_pull_report_progress(i, RAW_VERIFYING);

                r = pull_verify(i->raw_job, i->roothash_job, i->settings_job, i->checksum_job, i->signature_job);
                if (r < 0)
                        goto finish;

                raw_pull_report_progress(i, RAW_UNPACKING);

                r = raw_pull_maybe_convert_qcow2(i);
                if (r < 0)
                        goto finish;

                raw_pull_report_progress(i, RAW_FINALIZING);

                r = import_make_read_only_fd(i->raw_job->disk_fd);
                if (r < 0)
                        goto finish;

                r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path);
                if (r < 0) {
                        log_error_errno(r, "Failed to rename raw file to %s: %m", i->final_path);
                        goto finish;
                }

                i->temp_path = mfree(i->temp_path);

                if (i->roothash_job &&
                    i->roothash_job->error == 0) {
                        r = raw_pull_rename_auxiliary_file(i, ".roothash", &i->roothash_temp_path, &i->roothash_path);
                        if (r < 0)
                                goto finish;
                }

                if (i->settings_job &&
                    i->settings_job->error == 0) {
                        r = raw_pull_rename_auxiliary_file(i, ".nspawn", &i->settings_temp_path, &i->settings_path);
                        if (r < 0)
                                goto finish;
                }
        }

        raw_pull_report_progress(i, RAW_COPYING);

        r = raw_pull_make_local_copy(i);
        if (r < 0)
                goto finish;

        r = 0;

finish:
        if (i->on_finished)
                i->on_finished(i, r, i->userdata);
        else
                sd_event_exit(i->event, r);
}
/* Go through the file and parse each line */
int config_parse(const char *unit,
                 const char *filename,
                 FILE *f,
                 const char *sections,
                 ConfigItemLookup lookup,
                 const void *table,
                 ConfigParseFlags flags,
                 void *userdata) {

        _cleanup_free_ char *section = NULL, *continuation = NULL;
        _cleanup_fclose_ FILE *ours = NULL;
        unsigned line = 0, section_line = 0;
        bool section_ignored = false;
        int r;

        assert(filename);
        assert(lookup);

        if (!f) {
                f = ours = fopen(filename, "re");
                if (!f) {
                        /* Only log on request, except for ENOENT,
                         * since we return 0 to the caller. */
                        if ((flags & CONFIG_PARSE_WARN) || errno == ENOENT)
                                log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
                                               "Failed to open configuration file '%s': %m", filename);
                        return errno == ENOENT ? 0 : -errno;
                }
        }

        fd_warn_permissions(filename, fileno(f));

        for (;;) {
                _cleanup_free_ char *buf = NULL;
                bool escaped = false;
                char *l, *p, *e;

                r = read_line(f, LONG_LINE_MAX, &buf);
                if (r == 0)
                        break;
                if (r == -ENOBUFS) {
                        if (flags & CONFIG_PARSE_WARN)
                                log_error_errno(r, "%s:%u: Line too long", filename, line);

                        return r;
                }
                if (r < 0) {
                        if (CONFIG_PARSE_WARN)
                                log_error_errno(r, "%s:%u: Error while reading configuration file: %m", filename, line);

                        return r;
                }

                l = buf;
                if (!(flags & CONFIG_PARSE_REFUSE_BOM)) {
                        char *q;

                        q = startswith(buf, UTF8_BYTE_ORDER_MARK);
                        if (q) {
                                l = q;
                                flags |= CONFIG_PARSE_REFUSE_BOM;
                        }
                }

                if (continuation) {
                        if (strlen(continuation) + strlen(l) > LONG_LINE_MAX) {
                                if (flags & CONFIG_PARSE_WARN)
                                        log_error("%s:%u: Continuation line too long", filename, line);
                                return -ENOBUFS;
                        }

                        if (!strextend(&continuation, l, NULL)) {
                                if (flags & CONFIG_PARSE_WARN)
                                        log_oom();
                                return -ENOMEM;
                        }

                        p = continuation;
                } else
                        p = l;

                for (e = p; *e; e++) {
                        if (escaped)
                                escaped = false;
                        else if (*e == '\\')
                                escaped = true;
                }

                if (escaped) {
                        *(e-1) = ' ';

                        if (!continuation) {
                                continuation = strdup(l);
                                if (!continuation) {
                                        if (flags & CONFIG_PARSE_WARN)
                                                log_oom();
                                        return -ENOMEM;
                                }
                        }

                        continue;
                }

                r = parse_line(unit,
                               filename,
                               ++line,
                               sections,
                               lookup,
                               table,
                               flags,
                               &section,
                               &section_line,
                               &section_ignored,
                               p,
                               userdata);
                if (r < 0) {
                        if (flags & CONFIG_PARSE_WARN)
                                log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line);
                        return r;
                }

                continuation = mfree(continuation);
        }

        if (continuation) {
                r = parse_line(unit,
                               filename,
                               ++line,
                               sections,
                               lookup,
                               table,
                               flags,
                               &section,
                               &section_line,
                               &section_ignored,
                               continuation,
                               userdata);
                if (r < 0) {
                        if (flags & CONFIG_PARSE_WARN)
                                log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line);
                        return r;
                }
        }

        return 0;
}
Exemple #8
0
static int parse_argv(int argc, char *argv[]) {

        enum {
                ARG_VERSION = 0x100,
                ARG_ROOT,
                ARG_LOCALE,
                ARG_LOCALE_MESSAGES,
                ARG_KEYMAP,
                ARG_TIMEZONE,
                ARG_HOSTNAME,
                ARG_MACHINE_ID,
                ARG_ROOT_PASSWORD,
                ARG_ROOT_PASSWORD_FILE,
                ARG_PROMPT,
                ARG_PROMPT_LOCALE,
                ARG_PROMPT_KEYMAP,
                ARG_PROMPT_TIMEZONE,
                ARG_PROMPT_HOSTNAME,
                ARG_PROMPT_ROOT_PASSWORD,
                ARG_COPY,
                ARG_COPY_LOCALE,
                ARG_COPY_KEYMAP,
                ARG_COPY_TIMEZONE,
                ARG_COPY_ROOT_PASSWORD,
                ARG_SETUP_MACHINE_ID,
        };

        static const struct option options[] = {
                { "help",                 no_argument,       NULL, 'h'                      },
                { "version",              no_argument,       NULL, ARG_VERSION              },
                { "root",                 required_argument, NULL, ARG_ROOT                 },
                { "locale",               required_argument, NULL, ARG_LOCALE               },
                { "locale-messages",      required_argument, NULL, ARG_LOCALE_MESSAGES      },
                { "keymap",               required_argument, NULL, ARG_KEYMAP               },
                { "timezone",             required_argument, NULL, ARG_TIMEZONE             },
                { "hostname",             required_argument, NULL, ARG_HOSTNAME             },
                { "machine-id",           required_argument, NULL, ARG_MACHINE_ID           },
                { "root-password",        required_argument, NULL, ARG_ROOT_PASSWORD        },
                { "root-password-file",   required_argument, NULL, ARG_ROOT_PASSWORD_FILE   },
                { "prompt",               no_argument,       NULL, ARG_PROMPT               },
                { "prompt-locale",        no_argument,       NULL, ARG_PROMPT_LOCALE        },
                { "prompt-keymap",        no_argument,       NULL, ARG_PROMPT_KEYMAP        },
                { "prompt-timezone",      no_argument,       NULL, ARG_PROMPT_TIMEZONE      },
                { "prompt-hostname",      no_argument,       NULL, ARG_PROMPT_HOSTNAME      },
                { "prompt-root-password", no_argument,       NULL, ARG_PROMPT_ROOT_PASSWORD },
                { "copy",                 no_argument,       NULL, ARG_COPY                 },
                { "copy-locale",          no_argument,       NULL, ARG_COPY_LOCALE          },
                { "copy-keymap",          no_argument,       NULL, ARG_COPY_KEYMAP          },
                { "copy-timezone",        no_argument,       NULL, ARG_COPY_TIMEZONE        },
                { "copy-root-password",   no_argument,       NULL, ARG_COPY_ROOT_PASSWORD   },
                { "setup-machine-id",     no_argument,       NULL, ARG_SETUP_MACHINE_ID     },
                {}
        };

        int r, c;

        assert(argc >= 0);
        assert(argv);

        while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)

                switch (c) {

                case 'h':
                        return help();

                case ARG_VERSION:
                        return version();

                case ARG_ROOT:
                        r = parse_path_argument_and_warn(optarg, true, &arg_root);
                        if (r < 0)
                                return r;
                        break;

                case ARG_LOCALE:
                        if (!locale_is_valid(optarg))
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Locale %s is not valid.", optarg);

                        r = free_and_strdup(&arg_locale, optarg);
                        if (r < 0)
                                return log_oom();

                        break;

                case ARG_LOCALE_MESSAGES:
                        if (!locale_is_valid(optarg))
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Locale %s is not valid.", optarg);

                        r = free_and_strdup(&arg_locale_messages, optarg);
                        if (r < 0)
                                return log_oom();

                        break;

                case ARG_KEYMAP:
                        if (!keymap_is_valid(optarg))
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Keymap %s is not valid.", optarg);

                        r = free_and_strdup(&arg_keymap, optarg);
                        if (r < 0)
                                return log_oom();

                        break;

                case ARG_TIMEZONE:
                        if (!timezone_is_valid(optarg, LOG_ERR))
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Timezone %s is not valid.", optarg);

                        r = free_and_strdup(&arg_timezone, optarg);
                        if (r < 0)
                                return log_oom();

                        break;

                case ARG_ROOT_PASSWORD:
                        r = free_and_strdup(&arg_root_password, optarg);
                        if (r < 0)
                                return log_oom();
                        break;

                case ARG_ROOT_PASSWORD_FILE:
                        arg_root_password = mfree(arg_root_password);

                        r = read_one_line_file(optarg, &arg_root_password);
                        if (r < 0)
                                return log_error_errno(r, "Failed to read %s: %m", optarg);

                        break;

                case ARG_HOSTNAME:
                        if (!hostname_is_valid(optarg, true))
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Host name %s is not valid.", optarg);

                        hostname_cleanup(optarg);
                        r = free_and_strdup(&arg_hostname, optarg);
                        if (r < 0)
                                return log_oom();

                        break;

                case ARG_MACHINE_ID:
                        if (sd_id128_from_string(optarg, &arg_machine_id) < 0)
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Failed to parse machine id %s.", optarg);

                        break;

                case ARG_PROMPT:
                        arg_prompt_locale = arg_prompt_keymap = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = true;
                        break;

                case ARG_PROMPT_LOCALE:
                        arg_prompt_locale = true;
                        break;

                case ARG_PROMPT_KEYMAP:
                        arg_prompt_keymap = true;
                        break;

                case ARG_PROMPT_TIMEZONE:
                        arg_prompt_timezone = true;
                        break;

                case ARG_PROMPT_HOSTNAME:
                        arg_prompt_hostname = true;
                        break;

                case ARG_PROMPT_ROOT_PASSWORD:
                        arg_prompt_root_password = true;
                        break;

                case ARG_COPY:
                        arg_copy_locale = arg_copy_keymap = arg_copy_timezone = arg_copy_root_password = true;
                        break;

                case ARG_COPY_LOCALE:
                        arg_copy_locale = true;
                        break;

                case ARG_COPY_KEYMAP:
                        arg_copy_keymap = true;
                        break;

                case ARG_COPY_TIMEZONE:
                        arg_copy_timezone = true;
                        break;

                case ARG_COPY_ROOT_PASSWORD:
                        arg_copy_root_password = true;
                        break;

                case ARG_SETUP_MACHINE_ID:

                        r = sd_id128_randomize(&arg_machine_id);
                        if (r < 0)
                                return log_error_errno(r, "Failed to generate randomized machine ID: %m");

                        break;

                case '?':
                        return -EINVAL;

                default:
                        assert_not_reached("Unhandled option");
                }

        return 1;
}
 // . parse an incoming request
 // . return false and set g_errno on error
 // . CAUTION: we destroy "req" by replacing it's last char with a \0
 // . last char must be \n or \r for it to be a proper request anyway
 bool HttpRequest::set ( char *origReq , long origReqLen , TcpSocket *sock ) {
	 // reset number of cgi field terms
	 reset();

	 if ( ! m_reqBuf.reserve ( origReqLen + 1 ) ) {
		 log("http: failed to copy request: %s",mstrerror(g_errno));
		 return false;
	 }

	 // copy it to avoid mangling it
	 m_reqBuf.safeMemcpy ( origReq , origReqLen );
	 // NULL term
	 m_reqBuf.pushChar('\0');

	 m_reqBufValid = true;

	 // and point to that
	 char *req    = m_reqBuf.getBufStart();
	 long  reqLen = m_reqBuf.length() - 1;

	 // save this
	 m_userIP = 0; if ( sock ) m_userIP = sock->m_ip;
	 m_isSSL  = 0; if ( sock ) m_isSSL = (bool)sock->m_ssl;

	 // TcpServer should always give us a NULL terminated request
	 if ( req[reqLen] != '\0' ) { char *xx = NULL; *xx = 0; }
	 
	 // how long is the first line, the primary request
	 long i;
	 // for ( i = 0 ; i<reqLen && i<MAX_REQ_LEN && 
	 //	       req[i]!='\n' && req[i]!='\r'; i++);
	 // . now fill up m_buf, used to log the request
	 // . make sure the url was encoded correctly
	 // . we don't want assholes encoding every char so we can't see what
	 //   url they are submitting to be spidered/indexed
	 // . also, don't de-code encoded ' ' '+' '?' '=' '&' because that would
	 //   change the meaning of the url
	 // . and finally, non-ascii chars that don't display correctly
	 // . this should NULL terminate m_buf, too
	 // . turn this off for now, just try to log a different way
	 // m_bufLen = urlNormCode ( m_buf , MAX_REQ_LEN - 1 , req , i );
	 // ensure it's big enough to be a valid request
	 if ( reqLen < 5 ) { 
		 log("http: got reqlen<5 = %s",req);
		 g_errno = EBADREQUEST; 
		 return false; 
	 }
	 // or if first line too long
	 //if ( i >= 1024 )  { g_errno = EBADREQUEST; return false; }
	 // get the type, must be GET or HEAD
	 if      ( strncmp ( req , "GET "  , 4 ) == 0 ) m_requestType = 0;
	 // these means a compressed reply was requested. use by query
	 // compression proxies.
	 else if ( strncmp ( req , "ZET "  , 4 ) == 0 ) m_requestType = 0;
	 else if ( strncmp ( req , "HEAD " , 5 ) == 0 ) m_requestType = 1;
	 else if ( strncmp ( req , "POST " , 5 ) == 0 ) m_requestType = 2;
	 else { 
		 log("http: got bad request cmd: %s",req);
		 g_errno = EBADREQUEST; 
		 return false; 
	 }
	 // . NULL terminate the request (a destructive operation!)
	 // . this removes the last \n in the trailing \r\n 
	 // . shit, but it f***s up POST requests
	 if ( m_requestType != 2 ) { req [ reqLen - 1 ] = '\0'; reqLen--; }

	 // POST requests can be absolutely huge if you are injecting a 100MB
	 // file, so limit our strstrs to the end of the mime
	 char *d = NULL;
	 char  dc;
	 // check for body if it was a POST request
	 if ( m_requestType == 2 ) {
		 d = strstr ( req , "\r\n\r\n" );
		 if ( d ) { dc = *d; *d = '\0'; }
		 else log("http: Got POST request without \\r\\n\\r\\n.");
	 }

	 // . point to the file path 
	 // . skip over the "GET "
	 long filenameStart = 4 ;
	 // skip over extra char if it's a "HEAD " request
	 if ( m_requestType == 1 || m_requestType == 2 ) filenameStart++;

	 // are we a redirect?
	 i = filenameStart;
	 m_redirLen = 0;
	 if ( strncmp ( &req[i] , "/?redir=" , 8 ) == 0 ) {
		 for ( long k = i+8; k<reqLen && m_redirLen<126 ; k++) {
			 if ( req[k] == '\r' ) break;
			 if ( req[k] == '\n' ) break;
			 if ( req[k] == '\t' ) break;
			 if ( req[k] ==  ' ' ) break;
			 m_redir[m_redirLen++] = req[k];
		 }
	 }
	 m_redir[m_redirLen] = '\0';

	 // find a \n space \r or ? that delimits the filename
	 for ( i = filenameStart ; i < reqLen ; i++ ) {
		 if ( is_wspace_a ( req [ i ] ) ) break;
		 if ( req [ i ] == '?' ) break;
	 }

	 // now calc the filename length
	 m_filenameLen = i - filenameStart;
	 // return false and set g_errno if it's 0
	 if ( m_filenameLen <= 0  ) { 
		 log("http: got filenameLen<=0: %s",req);
		 g_errno = EBADREQUEST; 
		 return false; 
	 }
	 // . bitch if too big
	 // . leave room for strcatting "index.html" below
	 if ( m_filenameLen >= MAX_HTTP_FILENAME_LEN - 10 ) { 
		 log("http: got filenameLen>=max");
		 g_errno = EBADREQUEST; 
		 return false; 
	 }
	 // . decode the filename into m_filename and reassign it's length
	 // . decode %2F to / , etc...
	 m_filenameLen = urlDecode(m_filename,req+filenameStart,m_filenameLen);
	 // NULL terminate m_filename
	 m_filename [ m_filenameLen ] = '\0';
	 // does it have a file extension AFTER the last / in the filename?
	 bool hasExtension = false;
	 for ( long j = m_filenameLen-1 ; j >= 0 ; j-- ) {
		 if ( m_filename[j] == '.' ) { hasExtension = true; break; }
		 if ( m_filename[j] == '/' ) break;
	 }
	 // if it has no file extension append a /index.html
	 if ( ! hasExtension && m_filename [ m_filenameLen - 1 ] == '/' ) {
		 strcat ( m_filename , "index.html" );
		 m_filenameLen = gbstrlen ( m_filename );
	 }
	 // set file offset/size defaults
	 m_fileOffset = 0;
	 // -1 means ALL the file from m_fileOffset onwards
	 m_fileSize   = -1;  
	 // "e" points to where the range actually starts, if any
	 //char *e;
	 // . TODO: speed up by doing one strstr for Range: and maybe range:
	 // . do they have a Range: 0-100\n in the mime denoting a partial get?
	 //char *s = strstr ( req ,"Range:bytes=" );
	 //e = s + 12;
	 // try alternate formats
	 //if ( ! s ) { s = strstr ( req ,"Range: bytes=" ); e = s + 13; }
	 //if ( ! s ) { s = strstr ( req ,"Range: "       ); e = s +  7; }
	 // parse out the range if we got one
	 //if ( s ) {
	 //	long x = 0;
	 //	sscanf ( e ,"%li-%li" , &m_fileOffset , &x );
	 //	// get all file if range's 2nd number is non-existant
	 //	if ( x == 0 ) m_fileSize = -1;
	 //	else          m_fileSize = x - m_fileOffset;
	 //	// ensure legitimacy
	 //	if ( m_fileOffset < 0 ) m_fileOffset = 0;
	 //}
	 // reset our hostname
	 m_hostLen = 0;
	 // assume request is NOT from local network
	 //m_isAdmin = false;
	 m_isLocal = false;
	 // get the virtual hostname they want to use
	 char *s = strstr ( req ,"Host:" );
	 // try alternate formats
	 if ( ! s ) s = strstr ( req , "host:" ); 
	 // must be on its own line, otherwise it's not valid
	 if ( s && s > req && *(s-1) !='\n' ) s = NULL;
	 // parse out the host if we got one
	 if ( s ) {
		 // skip field name, host:
		 s += 5;
		 // skip e to beginning of the host name after "host:"
		 while ( *s==' ' || *s=='\t' ) s++;
		 // find end of the host name
		 char *end = s;
		 while ( *end && !is_wspace_a(*end) ) end++;
		 // . now *end should be \0, \n, \r, ' ', ...
		 // . get host len
		 m_hostLen = end - s;
		 // truncate if too big
		 if ( m_hostLen >= 255 ) m_hostLen = 254;
		 // copy into hostname
		 memcpy ( m_host , s , m_hostLen );
	 }
	 // NULL terminate it
	 m_host [ m_hostLen ] = '\0';

	 // get Referer: field
	 s = strstr ( req ,"Referer:" );
	 // find another
	 if ( ! s ) s = strstr ( req ,"referer:" );
	 // must be on its own line, otherwise it's not valid
	 if ( s && s > req && *(s-1) !='\n' ) s = NULL;
	 // assume no referer
	 m_refLen = 0;
	 // parse out the referer if we got one
	 if ( s ) {
		 // skip field name, referer:
		 s += 8;
		 // skip e to beginning of the host name after ':'
		 while ( *s==' ' || *s=='\t' ) s++;
		 // find end of the host name
		 char *end = s;
		 while ( *end && !is_wspace_a(*end) ) end++;
		 // . now *end should be \0, \n, \r, ' ', ...
		 // . get len
		 m_refLen = end - s;
		 // truncate if too big
		 if ( m_refLen >= 255 ) m_refLen = 254;
		 // copy into m_ref
		 memcpy ( m_ref , s , m_refLen );
	 }
	 // NULL terminate it
	 m_ref [ m_refLen ] = '\0';

	 // get User-Agent: field
	 s = strstr ( req ,"User-Agent:" );
	 // find another
	 if ( ! s ) s = strstr ( req ,"user-agent:" );
	 // must be on its own line, otherwise it's not valid
	 if ( s && s > req && *(s-1) !='\n' ) s = NULL;
	 // assume empty
	 long len = 0;
	 // parse out the referer if we got one
	 if ( s ) {
		 // skip field name, referer:
		 s += 11;
		 // skip e to beginning of the host name after ':'
		 while ( *s==' ' || *s=='\t' ) s++;
		 // find end of the agent name
		 char *end = s;
		 while ( *end && *end!='\n' && *end!='\r' ) end++;
		 // . now *end should be \0, \n, \r, ' ', ...
		 // . get agent len
		 len = end - s;
		 // truncate if too big
		 if ( len > 127 ) len = 127;
		 // copy into m_userAgent
		 memcpy ( m_userAgent , s , len );
	 }
	 // NULL terminate it
	 m_userAgent [ len ] = '\0';

	 m_isMSIE = false;
	 if ( strstr ( m_userAgent , "MSIE" ) )
		 m_isMSIE = true;

	 // get Cookie: field
	 s = strstr ( req, "Cookie:" );
	 // find another
	 if ( !s ) s = strstr ( req, "cookie:" );
	 // must be on its own line, otherwise it's not valid
	 if ( s && s > req && *(s-1) != '\n' ) s = NULL;
	 // assume empty
	 // m_cookieBufLen = 0;
	 m_cookiePtr = s;
	 // parse out the cookie if we got one
	 if ( s ) {
		 // skip field name, Cookie:
		 s += 7;
		 // skip s to beginning of cookie after ':'
		 while ( *s == ' ' || *s == '\t' ) s++;
		 // find end of the cookie
		 char *end = s;
		 while ( *end && *end != '\n' && *end != '\r' ) end++;
		 // save length
		 m_cookieLen = end - m_cookiePtr;
		 // get cookie len
		 //m_cookieBufLen = end - s;
		 // trunc if too big
		 //if (m_cookieBufLen > 1023) m_cookieBufLen = 1023;
		 // copy into m_cookieBuf
		 //memcpy(m_cookieBuf, s, m_cookieBufLen);
	 }
	 // NULL terminate it
	 if ( m_cookiePtr ) m_cookiePtr[m_cookieLen] = '\0';
	 //m_cookieBuf[m_cookieBufLen] = '\0';
	 // convert every '&' in cookie to a \0 for parsing the fields
	 // for ( long j = 0 ; j < m_cookieBufLen ; j++ ) 
	 //	 if ( m_cookieBuf[j] == '&' ) m_cookieBuf[j] = '\0';

	 // mark it as cgi if it has a ?
	 bool isCgi = ( req [ i ] == '?' ) ;
	 // reset m_filename length to exclude the ?* stuff
	 if ( isCgi ) {
		 // skip over the '?'
		 i++;
		 // find a space the delmits end of cgi
		 long j;
		 for ( j = i; j < reqLen; j++) if (is_wspace_a(req[j])) break;
		 // now add it
		 if ( ! addCgi ( &req[i] , j-i ) ) return false;
		 // update i
		 i = j;
	 }

	 // . set path ptrs
	 // . the whole /cgi/14.cgi?coll=xxx&..... thang
	 m_path = req + filenameStart;
	 m_plen = i - filenameStart;
	 // we're local if hostname is 192.168.[0|1].y
	 //if ( strncmp(iptoa(sock->m_ip),"192.168.1.",10) == 0) {
	 //	m_isAdmin = true; m_isLocal = true; }
	 //if ( strncmp(iptoa(sock->m_ip),"192.168.0.",10) == 0) {
	 //	m_isAdmin = true; m_isLocal = true; }
	 //if(strncmp(iptoa(sock->m_ip),"192.168.1.",10) == 0) m_isLocal = true;
	 //if(strncmp(iptoa(sock->m_ip),"192.168.0.",10) == 0) m_isLocal = true;
	 if ( sock && strncmp(iptoa(sock->m_ip),"192.168.",8) == 0) 
		 m_isLocal = true;
	 if ( sock && strncmp(iptoa(sock->m_ip),"10.",3) == 0) 
		 m_isLocal = true;
	 // steve cook's comcast at home:
	 // if ( sock && strncmp(iptoa(sock->m_ip),"68.35.100.143",13) == 0) 
	 // m_isLocal = true;
	 // procog's ip
	 // if ( sock && strncmp(iptoa(sock->m_ip),"216.168.36.21",13) == 0) 
	 //	 m_isLocal = true;

	 // roadrunner ip
	 // if ( sock && strncmp(iptoa(sock->m_ip),"66.162.42.131",13) == 0) 
	 //	 m_isLocal = true;

	 // cnsp ip
	 //if ( sock && strncmp(iptoa(sock->m_ip),"67.130.216.27",13) == 0) 
	 //	 m_isLocal = true;

	 // emily parker
	 //if ( sock && strncmp(iptoa(sock->m_ip),"69.92.68.202",12) == 0) 
	 //m_isLocal = true;
	 

	 // 127.0.0.1
	 if ( sock && sock->m_ip == 16777343 )
		 m_isLocal = true;
	 // steve cook's webserver
	 //if ( sock && strncmp(iptoa(sock->m_ip),"216.168.36.21",13) == 0) 
	 //	 m_isLocal = true;
	 // . also if we're coming from lenny at my house consider it local
	 // . this is a security risk, however... TODO: FIX!!!
	 //if ( sock->m_ip == atoip ("68.35.105.199" , 13 ) ) m_isAdmin = true;
	 // . TODO: now add any cgi data from a POST.....
	 // . look after the mime
	 //char *d = NULL;
	 // check for body if it was a POST request
	 //if ( m_requestType == 2 ) d = strstr ( req , "\r\n\r\n" );

	 // now put d's char back, just in case... does it really matter?
	 if ( d ) *d = dc;

	 // return true now if no cgi stuff to parse
	 if ( d ) {
		 char *post    = d + 4;
		 long  postLen = reqLen-(d+4-req) ;
		 // post sometimes has a \r or\n after it
		 while ( postLen > 0 && post[postLen-1]=='\r' ) postLen--;
		 // add it to m_cgiBuf, filter and everything
		 if ( ! addCgi ( post , postLen ) ) return false;
	 }
	 // sometimes i don't want to be admin
	 //if ( getLong ( "admin" , 1 ) == 0 ) m_isAdmin = false;
	 // success
	 
	 /////
	 // Handle Extra parms...

	 char *ep = g_conf.m_extraParms;
	 char *epend = g_conf.m_extraParms + g_conf.m_extraParmsLen;

	 char *qstr = m_cgiBuf;
	 long qlen = m_cgiBufLen;

	 while (ep < epend){
		 char buf[AUTOBAN_TEXT_SIZE];
		 long bufLen = 0;
		 // get next substring
		 while (*ep && ep < epend && *ep != ' ' && *ep != '\n'){
			 buf[bufLen++] = *ep++;
		 }
		 // skip whitespace
		 while (*ep && ep < epend && *ep == ' '){
			 ep++;
		 }
		 // null terminate 
		 buf[bufLen] = '\0';

		
		 // No match
		 if (!bufLen ||
		     !strnstr(qstr, qlen, buf)){
			 // skip to end of line
			 while (*ep && ep < epend && *ep != '\n') ep++;
			 // skip newline
			 while (*ep && ep < epend && *ep == '\n') ep++;
			 // try next substr
			 continue;
		 }
		 // found a match...
		 // get parm string
		 bufLen = 0;
		 while (*ep && ep < epend && *ep != '\n'){
			 buf[bufLen++] = *ep++;
		 }
		 buf[bufLen] = '\0';
		 
		 // skip newline
		 while (*ep && ep < epend && *ep == '\n') ep++;

		 logf(LOG_DEBUG, "query: appending \"%s\" to query", buf);
		
		 long newSize = m_cgiBuf2Size + bufLen+1;
		 char *newBuf = (char*)mmalloc(newSize, "extraParms");
		 if (!newBuf){
			 return log("query: unable to allocate %ld bytes "
				    "for extraParms", newSize);
		 }
		 char *p = newBuf;
		 if (m_cgiBuf2Size) {
			 memcpy(newBuf, m_cgiBuf2, m_cgiBuf2Size);
			 p += m_cgiBuf2Size-1;
			 mfree(m_cgiBuf2, m_cgiBuf2Size, "extraParms");
			 m_cgiBuf2 = NULL;
			 m_cgiBuf2Size = 0;
		 }
		 memcpy(p, buf, bufLen);
		 m_cgiBuf2 = newBuf;
		 m_cgiBuf2Size = newSize;
		 p += bufLen;
		 *p = '\0';
	 }

	 // Put '\0' back into the HttpRequest buffer...
	 if (m_cgiBuf){
		 // do not mangle the "ucontent"!
		 long cgiBufLen = m_cgiBufLen;
		 cgiBufLen -= m_ucontentLen;
		 char *buf = m_cgiBuf;
		 for (long i = 0; i < cgiBufLen ; i++) 
			 if (buf[i] == '&') buf[i] = '\0';
		 // don't decode the ucontent= field!
		 long decodeLen = m_cgiBufLen;
		 // so subtract that
		 if ( m_ucontent ) decodeLen -= m_ucontentLen;
		 // decode everything
		 long len = urlDecode ( m_cgiBuf , m_cgiBuf , decodeLen );
		 // we're parsing crap after the null if the last parm 
		 // has no value
		 //memset(m_cgiBuf+len, '\0', m_cgiBufLen-len);
		 m_cgiBufLen = len;
		 // ensure that is null i guess
		 if ( ! m_ucontent ) m_cgiBuf[len] = '\0';
	 }
	
	 if (m_cgiBuf2){
		 char *buf = m_cgiBuf2;
		 for (long i = 0; i < m_cgiBuf2Size-1 ; i++) 
			 if (buf[i] == '&') buf[i] = '\0';
		 long len = urlDecode ( m_cgiBuf2 , m_cgiBuf2 , m_cgiBuf2Size);
		 memset(m_cgiBuf2+len, '\0', m_cgiBuf2Size-len);
	 }
	 // . parse the fields after the ? in a cgi filename
	 // . or fields in the content if it's a POST
	 // . m_cgiBuf must be and is NULL terminated for this
	 parseFields ( m_cgiBuf , m_cgiBufLen );
	 // Add extra parms to the request.  
	 if (m_cgiBuf2Size){
		 parseFields(m_cgiBuf2, m_cgiBuf2Size);
	 }

	 // urldecode the cookie buf too!!
	 if ( m_cookiePtr ) {
		 char *p = m_cookiePtr;
		 for (long i = 0; i < m_cookieLen ; i++) {
			 //if (p[i] == '&') p[i] = '\0';
			 // cookies are separated with ';' in the request only
			 if (p[i] == ';') p[i] = '\0';
			 // a hack for the metacookie=....
			 // which uses &'s to separate its subcookies
			 // this is a hack for msie's limit of 50 cookies
			 if ( p[i] == '&' ) p[i] = '\0';
			 // set m_metaCookie to start of meta cookie
			 if ( p[i] == 'm' && p[i+1] == 'e' &&
			      strncmp(p,"metacookie",10) == 0 )
				 m_metaCookie = p;
		 }
		 long len = urlDecode ( m_cookiePtr , 
					m_cookiePtr,
					m_cookieLen );
		 // we're parsing crap after the null if the last parm 
		 // has no value
		 memset(m_cookiePtr+len, '\0', m_cookieLen-len);
		 m_cookieLen = len;
	 }

	 return true;
 }
Exemple #10
0
void PDFDocSaveUnPackedUnLinearized(PDFDocHandle Doc, PDFStreamHandle Strm)
{
    char str[128];
    ppUns32 i, xrefoffset;
	ppUns32 k;
    PDFCosHandle obj,wrk, ar, z, cr;
    PDFCosHandle tobj;
    PDFID ID, EID;
    char *pstr;
    TPDFCryptoType ncr, *UsedCrypto = NULL;
    ppBool crypting = false, delID = false;
    char c;

#ifndef NOT_USE_SIGN 
    sha1_Context hctx;
    PDFStreamHandle ms  = NULL;
    int fs, s1, o2, s2, hlen = SHA1_HASHSIZE;
    ppUns8 hash[SHA1_HASHSIZE]; 
#endif
    _CosNullNew (Doc, cr);
    _CosNullNew (Doc, tobj);

#ifndef NOT_USE_SIGN
	if ( _DOC->Signed ){
		sig_AddSigDict ( Doc );
		sig_AddSigAnnot ( Doc );
		sig_UpdateAcroForm ( Doc );
		sig_UpdatePageAnnots ( Doc );
		ms = ULStreamMemNew ( _LIB, 0 );
	}
#endif

	if ( _DOC->Remove ){
		PDFDocRemoveUnUsed ( Doc, NULL );
		k = 1;
		for ( i = 1; i < _DOC->Size; i++ ){
			if ( ( ( CosDoc ) Doc )->Entries[i].Used != etFree )
				( ( CosDoc ) Doc )->Entries[i].Additional = k++;
			else 
				( ( CosDoc ) Doc )->Entries[i].Additional = 0x7FFFFFFF;
		} 
		PDFDocRenumAllObjects ( Doc );
		PDFDocPackFree ( ( CosDoc ) Doc );
	}
    if ( _DOC->UseOldSecurity ){
        if ( _DOC->Crypted ){ 
            crypting = true;
            UsedCrypto = &( _DOC->CryptoInfo );
        };
    } else{
        if ( _DOC->NewCrypted ){
            crypting = true;
			ULSetNewCryptoData( Doc, &ncr );
			UsedCrypto = &ncr;
            delID = true;
        };
    };
    PDFTRY ( _LIB ){
		if ( crypting ){
            cr = ULPrepareCryptoDictionary (Doc, UsedCrypto );
			EID= _CosObjFullID (cr);
        };
		if (((CosDoc)Doc)->Version >= 9){
			_CosDictAppend(_DOC->Root,Extensions,obj = CosDictNew(Doc,false,1));
			_CosDictAppend(obj,ADBE,wrk = CosDictNew(Doc,false,2));
			_CosDictAppend(wrk,BaseVersion,CosNameNew(Doc, false,ULStringToAtom(_LIB,"1.7")));
			_CosDictAppend(wrk,ExtensionLevel, CosIntNew(Doc,false,3));
		}
/*
#ifndef NOT_USE_SIGN
        if ( _DOC->Signed ){
            sig_AddSigDict ( Doc );
            sig_AddSigAnnot ( Doc );
            sig_UpdateAcroForm ( Doc );
            sig_UpdatePageAnnots ( Doc );
            ms = ULStreamMemNew ( _LIB, 0 );
        }
#endif*/
        _CosNullNew(Doc, z);
        _CosNullNew(Doc, ar);
        PDFTRY ( _LIB ){
            tobj = CosDictNew ( Doc, false, 4 );
            _CosDictAppend ( tobj, Size, CosIntNew ( Doc, false, _DOC->Size ) );
            _CosDictAppend ( tobj, Root, _DOC->Root );
            _CosDictAppend ( tobj, Info, _DOC->Info );
            if ( crypting )
                _CosDictAppend ( tobj, Encrypt, cr );
            _CosDictAppend ( tobj, ID, ( ar = CosArrayNew ( Doc, false, 2 ) ) );
            if ( crypting )
                z = CosCopy ( Doc, UsedCrypto->FileID );
            else
                z = ULCreateFileID ( Doc, PDFEngine );
            _CosStringHex(z) =  true;
            CosArrayAppend ( ar, z );
            CosArrayAppend ( ar, CosCopy (Doc, z ) );         
        } PDFEXCEPT ( _LIB ){
            CosFree ( tobj );
            CosFree ( z );
            PDFRERAISE ( _LIB );
        }
        PDFTRYEND ( _LIB );
#ifndef NOT_USE_SIGN
        if ( _DOC->Signed )
            sha1_Init ( &hctx );
#endif
        SULStrToStrm ( Strm, "%PDF-1." );
        c =(ppInt8)( _DOC->Version + '0');
        SULStrmWriteChar ( Strm, c );
        SULStrToStrm ( Strm, "\r\n" );
        SULStrToStrm ( Strm, "%\330\302\300\314\r\n" );
        for ( i = 1; i < _DOC->Size; i++ ){
            if ( _DOC->Entries[i].Used != etFree ){
#ifndef NOT_USE_SIGN 
                if ( _DOC->Signed && _CosObjID( _DOC->SigCtx->Sign) == i )
                    break;
#endif
                obj = CosGetFromDoc ( Doc, i );
                if ( crypting ){
                    obj = CosCopy( Doc, obj ); 
                    ID.ID = i;
                    ID.GenID = _DOC->Entries[i].Generation;
                    if ( i != EID.ID )
                        CosCryptObject ( obj, UsedCrypto, ID, true );
                };
                _DOC->Entries[i].Offset = ULStreamGetPosition ( Strm );
                ULitostr ( i, str );
                SULStrToStrm ( Strm, str );
                SULStrToStrm ( Strm, " " );
                ULitostr ( _DOC->Entries[i].Generation, str );
                SULStrToStrm ( Strm, str );
                if ( _CosGetType ( obj ) < CosName )
                    SULStrToStrm ( Strm, " obj " )
                else
                    SULStrToStrm ( Strm, " obj" )
#ifndef NOT_USE_SIGN 
                if ( _DOC->Signed ){
                    CosCopyObjToStream (obj, ms );
                    sha1_Update ( &hctx, ( ppUns8 *) ULStrmGetMem ( ms ),
                                  ULStreamGetSize ( ms ) );
                    ULStreamCopyToStream ( ms, Strm );
                    ULStreamClear ( ms, 0 );
                } else
#endif
                    CosCopyObjToStream (obj, Strm );
                if ( crypting )
                    CosFree ( obj );
                SULStrToStrm ( Strm, "\nendobj\n" );
            };
        };
#ifndef NOT_USE_SIGN

        if ( _DOC->Signed ){
            fs = ULStreamGetPosition ( Strm );
            TailPass ( Doc, i, tobj, UsedCrypto, EID, &fs, &s1, &o2, NULL );
            s2 = fs - o2; sig_UpdateByteRange ( Doc, s1, o2, s2 );
            fs = ULStreamGetPosition ( Strm );
            TailPass ( Doc, i, tobj, UsedCrypto, EID, &fs, &s1, &o2, &hctx );
            sha1_Finish ( &hctx, hash );
            sig_UpdateContents ( Doc, hash, hlen );

            for ( ; i < _DOC->Size; i++ ){
                if ( _DOC->Entries[i].Used != etFree ){
                    obj = CosGetFromDoc ( Doc, i );
                    if ( crypting ){
                        obj = CosCopy( Doc, obj );
                        ID.ID = i; ID.GenID = _DOC->Entries[i].Generation;
                        if ( i != EID.ID )
                            CosCryptObject ( obj, UsedCrypto, ID, true );
                    }
                    _DOC->Entries[i].Offset = ULStreamGetPosition ( Strm );
                    ULitostr ( i, str );
                    ULStrToStrm ( Strm, str );
                    ULStrToStrm ( Strm, " " );
                    ULitostr ( _DOC->Entries[i].Generation, str );
                    ULStrToStrm ( Strm, str );
                    if ( _CosGetType ( obj ) < CosName )
                        ULStrToStrm ( Strm, " obj " );
                    else
                        ULStrToStrm ( Strm, " obj" );
                    CosCopyObjToStream ( obj, Strm );
                    if ( crypting )
                        CosFree ( obj );
                    ULStrToStrm ( Strm, "\nendobj\n" );
                }
            }
        }

#endif        
        xrefoffset = ULStreamGetPosition ( Strm );
        ULStrToStrm ( Strm, "xref\r\n0 " );
        ULitostr ( _DOC->Size, str );
        ULStrToStrm ( Strm, str );
        ULStrToStrm ( Strm, "\r\n0000000000 65535 f\r\n" );
        for ( i = 1; i < _DOC->Size; i++ ){
            if ( _DOC->Entries[i].Used != etFree ){
                pstr = ULIntToStrWithZero ( _LIB, _DOC->Entries[i].Offset, 10 );
                ULStrToStrm ( Strm, pstr );
                mfree (  _LIB, pstr );
                ULStreamWriteChar ( Strm, ' ' );
            } else
                ULStrToStrm ( Strm, "0000000000 " );

            if ( _DOC->Entries[i].Generation == 0xFFFF )
                pstr = ULIntToStrWithZero ( _LIB, 0, 5 );
            else
                pstr = ULIntToStrWithZero ( _LIB, _DOC->Entries[i].Generation,
                                            5 );
            ULStrToStrm ( Strm, pstr );
            mfree ( _LIB, pstr );
            _DOC->Entries[i].Used != etFree ? ULStrToStrm ( Strm, " n\r\n" ) :
            ULStrToStrm ( Strm, " f\r\n" );
        }
        ULStrToStrm ( Strm, "trailer\r\n" );
        CosCopyObjToStream ( tobj, Strm );
        CosFree ( tobj );
        ULStrToStrm ( Strm, "\r\nstartxref\r\n" );
        ULIntToStrm ( Strm, xrefoffset );
        ULStrToStrm ( Strm, "\r\n%%EOF" );
        if ( crypting )
            PDFDocDeleteObjEx ( Doc, EID.ID);
#ifndef NOT_USE_SIGN
        if ( _DOC->Signed )
            ULStreamClose ( ms );
#endif
    } PDFEXCEPT ( _LIB ){
        CosFree ( ncr.FileID );
#ifndef NOT_USE_SIGN
        if ( ms )
            ULStreamClose ( ms );
#endif
        CosFree ( tobj );
        PDFRERAISE ( _LIB );
    }
    PDFTRYEND ( _LIB );
    if ( delID )
        CosFree ( ncr.FileID );
}
//
// new code for drawing graph in html with absolute divs instead
// of using GIF plotter library which had issues
//
void Stats::printGraphInHtml ( SafeBuf &sb ) {

	// gif size
	char tmp[64];
	sprintf ( tmp , "%lix%li", (long)DX+40 , (long)DY+40 ); // "1040x440"

	// 20 pixel borders
	//int bx = 10;
	//int by = 30;
	// define the space with boundaries 100 unit wide boundaries
	//plotter.space ( -bx , -by , DX + bx , DY + by );
	// draw the x-axis
	//plotter.line ( 0 , 0 , DX , 0  );
	// draw the y-axis
	//plotter.line ( 0 , 0 ,  0 , DY );

	// find time ranges
	long long t2 = 0;
	for ( long i = 0 ; i < MAX_POINTS ; i++ ) {
		// skip empties
		if ( m_pts[i].m_startTime == 0 ) continue;
		// set min/max
		if ( m_pts[i].m_endTime   > t2 ) t2 = m_pts[i].m_endTime;
	}
	// now compute the start time for the graph
	long long t1 = 0x7fffffffffffffffLL;
	// now recompute t1
	for ( long i = 0 ; i < MAX_POINTS ; i++ ) {
		// skip empties
		if ( m_pts[i].m_startTime == 0 ) continue;
		// can't be behind more than 1 second
		if ( m_pts[i].m_startTime   < t2 - DT ) continue;
		// otherwise, it's a candidate for the first time
		if ( m_pts[i].m_startTime < t1 ) t1 = m_pts[i].m_startTime;
	}

	//
	// main graphing window
	//
	sb.safePrintf("<div style=\"position:relative;"
		      "background-color:#c0c0c0;"

		      // match style of tables
		      "border-radius:10px;"
		      "border:#6060f0 2px solid;"
		      
		      //"overflow-y:hidden;"
		      "overflow-x:hidden;"
		      "z-index:-10;"
		      // the tick marks we print below are based on it
		      // being a window of the last 20 seconds... and using
		      // DX pixels
		      "min-width:%lipx;"
		      "min-height:%lipx;"
		      //"width:100%%;"
		      //"min-height:600px;"
		      //"margin-top:10px;"
		      "margin-bottom:10px;"
		      //"margin-right:10px;"
		      //"margin-left:10px;"
		      "\">"
		      ,(long)DX
		      ,(long)DY +20); // add 10 more for "2s" labels etc.

	// 10 x-axis tick marks
	for ( int x = DX/20 ; x <= DX ; x += DX/20 ) {
		// tick mark
		//plotter.line ( x , -20 , x , 20 );
		sb.safePrintf("<div style=\"position:absolute;"
			      "left:%li;"
			      "bottom:0;"
			      "background-color:#000000;"
			      "z-index:110;"
			      "min-height:20px;"
			      "min-width:3px;\"></div>\n"
			      , (long)x-1
			      );
		// generate label
		//char buf [ 32 ];
		//sprintf ( buf , "%li" , 
		//	  (long)(DT * (long long)x / (long long)DX) );
		// LABEL
		sb.safePrintf("<div style=\"position:absolute;"
			      "left:%li;"
			      "bottom:20;"
			      //"background-color:#000000;"
			      "z-index:110;"
			      "min-height:20px;"
			      "min-width:3px;\">%lis</div>\n"
			      , (long)x-10
			      // the label:
			      ,(long)(DT * (long long)x / (long long)DX)/1000
			      );

		// move cursor
		//plotter.move ( x , -by / 2 - 9 );
		// plot label
		//plotter.alabel     ( 'c' , 'c' , buf );
	}

	// . each line consists of several points
	// . we need to know each point for adding otherlines
	// . is about [400/6][1024] = 70k
	// . each line can contain multiple data points
	// . each data point is expressed as a horizontal line segment
	void *lrgBuf;
	long lrgSize = 0;
	lrgSize += MAX_LINES * MAX_POINTS * sizeof(StatPoint *);
	lrgSize += MAX_LINES * sizeof(long);
	lrgBuf = (char *) mmalloc(lrgSize, "Stats.cpp"); 
	if (! lrgBuf) {
	    log("could not allocate memory for local buffer in Stats.cpp"
		"%li bytes needed", lrgSize);
	    return;
	}
	char *lrgPtr = (char *)lrgBuf;
	StatPoint **points = (StatPoint **)lrgPtr;   
	lrgPtr += MAX_LINES * MAX_POINTS * sizeof(StatPoint *);
	long *numPoints = (long *)lrgPtr;
	lrgPtr += MAX_LINES * sizeof(long);
	memset ( (char *)numPoints , 0 , MAX_LINES * sizeof(long) );

	// store the data points into "lines"
	long count = MAX_POINTS;
	for ( long i = m_next ; count >= 0 ; i++ , count-- ) {
		// wrap around the array
		if ( i >= MAX_POINTS ) i = 0;
		// skip point if empty
		if ( m_pts[i].m_startTime == 0 ) continue;
		// skip if too early
		if ( m_pts[i].m_endTime < t1 ) continue;
		// . find the lowest line the will hold us
		// . this adds point to points[x][n] where x is determined
		addPoint ( points , numPoints , &m_pts[i] );
	}

	int y1 = 21;
	// plot the points (lines) in each line
	for ( long i = 0 ; i < MAX_LINES    ; i++ ) {
		// increase vert
		y1 += MAX_WIDTH + 1;
		// wrap back down if necessary
		if ( y1 >= DY ) y1 = 21;
		// plt all points in this row
	for ( long j = 0 ; j < numPoints[i] ; j++ ) {
		// get the point
		StatPoint *p =  points[MAX_POINTS * i + j];
		// transform time to x coordinates
		int x1 = (p->m_startTime - t1) * (long long)DX / DT;
		int x2 = (p->m_endTime   - t1) * (long long)DX / DT;
		// if x2 is negative, skip it
		if ( x2 < 0 ) continue;
		// if x1 is negative, boost it to -2
		if ( x1 < 0 ) x1 = -2;
		// . line thickness is function of read/write size
		// . take logs
		int w = (int)log(((double)p->m_numBytes)/8192.0) + 3;
		//log("log of %li is %i",m_pts[i].m_numBytes,w);
		if ( w < 3         ) w = 3;
		if ( w > MAX_WIDTH ) w = MAX_WIDTH;
		//plotter.linewidth ( w );       
		// use the color specified from addStat_r() for this line/pt
		//plotter.pencolor ( ((p->m_color >> 16) & 0xff) << 8 ,
		//		   ((p->m_color >>  8) & 0xff) << 8 ,
		//		   ((p->m_color >>  0) & 0xff) << 8 );
		// ensure at least 3 units wide for visibility
		if ( x2 < x1 + 3 ) x2 = x1 + 3;
		// . flip the y so we don't have to scroll the browser down
		// . DY does not include the axis and tick marks
		long fy1 = DY - y1 + 20 ;
		// plot it
		//plotter.line ( x1 , fy1 , x2 , fy1 );
		drawLine2 ( sb , x1 , x2 , fy1 , p->m_color , w );
		// debug msg
		//log("line (%i,%i, %i,%i) ", x1 , vert , x2 , vert );
		//log("bytes = %li width = %li ", m_pts[i].m_numBytes,w);
		//log("st=%i, end=%i color=%lx " ,
		//      (int)m_pts[i].m_startTime , 
		//      (int)m_pts[i].m_endTime   , 
		//      m_pts[i].m_color );
	}
	}

	sb.safePrintf("</div>\n");

	mfree(lrgBuf, lrgSize, "Stats.cpp");
}
Exemple #12
0
void TailPass(PDFDocHandle Doc, int start, PDFCosHandle tobj,
              TPDFCryptoType *crypto, PDFID EID, int *fsize, int *s1, int *o2,
              sha1_Context *ctx)
{
    PDFStreamHandle strm= NULL;
    PDFCosHandle obj    ;
    PDFID ID;
    ppBool crypting;
    char str[128], *pstr, *p, *q;
    ppUns32 i, l;

    _CosNullNew(Doc, obj);

    crypting = (ppBool)( crypto != NULL );
    PDFTRY ( _LIB ){
        strm = ULStreamMemNew ( _LIB, 0 );
        obj = CosGetFromDoc ( Doc, start);
        if ( crypting ){
            obj= CosCopy( Doc, obj );
            ID.ID = start;
            ID.GenID = _DOC->Entries[start].Generation;
            CosCryptObject ( obj, crypto, ID, true );
        }
        _DOC->Entries[start].Offset = *fsize;
        ULitostr ( start, str );
        ULStrToStrm ( strm, str );
        ULStrToStrm ( strm, " " );
        ULitostr ( _DOC->Entries[start].Generation, str );
        ULStrToStrm ( strm, str );
        if ( _CosGetType ( obj ) < CosName )
            ULStrToStrm ( strm, " obj " );
        else
            ULStrToStrm ( strm, " obj" );
        CosCopyObjToStream ( obj, strm );
        if ( crypting )
            CosFree ( obj );
        ULStrToStrm ( strm, "\nendobj\n" );
        p = ( char * ) ULStrmGetMem ( strm );
        q = strstr ( p, "/Contents" );
        q += strlen ( "/Contents" );
        ( *s1 ) = *fsize + ( int ) ( q - p );
        if ( ctx != NULL )
            sha1_Update ( ctx, (ppUns8 *) p, ( int ) ( q - p ) );
        q = strchr ( p, '>' );
        l = ULStreamGetSize ( strm );
        if ( ctx != NULL )
            sha1_Update ( ctx, (ppUns8 *) (q + 1), l - ( int ) ( q - p ) - 1 );
        ( *o2 ) = *fsize + ( int ) ( q - p ) + 1;
        ( *fsize ) += ULStreamGetSize ( strm );
        ULStreamClear ( strm, 0 );

        for ( i = start + 1; i < _DOC->Size; i++ ){
            if ( _DOC->Entries[i].Used != etFree ){
                obj = CosGetFromDoc ( Doc, i );
                if ( crypting ){
                    obj = CosCopy ( Doc, obj );
                    ID.ID = i;
                    ID.GenID = _DOC->Entries[i].Generation;
                    if ( i != EID.ID )
                        CosCryptObject ( obj, crypto, ID, true );
                }
                _DOC->Entries[i].Offset = *fsize;
                ULitostr ( i, str );
                ULStrToStrm ( strm, str );
                ULStrToStrm ( strm, " " );
                ULitostr ( _DOC->Entries[i].Generation, str );
                ULStrToStrm ( strm, str );
                if ( _CosGetType ( obj ) < CosName )
                    ULStrToStrm ( strm, " obj " );
                else
                    ULStrToStrm ( strm, " obj" );
                CosCopyObjToStream ( obj, strm );
                if ( crypting )
                    CosFree ( obj );
                ULStrToStrm ( strm, "\nendobj\n" );
                ( *fsize ) += ULStreamGetSize ( strm );
                if ( ctx != NULL )
                    sha1_Update ( ctx, ( ppUns8 * ) ULStrmGetMem ( strm ),
                                  ULStreamGetSize ( strm ) );
                ULStreamClear ( strm, 0 );
            }
        }

        ULStrToStrm ( strm, "xref\r\n0 " );
        ULitostr ( _DOC->Size, str );
        ULStrToStrm ( strm, str );
        ULStrToStrm ( strm, "\r\n0000000000 65535 f\r\n" );
        for ( i = 1; i < _DOC->Size; i++ ){
            if ( _DOC->Entries[i].Used != etFree ){
                pstr = ULIntToStrWithZero ( _LIB, _DOC->Entries[i].Offset, 10 );
                ULStrToStrm ( strm, pstr );
                mfree ( _LIB, pstr );
                ULStreamWriteChar ( strm, ' ' );
            } else
                ULStrToStrm ( strm, "0000000000 " );

            if ( _DOC->Entries[i].Generation == 0xFFFF )
                pstr = ULIntToStrWithZero ( _LIB, 0, 5 );
            else
                pstr = ULIntToStrWithZero ( _LIB, _DOC->Entries[i].Generation, 5 );
            ULStrToStrm ( strm, pstr );
            mfree ( _LIB, pstr );
            if ( _DOC->Entries[i].Used != etFree )
                ULStrToStrm ( strm, " n\r\n" );
            else
                ULStrToStrm ( strm, " f\r\n" );
        }
        ULStrToStrm ( strm, "trailer\r\n" );
        CosCopyObjToStream (tobj, strm );
        ULStrToStrm ( strm, "\r\nstartxref\r\n" );
        ULIntToStrm ( strm, *fsize );
        ULStrToStrm ( strm, "\r\n%%EOF" );
        ( *fsize ) += ULStreamGetSize ( strm );
        if ( ctx != NULL )
            sha1_Update ( ctx, ( ppUns8 * ) ULStrmGetMem ( strm ), ULStreamGetSize ( strm ) );
        ULStreamClose ( strm );
    } PDFEXCEPT ( _LIB ){
        if ( strm )
            ULStreamClose ( strm );
        if ( crypting )
            CosFree ( obj );
        PDFRERAISE ( _LIB );
    }
    PDFTRYEND ( _LIB );
}
Blaster::~Blaster() {
	if (m_buf1)
		mfree(m_buf1,m_bufSize1,"blaster1");
	if (m_buf2)
		mfree(m_buf2,m_bufSize2,"blaster2");
}
void CountryCode::freeRegexTable(void) {
	if(!s_countryRegex) return;
	for(int x = 1; x < s_numCountryCodes; x++)
		regfree(&s_countryRegex[x]);
	mfree(s_countryRegex, s_numCountryCodes * sizeof(regex_t), "CountryRegex");
}
Exemple #15
0
void
gc(void)
{
	int i, j;
	U *p;

	// tag everything

	for (i = 0; i < mcount; i++) {
		p = mem[i];
		for (j = 0; j < N; j++)
			p[j].tag = 1;
	}

	// untag what's used

	untag(p0);
	untag(p1);
	untag(p2);
	untag(p3);
	untag(p4);
	untag(p5);
	untag(p6);
	untag(p7);
	untag(p8);
	untag(p9);

	untag(one);
	untag(zero);
	untag(imaginaryunit);

	for (i = 0; i < NSYM; i++) {
		untag(binding[i]);
		untag(arglist[i]);
	}

	for (i = 0; i < tos; i++)
		untag(stack[i]);

	for (i = (int) (frame - stack); i < TOS; i++)
		untag(stack[i]);

	// collect everything that's still tagged

	free_count = 0;

	for (i = 0; i < mcount; i++) {
		p = mem[i];
		for (j = 0; j < N; j++) {
			if (p[j].tag == 0)
				continue;
			// still tagged so it's unused, put on free list
			switch (p[j].k) {
			case TENSOR:
				free(p[j].u.tensor);
				break;
			case STR:
				free(p[j].u.str);
				break;
			case NUM:
				mfree(p[j].u.q.a);
				mfree(p[j].u.q.b);
				break;
			}
			p[j].k = CONS; // so no double free occurs above
			p[j].u.cons.cdr = free_list;
			free_list = p + j;
			free_count++;
		}
	}
}
int HECMW_vis_surface_compute(Surface *sff, struct hecmwST_local_mesh *mesh,
                              struct hecmwST_result_data *data, int *bdflag,
                              int *sum_v, int *sum_t, int *tvertex, int *tpatch,
                              double *minc, double *maxc, Result *result,
                              int sf_i, int mynode, HECMW_Comm VIS_COMM)

{
  /* in_volume */
  int i, j, k, mm;
  Point **CS_verts_head;
  Polygon **CS_polys_head;
  int alpha_index, beta_index;
  int sum_verts;
  int sum_table;
  Point **CS_verts_tail, **CS_verts_refer;
  Polygon **CS_polys_tail;
  Cube_polygons alpha_cube, beta_cube;

  int n_elem, tmp_int;
  Cell *cell;
  Tetra *tetra;

  int disamb_flag;

  Polygon *CS_polys, *CS_polys_tmp;
  Point *CS_verts, *CS_verts_tmp;
  int sum_polys, poly_num;
  int aplist_size, bplist_size, cplist_size;
  int num_nh_verts,
      num_nh_patch; /* vertex on patches generated in non-hexahedra */
  int flag_hexa, flag_tetra;
  Hash_vertex *vertex_hash_table;
  Tetra_point *tetra_point;
  Head_patch_tetra *head_patch_tetra;
  Tetra_point *p1, *p2;
  Patch_tetra *t1, *t2;
  Hash_vertex *h1, *h2;
  int minus_patch;
  double tmp_data[9];
  int tn_component, c_base;
  double tmp;

  sum_verts    = 0;
  num_nh_verts = 0;
  num_nh_patch = 0;
  sum_polys    = 0;

  n_elem       = mesh->n_elem;
  tn_component = 0;
  for (i = 0; i < data->nn_component; i++) tn_component += data->nn_dof[i];

  /*  prism = (Prism *)HECMW_malloc(sizeof(Prism));
   */
  if (mesh->elem_type[0] > 300) {
    flag_hexa  = 0;
    flag_tetra = 0;

    disamb_flag = 1;
    /*   fprintf(stderr, "sff inf: color=%d color_sub=%d con=%lf %lf %lf% lf\n",
sff->color_comp, sff->color_subcomp, sff->cont_equ[6],
sff->cont_equ[7], sff->cont_equ[8],sff->cont_equ[9]);

sprintf(test_file, "test_ucd.%d.%d.inp", time_step, mynode);
write_mesh_display(test_file, mesh, data);
HECMW_Barrier(VIS_COMM);
     */
    /*
for(i = 0; i < mesh->ne_internal; i++) {
    tmp_int=mesh->elem_internal_list[i]-1;
     */
    for (i = 0; i < mesh->n_elem; i++)
      if (mesh->elem_ID[i * 2 + 1] == mynode) {
        tmp_int = i;
        if ((mesh->elem_type[tmp_int] == 361) ||
            (mesh->elem_type[tmp_int] == 362) ||
            (mesh->elem_type[tmp_int] == 351) ||
            (mesh->elem_type[tmp_int] == 352)) {
          if (flag_hexa == 0) {
            flag_hexa = 1;

            CS_polys_head = (Polygon **)HECMW_malloc(sizeof(Polygon *));
            CS_verts_head = (Point **)HECMW_calloc(TABLE_SIZE, sizeof(Point *));
            sum_table     = TABLE_SIZE;
            CS_verts_tail = (Point **)HECMW_calloc(sum_table, sizeof(Point *));
            CS_verts_refer = (Point **)HECMW_calloc(sum_table, sizeof(Point *));
            for (j = 0; j < sum_table; j++) {
              if ((CS_verts_refer[j] = CS_verts_tail[j] = CS_verts_head[j] =
                       alloc_verts(VERTEX_PACK)) == NULL)
                HECMW_vis_memory_exit("verts for hexahedra");
            }

            CS_polys_tail = (Polygon **)HECMW_malloc(sizeof(Polygon *));
            if ((*CS_polys_tail = *CS_polys_head =
                     alloc_polygons(POLYGON_PACK)) == NULL)
              HECMW_vis_memory_exit("CS_polys_tail");

            alpha_cube.isosurf = (int **)HECMW_malloc(sizeof(int *));
            beta_cube.isosurf  = (int **)HECMW_malloc(sizeof(int *));
            cell               = (Cell *)HECMW_malloc(sizeof(Cell));
          }
          get_data(sff, mesh, data, tmp_int, cell, tn_component);
          if (sff->surface_style == 2) {
            alpha_index = make_tile(mesh, cell, sff->iso_value, 0, &alpha_cube,
                                    disamb_flag);
            beta_index = make_tile(mesh, cell, sff->iso_value, 1, &beta_cube,
                                   disamb_flag);
            if (alpha_index && beta_index) {
              if ((alpha_index + beta_index) == HEX_NODE_INDEX) {
                if (!merge_vol_iso(0, cell, sff->iso_value, &alpha_cube, 0,
                                   &beta_cube, bdflag[i], &sum_verts,
                                   CS_verts_tail, CS_verts_refer, CS_verts_head,
                                   CS_polys_tail)) {
                  return 0;
                }
              }
            }

          } else if (sff->surface_style == 3) {
            alpha_index = make_tile(mesh, cell, 0, 0, &alpha_cube, disamb_flag);
            beta_index  = make_tile(mesh, cell, 0, 1, &beta_cube, disamb_flag);
            if (alpha_index && beta_index) {
              if ((alpha_index + beta_index) == HEX_NODE_INDEX) {
                if (!merge_vol_iso(0, cell, 0, &alpha_cube, 0, &beta_cube,
                                   bdflag[i], &sum_verts, CS_verts_tail,
                                   CS_verts_refer, CS_verts_head,
                                   CS_polys_tail)) {
                  return 0;
                }
              }
            }
          }
        } else if ((mesh->elem_type[tmp_int] == 341) ||
                   (mesh->elem_type[tmp_int] == 342)) {
          /* tetrahedra */
          if (flag_tetra == 0) {
            flag_tetra = 1;
            /* initialize  */
            tetra             = (Tetra *)HECMW_malloc(sizeof(Tetra));
            vertex_hash_table = (Hash_vertex *)HECMW_calloc(
                mesh->n_node * 2, sizeof(Hash_vertex));
            tetra_point = (Tetra_point *)HECMW_malloc(sizeof(Tetra_point));
            head_patch_tetra =
                (Head_patch_tetra *)HECMW_malloc(sizeof(Head_patch_tetra));
            if ((vertex_hash_table == NULL) || (tetra == NULL) ||
                (tetra_point == NULL) || (head_patch_tetra == NULL))
              HECMW_vis_memory_exit("initialize tetra");
            for (j = 0; j < mesh->n_node * 2; j++) {
              vertex_hash_table[j].ident       = 0;
              vertex_hash_table[j].next_vertex = NULL;
            }
            tetra_point->ident          = 0;
            head_patch_tetra->num_patch = 0;
          }
          get_tetra_data(sff, mesh, data, tmp_int, tetra, tn_component);
          if (sff->surface_style == 3) sff->iso_value = 0.0;
          find_intersection_tetra(tetra, sff->iso_value, tetra_point,
                                  head_patch_tetra, vertex_hash_table);
        }
      }
    if (flag_tetra == 1) {
      num_nh_verts = tetra_point->ident;
      num_nh_patch = head_patch_tetra->num_patch;
      HECMW_free(tetra);
      for (j = 0; j < mesh->n_node * 2; j++) {
        h1 = vertex_hash_table[j].next_vertex;
        for (i = 0; i < vertex_hash_table[j].ident; i++) {
          h2 = h1->next_vertex;
          HECMW_free(h1);
          h1 = h2;
        }
      }
      HECMW_free(vertex_hash_table);
    }

    if (flag_hexa > 0) {
      mfree(alpha_cube.isosurf);
      mfree(beta_cube.isosurf);
      mfree(CS_verts_tail);
      mfree(CS_verts_refer);
      mfree(CS_polys_tail);

      *sum_v = sum_verts;
      *sum_t = sum_table;
      HECMW_free(cell);

      CS_polys = *CS_polys_head;

      sum_polys = 0;

      aplist_size = bplist_size = cplist_size = 1;
      while (CS_polys->plist != NULL) {
        switch (CS_polys->type) {
          case 0:
            aplist_size += CS_polys->plist[0] + 1;
            sum_polys++;
            break;
          case 1:
            bplist_size += CS_polys->plist[0] + 1;
            sum_polys++;
            break;
          case 2:
            cplist_size += (CS_polys->plist[0] - 2) * 4;
            sum_polys += CS_polys->plist[0] - 2;
            break;
        }
        CS_polys = CS_polys->nextpolygon;
      }
    }
    /*sum_polys=sum_polys*2;*/
    if ((sum_verts + num_nh_verts) > 0) {
      result[sf_i].n_vertex = sum_verts + num_nh_verts;
      result[sf_i].n_patch  = sum_polys + num_nh_patch;
      result[sf_i].vertex =
          (double *)HECMW_calloc(result[sf_i].n_vertex * 3, sizeof(double));
      result[sf_i].patch =
          (int *)HECMW_calloc(result[sf_i].n_patch * 3, sizeof(int));
      result[sf_i].color =
          (double *)HECMW_calloc(result[sf_i].n_vertex, sizeof(double));
      if ((result[sf_i].vertex == NULL) || (result[sf_i].patch == NULL) ||
          (result[sf_i].color == NULL))
        HECMW_vis_memory_exit("result");
    }
    mm = 0;
    if (sum_verts > 0) {
      /*  make main vertex table of CS  */
      for (i = 0; i < sum_table; i++) {
        CS_verts_tmp = CS_verts = CS_verts_head[i];
        j                       = 0;
        while (CS_verts->ident != 0) {
          /*      verts_geom[CS_verts->ident] = CS_verts->geom;
verts_field[CS_verts->ident] = CS_verts->field;
verts_color[CS_verts->ident] = CS_verts->cdata;

fprintf(vfile, " %d %lf %lf %lf\n",  *tvertex+CS_verts->ident,
verts_geom[CS_verts->ident].x,
verts_geom[CS_verts->ident].y,
verts_geom[CS_verts->ident].z);
           */
          result[sf_i].vertex[mm * 3]     = CS_verts->geom.x;
          result[sf_i].vertex[mm * 3 + 1] = CS_verts->geom.y;
          result[sf_i].vertex[mm * 3 + 2] = CS_verts->geom.z;
          result[sf_i].color[mm]          = CS_verts->cdata;
          mm++;
          CS_verts = CS_verts->nextpoint;
          if (!((++j) % VERTEX_PACK)) {
            mfree(CS_verts_tmp);
            CS_verts_tmp = CS_verts;
          }
        }
        mfree(CS_verts_tmp);
      }
      mfree(CS_verts_head);

      /*  make polygon table and decide vertex ID
of each object (alpha,beta,cross)  */
      /*  trilist=(Triangle *)HECMW_calloc(sum_polys+1,sizeof(Triangle));
       */
      CS_polys_tmp = CS_polys = *CS_polys_head;
      i                       = 0;
      poly_num                = 1;
      minus_patch             = 0;

      while (CS_polys->plist != NULL) {
        switch (CS_polys->type) {
          case 0:
            /*	      fprintf(pfile, "%d ", poly_num+(*tpatch));
             */
            k = -1;
            for (j = 1; j <= CS_polys->plist[0]; j++) {
              k++;
              /*		fprintf(pfile, "%d ",
(*tvertex)+CS_polys->plist[j]);

trilist[poly_num -1].vertex[k]=CS_polys->plist[j];
               */
              if ((sff->output_type == 1) || (sff->output_type == 2))
                result[sf_i].patch[(poly_num - 1) * 3 + k] =
                    *tvertex + CS_polys->plist[j];
              else
                result[sf_i].patch[(poly_num - 1) * 3 + k] = CS_polys->plist[j];

              tmp_data[k * 3] =
                  result[sf_i].vertex[(CS_polys->plist[j] - 1) * 3];
              tmp_data[k * 3 + 1] =
                  result[sf_i].vertex[(CS_polys->plist[j] - 1) * 3 + 1];
              tmp_data[k * 3 + 2] =
                  result[sf_i].vertex[(CS_polys->plist[j] - 1) * 3 + 2];
            }
            if (((fabs(tmp_data[0] - tmp_data[3]) < EPSILON) &&
                 (fabs(tmp_data[1] - tmp_data[4]) < EPSILON) &&
                 (fabs(tmp_data[2] - tmp_data[5]) < EPSILON)) ||
                ((fabs(tmp_data[0] - tmp_data[6]) < EPSILON) &&
                 (fabs(tmp_data[1] - tmp_data[7]) < EPSILON) &&
                 (fabs(tmp_data[2] - tmp_data[8]) < EPSILON)) ||
                ((fabs(tmp_data[6] - tmp_data[3]) < EPSILON) &&
                 (fabs(tmp_data[7] - tmp_data[4]) < EPSILON) &&
                 (fabs(tmp_data[8] - tmp_data[5]) < EPSILON)))
              minus_patch++;
            else
              poly_num++;

            break;
        }

        CS_polys = CS_polys->nextpolygon;
        if (!((++i) % POLYGON_PACK)) {
          mfree(CS_polys_tmp->plist);

          mfree(CS_polys_tmp);
          CS_polys_tmp = CS_polys;
        }
      }
      /*#ifdef DEBUG
fprintf(stderr, "the previous patch num is %d now is %d\n",
result[sf_i].n_patch, result[sf_i].n_patch-minus_patch);
#endif
       */
      result[sf_i].n_patch -= minus_patch;

      mfree(CS_polys_tmp);
    }
    if (num_nh_verts > 0) {
      p1 = tetra_point->nextpoint;
      for (i = 0; i < tetra_point->ident; i++) {
        for (j                                                 = 0; j < 3; j++)
          result[sf_i].vertex[(sum_verts + p1->ident) * 3 + j] = p1->geom[j];
        result[sf_i].color[sum_verts + p1->ident]              = p1->cdata;
        p2                                                     = p1;
        p1                                                     = p1->nextpoint;
        HECMW_free(p2);
      }
      HECMW_free(tetra_point);
    }
    if (num_nh_patch > 0) {
      t1 = head_patch_tetra->patch_link;
      for (i = 0; i < head_patch_tetra->num_patch; i++) {
        for (j = 0; j < 3; j++) {
          if (sff->output_type == 3)
            result[sf_i].patch[(sum_polys - minus_patch + i) * 3 + j] =
                t1->patch[j] + 1 + sum_verts;
          else
            result[sf_i].patch[(sum_polys - minus_patch + i) * 3 + j] =
                *tvertex + t1->patch[j] + 1 + sum_verts;
        }
        t2 = t1;
        t1 = t1->next_patch;
        HECMW_free(t2);
      }
      HECMW_free(head_patch_tetra);
    }

    /*
fprintf(stderr, "On surface %d PE %d: n_vertex is %d  n_patch is %d\n", sf_i,
mynode, result[sf_i].n_vertex, result[sf_i].n_patch);
     */
    if (result[sf_i].n_vertex > 0) {
      *minc = *maxc = result[sf_i].color[0];
      for (i = 1; i <= result[sf_i].n_vertex; i++) {
        if (result[sf_i].color[i - 1] < (*minc))
          (*minc) = result[sf_i].color[i - 1];
        if (result[sf_i].color[i - 1] > (*maxc))
          (*maxc) = result[sf_i].color[i - 1];
      }
      /*
#ifdef DEBUG
fprintf(stderr,"On surface %d PE %d: minimum color=%lf maximum color=%lf\n",
sf_i, mynode, *minc,*maxc);
#endif
       */
    }
  } /* endof if elem_type>300 */
  else if ((mesh->elem_type[0] > 200) && (mesh->elem_type[0] < 300)) {
    result[sf_i].n_patch = 0;
    for (i = 0; i < n_elem; i++) {
      if (mesh->elem_type[i] == 231)
        result[sf_i].n_patch++;
      else if (mesh->elem_type[i] == 241)
        result[sf_i].n_patch += 2;
    }
    result[sf_i].n_vertex = mesh->n_node;
    result[sf_i].vertex =
        (double *)HECMW_calloc(mesh->n_node * 3, sizeof(double));
    result[sf_i].color = (double *)HECMW_calloc(mesh->n_node, sizeof(double));
    result[sf_i].patch =
        (int *)HECMW_calloc(result[sf_i].n_patch * 3, sizeof(int));
    if ((result[sf_i].vertex == NULL) || (result[sf_i].color == NULL) ||
        (result[sf_i].patch == NULL))
      HECMW_vis_memory_exit("result: vertex, color and patch");
    for (i = 0; i < mesh->n_node; i++) {
      for (j                           = 0; j < 3; j++)
        result[sf_i].vertex[i * 3 + j] = mesh->node[i * 3 + j];
    }
    if (data->nn_dof[sff->color_comp] == 1) {
      c_base = 0;
      for (i = 0; i < sff->color_comp; i++) c_base += data->nn_dof[i];
    } else if (data->nn_dof[sff->color_comp] > 1) {
      c_base = 0;
      for (i = 0; i < sff->color_comp; i++) c_base += data->nn_dof[i];
    }

    if ((data->nn_dof[sff->color_comp] > 1) && (sff->color_subcomp == 0)) {
      for (i = 0; i < mesh->n_node; i++) {
        result[sf_i].color[i] = 0.0;
        for (j = 0; j < data->nn_dof[sff->color_comp]; j++) {
          tmp = data->node_val_item[c_base + i * tn_component + j];
          result[sf_i].color[i] += tmp * tmp;
        }
        result[sf_i].color[i] = sqrt(result[sf_i].color[i]);
      }
    }

    else if (data->nn_dof[sff->color_comp] > 1) {
      for (i = 0; i < mesh->n_node; i++) {
        result[sf_i].color[i] = data->node_val_item[c_base + i * tn_component +
                                                    (sff->color_subcomp - 1)];
      }
    } else if (data->nn_dof[sff->color_comp] == 1) {
      for (i = 0; i < mesh->n_node; i++) {
        result[sf_i].color[i] = data->node_val_item[c_base + i * tn_component];
      }
    }
    poly_num = 0;
    for (i = 0; i < n_elem; i++) {
      if (mesh->elem_type[i] == 231) {
        for (j = 0; j < 3; j++)
          result->patch[poly_num * 3 + j] =
              mesh->elem_node_item[mesh->elem_node_index[i] + j] + *tvertex;
        poly_num++;
      } else if (mesh->elem_type[i] == 241) {
        for (j = 0; j < 3; j++)
          result->patch[poly_num * 3 + j] =
              mesh->elem_node_item[mesh->elem_node_index[i] + j] + *tvertex;
        poly_num++;
        result->patch[poly_num * 3 + 0] =
            mesh->elem_node_item[mesh->elem_node_index[i] + 0] + *tvertex;
        result->patch[poly_num * 3 + 1] =
            mesh->elem_node_item[mesh->elem_node_index[i] + 2] + *tvertex;
        result->patch[poly_num * 3 + 2] =
            mesh->elem_node_item[mesh->elem_node_index[i] + 3] + *tvertex;
        poly_num++;
      }
    }
    /*
fprintf(stderr, "n_vertex is %d  n_patch is %d\n", result[sf_i].n_vertex,
result[sf_i].n_patch);
     */
    if (result[sf_i].n_vertex > 0) {
      *minc = *maxc = result[sf_i].color[0];
      for (i = 1; i <= result[sf_i].n_vertex; i++) {
        if (result[sf_i].color[i - 1] < (*minc))
          (*minc) = result[sf_i].color[i - 1];
        if (result[sf_i].color[i - 1] > (*maxc))
          (*maxc) = result[sf_i].color[i - 1];
      }
      /*
#ifdef DEBUG
fprintf(stderr,"On surface %d PE %d: minimum color=%lf maximum color=%lf\n",
sf_i, mynode, *minc,*maxc);
#endif
       */
    }
  }

  (*tvertex) += result[sf_i].n_vertex;
  (*tpatch) += result[sf_i].n_patch;
  /*  if(sum_verts>0) {
   *minv=mincolor;
   *maxv=maxcolor;
}

mfree(verts_info);
mfree(verts_geom);
mfree(verts_field);
mfree(verts_color);
mfree(trilist);
   */

  return (1);
}
Exemple #17
0
int peer_kill(struct peer *p)
{
    if(!p)
        return 0;
    if(__sync_bool_compare_and_swap(&p->status,PEER_CONNECTED,PEER_DISCONNECTED))
    {
		close(p->sd);
		fdev_del(&p->ioev);
        log_error(p->ns->log,"ns peer socket closed,peer ip:%s.", inet_ntoa(p->addr.sin_addr));
		//push one msg to notify disconnect
        if(!p->ns->close_func)
        {
            struct msg_t *msg = (struct msg_t *)mmalloc(p->ns->allocator,
                    sizeof(struct msg_t));
            msg->buf = NULL;
            msg->len = 0;
            msg->peer_id = p->id;
            msg->type = MSG_DISCONNECT;

            queue_push(p->ns->recv_queue,msg);
            log_error(p->ns->log,"ns push notify msg for client:%s disconneced.", inet_ntoa(p->addr.sin_addr));
        }
        else
        {
            log_error(p->ns->log,"ns call close_func for client:%s disconneced.", inet_ntoa(p->addr.sin_addr));
            p->ns->close_func(p->ns,p->id);
        }
	}

	if(__sync_bool_compare_and_swap(&p->refcount,0,1))
	{
        log_error(p->ns->log,"ns peer freed,peer ip:%s.", inet_ntoa(p->addr.sin_addr));
		iobuf_free(p->allocator,&p->recvbuf);
		iobuf_free(p->allocator,&p->sendbuf);
		//free send queue
		struct msg_t *msg = NULL,*next = NULL;
		thread_mutex_lock(p->sq_mutex);
		msg = BTPDQ_FIRST(&p->send_queue);
		while(msg){
			next = BTPDQ_NEXT(msg,msg_entry);
			BTPDQ_REMOVE(&p->send_queue,msg,msg_entry);

			mfree(p->allocator,msg->buf);
			mfree(p->allocator,msg);
			msg = next;
		}
		thread_mutex_unlock(p->sq_mutex);

		thread_mutex_destroy(p->mpool_mutex);
		thread_mutex_destroy(p->sq_mutex);

		allocator_destroy(p->allocator);

		mfree(p->ns->allocator,p);

		thread_mutex_lock(p->ns->ptbl_mutex);
		ptbl_remove(p->ns->ptbl,&p->id);
		p->ns->npeers--;
		thread_mutex_unlock(p->ns->ptbl_mutex);
	}
	return 0;
}
void handleRequest ( UdpSlot *slot , int32_t netnice ) {
	char *p = slot->m_readBuf;

	int32_t numBytes = *(int32_t*)p;
	p += sizeof(int32_t);


	char *filename = g_hostdb.m_logFilename;

	// running just ./gb will log to stderr...
	if ( strcmp(filename ,"/dev/stderr") == 0 ) {
		g_errno = EBADFILE;
		log(LOG_ERROR,"%s:%s:%d: call sendErrorReply.", __FILE__, __func__, __LINE__);
		g_udpServer.sendErrorReply ( slot, g_errno ); 
		return;
	}

	int32_t fd = open ( filename , O_RDONLY ,
			    getFileCreationFlags() );
			 // S_IRUSR |S_IWUSR |S_IRGRP |S_IWGRP| S_IROTH );
	if ( ! fd ) {
		log(LOG_DEBUG, "logviewer: Failed to open %s for reading: ",
		    filename);
		g_errno = EBADFILE;
		log(LOG_ERROR,"%s:%s:%d: call sendErrorReply.", __FILE__, __func__, __LINE__);
		g_udpServer.sendErrorReply ( slot, g_errno ); 
		return;
	}

	char stackSpace[LOG_WINDOW];
	char *buf = stackSpace;
	char *allocBuf = NULL;
	int32_t allocBufSize = 0;

	if(numBytes > LOG_WINDOW) {
		buf = (char*)mmalloc(numBytes, "Msg1fA");
		if(!buf) {
			log(LOG_INFO, 
			    "admin: malloc of %" PRId32" bytes failed "
			    "for logview,"
			    " falling back on stack buffer.",
			    numBytes);
			buf = stackSpace;
			numBytes = LOG_WINDOW;
		}
		else {
			allocBuf     = buf;
			allocBufSize = numBytes;
		}
	}

	lseek(fd, -1 * numBytes, SEEK_END);
	if(errno == EINVAL) {
		//oops! we seeked to before the begining of the file
		//log(LOG_WARN, "bad seek!");
		lseek(fd, 0, SEEK_SET);
	}

	int32_t numRead = read(fd, buf, numBytes-1);
	close(fd);
	if(numRead > 0)	buf[numRead-1] = '\0';
	else          {  
		buf[0] = '\0'; 
		numRead = 0;
		if(allocBuf) mfree(allocBuf,	allocBufSize, "Msg1fA");
		allocBufSize = 0;
		allocBuf = NULL;
		log(LOG_ERROR,"%s:%s:%d: call sendErrorReply.", __FILE__, __func__, __LINE__);
		g_udpServer.sendErrorReply ( slot, EBADFILE ); 
		return;
	}
	//log(LOG_DEBUG, "bytes read! %" PRId32" ", numRead);

	g_udpServer.sendReply_ass (buf, numRead, allocBuf,allocBufSize, slot); //send
}
/* Parse a single logical line */
static int parse_line(
                const char* unit,
                const char *filename,
                unsigned line,
                const char *sections,
                ConfigItemLookup lookup,
                const void *table,
                ConfigParseFlags flags,
                char **section,
                unsigned *section_line,
                bool *section_ignored,
                char *l,
                void *userdata) {

        char *e, *include;

        assert(filename);
        assert(line > 0);
        assert(lookup);
        assert(l);

        l = strstrip(l);
        if (!*l)
                return 0;

        if (strchr(COMMENTS "\n", *l))
                return 0;

        include = first_word(l, ".include");
        if (include) {
                _cleanup_free_ char *fn = NULL;

                /* .includes are a bad idea, we only support them here
                 * for historical reasons. They create cyclic include
                 * problems and make it difficult to detect
                 * configuration file changes with an easy
                 * stat(). Better approaches, such as .d/ drop-in
                 * snippets exist.
                 *
                 * Support for them should be eventually removed. */

                if (!(flags & CONFIG_PARSE_ALLOW_INCLUDE)) {
                        log_syntax(unit, LOG_ERR, filename, line, 0, ".include not allowed here. Ignoring.");
                        return 0;
                }

                log_syntax(unit, LOG_WARNING, filename, line, 0,
                           ".include directives are deprecated, and support for them will be removed in a future version of systemd. "
                           "Please use drop-in files instead.");

                fn = file_in_same_dir(filename, strstrip(include));
                if (!fn)
                        return -ENOMEM;

                return config_parse(unit, fn, NULL, sections, lookup, table, flags, userdata);
        }

        if (!utf8_is_valid(l))
                return log_syntax_invalid_utf8(unit, LOG_WARNING, filename, line, l);

        if (*l == '[') {
                size_t k;
                char *n;

                k = strlen(l);
                assert(k > 0);

                if (l[k-1] != ']') {
                        log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid section header '%s'", l);
                        return -EBADMSG;
                }

                n = strndup(l+1, k-2);
                if (!n)
                        return -ENOMEM;

                if (sections && !nulstr_contains(sections, n)) {

                        if (!(flags & CONFIG_PARSE_RELAXED) && !startswith(n, "X-"))
                                log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown section '%s'. Ignoring.", n);

                        free(n);
                        *section = mfree(*section);
                        *section_line = 0;
                        *section_ignored = true;
                } else {
                        free_and_replace(*section, n);
                        *section_line = line;
                        *section_ignored = false;
                }

                return 0;
        }

        if (sections && !*section) {

                if (!(flags & CONFIG_PARSE_RELAXED) && !*section_ignored)
                        log_syntax(unit, LOG_WARNING, filename, line, 0, "Assignment outside of section. Ignoring.");

                return 0;
        }

        e = strchr(l, '=');
        if (!e) {
                log_syntax(unit, LOG_WARNING, filename, line, 0, "Missing '='.");
                return -EINVAL;
        }

        *e = 0;
        e++;

        return next_assignment(unit,
                               filename,
                               line,
                               lookup,
                               table,
                               *section,
                               *section_line,
                               strstrip(l),
                               strstrip(e),
                               flags,
                               userdata);
}
Exemple #20
0
static void context_free_x11(Context *c) {
        c->x11_layout = mfree(c->x11_layout);
        c->x11_options = mfree(c->x11_options);
        c->x11_model = mfree(c->x11_model);
        c->x11_variant = mfree(c->x11_variant);
}
Exemple #21
0
static void ntp_status_info_clear(NTPStatusInfo *p) {
        p->server_address = mfree(p->server_address);
}
Exemple #22
0
static void context_free_vconsole(Context *c) {
        c->vc_keymap = mfree(c->vc_keymap);
        c->vc_keymap_toggle = mfree(c->vc_keymap_toggle);
}
void MemPool::reset ( ) {
	if ( m_mem ) mfree ( m_mem , m_memSize , "MemPool" );
	m_mem     = NULL;
	m_memSize = 0;
}
Exemple #24
0
static void context_free_locale(Context *c) {
        int p;

        for (p = 0; p < _VARIABLE_LC_MAX; p++)
                c->locale[p] = mfree(c->locale[p]);
}
Exemple #25
0
static void read_stream_control (MelodyLine *ml) {
    MelodyEvent *me = mmalloc (sizeof(MelodyEvent));
    StreamControl *sc = &me->u.s;      /* for ease of access */
    int c;
    char *p, *str = NULL;

    me->type = EV_STREAM;
    me->line = line_no;
    me->col = col_no;
    sc->text = NULL;

    switch (c = nd_gc()) {
      case 'Z':	
	gc();
	sc->type = SC_ZERONOTE;
	break;
      case '[':
	gc();
	sc->type = SC_BEAMSTART;
	break;
      case ']':
	gc();
	sc->type = SC_BEAMSTOP;
	if (nd_gc() == '-') {
	    gc();
	    if (nd_gc() != '[') {
		error (me->line, me->col, "syntax error in melody line:"
		       " expected `[' after `]-'");
		return;
	    }
	    sc->type = SC_BEAMBREAK;
	    gc();
	}
	break;
      case '/':
	gc();
	sc->type = SC_SLURSTART;
	break;
      case '\\':
	gc();
	sc->type = SC_SLURSTOP;
	break;
      case '(':
	gc();
	sc->type = SC_NTUPLET;
	sc->ntuplet_denom = 0;
	while ( (c=gc()) >= '0' && c <= '9')
	    sc->ntuplet_denom = (10*sc->ntuplet_denom) + c-'0';
	if (c != '/') {
	    error (me->line, me->col,
		   "expected `/' after numerator of n-tuplet");
	    return;
	}
	sc->ntuplet_num = 0;
	while ( (c=gc()) >= '0' && c <= '9')
	    sc->ntuplet_num = (10*sc->ntuplet_num) + c-'0';
	if (c != ':') {
	    error (me->line, me->col,
		   "expected `:' after denominator of n-tuplet");
	    return;
	}
	wrk.factor = lcm (wrk.factor, sc->ntuplet_denom);
	break;
      case ')':
	gc();
	sc->type = SC_NTUPLET_END;
	break;
      case '<':
	gc();
	/* Could be <p>, <d>, <8va>, <8vb>, <,>, </>, <~> */
	switch (c = gc()) {
	  case 'P':
	    sc->type = SC_FORCE_DOWN;
	    break;
	  case 'D':
	    sc->type = SC_FORCE_UP;
	    break;
	  case '8':
	    if (gc() != 'V') {
		error (me->line, me->col, "syntax error in melody line:"
		       " expected `v' after `<8'");
		return;
	    }
	    c = gc();
	    if (c == 'A')
		sc->type = SC_8VA;
	    else if (c == 'B')
		sc->type = SC_8VB;
	    else {
		error (me->line, me->col, "syntax error in melody line:"
		       " expected `a' or `b' after `<8v'");
		return;
	    }
	    break;
	  case ',':
	    sc->type = SC_BREATH;
	    break;
	  case '/':
	    sc->type = SC_GENPAUSE;
	    break;
	  case 'U':
	    if (nd_gc() == '!') {
		sc->type = SC_INVTURN;
		gc();
	    } else
		sc->type = SC_TURN;
	    break;
	  default:
	    error (me->line, me->col, "syntax error in melody line:"
		   " expected `p', `d', `8', `,', `/' or `u' after `<'");
	    return;
	}
	if (gc() != '>') {
	    error (me->line, me->col, "syntax error in melody line:"
		   " expected `>' to end `<...>' control");
	    return;
	}
	break;
      case '"':
	/* It's some kind of quoted string; get it into memory first. */
	getword (&str);
	/* Check if the string is actually empty. */
	if (!str[0] || !str[1] || str[1] == '"') {
	    error (me->line, me->col, "quoted string is empty");
	    return;
	}
	/* Check the second character, because it's general. */
	if (str[1] != '<' && str[1] != '>' && str[2] != ' ') {
	    error (me->line, me->col,
		   "expected space in quoted string after `%c'", str[1]);
	    return;
	}
	/* Remove the trailing quote. */
	str[strlen(str)-1] = '\0';
	/* Could be dynamics, lyrics, above or below text, cresc or dim. */
	switch (str[1]) {
	  case '<': case '>':
	    /* cresc or dim */
	    if (str[2]) {
		error (me->line, me->col,
		       "unexpected text after `%c' in quoted string", str[0]);
		return;
	    }
	    sc->type = (str[1] == '<' ? SC_CRESC : SC_DIM);
	    break;
	  case 'D': case 'd':
	    /* dynamics */
	    p = str+3;
	    while (*p && !isspace(*p)) {
		static const char *const dynamic_str = "fmpsz";
		char *q = strchr(dynamic_str, *p);
		if (!q) {
		    error (me->line, me->col,
			   "character `%c' not a valid dynamic", *p);
		    return;
		}
		*p++ = q - dynamic_str + '\xD1';
	    }
	    sc->type = SC_DYNAMIC;
	    sc->text = dupstr (str+3);
	    break;
	  case 'L': case 'l': case 'A': case 'a': case 'B': case 'b':
	    sc->text = dupstr (str+3);
	    sc->type = (str[1]=='L' || str[1]=='l' ? SC_LYRICS :
			str[1]=='A' || str[1]=='a' ? SC_TEXT_ABOVE :
			str[1]=='B' || str[1]=='b' ? SC_TEXT_BELOW : -1);
	    break;
	}
	break;
      default:			       /* should never happen */
	gc();
	fatal(me->line, me->col, "internal fault: reached `default'"
	      " clause in `read_stream_control': char %d", c);
	break;			       /* *certainly* shouldn't reach this! */
    }
    add_event (ml, me);
    mfree (str);
}
Exemple #26
0
/* Go through the file and parse each line */
int config_parse(const char *unit,
                 const char *filename,
                 FILE *f,
                 const char *sections,
                 ConfigItemLookup lookup,
                 const void *table,
                 bool relaxed,
                 bool allow_include,
                 bool warn,
                 void *userdata) {

        _cleanup_free_ char *section = NULL, *continuation = NULL;
        _cleanup_fclose_ FILE *ours = NULL;
        unsigned line = 0, section_line = 0;
        bool section_ignored = false, allow_bom = true;
        int r;

        assert(filename);
        assert(lookup);

        if (!f) {
                f = ours = fopen(filename, "re");
                if (!f) {
                        /* Only log on request, except for ENOENT,
                         * since we return 0 to the caller. */
                        if (warn || errno == ENOENT)
                                log_full(errno == ENOENT ? LOG_DEBUG : LOG_ERR,
                                         "Failed to open configuration file '%s': %m", filename);
                        return errno == ENOENT ? 0 : -errno;
                }
        }

        fd_warn_permissions(filename, fileno(f));

        for (;;) {
                char buf[LINE_MAX], *l, *p, *c = NULL, *e;
                bool escaped = false;

                if (!fgets(buf, sizeof buf, f)) {
                        if (feof(f))
                                break;

                        return log_error_errno(errno, "Failed to read configuration file '%s': %m", filename);
                }

                l = buf;
                if (allow_bom && startswith(l, UTF8_BYTE_ORDER_MARK))
                        l += strlen(UTF8_BYTE_ORDER_MARK);
                allow_bom = false;

                truncate_nl(l);

                if (continuation) {
                        c = strappend(continuation, l);
                        if (!c) {
                                if (warn)
                                        log_oom();
                                return -ENOMEM;
                        }

                        continuation = mfree(continuation);
                        p = c;
                } else
                        p = l;

                for (e = p; *e; e++) {
                        if (escaped)
                                escaped = false;
                        else if (*e == '\\')
                                escaped = true;
                }

                if (escaped) {
                        *(e-1) = ' ';

                        if (c)
                                continuation = c;
                        else {
                                continuation = strdup(l);
                                if (!continuation) {
                                        if (warn)
                                                log_oom();
                                        return -ENOMEM;
                                }
                        }

                        continue;
                }

                r = parse_line(unit,
                               filename,
                               ++line,
                               sections,
                               lookup,
                               table,
                               relaxed,
                               allow_include,
                               &section,
                               &section_line,
                               &section_ignored,
                               p,
                               userdata);
                free(c);

                if (r < 0) {
                        if (warn)
                                log_warning_errno(r, "Failed to parse file '%s': %m",
                                                  filename);
                        return r;
                }
        }

        return 0;
}
Exemple #27
0
static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) {
        Context *c = userdata;
        const char *name;
        int interactive;
        int r;

        assert(m);
        assert(c);

        r = sd_bus_message_read(m, "sb", &name, &interactive);
        if (r < 0)
                return r;

        if (isempty(name))
                name = NULL;

        if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME]))
                return sd_bus_reply_method_return(m, NULL);

        r = bus_verify_polkit_async(
                        m,
                        CAP_SYS_ADMIN,
                        "org.freedesktop.hostname1.set-static-hostname",
                        NULL,
                        interactive,
                        UID_INVALID,
                        &c->polkit_registry,
                        error);
        if (r < 0)
                return r;
        if (r == 0)
                return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */

        if (isempty(name)) {
                c->data[PROP_STATIC_HOSTNAME] = mfree(c->data[PROP_STATIC_HOSTNAME]);
        } else {
                char *h;

                if (!hostname_is_valid(name, false))
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);

                h = strdup(name);
                if (!h)
                        return -ENOMEM;

                free(c->data[PROP_STATIC_HOSTNAME]);
                c->data[PROP_STATIC_HOSTNAME] = h;
        }

        r = context_update_kernel_hostname(c);
        if (r < 0) {
                log_error_errno(r, "Failed to set host name: %m");
                return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %s", strerror(-r));
        }

        r = context_write_data_static_hostname(c);
        if (r < 0) {
                log_error_errno(r, "Failed to write static host name: %m");
                return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %s", strerror(-r));
        }

        log_info("Changed static host name to '%s'", strna(c->data[PROP_STATIC_HOSTNAME]));

        (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "StaticHostname", NULL);

        return sd_bus_reply_method_return(m, NULL);
}
Exemple #28
0
/* free_sres frees parameters required by libSRES and calls libSRES's deinitialization function
	parameters:
		sp: parameters required by libSRES
	returns: nothing
	notes:
	todo:
*/
void free_sres (sres_params& sp) {
	mfree(sp.trsfm);
	mfree(sp.lb);
	mfree(sp.ub);
	ESDeInitial(sp.param, sp.population, sp.stats);
}
void Pos::reset() {
    if ( m_buf && m_needsFree )
        mfree ( m_buf , m_bufSize , "Pos" );
    m_buf = NULL;
}
// print out the mem table
// but combine allocs with the same label
// sort by mem allocated
bool Mem::printMemBreakdownTable ( SafeBuf* sb, 
				   char *lightblue, 
				   char *darkblue) {
	char *ss = "";

	sb->safePrintf (
		       "<table>"

		       "<table %s>"
		       "<tr>"
		       "<td colspan=3 bgcolor=#%s>"
		       "<center><b>Mem Breakdown%s</b></td></tr>\n"

		       "<tr bgcolor=#%s>"
		       "<td><b>allocator</b></td>"
		       "<td><b>num allocs</b></td>"
		       "<td><b>allocated</b></td>"
		       "</tr>" ,
		       TABLE_STYLE, darkblue , ss , darkblue );

	int32_t n = m_numAllocated * 2;
	MemEntry *e = (MemEntry *)mcalloc ( sizeof(MemEntry) * n , "Mem" );
	if ( ! e ) {
		log("admin: Could not alloc %" PRId32" bytes for mem table.",
		    (int32_t)sizeof(MemEntry)*n);
		return false;
	}

	// hash em up, combine allocs of like label together for this hash
	for ( int32_t i = 0 ; i < (int32_t)m_memtablesize ; i++ ) {
		// skip empty buckets
		if ( ! s_mptrs[i] ) continue;
		// get label ptr, use as a hash
		char *label = &s_labels[i*16];
		int32_t  h     = hash32n ( label );
		if ( h == 0 ) h = 1;
		// accumulate the size
		int32_t b = (uint32_t)h % n;
		// . chain till we find it or hit empty
		// . use the label as an indicator if bucket is full or empty
		while ( e[b].m_hash && e[b].m_hash != h )
			if ( ++b >= n ) b = 0;
		// add it in
		e[b].m_hash       = h;
		e[b].m_label      = label;
		e[b].m_allocated += s_sizes[i];
		e[b].m_numAllocs++;
	}

	// get the top 20 users of mem
	MemEntry *winners [ PRINT_TOP ];

	int32_t i = 0;
	int32_t count = 0;
	for ( ; i < n && count < PRINT_TOP ; i++ )
		// if non-empty, add to winners array
		if ( e[i].m_hash ) winners [ count++ ] = &e[i];

	// compute new min
	int32_t min  = 0x7fffffff;
	int32_t mini = -1000;
	for ( int32_t j = 0 ; j < count ; j++ ) {
		if ( winners[j]->m_allocated > min ) continue;
		min  = winners[j]->m_allocated;
		mini = j;
	}

	// now the rest must compete
	for ( ; i < n ; i++ ) {
		// if empty skip
		if ( ! e[i].m_hash ) continue;
		//if ( e[i].m_allocated > 120 && e[i].m_allocated < 2760 )
		//	log("hey %" PRId32, e[i].m_allocated);
		// skip if not a winner
		if ( e[i].m_allocated <= min ) continue;
		// replace the lowest winner
		winners[mini] = &e[i];
		// compute new min
		min = 0x7fffffff;
		for ( int32_t j = 0 ; j < count ; j++ ) {
			if ( winners[j]->m_allocated > min ) continue;
			min  = winners[j]->m_allocated;
			mini = j;
		}
	}

	// now sort them
	bool flag = true;
	while ( flag ) {
		flag = false;
		for ( int32_t i = 1 ; i < count ; i++ ) {
			// no need to swap?
			if ( winners[i-1]->m_allocated >= 
			     winners[i]->m_allocated ) continue;
			// swap
			flag = true;
			MemEntry *tmp = winners[i-1];
			winners[i-1]  = winners[i];
			winners[i  ]  = tmp;
		}
	}
			
	// now print into buffer
	for ( int32_t i = 0 ; i < count ; i++ ) 
		sb->safePrintf (
			       "<tr bgcolor=%s>"
			       "<td>%s</td>"
			       "<td>%" PRId32"</td>"
			       "<td>%" PRId32"</td>"
			       "</tr>\n",
			       LIGHT_BLUE,
			       winners[i]->m_label,
			       winners[i]->m_numAllocs,
			       winners[i]->m_allocated);

	sb->safePrintf ( "</table>\n");

	// don't forget to release this mem
	mfree ( e , (int32_t)sizeof(MemEntry) * n , "Mem" );

	return true;
}