Пример #1
0
/* kind = 0 for sent, 1 for toobig */
static void xmsg_unlink_dotfiles(session_t *s, const char *varname)
{
	if (session_int_get(s, varname)) {
		const int kind = !xstrcasecmp(varname, "unlink_sent");
		const int maxfs = session_int_get(s, "max_filesize");
		const char *dfsuffix = session_get(s, "dotfile_suffix");
		const char *dir = xmsg_dirfix(session_uid_get(s)+XMSG_UID_DIROFFSET);
		DIR *d;
		struct dirent *de;
		struct stat st, std;
		char *df, *dfd, *dp, *dpd;
		
		if (!dir || !(d = opendir(dir))) {
			xdebug("unable to open specified directory");
			return;
		}
		
		df = xmalloc(xstrlen(dir) + NAME_MAX + 2);
		dfd = xmalloc(xstrlen(dir) + NAME_MAX + 3 + xstrlen(dfsuffix));
		xstrcpy(df, dir);
		dp = df + xstrlen(df);
		*(dp++) = '/';
		xstrcpy(dfd, df);
		dpd = dfd + xstrlen(dfd);
		*(dpd++) = '.';
		
		while ((de = readdir(d))) {
			if (de->d_name[0] == '.')
				continue;
			if (xstrlen(de->d_name) > NAME_MAX) {
				xdebug2(DEBUG_ERROR, "Filename longer than NAME_MAX (%s), skipping.", de->d_name);
				continue;
			}
			xstrcpy(dp, de->d_name);
			xstrcpy(dpd, de->d_name);
			xstrcat(dpd, dfsuffix);
			if (!stat(df, &st) && !stat(dfd, &std)
					&& ((!maxfs || (st.st_size < maxfs)) == kind)) {
				xdebug("removing %s", de->d_name);
				unlink(df);
				unlink(dfd);
			}
		}

		closedir(d);
		xfree(df);
		xfree(dfd);
	}
}
Пример #2
0
static WATCHER(xmsg_handle_data)
{
	int n;
	int c = 0;
	struct inotify_event *evp;

	if (type)
		return -1;

	ioctl(fd, FIONREAD, &n);
	if (n == 0)
		return 0;

	ev = xrealloc(ev, n);
	n = read(fd, ev, n);

	if (n < 0)
		xerrn("inotify read() failed");
	
	for (evp = ev; n > 0; n -= (evp->len + sizeof(struct inotify_event)), evp = (void*) evp + (evp->len + sizeof(struct inotify_event))) {
		session_t *s;

		for (s = sessions; s; s = s->next) {
			if (s && (s->priv == (void*) (long int) evp->wd) && (s->plugin == &xmsg_plugin))
				break;
		}
		
		xdebug("n = %d, wd = %d, str = %s", n, evp->wd, evp->name);
			
		if ((evp->mask & IN_IGNORED) || !s || !session_connected_get(s))
			continue;
		else if (evp->mask & IN_UNMOUNT)
			xmsg_disconnect(NULL, NULL, s, NULL, -1);
		else if (!(evp->mask & IN_Q_OVERFLOW) && (c != -1) && (!xmsg_handle_file(s, evp->name))) 
			c++;
		
		if ((evp->mask & IN_Q_OVERFLOW) || ((config_maxinotifycount > 0) && c >= config_maxinotifycount)) {
			for (s = sessions; s; s = s->next) {
				if (s && (s->plugin == &xmsg_plugin)) {
					const int i = session_int_get(s, "oneshot_resume_timer");
					if (!timer_remove_session(s, "o"))
						xdebug("old oneshot resume timer removed");
					if ((i > 0) && timer_add_session(s, "o", i, 0, xmsg_iterate_dir)) {
						xdebug("oneshot resume timer added");
						session_status_set(s, EKG_STATUS_AWAY);
					} else
						session_status_set(s, EKG_STATUS_AVAIL);
					c = -1;
				}
			}
		}
	}
	if (c >= 0)
		xdebug("processed %d files", c);
	else
		xdebug("reached max_inotifycount");

	return 0;
}
Пример #3
0
Файл: ekg.c Проект: pawelz/ekg2
void ekg_loop() {
	g_main_context_iteration(NULL, FALSE);
	{

#ifdef WATCHES_FIXME
		{		/* przejrzyj deskryptory */
			list_t l;

			for (l = watches; l; l = l->next) {
				watch_t *w = l->data;

				if (!w)
					continue;

				if (!FD_ISSET(w->fd, &rd) && !FD_ISSET(w->fd, &wd)) { /* timeout checking */
					if (w->timeout < 1 || (tv.tv_sec - w->started) < w->timeout)
						continue;
					w->removed = -1;
					if (w->buf) {
						int (*handler)(int, int, char*, void*) = w->handler;
						if (handler(2, w->fd, NULL, w->data) == -1 || w->removed == 1) {
							w->removed = 0;
							watch_free(w);
							continue;
						}
					} else {
						int (*handler)(int, int, int, void*) = w->handler;
						if (handler(2, w->fd, w->type, w->data) == -1 || w->removed == 1) {
							w->removed = 0;
							watch_free(w);
							continue;
						}
					}
					w->removed = 0;

					continue;
				}

				if (w->fd == 0) {
					session_t *s;
					for (s = sessions; s; s = s->next) 
					{
						if (!s->connected || !s->autoaway)
							continue;

						if (session_int_get(s, "auto_back") == 2)
							command_exec(NULL, s, ("/_autoback"), 2);
					}
				}
			}
		}
#endif

	}
#undef tv

	return;
}
Пример #4
0
int irc_autorejoin(session_t *s, int when, char *chan) {
	irc_private_t *j;
	string_t st;
	window_t *w;
	char *chanprefix;
	int rejoin;

#if 1	/* there's no need of doing it, already checked by irc_onkick_handler() or if it goes through irc_c_init() it's even better. */
	if (!s || !(j = s->priv) || (s->plugin != &irc_plugin))
		return -1;
#endif
	chanprefix = SOP(_005_CHANTYPES);
	rejoin = session_int_get(s, "REJOIN");

	if (!(rejoin&(1<<(when))))
		return -1;

	switch (when) {
		case IRC_REJOIN_CONNECT:
			st = string_init(NULL);
			for (w = windows; w; w = w->next) {
				if (!w->target || w->session != s)			/* check if sessions match and has w->target */
					continue;

				if (valid_plugin_uid(s->plugin, w->target) != 1)	/* check if window is correct for irc: */
					continue;

				if (!xstrchr(chanprefix, (w->target)[4]))		/* check if this is channel.. */
					continue;

				if (st->len)
					string_append_c(st, ',');
				if ((w->target)[4] == '!') {
					string_append_c(st, '!');
					string_append(st, w->target + 10);
				} else {
					string_append(st, w->target + 4);
				}
			}
			if (st->len)
				irc_write(s, "JOIN %s\r\n", st->str);
			string_free(st, 1);
			break;

		case IRC_REJOIN_KICK:
			irc_write(s, "JOIN %s\r\n", chan);
			break;

		default:
			return -1;
	}
	return 0;
}
Пример #5
0
static void xmsg_timer_change(session_t *s, const char *varname)
{
	int n = (varname ? session_int_get(s, varname) : 0);
	
	xdebug("n = %d", n);
	if (!varname || session_connected_get(s)) {
		if (!timer_remove_session(s, "w"))
			xdebug("old timer removed");
		if (n > 0) {
			if (timer_add_session(s, "w", n, 1, xmsg_iterate_dir))
				xdebug("new timer added");
		}
	}
}
Пример #6
0
Файл: ekg.c Проект: pawelz/ekg2
/**
 * ekg_autoaway_timer()
 *
 *
 * less important things which don't need to be checked every main loop iteration
 * e.g. autoaways 
 *
 * executed each second.
 */
static TIMER(ekg_autoaway_timer) {
	session_t *sl;
	time_t t;

	if (type)
		return 0;

	t = time(NULL);

	/* sprawd¼ autoawaye ró¿nych sesji */
	for (sl = sessions; sl; sl = sl->next) {
		session_t *s = sl;
		int tmp;

		if (!s->connected || (s->status < EKG_STATUS_AWAY)) /* lowest autostatus is autoxa, so from xa and lower ones
								       we can't go further */
			continue;

		do {
			if ((s->status == EKG_STATUS_AWAY) || (tmp = session_int_get(s, "auto_away")) < 1 || !s->activity)
				break;

			if (t - s->activity > tmp)
				command_exec(NULL, s, ("/_autoaway"), 0);
		} while (0);

		do {
			if ((tmp = session_int_get(s, "auto_xa")) < 1 || !s->activity)
				break;

			if (t - s->activity > tmp)
				command_exec(NULL, s, ("/_autoxa"), 0);
		} while (0);
	}

	return 0;
}
Пример #7
0
static TIMER_SESSION(xmsg_iterate_dir)
{
	const char *dir;
	DIR *d;
	struct dirent *de;
	int n = 0;
	const int maxn = session_int_get(s, "max_oneshot_files");

	if (type || !s || !session_connected_get(s))
		return -1;
	
	session_status_set(s, EKG_STATUS_AVAIL);
	if (!(dir = xmsg_dirfix(session_uid_get(s)+XMSG_UID_DIROFFSET))
			|| !(d = opendir(dir))) {

		xerr("unable to open specified directory");
		return 0;
	}
	
	while ((de = readdir(d))) {
		if (!xmsg_handle_file(s, de->d_name))
			n++;
		
		if ((maxn > 0) && n >= maxn) {
			const int i = session_int_get(s, "oneshot_resume_timer");
			if ((i > 0) && timer_add_session(s, "o", i, 0, xmsg_iterate_dir))
				xdebug("oneshot resume timer added");
			session_status_set(s, EKG_STATUS_AWAY);
			break;
		}
	}
	closedir(d);
	xdebug("processed %d files", n);

	return 0;
}
Пример #8
0
static int xmsg_handle_file(session_t *s, const char *fn)
{
	const int nounlink = !session_int_get(s, "unlink_sent");
	const int utb = session_int_get(s, "unlink_toobig");
	const int maxfs = session_int_get(s, "max_filesize");
	const char *dfsuffix = session_get(s, "dotfile_suffix");
	char *namesep = (char*) session_get(s, "name_separator");
	char *dir;
	int dirlen;

	char *msg = NULL;
	int err, fs;
	time_t ft = 0;
	
	if (*fn == '.') /* we're skipping ALL dotfiles */
		return -1;
	dir = (char*) xmsg_dirfix(session_uid_get(s)+XMSG_UID_DIROFFSET);
	dirlen = xstrlen(dir);
		/* first check if buffer is long enough to fit the whole path for dotfile */
	if (strlcpy(dir+dirlen+1, fn, PATH_MAX-dirlen-2-xstrlen(dfsuffix)) >= PATH_MAX-dirlen-2-xstrlen(dfsuffix))
		xerr("Buffer too small for: fn = %s, len(fn) = %d, dirlen = %d, dfsuffixlen = %d", fn, xstrlen(fn), dirlen, xstrlen(dfsuffix));

		/* then fill in middle part of path */
	dir[dirlen] = '/';
		/* and take a much closer look the file */	
	xdebug("s = %s, d = %s, fn = %s", session_uid_get(s), dir, fn);
	if ((err = xmsg_checkoutfile(dir, &msg, &fs, &ft, maxfs))) {
		if (err == EFBIG) {
			print((utb ? "xmsg_toobigrm" : "xmsg_toobig"), fn, session_name(s));
			if (utb) {
				unlink(dir);
				return -1;
			} /* else we need to create the dotfile first */
		} else if (err != ENOENT && err != EINVAL)
			return -1;
	} else if (!nounlink && (utb == (err == EFBIG)))
		unlink(dir);

		/* here: dir = dotf */
	memmove(dir+dirlen+2, dir+dirlen+1, xstrlen(dir) - dirlen);
	dir[dirlen+1] = '.';
	xstrcpy(dir+xstrlen(dir), dfsuffix); /* we've already checked whether it fits */
	
	{
		struct stat st;
		int r;
		
		if (nounlink || !utb) {
			r = !(stat(dir, &st) || S_ISDIR(st.st_mode));
		} else
			r = 0;
		
		if (err == ENOENT) {
			if (r) /* clean up stale dotfile */
				unlink(dir);
			xfree(msg);
			return -1;
		} else if (r) {
			xfree(msg); /* XXX: I think that we rather shouldn't first read, then check if it is needed,
					at least for nounlink mode */
			return -1;
		} else if ((nounlink && !(utb && err == EFBIG)) || (!utb && err == EFBIG))
			close(open(dir, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, 0600));
	}
	
	if (err == EFBIG)
		return -1;
	else if (err == EINVAL)
		xdebug("empty file, not submitting");
	else {
		char *uid	= xmalloc(strlen(fn) + 6);
		char *msgx	= NULL;

		{
			const char *charset = session_get(s, "charset");

			if (charset && (msgx = ekg_convert_string(msg, charset, NULL)))
				xfree(msg);
			else
				msgx = msg;
		}

		xstrcpy(uid, "xmsg:");
		xstrcat(uid, fn);
		if (namesep) {
			char *p, *q = NULL;

			for (p = namesep; *p; p++) {
				char *r = xstrrchr(uid+XMSG_UID_DIROFFSET, *p);
				if (r > q)
					q = r;
			}
			if (q)
				*q = '\0';
		}

		protocol_message_emit(s, uid, NULL, msgx, NULL, ft, EKG_MSGCLASS_CHAT, NULL, EKG_TRY_BEEP, 0);

		xfree(msgx);
		xfree(uid);
	}
	
	return 0;
}