mirror of
https://github.com/Llewellynvdm/conky.git
synced 2024-12-28 04:55:08 +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;
|
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)
|
void *imap_thread(void *arg)
|
||||||
{
|
{
|
||||||
int sockfd, numbytes;
|
int sockfd, numbytes;
|
||||||
@ -1663,6 +1690,7 @@ void *imap_thread(void *arg)
|
|||||||
struct sockaddr_in their_addr; // connector's address information
|
struct sockaddr_in their_addr; // connector's address information
|
||||||
struct mail_s *mail = (struct mail_s *)arg;
|
struct mail_s *mail = (struct mail_s *)arg;
|
||||||
int has_idle = 0;
|
int has_idle = 0;
|
||||||
|
int threadfd = timed_thread_readfd(mail->p_timed_thread);
|
||||||
|
|
||||||
#ifdef HAVE_GETHOSTBYNAME_R
|
#ifdef HAVE_GETHOSTBYNAME_R
|
||||||
if (gethostbyname_r(mail->host, &he, hostbuff, sizeof(hostbuff), &he_res, &he_errno)) { // get the host info
|
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, " ", MAXDATASIZE - strlen(sendbuf) - 1);
|
||||||
strncat(sendbuf, mail->pass, MAXDATASIZE - strlen(sendbuf) - 1);
|
strncat(sendbuf, mail->pass, MAXDATASIZE - strlen(sendbuf) - 1);
|
||||||
strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
|
strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
|
||||||
if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
|
if (imap_command(sockfd, sendbuf, recvbuf, "a1 OK")) {
|
||||||
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);
|
|
||||||
fail++;
|
fail++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1764,26 +1773,7 @@ void *imap_thread(void *arg)
|
|||||||
strncat(sendbuf, mail->folder, MAXDATASIZE - strlen(sendbuf) - 1);
|
strncat(sendbuf, mail->folder, MAXDATASIZE - strlen(sendbuf) - 1);
|
||||||
strncat(sendbuf, " (MESSAGES UNSEEN)\r\n",
|
strncat(sendbuf, " (MESSAGES UNSEEN)\r\n",
|
||||||
MAXDATASIZE - strlen(sendbuf) - 1);
|
MAXDATASIZE - strlen(sendbuf) - 1);
|
||||||
if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
|
if (imap_command(sockfd, sendbuf, recvbuf, "a2 OK")) {
|
||||||
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);
|
|
||||||
fail++;
|
fail++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1817,51 +1807,13 @@ void *imap_thread(void *arg)
|
|||||||
strncpy(sendbuf, "a4 SELECT ", MAXDATASIZE);
|
strncpy(sendbuf, "a4 SELECT ", MAXDATASIZE);
|
||||||
strncat(sendbuf, mail->folder, MAXDATASIZE - strlen(sendbuf) - 1);
|
strncat(sendbuf, mail->folder, MAXDATASIZE - strlen(sendbuf) - 1);
|
||||||
strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
|
strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
|
||||||
if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
|
if (imap_command(sockfd, sendbuf, recvbuf, "a4 OK")) {
|
||||||
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);
|
|
||||||
fail++;
|
fail++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(sendbuf, "a5 IDLE\r\n", MAXDATASIZE);
|
strncpy(sendbuf, "a5 IDLE\r\n", MAXDATASIZE);
|
||||||
if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
|
if (imap_command(sockfd, sendbuf, recvbuf, "+ idling")) {
|
||||||
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);
|
|
||||||
fail++;
|
fail++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1870,17 +1822,17 @@ void *imap_thread(void *arg)
|
|||||||
while (1) {
|
while (1) {
|
||||||
FD_ZERO(&fdset);
|
FD_ZERO(&fdset);
|
||||||
FD_SET(sockfd, &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)) {
|
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) || FD_ISSET(threadfd, &fdset)) {
|
||||||
if (res == -1 && errno == EINTR) {
|
|
||||||
timed_thread_exit(mail->p_timed_thread);
|
timed_thread_exit(mail->p_timed_thread);
|
||||||
} else if (res > 0) {
|
} else if (res > 0) {
|
||||||
if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
|
if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
|
||||||
perror("recv idling");
|
perror("recv idling");
|
||||||
fail++;
|
fail++;
|
||||||
printf("fail\n");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1888,9 +1840,12 @@ void *imap_thread(void *arg)
|
|||||||
}
|
}
|
||||||
recvbuf[numbytes] = '\0';
|
recvbuf[numbytes] = '\0';
|
||||||
if (strlen(recvbuf) > 2) {
|
if (strlen(recvbuf) > 2) {
|
||||||
unsigned long messages, unseen;
|
unsigned long messages, recent;
|
||||||
char *buf = recvbuf;
|
char *buf = recvbuf;
|
||||||
buf = strstr(buf, "EXISTS");
|
buf = strstr(buf, "EXISTS");
|
||||||
|
while (buf && strlen(buf) > 1 && strstr(buf + 1, "EXISTS")) {
|
||||||
|
buf = strstr(buf + 1, "EXISTS");
|
||||||
|
}
|
||||||
if (buf) {
|
if (buf) {
|
||||||
// back up until we reach '*'
|
// back up until we reach '*'
|
||||||
while (buf >= recvbuf && buf[0] != '*') {
|
while (buf >= recvbuf && buf[0] != '*') {
|
||||||
@ -1904,14 +1859,20 @@ void *imap_thread(void *arg)
|
|||||||
}
|
}
|
||||||
buf = recvbuf;
|
buf = recvbuf;
|
||||||
buf = strstr(buf, "RECENT");
|
buf = strstr(buf, "RECENT");
|
||||||
|
while (buf && strlen(buf) > 1 && strstr(buf + 1, "RECENT")) {
|
||||||
|
buf = strstr(buf + 1, "RECENT");
|
||||||
|
}
|
||||||
if (buf) {
|
if (buf) {
|
||||||
// back up until we reach '*'
|
// back up until we reach '*'
|
||||||
while (buf >= recvbuf && buf[0] != '*') {
|
while (buf >= recvbuf && buf[0] != '*') {
|
||||||
buf--;
|
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);
|
timed_thread_lock(mail->p_timed_thread);
|
||||||
mail->unseen = unseen;
|
mail->unseen = recent;
|
||||||
timed_thread_unlock(mail->p_timed_thread);
|
timed_thread_unlock(mail->p_timed_thread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
#ifndef HAVE_CLOCK_GETTIME
|
#ifndef HAVE_CLOCK_GETTIME
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
@ -47,6 +48,7 @@ struct _timed_thread {
|
|||||||
void *arg; /* thread function argument */
|
void *arg; /* thread function argument */
|
||||||
struct timespec interval_time; /* interval_usecs as a struct timespec */
|
struct timespec interval_time; /* interval_usecs as a struct timespec */
|
||||||
struct timespec wait_time; /* absolute future time next timed_thread_test will wait until */
|
struct timespec wait_time; /* absolute future time next timed_thread_test will wait until */
|
||||||
|
int pipefd[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* linked list of created threads */
|
/* 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_head = NULL;
|
||||||
static timed_thread_list *p_timed_thread_list_tail = 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)
|
static int now(struct timespec *abstime)
|
||||||
{
|
{
|
||||||
#ifndef HAVE_CLOCK_GETTIME
|
#ifndef HAVE_CLOCK_GETTIME
|
||||||
@ -96,6 +103,11 @@ timed_thread *timed_thread_create(void *start_routine(void *), void *arg,
|
|||||||
return NULL;
|
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 */
|
/* init attributes, e.g. joinable thread */
|
||||||
pthread_attr_init(&p_timed_thread->thread_attr);
|
pthread_attr_init(&p_timed_thread->thread_attr);
|
||||||
pthread_attr_setdetachstate(&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_mutex_lock(&p_timed_thread->runnable_mutex);
|
||||||
pthread_cond_signal(&p_timed_thread->runnable_cond);
|
pthread_cond_signal(&p_timed_thread->runnable_cond);
|
||||||
pthread_mutex_unlock(&p_timed_thread->runnable_mutex);
|
pthread_mutex_unlock(&p_timed_thread->runnable_mutex);
|
||||||
|
write(p_timed_thread->pipefd[1], "die", 3);
|
||||||
|
|
||||||
/* join the terminating thread */
|
/* join the terminating thread */
|
||||||
if (p_timed_thread->thread) {
|
if (p_timed_thread->thread) {
|
||||||
@ -236,6 +249,9 @@ void timed_thread_exit(timed_thread *p_timed_thread)
|
|||||||
{
|
{
|
||||||
assert(p_timed_thread != NULL);
|
assert(p_timed_thread != NULL);
|
||||||
|
|
||||||
|
close(p_timed_thread->pipefd[0]);
|
||||||
|
close(p_timed_thread->pipefd[1]);
|
||||||
|
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,4 +63,7 @@ int timed_thread_register(timed_thread *p_timed_thread,
|
|||||||
/* destroy all registered timed threads */
|
/* destroy all registered timed threads */
|
||||||
void timed_thread_destroy_registered_threads(void);
|
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_ */
|
#endif /* #ifdef _TIMED_THREAD_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user