Exemple #1
0
CAMLprim value caseIgnoreCompare(value v1, value v2)
{
    /* based on byterun/compare.c */
    long res = 0;
    mlsize_t len1, len2, len;
    unsigned char * p1, * p2;

    if (v1 != v2) { /* if they don't point to the same thing */
        len1 = caml_string_length(v1);
        len2 = caml_string_length(v2);
        if (len1 != len2) res = len1 - len2;
        else { /* if the length is the same for both */
            for (len = len1,
                     p1 = (unsigned char *) String_val(v1),
                     p2 = (unsigned char *) String_val(v2);
                 len > 0;
                 len--, p1++, p2++)
                if (*p1 != *p2)
                    if (to_lowercase (*p1) != to_lowercase(*p2)) {
                        res = (long)*p1 - (long)*p2;
                        break;
                    }
        }
    }

    if (res < 0)
        return Val_int(LESS);
    else if (res > 0)
        return Val_int(GREATER);
    else
        return Val_int(EQUAL);
}
Exemple #2
0
void FontManager::readFontMap(std::string path) {
	clearFonts();
	if (path.length()==0)
		path=path_font_cfg;
	auto doc = resourceHandler->xml.getResource(path_font_cfg);
	auto cfg = doc->doc->first_node();
	assert(!strcmp(to_lowercase(cfg->name()).c_str(),"fontset"));
	auto children = xop.getChildren(cfg);
	for (auto iter : children) {
		if (!strcmp(to_lowercase(iter->name()).c_str(),"font")){
			auto attributes = xop.getAttributes(iter);
			fkey key;
			fpath path;
			for (auto attr : attributes) {
				std::string field = to_lowercase(attr->name()).c_str();
				std::string val = attr->value();
				if (streq(field,"use")) {
					key = std::string(val);
					continue;
				}
				if (streq(field, "path")) {
					path = std::string(val);
					continue;
				}
			}
			setFontPath(key,path);
		}
	}
}
Exemple #3
0
bool ShibINIPriv::exists(const std::string& header, const std::string& tag)
{
  string h = header;
  string t = tag;

  if (!cs) {
    to_lowercase (h);
    to_lowercase (t);
  }

  if (!exists(h)) return false;
  return (table[h].find(t) != table[h].end());
}
Exemple #4
0
errcode_t setup_tree(root_t **roots, const char *word)
{
	root_t *root;
	node_t *p;
	int len, i, idx;
	char c;

	len = strlen(word);

	assert(roots && word && len > 0);

	if ((c = to_lowercase(word[0])) < 0) {
		return 0;
	}

	idx = c - 'a';
	root = roots[idx];

	for (i = 1, p = root->n; i < len; i++) {
		/* Illegal word, skip it, resulting in leaf node's cnt == 0 */
		if ((c = to_lowercase(word[i])) < 0) {
			return 0;
		}

		idx = c - 'a';

		if (p->children[idx] != NULL) {
			p = p->children[idx];
			continue;
		}

		pthread_mutex_lock(&root->mutex);
		if (!p->children[idx]) {
			if (!(p->children[idx] = create_node(c))) {
				pthread_mutex_unlock(&root->mutex);
				return ERR_NO_MEM;
			}
		}
		pthread_mutex_unlock(&root->mutex);

		p = p->children[idx];
	}

	/* update counter on the leaf node */
	pthread_mutex_lock(&root->mutex);
	p->cnt++;
	pthread_mutex_unlock(&root->mutex);

	return 0;
}
Exemple #5
0
// process submitted tip
void api::tips_process() {
	// only allow post
	if(request().request_method() != "POST") {
		json::send("DX-REJECTED", "http POST is only method allowed on this page", response().out());
		return;
	}
	// ensure logged in
	if(!Pages::logged_in(session())) {
		json::send("DX-REJECTED", "Must be logged in to submit a tip", response().out());
		return;
	}
	// ensure tip field not empty
	std::string tip = db->conn.esc(to_lowercase(request().post("tip")));

	if(tip == "") {
		json::send("DX-REJECTED", "Cannot submit empty tip", response().out());
		return;
	}

	// submit tip
	mail::tip(tip);

	json::send("DX-OK", "Tip submitted", response().out());
	return;
}
Exemple #6
0
void api::settings_unblock() {
	session().load();
	// only allow POST
	if(request().request_method() != "POST") {
		json::send("DX-REJECTED", "http POST is only method allowed on this page", response().out());
		return;
	}

	// ensure logged in
	if(!Pages::logged_in(session())) {
		json::send("DX-REJECTED", "Must be logged in!", response().out());
	}
	
	std::string username = to_lowercase(request().post("username"));
	
	// ensure valid username was specified
	if(!form::validUsername(username)) {
		json::send("DX-REJECTED", "Not a valid username", response().out());
		return;
	}

	// if user's username, skip to success
	if(session().get("USERNAME") == username) {
		json::send("DX-OK", "Unblocked", response().out());
		return;
	}
	
	// remove user from blocked list
	db::unblock::by_id(db, session().get<int>("USER_ID"), username);

	json::send("DX-OK", "Unblocked", response().out());
	return;
}
Exemple #7
0
/*
 * The higher the relevance is, the better the name match the query. A relevance of
 * zero means the result will be ignored.
 */
static unsigned get_relevance(char *hex, char *query)
{
	unsigned relevance;
	char *tmp;
	char name[NAME_LENGTH];

	/* Lowercase the name to have case insensitive search */
	hexname_to_name(hex, name);
	to_lowercase(name, name);

	if (!(tmp = strstr(name, query)))
		return 0;

	relevance = 10;

	/* A query matching the beginning of a name is relevant */
	if (tmp == name)
		relevance += 20;

	/* A query matching the end of a name is relevant as well */
	if (tmp == name + strlen(name) - strlen(query))
		relevance += 15;

	/*
	 * Let's note that if a query match exactly the name, both conditions
	 * above will be matched and the relevance will be 50.
	 */
	return relevance;
}
Exemple #8
0
bool ShibINIPriv::exists(const std::string& header)
{
  string h = header;
  if (!cs) to_lowercase (h);

  return (table.find(h) != table.end());
}
Exemple #9
0
static void search(char *query, struct list *list)
{
	DIR *dir;
	struct dirent *dp;
	static char path[PATH_MAX];
	char lowercase_query[NAME_LENGTH];

	assert(strlen(query) < NAME_LENGTH);

	if (snprintf(path, PATH_MAX, "%s/players", config.root) >= PATH_MAX) {
		fprintf(stderr, "Path to teerank database too long\n");
		exit(EXIT_FAILURE);
	}

	if (!(dir = opendir(path))) {
		fprintf(stderr, "opendir(%s): %s\n", path, strerror(errno));
		exit(EXIT_FAILURE);
	}

	to_lowercase(query, lowercase_query);
	init_list(list);

	while ((dp = readdir(dir))) {
		unsigned relevance;

		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
			continue;

		relevance = get_relevance(dp->d_name, lowercase_query);
		try_add_result(list, relevance, dp->d_name);
	}

	closedir(dir);
}
Exemple #10
0
int main(int argc, char *argv[])
{
	FILE *in = stdin;
	char buf[0x4000]; /* limited to 16K character word length */
	cp_avltree *wordlist;
	cp_avltree *freqlist;
	int count = 0;
	int one = 1;
	int *wc;

	if (argc > 1) 
	{
		in = fopen(argv[1], "r");
		if (in == NULL)
		{
			fprintf(stderr, "can\'t open %s\n", argv[1]);
			exit(1);
		}
	}
	
	/* wordlist keys are distinct */
	wordlist = 
		cp_avltree_create_by_option(COLLECTION_MODE_NOSYNC | 
									COLLECTION_MODE_COPY | 
									COLLECTION_MODE_DEEP, 
									(cp_compare_fn) strcmp, 
									(cp_copy_fn) strdup, free, 
									(cp_copy_fn) intdup, free);
	
	while ((fscanf(in, "%s", buf)) != EOF)
	{
		filter_string(buf, PUNCT);
		to_lowercase(buf);
		wc = cp_avltree_get(wordlist, buf);
		if (wc) 
			(*wc)++;
		else
			cp_avltree_insert(wordlist, buf, &one);
		count++;
	}

	fclose(in);

	/* frequency list entry keys are not distinct */
	freqlist = 	
		cp_avltree_create_by_option(COLLECTION_MODE_NOSYNC | 
									COLLECTION_MODE_MULTIPLE_VALUES,
									(cp_compare_fn) freqcmp, 
									NULL, NULL, NULL, NULL);
	
	cp_avltree_callback(wordlist, add_freq, freqlist);
	cp_avltree_callback(freqlist, print_word_freq, &one);
	printf("%d words, %d distinct entries\n", count, cp_avltree_count(wordlist));

	cp_avltree_destroy(freqlist);
	cp_avltree_destroy(wordlist);

	return 0;
}
Exemple #11
0
//a,ns,txt,cname,soa,srv,aaaa,mx
int
fill_rrset_in_buffer(uchar * buffer, uchar * label, uchar * hdr, int lth,
                     int type, struct hlpp *hlp)
{
    int mlen = 0;
    uint16_t len = lth;
//     uchar nsc[512] = { 0 };
    struct srv *from, *to;
    switch (type) {
    case A:
        mlen = 4;
        memcpy(buffer, label, 4);
        break;
    case NS:
    case CNAME:
        get_domain_from_msg(label, hdr, buffer, &mlen);
        to_lowercase(buffer, mlen);
        break;
    case SOA:                  //do nothing
        mlen = 0;
        break;
    case AAAA:
        mlen = 16;
        memcpy(buffer, label, 16);
        break;
    case MX:
        memcpy(buffer, label, 2);       //reference value
        label += 2;             //16bits
        buffer += 2;
        get_domain_from_msg(label, hdr, buffer, &mlen);
        mlen += 2;
        break;
    case SRV:
        from = (struct srv *) label;
        to = (struct srv *) buffer;
        to->pri = from->pri;    //net endian
        to->wei = from->wei;
        to->port = from->port;
        buffer += sizeof(uint16_t) * 3;
        label += sizeof(uint16_t) * 3;
        get_domain_from_msg(label, hdr, buffer, &mlen);
        mlen += sizeof(uint16_t) * 3;
        break;
    case TXT:                  //the only case that lth used
        memcpy(buffer, &len, sizeof(uint16_t)); //uint16_t
        buffer += sizeof(uint16_t);
        memcpy(buffer, label, lth);
        mlen = lth + sizeof(uint16_t);
        break;
    default:
        return -1;
    }
    return mlen;
}
Exemple #12
0
// Add new email
void api::settings_add_email() {
	session().load();
	// allow only POST
	if(request().request_method() != "POST") {
		response().status(404);
		response().out() << "http POST is only method allowed on this endpoint";
		return;
	}
	// ensure logged in
	if(!Pages::logged_in(session())) {
		json::send("DX-REJECTED", "Must be logged in", response().out());
		return;
	}
	// ensure we've been given a valid email
	if(!form::validEmail(request().post("email"))) {
		json::send("DX-REJECTED", "Not a valid email address", response().out());
		return;
	}
	// check if email is in use
	if(db::check_exist::email(db, to_lowercase(request().post("email")))) {
		json::send("DX-REJECTED", "Email in use", response().out());
		return;
	}
	// add email to user's account
	std::pair<std::string, std::string> data1("secondary_email", to_lowercase(request().post("email")));
	try {
		// add the user to the database
		db::update::user::by_username(db, session().get("USERNAME"), data1);
		// send email to user telling them email has been added
		mail::external::notice_new_email(request().post("email"), session().get("USERNAME"));
	} catch(std::exception &e) {
		json::send("DX-FAILED", "Server error occurred, please try again", response().out());
		return;
	}
	// update session
	session().set("SECONDARY_EMAIL", to_lowercase(request().post("email")));
	// added email, return ok
	json::send("DX-OK", "Email added!", response().out());
	return;
}
Exemple #13
0
const std::string ShibINI::get (const string& header, const string& tag)
{
  ReadLock rwlock(m_priv->rwlock);
  refresh();

  static string empty = "";

  string h = header;
  string t = tag;

  if (!m_priv->cs) {
    to_lowercase (h);
    to_lowercase (t);
  }

  if (!m_priv->exists(h)) return empty;

  map<string,string>::const_iterator i = m_priv->table[h].find(t);
  if (i == m_priv->table[h].end())
    return empty;
  return i->second;
}
Exemple #14
0
char *get_mimetype_by_ext(char **ext)
{

    char *extension = *ext;//local copy
    to_lowercase(extension);

    int i;
    for (i = 0; i < sizeof(mimes) / sizeof(mime); i++)
    {
        if (strcmp(mimes[i].extension, extension) == 0)
        {
            return mimes[i].type;
        }
    }
    //nothing found - return NULL
    return NULL;
}
Exemple #15
0
void api::settings_block() {
	session().load();
	// only allow POST
	if(request().request_method() != "POST") {
		json::send("DX-REJECTED", "http POST is only method allowed on this page", response().out());
		return;
	}

	// ensure logged in
	if(!Pages::logged_in(session())) {
		json::send("DX-REJECTED", "Must be logged in!", response().out());
	}

	std::string username = to_lowercase(request().post("username"));

	// ensure valid username specified
	if(!form::validUsername(username)) {
		json::send("DX-REJECTED", "Not a valid username", response().out());
		return;
	}

	// ensure this is not the user's username
	if(session().get("USERNAME") == username) {
		json::send("DX-REJECTED", "Cannot block yourself", response().out());
		return;
	}

	// if user already blocked send DX-OK
	if(db::check_in::blocked_list::by_id(db, session().get<int>("USER_ID"), username)) {
		json::send("DX-OK", "Already blocked", response().out());
		return;
	}

	// Add to block list
	db::block::by_id(db, session().get<int>("USER_ID"), username);
	
	json::send("DX-OK", "Blocked", response().out());
	return;
}
Exemple #16
0
errcode_t setup_node(node_t *node, const char *word)
{
	node_t *p;
	int len, i, idx;
	char c;

	len = strlen(word);

	assert(node && word && len > 0);

	for (i = 0, p = node; i < len; i++) {
		/* Illegal word, skip it, resulting in leaf node's cnt == 0 */
		if ((c = to_lowercase(word[i])) < 0) {
			return 0;
		}

		idx = c - 'a';

		if (p->children[idx] != NULL) {
			p = p->children[idx];
			continue;
		}

		if (!p->children[idx]) {
			if (!(p->children[idx] = create_node(c))) {
				return ERR_NO_MEM;
			}
		}

		p = p->children[idx];
	}

	/* update counter on the leaf node */
	p->cnt++;

	return 0;
}
Exemple #17
0
int main(int argc, char **argv) 
{ 
	int i;
	int dont_support_command_num;
	int rt_val;
	int left, right, mid;
	bool dont_support;
	bool print_info = false;
	bool have_command = false;
	char input_command[128];
	char buf_command[128];
	char path[128];
	char internal_command_prefix[] = "4dos.com /c ";

	command dont_support_command[] = { {"fdisk", 5}, {"format", 6} };

	Serial.begin(115200);

	fp = fopen("Z:\\tmp.txt", "w+");
	if(fp == NULL)
		return EXIT_FAILURE;

	printf("================================================================================\n");
	printf("                      ___   __   ____        _\n");
	printf("                     ( _ ) / /_ |  _ \\ _   _(_)_ __   ___\n");
	printf("                     / _ \\| '_ \\| | | | | | | | '_ \\ / _ \\\n");
	printf("                    | (_) | (_) | |_| | |_| | | | | | (_) |\n");
	printf("                     \\___/ \\___/|____/ \\____|_|_| |_|\\___/\n");
	printf("\n 86UsbSh v1.1, author: PING-HUI WEI, E-mail: [email protected], 2015/12/25\n");
	printf("================================================================================\n");

	old_stderr = dup(fileno(stderr));
	dup2(fileno(fp), fileno(stderr));
	old_stdout = dup(fileno(stdout));
	dup2(fileno(fp), fileno(stdout));

	dont_support = false;
	dont_support_command_num = sizeof(dont_support_command) / sizeof(command);

	// while(kbhit() != 1)
	while(1)
	{
		if(kbhit() == 1)
		{
			gets(input_command);

			if(strcmp(input_command, "q") == 0 || strcmp(input_command, "Q") == 0)
				break;

			have_command = true;
		}
		else
		{
			if(!Serial)
			{
				print_info = false;
			}
			else
			{
				if(print_info == false)
				{
					getcwd(path, sizeof(path) / sizeof(char) - 1);

					Serial.println("================================================================================");
					Serial.println("                      ___   __   ____        _");
					Serial.println("                     ( _ ) / /_ |  _ \\ _   _(_)_ __   ___");
					Serial.println("                     / _ \\| '_ \\| | | | | | | | '_ \\ / _ \\");
					Serial.println("                    | (_) | (_) | |_| | |_| | | | | | (_) |");
					Serial.println("                     \\___/ \\___/|____/ \\____|_|_| |_|\\___/");
					Serial.println("\n 86UsbSh v1.1, author: PING-HUI WEI, E-mail: [email protected], 2015/12/25");
					Serial.println("================================================================================");
					Serial.println();
					Serial.print(path);
					Serial.println('>');			

					print_info = true;
				}
			
				rt_val = Serial.available();
				if(rt_val > 127)
					Serial.println("Command is too long!");
				else if(rt_val > 0)
				{
					Serial.readBytes(input_command, rt_val);
					input_command[rt_val] = '\0';
					to_lowercase(input_command);

					if(strcmp(input_command, "quit") == 0)
						break;

					have_command = true;
				}
			}
		}

		if(have_command == true)
		{
			have_command = false;

			for(i = 0; i < dont_support_command_num; i++)
			{
				if(strncmp(input_command, dont_support_command[i].name, dont_support_command[i].size) == 0)
				{
					dont_support = true;
					break;
				}
			}
			if(dont_support == true)
			{
				Serial.println("Don't support command!");
				dont_support = false;
				continue;
			}

			Serial.print(path);
			Serial.print('>');
			Serial.println(input_command);

			if(strncmp("dir", input_command, 3) == 0)
			{
				strcpy(buf_command, internal_command_prefix);
				strcat(buf_command, input_command);

				do_command(buf_command);
			}
			else
			{
				do_command(input_command);

				if(strncmp("cd", input_command, 2) == 0)
					getcwd(path, sizeof(path) / sizeof(char) - 1);
			}

			Serial.print(path);
			Serial.println('>');
		}		
	}

	dup2(old_stderr, fileno(stderr));
	dup2(old_stdout, fileno(stdout));
	fclose(fp);
	Serial.end();

	return EXIT_SUCCESS; 
} 
Exemple #18
0
//
// Must be called holding the ReadLock.
//
void ShibINI::refresh(void)
{
  saml::NDC ndc("refresh");

  // check if we need to refresh
#ifdef _WIN32
  struct _stat stat_buf;
  if (_stat (m_priv->file.c_str(), &stat_buf) < 0)
#else
  struct stat stat_buf;
  if (stat (m_priv->file.c_str(), &stat_buf) < 0)
#endif
    m_priv->log->error("stat failed: %s", m_priv->file.c_str());

#ifdef DEBUG
  m_priv->log->info("refresh: last modtime at %d; file is %d; iters: %d",
		    m_priv->modtime, stat_buf.st_mtime, m_priv->iterators);
#endif

  if (m_priv->modtime >= stat_buf.st_mtime || m_priv->iterators > 0)
    return;

  // Release the read lock -- grab the write lock.  Don't worry if
  // this is non-atomic -- we'll recheck the status.
  m_priv->rwlock->unlock();
  m_priv->rwlock->wrlock();

  // Recheck the modtime
  if (m_priv->modtime >= stat_buf.st_mtime) {
    // Yep, another thread got to it.  We can exit now...  Release
    // the write lock and reaquire the read-lock.

    m_priv->rwlock->unlock();
    m_priv->rwlock->rdlock();
    return;
  }

  // Ok, we've got the write lock.  Let's update our state.

  m_priv->modtime = stat_buf.st_mtime;

  // clear the existing maps
  m_priv->table.clear();

  m_priv->log->info("reading %s", m_priv->file.c_str());
  
  // read the file
  try
  {
    ifstream infile (m_priv->file.c_str());
    if (!infile) {
      m_priv->log->warn("cannot open file: %s", m_priv->file.c_str());
      m_priv->rwlock->unlock();
      m_priv->rwlock->rdlock();
      return;
    }

    const int MAXLEN = 1024;
    char linebuffer[MAXLEN];
    string current_header;
    bool have_header = false;

    while (infile) {
      infile.getline (linebuffer, MAXLEN);
      string line (linebuffer);

      if (line[0] == '#') continue;

      trimline (line);
      if (line.size() <= 1) continue;

      if (line[0] == '[') {
	// this is a header

#ifdef DEBUG
	m_priv->log->info("Found what appears to be a header line");
#endif

	have_header = false;

	// find the end of the header
	int endpos = line.find (']');
	if (endpos == line.npos) {
#ifdef DEBUG
	  m_priv->log->info("Weird: no end found.. punting");
#endif
	  continue; // HUH?  No end?
	}

	// found it
	current_header = line.substr (1, endpos-1);
	trimline (current_header);

	if (!m_priv->cs) to_lowercase (current_header);

	m_priv->table[current_header] = map<string,string>();
	have_header = true;
#ifdef DEBUG
	m_priv->log->info("current header: \"%s\"", current_header.c_str());
#endif

      } else if (have_header) {
	// this is a tag

#ifdef DEBUG
	m_priv->log->info("Found what appears to be a tag line");
#endif

	string tag, setting;
	int mid = line.find ('=');

	if (mid == line.npos) {
#ifdef DEBUG
	  m_priv->log->info("Weird: no '=' found.. punting");
#endif
	  continue; // Can't find the value's setting
	}

	tag = line.substr (0,mid);
	setting = line.substr (mid+1, line.size()-mid);

	trimline (tag);
	trimline (setting);

	if (!m_priv->cs) to_lowercase (tag);

	// If it already exists, log an error and do not save it
	if (m_priv->exists (current_header, tag))
	  m_priv->log->error("Duplicate tag found in section %s: \"%s\"",
			     current_header.c_str(), tag.c_str());
	else
	  (m_priv->table[current_header])[tag] = setting;

#ifdef DEBUG
	m_priv->log->info("new tag: \"%s\" = \"%s\"",
			  tag.c_str(), setting.c_str());
#endif

      }

    } // until the file ends

  } catch (...) {
    // In case there are exceptions.
  }

  // Now release the write lock and reaquire the read lock
  m_priv->rwlock->unlock();
  m_priv->rwlock->rdlock();
}
/* takes a string of days e.g. "Monday, Tuesday, Friday", and turns into an array of 7 longs
 * each 0 or 1, one for each weekday starting with sunday, e.g. [0,1,1,0,0,1,0] for our example 
 */
long* parse_weekdays(char* wd_str)
{
	long* weekdays = (long*)malloc(7*sizeof(long));
	weekdays[0] = weekdays[1] = weekdays[2] = weekdays[3] = weekdays[4] = weekdays[5] = weekdays[6] = 0;

	char** days = split_on_separators(wd_str, ",", 1, -1, 0);
	int day_index;
	int found = 0;
	for(day_index=0; days[day_index] != NULL; day_index++)
	{
		char day[4];
		trim_flanking_whitespace(days[day_index]);
		memcpy(day, days[day_index], 3);
		free(days[day_index]);
		day[3] = '\0';
		to_lowercase(day);
		if(strcmp(day, "sun") == 0)
		{
			weekdays[0] = 1;
			found = 1;
		}
		else if(strcmp(day, "mon") ==0)
		{
			weekdays[1] = 1;
			found = 1;
		}
		else if(strcmp(day, "tue") ==0)
		{
			weekdays[2] = 1;
			found = 1;
		}
		else if(strcmp(day, "wed") ==0)
		{
			weekdays[3] = 1;
			found = 1;
		}	
		else if(strcmp(day, "thu") ==0)
		{
			weekdays[4] = 1;
			found = 1;
		}
		else if(strcmp(day, "fri") ==0)
		{
			weekdays[5] = 1;
			found = 1;
		}
		else if(strcmp(day, "sat") ==0)
		{
			weekdays[6] = 1;
			found = 1;
		}
		else if(strcmp(day, "all") ==0)
		{
			weekdays[0] = weekdays[1] = weekdays[2] = weekdays[3] = weekdays[4] = weekdays[5] = weekdays[6] = 1;
			found = 1;
		}
	}
	free(days);
	if(found == 0)
	{
		free(weekdays);
		weekdays = NULL;
	}
	return weekdays;	
}
Exemple #20
0
int main(int argc, char **argv) {
	DBHANDLE db;
	int rc,c, flags, len;
	char *ptr_command, *ptr_key, *find;
	char *command, *key, *value;
	command = key = value = NULL;
	char *help_cmd = "command list:\n [add | update] key value \n [del | find] key \n [open | close] dbname\n [help count iterate exit]";

	flags = O_RDWR;
	while ((c = getopt(argc, argv, "nt?")) != -1) {
		switch (c) {
		case 'n':
			flags |= O_CREAT;
			break;
		case 't':
			flags |= O_TRUNC;
			break;
		case '?':
			err_quit("usage: [-n] create new file [-t] truncate db <filename>");
			break;
		}
	}
	if (optind != argc - 1) {
		err_quit("usage: [-n] create new file [-t] truncate db <filename>");
	}

	if ((db = db_open(argv[optind], flags, FILE_MODE)) == NULL) {
		err_sys("db_open %s error", argv[optind]);
	}

	for (;;) {
		char buf[MAX_LEN];
		printf("APUEDB> ");
		if (fgets(buf, MAX_LEN, stdin) == NULL) {
			printf("Bye~\n");
			exit(1);
		}
		to_lowercase(buf);
		len = strlen(buf);
		if ((ptr_command = strchr(buf,COMMAND_SEP)) == NULL) {
			buf[len-1] = '\0';
			if (strcmp(buf,"help") == 0) {
				printf("%s\n", help_cmd);
				continue;
			} else if (strcmp(buf, "count") == 0) {
				printf("%d\n", db_count(db));
			} else if (strcmp(buf, "iterate") == 0) {
				char *ptr;
				db_rewind(db);
				while ((ptr = db_nextrec(db, NULL)) != NULL) {
					printf("%s\n", ptr);
				}
				continue;
			} else if (strcmp(buf, "exit") == 0) {
				printf("Bye~\n");
				exit(1);
			} else {
				printf("invalid command, use command help for help\n");
				continue;
			}
		}
		command = strndup(buf, ptr_command - buf);

		if (strcmp(command, "add") == 0) {
			if ((ptr_key = strchr(ptr_command+1, COMMAND_SEP)) == NULL) {
				printf("invalid add command, usage: add key value\n");
			} else {
				key = strndup(ptr_command+1, ptr_key - ptr_command - 1);
				value = strndup(ptr_key+1, buf + len - 1 - ptr_key - 1);
				rc = db_store(db, key, value, DB_INSERT);
				if (rc == 0) {
					printf("add +OK\n");
				} else {
					printf("key %s already exist\n", key);
				}
			}
		} else if (strcmp(command, "update") == 0) {
			if ((ptr_key = strchr(ptr_command+1, COMMAND_SEP)) == NULL) {
				printf("invalid add command, usage: add key value\n");
			} else {
				key = strndup(ptr_command+1, ptr_key - ptr_command - 1);
				value = strndup(ptr_key+1, buf + len - 1 - ptr_key - 1);
				rc = db_store(db, key, value, DB_REPLACE);
				if (rc == 0) {
					printf("update +OK\n");
				} else {
					printf("key %s not found\n", key);
				}
			}
		} else if (strcmp(command, "del") == 0) {
			if ((ptr_key = strchr(ptr_command+1, COMMAND_SEP)) != NULL) {
				printf("invalid del command, usage: del key\n");
				continue;
			}
			key = strndup(ptr_command+1, buf + len - 1 - ptr_command -1);
			rc = db_delete(db, key);
			if (rc == 0) {
				printf("del +OK\n");
			} else {
				printf("key %s not found\n", key);
			}
		} else if (strcmp(command, "find") == 0) {
			if ((ptr_key = strchr(ptr_command+1, COMMAND_SEP)) != NULL) {
				printf("invalid find command, usage: find key\n");
				continue;
			}
			key = strndup(ptr_command+1, buf + len - 1 - ptr_command -1);
			find = db_fetch(db, key);
			if (find != NULL) {
				printf("%d,%s\n", strlen(find), find);
			} else {
				printf("key %s not found\n", key);
			}
		}
		if (key != NULL) {
			free(key);
			key = NULL;
		}
		if (command != NULL) {
			free(command);
			command = NULL;
		}
		if (value != NULL) {
			free(value);
			value = NULL;
		}
	}
}
/* 
 * assumes 24hr time, not am/pm, in format:
 * (Day of week) hours:minutes:seconds
 * if day of week is present, returns seconds since midnight on Sunday
 * otherwise, seconds since midnight
 */
unsigned long parse_time(char* time_str)
{
	while((*time_str == ' ' || *time_str == '\t') && *time_str != '\0') { time_str++; }
	
	int weekday = -1;
	if(strlen(time_str) > 3)
	{
		char wday_test[4];
		memcpy(wday_test, time_str, 3);
		wday_test[3] = '\0';
		to_lowercase(wday_test);
		if(strcmp(wday_test, "sun") == 0)
		{
			weekday = 0;
		}
		else if(strcmp(wday_test, "mon") == 0)
		{
			weekday = 1;
		}
		else if(strcmp(wday_test, "tue") == 0)
		{
			weekday = 2;
		}
		else if(strcmp(wday_test, "wed") == 0)
		{
			weekday = 3;
		}
		else if(strcmp(wday_test, "thu") == 0)
		{
			weekday = 4;
		}
		else if(strcmp(wday_test, "fri") == 0)
		{
			weekday = 5;
		}
		else if(strcmp(wday_test, "sat") == 0)
		{
			weekday = 6;
		}
	}

	if(weekday >= 0)
	{
		time_str = time_str + 3;
		while( (*time_str < 48 || *time_str > 57) && *time_str != '\0') { time_str++; }
	}

	char** time_parts=split_on_separators(time_str, ":", 1, -1, 0);
	unsigned long seconds = weekday < 0 ? 0 : ( ((unsigned long)(weekday))*60*60*24 );
	unsigned long tmp;
	unsigned long multiple = 60*60;

	int tp_index = 0;
	for(tp_index=0; time_parts[tp_index] != NULL; tp_index++)
	{
		sscanf(time_parts[tp_index], "%ld", &tmp);
		seconds = seconds + (tmp*multiple);
		multiple = (unsigned long)(multiple/60);
		free(time_parts[tp_index]);
	}
	free(time_parts);

	return seconds;
}