mirror of
https://github.com/Llewellynvdm/conky.git
synced 2024-12-27 20:44:56 +00:00
improving IMAP IDLE support
git-svn-id: https://conky.svn.sourceforge.net/svnroot/conky/trunk/conky1@1257 7f574dfc-610e-0410-a909-a81674777703
This commit is contained in:
parent
c15287e798
commit
e80ec4cc5f
135
src/conky.c
135
src/conky.c
@ -1647,6 +1647,33 @@ struct mail_s *parse_mail_args(char type, const char *arg)
|
||||
return mail;
|
||||
}
|
||||
|
||||
int imap_command(int sockfd, char *command, char *response, const char *verify)
|
||||
{
|
||||
struct timeval timeout;
|
||||
fd_set fdset;
|
||||
int res, numbytes;
|
||||
if (send(sockfd, command, strlen(command), 0) == -1) {
|
||||
perror("send");
|
||||
return -1;
|
||||
}
|
||||
timeout.tv_sec = 60; // 60 second timeout i guess
|
||||
timeout.tv_usec = 0;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sockfd, &fdset);
|
||||
res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
|
||||
if (res > 0) {
|
||||
if ((numbytes = recv(sockfd, response, MAXDATASIZE - 1, 0)) == -1) {
|
||||
perror("recv");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
response[numbytes] = '\0';
|
||||
if (strstr(response, verify) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *imap_thread(void *arg)
|
||||
{
|
||||
int sockfd, numbytes;
|
||||
@ -1663,6 +1690,7 @@ void *imap_thread(void *arg)
|
||||
struct sockaddr_in their_addr; // connector's address information
|
||||
struct mail_s *mail = (struct mail_s *)arg;
|
||||
int has_idle = 0;
|
||||
int threadfd = timed_thread_readfd(mail->p_timed_thread);
|
||||
|
||||
#ifdef HAVE_GETHOSTBYNAME_R
|
||||
if (gethostbyname_r(mail->host, &he, hostbuff, sizeof(hostbuff), &he_res, &he_errno)) { // get the host info
|
||||
@ -1733,26 +1761,7 @@ void *imap_thread(void *arg)
|
||||
strncat(sendbuf, " ", MAXDATASIZE - strlen(sendbuf) - 1);
|
||||
strncat(sendbuf, mail->pass, MAXDATASIZE - strlen(sendbuf) - 1);
|
||||
strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
|
||||
if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
|
||||
perror("send a1");
|
||||
fail++;
|
||||
break;
|
||||
}
|
||||
timeout.tv_sec = 60; // 60 second timeout i guess
|
||||
timeout.tv_usec = 0;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sockfd, &fdset);
|
||||
res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
|
||||
if (res > 0) {
|
||||
if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
|
||||
perror("recv a1");
|
||||
fail++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
recvbuf[numbytes] = '\0';
|
||||
if (strstr(recvbuf, "a1 OK") == NULL) {
|
||||
ERR("IMAP server login failed: %s", recvbuf);
|
||||
if (imap_command(sockfd, sendbuf, recvbuf, "a1 OK")) {
|
||||
fail++;
|
||||
break;
|
||||
}
|
||||
@ -1764,26 +1773,7 @@ void *imap_thread(void *arg)
|
||||
strncat(sendbuf, mail->folder, MAXDATASIZE - strlen(sendbuf) - 1);
|
||||
strncat(sendbuf, " (MESSAGES UNSEEN)\r\n",
|
||||
MAXDATASIZE - strlen(sendbuf) - 1);
|
||||
if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
|
||||
perror("send a2");
|
||||
fail++;
|
||||
break;
|
||||
}
|
||||
timeout.tv_sec = 60; // 60 second timeout i guess
|
||||
timeout.tv_usec = 0;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sockfd, &fdset);
|
||||
res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
|
||||
if (res > 0) {
|
||||
if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
|
||||
perror("recv a2");
|
||||
fail++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
recvbuf[numbytes] = '\0';
|
||||
if (strstr(recvbuf, "a2 OK") == NULL) {
|
||||
ERR("IMAP status failed: %s", recvbuf);
|
||||
if (imap_command(sockfd, sendbuf, recvbuf, "a2 OK")) {
|
||||
fail++;
|
||||
break;
|
||||
}
|
||||
@ -1817,51 +1807,13 @@ void *imap_thread(void *arg)
|
||||
strncpy(sendbuf, "a4 SELECT ", MAXDATASIZE);
|
||||
strncat(sendbuf, mail->folder, MAXDATASIZE - strlen(sendbuf) - 1);
|
||||
strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
|
||||
if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
|
||||
perror("send a4");
|
||||
fail++;
|
||||
break;
|
||||
}
|
||||
timeout.tv_sec = 60; // 60 second timeout i guess
|
||||
timeout.tv_usec = 0;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sockfd, &fdset);
|
||||
res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
|
||||
if (res > 0) {
|
||||
if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
|
||||
perror("recv a4");
|
||||
fail++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
recvbuf[numbytes] = '\0';
|
||||
if (strstr(recvbuf, "a4 OK") == NULL) {
|
||||
ERR("IMAP status failed: %s", recvbuf);
|
||||
if (imap_command(sockfd, sendbuf, recvbuf, "a4 OK")) {
|
||||
fail++;
|
||||
break;
|
||||
}
|
||||
|
||||
strncpy(sendbuf, "a5 IDLE\r\n", MAXDATASIZE);
|
||||
if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
|
||||
perror("send a5");
|
||||
fail++;
|
||||
break;
|
||||
}
|
||||
timeout.tv_sec = 60; // 60 second timeout i guess
|
||||
timeout.tv_usec = 0;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sockfd, &fdset);
|
||||
res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
|
||||
if (res > 0) {
|
||||
if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
|
||||
perror("recv a5");
|
||||
fail++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
recvbuf[numbytes] = '\0';
|
||||
if (strstr(recvbuf, "+ idling") == NULL) {
|
||||
ERR("IMAP status failed: %s", recvbuf);
|
||||
if (imap_command(sockfd, sendbuf, recvbuf, "+ idling")) {
|
||||
fail++;
|
||||
break;
|
||||
}
|
||||
@ -1870,17 +1822,17 @@ void *imap_thread(void *arg)
|
||||
while (1) {
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sockfd, &fdset);
|
||||
FD_SET(threadfd, &fdset);
|
||||
res = pselect(MAX(sockfd + 1, threadfd + 1), &fdset, NULL, NULL, NULL, &oldmask);
|
||||
if (timed_thread_test(mail->p_timed_thread)) {
|
||||
break;
|
||||
timed_thread_exit(mail->p_timed_thread);
|
||||
}
|
||||
res = pselect(sockfd + 1, &fdset, NULL, NULL, NULL, &oldmask);
|
||||
if (res == -1 && errno == EINTR) {
|
||||
if ((res == -1 && errno == EINTR) || FD_ISSET(threadfd, &fdset)) {
|
||||
timed_thread_exit(mail->p_timed_thread);
|
||||
} else if (res > 0) {
|
||||
if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
|
||||
perror("recv idling");
|
||||
fail++;
|
||||
printf("fail\n");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -1888,9 +1840,12 @@ void *imap_thread(void *arg)
|
||||
}
|
||||
recvbuf[numbytes] = '\0';
|
||||
if (strlen(recvbuf) > 2) {
|
||||
unsigned long messages, unseen;
|
||||
unsigned long messages, recent;
|
||||
char *buf = recvbuf;
|
||||
buf = strstr(buf, "EXISTS");
|
||||
while (buf && strlen(buf) > 1 && strstr(buf + 1, "EXISTS")) {
|
||||
buf = strstr(buf + 1, "EXISTS");
|
||||
}
|
||||
if (buf) {
|
||||
// back up until we reach '*'
|
||||
while (buf >= recvbuf && buf[0] != '*') {
|
||||
@ -1904,14 +1859,20 @@ void *imap_thread(void *arg)
|
||||
}
|
||||
buf = recvbuf;
|
||||
buf = strstr(buf, "RECENT");
|
||||
while (buf && strlen(buf) > 1 && strstr(buf + 1, "RECENT")) {
|
||||
buf = strstr(buf + 1, "RECENT");
|
||||
}
|
||||
if (buf) {
|
||||
// back up until we reach '*'
|
||||
while (buf >= recvbuf && buf[0] != '*') {
|
||||
buf--;
|
||||
}
|
||||
if (sscanf(buf, "* %lu RECENT\r\n", &unseen) == 1) {
|
||||
if (sscanf(buf, "* %lu RECENT\r\n", &recent) == 1) {
|
||||
/*
|
||||
* if we have > 0 recent, re-check the unseen count
|
||||
*/
|
||||
timed_thread_lock(mail->p_timed_thread);
|
||||
mail->unseen = unseen;
|
||||
mail->unseen = recent;
|
||||
timed_thread_unlock(mail->p_timed_thread);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#ifndef HAVE_CLOCK_GETTIME
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
@ -47,6 +48,7 @@ struct _timed_thread {
|
||||
void *arg; /* thread function argument */
|
||||
struct timespec interval_time; /* interval_usecs as a struct timespec */
|
||||
struct timespec wait_time; /* absolute future time next timed_thread_test will wait until */
|
||||
int pipefd[2];
|
||||
};
|
||||
|
||||
/* linked list of created threads */
|
||||
@ -59,6 +61,11 @@ typedef struct _timed_thread_list {
|
||||
static timed_thread_list *p_timed_thread_list_head = NULL;
|
||||
static timed_thread_list *p_timed_thread_list_tail = NULL;
|
||||
|
||||
int timed_thread_readfd(timed_thread *p_timed_thread)
|
||||
{
|
||||
return p_timed_thread->pipefd[0];
|
||||
}
|
||||
|
||||
static int now(struct timespec *abstime)
|
||||
{
|
||||
#ifndef HAVE_CLOCK_GETTIME
|
||||
@ -96,6 +103,11 @@ timed_thread *timed_thread_create(void *start_routine(void *), void *arg,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create thread pipe (used to tell threads to die) */
|
||||
if (pipe(p_timed_thread->pipefd)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* init attributes, e.g. joinable thread */
|
||||
pthread_attr_init(&p_timed_thread->thread_attr);
|
||||
pthread_attr_setdetachstate(&p_timed_thread->thread_attr,
|
||||
@ -147,6 +159,7 @@ void timed_thread_destroy(timed_thread *p_timed_thread,
|
||||
pthread_mutex_lock(&p_timed_thread->runnable_mutex);
|
||||
pthread_cond_signal(&p_timed_thread->runnable_cond);
|
||||
pthread_mutex_unlock(&p_timed_thread->runnable_mutex);
|
||||
write(p_timed_thread->pipefd[1], "die", 3);
|
||||
|
||||
/* join the terminating thread */
|
||||
if (p_timed_thread->thread) {
|
||||
@ -236,6 +249,9 @@ void timed_thread_exit(timed_thread *p_timed_thread)
|
||||
{
|
||||
assert(p_timed_thread != NULL);
|
||||
|
||||
close(p_timed_thread->pipefd[0]);
|
||||
close(p_timed_thread->pipefd[1]);
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
|
@ -63,4 +63,7 @@ int timed_thread_register(timed_thread *p_timed_thread,
|
||||
/* destroy all registered timed threads */
|
||||
void timed_thread_destroy_registered_threads(void);
|
||||
|
||||
/* returns read file descriptor for thread pipe */
|
||||
int timed_thread_readfd(timed_thread *p_timed_thread);
|
||||
|
||||
#endif /* #ifdef _TIMED_THREAD_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user