Пример #1
0
static int
getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf )
{
	char *arg;
	uint i;

	if (!strcasecmp( "Sync", cfile->cmd )) {
		arg = cfile->val;
		do
			if (!strcasecmp( "Push", arg ))
				*cops |= XOP_PUSH;
			else if (!strcasecmp( "Pull", arg ))
				*cops |= XOP_PULL;
			else if (!strcasecmp( "ReNew", arg ))
				*cops |= OP_RENEW;
			else if (!strcasecmp( "New", arg ))
				*cops |= OP_NEW;
			else if (!strcasecmp( "Delete", arg ))
				*cops |= OP_DELETE;
			else if (!strcasecmp( "Flags", arg ))
				*cops |= OP_FLAGS;
			else if (!strcasecmp( "PullReNew", arg ))
				conf->ops[S] |= OP_RENEW;
			else if (!strcasecmp( "PullNew", arg ))
				conf->ops[S] |= OP_NEW;
			else if (!strcasecmp( "PullDelete", arg ))
				conf->ops[S] |= OP_DELETE;
			else if (!strcasecmp( "PullFlags", arg ))
				conf->ops[S] |= OP_FLAGS;
			else if (!strcasecmp( "PushReNew", arg ))
				conf->ops[M] |= OP_RENEW;
			else if (!strcasecmp( "PushNew", arg ))
				conf->ops[M] |= OP_NEW;
			else if (!strcasecmp( "PushDelete", arg ))
				conf->ops[M] |= OP_DELETE;
			else if (!strcasecmp( "PushFlags", arg ))
				conf->ops[M] |= OP_FLAGS;
			else if (!strcasecmp( "All", arg ) || !strcasecmp( "Full", arg ))
				*cops |= XOP_PULL|XOP_PUSH;
			else if (strcasecmp( "None", arg ) && strcasecmp( "Noop", arg )) {
				error( "%s:%d: invalid Sync arg '%s'\n",
				       cfile->file, cfile->line, arg );
				cfile->err = 1;
			}
		while ((arg = get_arg( cfile, ARG_OPTIONAL, 0 )));
		conf->ops[M] |= XOP_HAVE_TYPE;
	} else if (!strcasecmp( "SyncState", cfile->cmd ))
		conf->sync_state = expand_strdup( cfile->val );
	else if (!strcasecmp( "CopyArrivalDate", cfile->cmd ))
		conf->use_internal_date = parse_bool( cfile );
	else if (!strcasecmp( "MaxMessages", cfile->cmd ))
		conf->max_messages = parse_int( cfile );
	else if (!strcasecmp( "ExpireUnread", cfile->cmd ))
		conf->expire_unread = parse_bool( cfile );
	else {
		for (i = 0; i < as(boxOps); i++) {
			if (!strcasecmp( boxOps[i].name, cfile->cmd )) {
				int op = boxOps[i].op;
				arg = cfile->val;
				do {
					if (!strcasecmp( "Both", arg )) {
						*cops |= op;
					} else if (!strcasecmp( "Master", arg )) {
						conf->ops[M] |= op;
					} else if (!strcasecmp( "Slave", arg )) {
						conf->ops[S] |= op;
					} else if (strcasecmp( "None", arg )) {
						error( "%s:%d: invalid %s arg '%s'\n",
						       cfile->file, cfile->line, boxOps[i].name, arg );
						cfile->err = 1;
					}
				} while ((arg = get_arg( cfile, ARG_OPTIONAL, 0 )));
				conf->ops[M] |= op * (XOP_HAVE_EXPUNGE / OP_EXPUNGE);
				return 1;
			}
		}
		return 0;
	}
	return 1;
}
Пример #2
0
int
load_config( const char *where, int pseudo )
{
	conffile_t cfile;
	store_conf_t *store, **storeapp = &stores;
	channel_conf_t *channel, **channelapp = &channels;
	group_conf_t *group, **groupapp = &groups;
	string_list_t *chanlist, **chanlistapp;
	char *arg, *p;
	int len, cops, gcops, max_size, ms, i;
	char path[_POSIX_PATH_MAX];
	char buf[1024];

	if (!where) {
		assert( !pseudo );
		nfsnprintf( path, sizeof(path), "%s/." EXE "rc", Home );
		cfile.file = path;
	} else
		cfile.file = where;

	if (!pseudo)
		info( "Reading configuration file %s\n", cfile.file );

	if (!(cfile.fp = fopen( cfile.file, "r" ))) {
		sys_error( "Cannot open config file '%s'", cfile.file );
		return 1;
	}
	buf[sizeof(buf) - 1] = 0;
	cfile.buf = buf;
	cfile.bufl = sizeof(buf) - 1;
	cfile.line = 0;
	cfile.err = 0;
	cfile.rest = 0;

	gcops = 0;
	global_conf.expire_unread = -1;
  reloop:
	while (getcline( &cfile )) {
		if (!cfile.cmd)
			continue;
		for (i = 0; i < N_DRIVERS; i++)
			if (drivers[i]->parse_store( &cfile, &store )) {
				if (store) {
					if (!store->max_size)
						store->max_size = INT_MAX;
					*storeapp = store;
					storeapp = &store->next;
					*storeapp = 0;
				}
				goto reloop;
			}
		if (!strcasecmp( "Channel", cfile.cmd ))
		{
			channel = nfcalloc( sizeof(*channel) );
			channel->name = nfstrdup( cfile.val );
			channel->max_messages = global_conf.max_messages;
			channel->expire_unread = global_conf.expire_unread;
			channel->use_internal_date = global_conf.use_internal_date;
			cops = 0;
			max_size = -1;
			while (getcline( &cfile ) && cfile.cmd) {
				if (!strcasecmp( "MaxSize", cfile.cmd ))
					max_size = parse_size( &cfile );
				else if (!strcasecmp( "Pattern", cfile.cmd ) ||
				         !strcasecmp( "Patterns", cfile.cmd ))
				{
					arg = cfile.val;
					do
						add_string_list( &channel->patterns, arg );
					while ((arg = get_arg( &cfile, ARG_OPTIONAL, 0 )));
				}
				else if (!strcasecmp( "Master", cfile.cmd )) {
					ms = M;
					goto linkst;
				} else if (!strcasecmp( "Slave", cfile.cmd )) {
					ms = S;
				  linkst:
					if (*cfile.val != ':' || !(p = strchr( cfile.val + 1, ':' ))) {
						error( "%s:%d: malformed mailbox spec\n",
						       cfile.file, cfile.line );
						cfile.err = 1;
						continue;
					}
					*p = 0;
					for (store = stores; store; store = store->next)
						if (!strcmp( store->name, cfile.val + 1 )) {
							channel->stores[ms] = store;
							goto stpcom;
						}
					error( "%s:%d: unknown store '%s'\n",
					       cfile.file, cfile.line, cfile.val + 1 );
					cfile.err = 1;
					continue;
				  stpcom:
					if (*++p)
						channel->boxes[ms] = nfstrdup( p );
				} else if (!getopt_helper( &cfile, &cops, channel )) {
					error( "%s:%d: unknown keyword '%s'\n", cfile.file, cfile.line, cfile.cmd );
					cfile.err = 1;
				}
			}
			if (!channel->stores[M]) {
				error( "channel '%s' refers to no master store\n", channel->name );
				cfile.err = 1;
			} else if (!channel->stores[S]) {
				error( "channel '%s' refers to no slave store\n", channel->name );
				cfile.err = 1;
			} else if (merge_ops( cops, channel->ops ))
				cfile.err = 1;
			else {
				if (max_size >= 0) {
					if (!max_size)
						max_size = INT_MAX;
					channel->stores[M]->max_size = channel->stores[S]->max_size = max_size;
				}
				*channelapp = channel;
				channelapp = &channel->next;
			}
		}
		else if (!strcasecmp( "Group", cfile.cmd ))
		{
			group = nfmalloc( sizeof(*group) );
			group->name = nfstrdup( cfile.val );
			*groupapp = group;
			groupapp = &group->next;
			*groupapp = 0;
			chanlistapp = &group->channels;
			*chanlistapp = 0;
			while ((arg = get_arg( &cfile, ARG_OPTIONAL, 0 ))) {
			  addone:
				len = strlen( arg );
				chanlist = nfmalloc( sizeof(*chanlist) + len );
				memcpy( chanlist->string, arg, len + 1 );
				*chanlistapp = chanlist;
				chanlistapp = &chanlist->next;
				*chanlistapp = 0;
			}
			while (getcline( &cfile )) {
				if (!cfile.cmd)
					goto reloop;
				if (!strcasecmp( "Channel", cfile.cmd ) ||
				    !strcasecmp( "Channels", cfile.cmd ))
				{
					arg = cfile.val;
					goto addone;
				}
				else
				{
					error( "%s:%d: unknown keyword '%s'\n",
					       cfile.file, cfile.line, cfile.cmd );
					cfile.err = 1;
				}
			}
			break;
		}
		else if (!strcasecmp( "FSync", cfile.cmd ))
		{
			UseFSync = parse_bool( &cfile );
		}
		else if (!strcasecmp( "FieldDelimiter", cfile.cmd ))
		{
			if (strlen( cfile.val ) != 1) {
				error( "%s:%d: Field delimiter must be exactly one character long\n", cfile.file, cfile.line );
				cfile.err = 1;
			} else {
				FieldDelimiter = cfile.val[0];
				if (!ispunct( FieldDelimiter )) {
					error( "%s:%d: Field delimiter must be a punctuation character\n", cfile.file, cfile.line );
					cfile.err = 1;
				}
			}
		}
		else if (!strcasecmp( "BufferLimit", cfile.cmd ))
		{
			BufferLimit = parse_size( &cfile );
			if (BufferLimit <= 0) {
				error( "%s:%d: BufferLimit must be positive\n", cfile.file, cfile.line );
				cfile.err = 1;
			}
		}
		else if (!getopt_helper( &cfile, &gcops, &global_conf ))
		{
			error( "%s:%d: unknown section keyword '%s'\n",
			       cfile.file, cfile.line, cfile.cmd );
			cfile.err = 1;
			while (getcline( &cfile ))
				if (!cfile.cmd)
					goto reloop;
			break;
		}
	}
	fclose (cfile.fp);
	cfile.err |= merge_ops( gcops, global_conf.ops );
	if (!global_conf.sync_state)
		global_conf.sync_state = expand_strdup( "~/." EXE "/" );
	if (!cfile.err && pseudo)
		unlink( where );
	return cfile.err;
}
Пример #3
0
static int
getopt_helper( conffile_t *cfile, int *cops, int ops[], char **sync_state )
{
	char *arg;

	if (!strcasecmp( "Sync", cfile->cmd )) {
		arg = cfile->val;
		do
			if (!strcasecmp( "Push", arg ))
				*cops |= XOP_PUSH;
			else if (!strcasecmp( "Pull", arg ))
				*cops |= XOP_PULL;
			else if (!strcasecmp( "ReNew", arg ))
				*cops |= OP_RENEW;
			else if (!strcasecmp( "New", arg ))
				*cops |= OP_NEW;
			else if (!strcasecmp( "Delete", arg ))
				*cops |= OP_DELETE;
			else if (!strcasecmp( "Flags", arg ))
				*cops |= OP_FLAGS;
			else if (!strcasecmp( "PullReNew", arg ))
				ops[S] |= OP_RENEW;
			else if (!strcasecmp( "PullNew", arg ))
				ops[S] |= OP_NEW;
			else if (!strcasecmp( "PullDelete", arg ))
				ops[S] |= OP_DELETE;
			else if (!strcasecmp( "PullFlags", arg ))
				ops[S] |= OP_FLAGS;
			else if (!strcasecmp( "PushReNew", arg ))
				ops[M] |= OP_RENEW;
			else if (!strcasecmp( "PushNew", arg ))
				ops[M] |= OP_NEW;
			else if (!strcasecmp( "PushDelete", arg ))
				ops[M] |= OP_DELETE;
			else if (!strcasecmp( "PushFlags", arg ))
				ops[M] |= OP_FLAGS;
			else if (!strcasecmp( "All", arg ) || !strcasecmp( "Full", arg ))
				*cops |= XOP_PULL|XOP_PUSH;
			else if (strcasecmp( "None", arg ) && strcasecmp( "Noop", arg )) {
				error( "%s:%d: invalid Sync arg '%s'\n",
				       cfile->file, cfile->line, arg );
				cfile->err = 1;
			}
		while ((arg = get_arg( cfile, ARG_OPTIONAL, 0 )));
		ops[M] |= XOP_HAVE_TYPE;
	} else if (!strcasecmp( "Expunge", cfile->cmd )) {
		arg = cfile->val;
		do
			if (!strcasecmp( "Both", arg ))
				*cops |= OP_EXPUNGE;
			else if (!strcasecmp( "Master", arg ))
				ops[M] |= OP_EXPUNGE;
			else if (!strcasecmp( "Slave", arg ))
				ops[S] |= OP_EXPUNGE;
			else if (strcasecmp( "None", arg )) {
				error( "%s:%d: invalid Expunge arg '%s'\n",
				       cfile->file, cfile->line, arg );
				cfile->err = 1;
			}
		while ((arg = get_arg( cfile, ARG_OPTIONAL, 0 )));
		ops[M] |= XOP_HAVE_EXPUNGE;
	} else if (!strcasecmp( "Create", cfile->cmd )) {
		arg = cfile->val;
		do
			if (!strcasecmp( "Both", arg ))
				*cops |= OP_CREATE;
			else if (!strcasecmp( "Master", arg ))
				ops[M] |= OP_CREATE;
			else if (!strcasecmp( "Slave", arg ))
				ops[S] |= OP_CREATE;
			else if (strcasecmp( "None", arg )) {
				error( "%s:%d: invalid Create arg '%s'\n",
				       cfile->file, cfile->line, arg );
				cfile->err = 1;
			}
		while ((arg = get_arg( cfile, ARG_OPTIONAL, 0 )));
		ops[M] |= XOP_HAVE_CREATE;
	} else if (!strcasecmp( "SyncState", cfile->cmd ))
		*sync_state = expand_strdup( cfile->val );
	else
		return 0;
	return 1;
}