Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117751462
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
11 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/imap/fetchnews.c b/imap/fetchnews.c
index 4215b258c..3cf478af7 100644
--- a/imap/fetchnews.c
+++ b/imap/fetchnews.c
@@ -1,392 +1,381 @@
/* fetchnews.c -- Program to pull new articles from a peer and push to server
*
* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: fetchnews.c,v 1.2 2003/10/22 18:02:57 rjs3 Exp $
+ * $Id: fetchnews.c,v 1.3 2004/01/02 01:14:32 ken3 Exp $
*/
#include <config.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <signal.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include "exitcodes.h"
#include "global.h"
#include "lock.h"
#include "prot.h"
#include "xmalloc.h"
/* global state */
const int config_need_data = 0;
void usage(void)
{
fprintf(stderr,
- "fetchnews [-C <altconfig>] [-s <server>] [-w <wildmat>] [-f <tstamp file>] <peer>\n");
+ "fetchnews [-C <altconfig>] [-s <server>] [-w <wildmat>] [-f <tstamp file>]\n"
+ " [-a <authname> -p <password>] <peer>\n");
exit(-1);
}
int init_net(const char *host, char *port,
struct protstream **in, struct protstream **out)
{
int sock = -1, err;
struct addrinfo hints, *res, *res0;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
if ((err = getaddrinfo(host, port, &hints, &res0)) != 0) {
syslog(LOG_ERR, "getaddrinfo(%s, %s) failed: %m", host, port);
return -1;
}
for (res = res0; res; res = res->ai_next) {
if ((sock = socket(res->ai_family, res->ai_socktype,
res->ai_protocol)) < 0)
continue;
if (connect(sock, res->ai_addr, res->ai_addrlen) >= 0)
break;
close(sock);
sock = -1;
}
freeaddrinfo(res0);
if(sock < 0) {
syslog(LOG_ERR, "connect(%s:%s) failed: %m", host, port);
return -1;
}
*in = prot_new(sock, 0);
*out = prot_new(sock, 1);
prot_setflushonread(*in, *out);
return sock;
}
#define MSGID_GROW 100
int main(int argc, char *argv[])
{
extern char *optarg;
int opt;
char *alt_config = NULL, *port = "119";
const char *peer = NULL, *server = "localhost", *wildmat = "*";
char *authname = NULL, *password = NULL;
int psock = -1, ssock = -1;
struct protstream *pin, *pout, *sin, *sout;
char buf[4096], sbuf[4096];
char sfile[1024] = "";
int fd, i, offered, rejected, accepted, failed;
time_t stamp;
struct tm *tm;
char **msgid = NULL;
if (geteuid() == 0) fatal("must run as the Cyrus user", EC_USAGE);
while ((opt = getopt(argc, argv, "C:s:w:f:a:p:")) != EOF) {
switch (opt) {
case 'C': /* alt config file */
alt_config = optarg;
break;
case 's': /* server */
server = xstrdup(optarg);
if ((port = strchr(server, ':')))
*port++ = '\0';
else
port = "119";
break;
case 'w': /* wildmat */
wildmat = optarg;
break;
case 'f': /* timestamp file */
snprintf(sfile, sizeof(sfile), optarg);
break;
case 'a': /* authname */
authname = optarg;
break;
case 'p': /* password */
password = optarg;
break;
default:
usage();
/* NOTREACHED */
}
}
if (argc - optind < 1) {
usage();
/* NOTREACHED */
}
peer = argv[optind++];
cyrus_init(alt_config, "fetchnews");
/* connect to the peer */
/* xxx configurable port number? */
if ((psock = init_net(peer, "119", &pin, &pout)) < 0) {
fprintf(stderr, "connection to %s failed\n", peer);
cyrus_done();
exit(-1);
}
/* read the initial greeting */
if (!prot_fgets(buf, sizeof(buf), pin) || strncmp("20", buf, 2)) {
syslog(LOG_ERR, "peer not available");
goto quit;
}
if (authname) {
/* authenticate to peer */
/* XXX this should be modified to support SASL and STARTTLS */
prot_printf(pout, "AUTHINFO USER %s\r\n", authname);
if (!prot_fgets(buf, sizeof(buf), pin)) {
syslog(LOG_ERR, "AUTHINFO USER terminated abnormally");
goto quit;
}
else if (!strncmp("381", buf, 3)) {
/* password required */
if (!password)
password = getpass("Please enter the password: ");
if (!password) {
fprintf(stderr, "failed to get password\n");
goto quit;
}
prot_printf(pout, "AUTHINFO PASS %s\r\n", password);
if (!prot_fgets(buf, sizeof(buf), pin)) {
syslog(LOG_ERR, "AUTHINFO PASS terminated abnormally");
goto quit;
}
}
if (strncmp("281", buf, 3)) {
/* auth failed */
goto quit;
}
}
/* change to reader mode - not always necessary, so ignore result */
prot_printf(pout, "MODE READER\r\n");
prot_fgets(buf, sizeof(buf), pin);
- /* connect to the server */
- if ((ssock = init_net(server, port, &sin, &sout)) < 0) {
- fprintf(stderr, "connection to %s failed\n", server);
- goto quit;
- }
-
- /* read the initial greeting */
- if (!prot_fgets(buf, sizeof(buf), sin) || strncmp("20", buf, 2)) {
- syslog(LOG_ERR, "server not available");
- goto quit;
- }
-
- /* tell the server we're going to do streaming */
- prot_printf(sout, "MODE STREAM\r\n");
- if (!prot_fgets(sbuf, sizeof(sbuf), sin)) {
- syslog(LOG_ERR, "MODE STREAM terminated abnormally");
- goto quit;
- }
- else if (strncmp("203", sbuf, 3)) {
- /* server doesn't support STREAM */
- goto quit;
- }
-
/* read the previous timestamp */
if (!sfile[0]) snprintf(sfile, sizeof(sfile), "%s/newsstamp", config_dir);
if ((fd = open(sfile, O_RDWR | O_CREAT, 0644)) == -1) {
syslog(LOG_ERR, "can not open %s", sfile);
goto quit;
}
if (lock_nonblocking(fd) == -1) {
syslog(LOG_ERR, "can not lock %s: %m", sfile);
goto quit;
}
if (read(fd, &stamp, sizeof(stamp)) < sizeof(stamp)) {
/* XXX do something better here */
stamp = time(NULL);
}
/* ask for new articles */
tm = gmtime(&stamp);
strftime(buf, sizeof(buf), "%Y%m%d %H%M%S", tm);
prot_printf(pout, "NEWNEWS %s %s GMT\r\n", wildmat, buf);
if (!prot_fgets(buf, sizeof(buf), pin) || strncmp("23", buf, 2)) {
syslog(LOG_ERR, "peer doesn't support NEWNEWS");
goto quit;
}
/* process the list */
stamp = time(NULL);
offered = rejected = accepted = failed = 0;
while (prot_fgets(buf, sizeof(buf), pin)) {
if (buf[0] == '.') break;
if (!(offered % MSGID_GROW)) { /* time to alloc more */
msgid = (char **)
xrealloc(msgid, (offered + MSGID_GROW) * sizeof(char *));
}
msgid[offered++] = xstrdup(buf);
}
if (buf[0] != '.') {
syslog(LOG_ERR, "NEWNEWS terminated abnormally");
goto quit;
}
+ if (!offered) goto quit;
+
+ /* connect to the server */
+ if ((ssock = init_net(server, port, &sin, &sout)) < 0) {
+ fprintf(stderr, "connection to %s failed\n", server);
+ goto quit;
+ }
+
+ /* read the initial greeting */
+ if (!prot_fgets(buf, sizeof(buf), sin) || strncmp("20", buf, 2)) {
+ syslog(LOG_ERR, "server not available");
+ goto quit;
+ }
/* fetch and store articles */
/* XXX the output of NEWNEWS already contains the terminating \r\n
- after the msgid, so we don't need to add it to CHECK/ARTICLE/TAKETHIS */
+ after the msgid, so we don't need to add it to IHAVE or ARTICLE */
for (i = 0; i < offered; i++) {
/* see if we want this article */
- prot_printf(sout, "CHECK %s", msgid[i]);
+ prot_printf(sout, "IHAVE %s", msgid[i]);
if (!prot_fgets(sbuf, sizeof(sbuf), sin)) {
- syslog(LOG_ERR, "CHECK terminated abnormally");
+ syslog(LOG_ERR, "IHAVE terminated abnormally");
goto quit;
}
- else if (strncmp("238", sbuf, 3)) {
+ else if (strncmp("335", sbuf, 3)) {
/* don't want it */
rejected++;
continue;
}
/* fetch the article */
prot_printf(pout, "ARTICLE %s", msgid[i]);
if (!prot_fgets(buf, sizeof(buf), pin)) {
syslog(LOG_ERR, "ARTICLE terminated abnormally");
goto quit;
}
else if (strncmp("220", buf, 3)) {
- /* doh! the article doesn't exist */
- failed++;
- continue;
+ /* doh! the article doesn't exist, terminate IHAVE */
+ prot_printf(sout, ".\r\n");
}
else {
/* store the article */
- prot_printf(sout, "TAKETHIS %s", msgid[i]);
while (prot_fgets(buf, sizeof(buf), pin)) {
prot_write(sout, buf, strlen(buf));
if (buf[0] == '.' && buf[1] != '.') break;
}
if (buf[0] != '.') {
syslog(LOG_ERR, "ARTICLE terminated abnormally");
goto quit;
}
}
/* see how we did */
if (!prot_fgets(buf, sizeof(buf), sin)) {
- syslog(LOG_ERR, "TAKETHIS terminated abnormally");
+ syslog(LOG_ERR, "IHAVE terminated abnormally");
goto quit;
}
- else if (!strncmp("239", buf, 3))
+ else if (!strncmp("235", buf, 3))
accepted++;
else
failed++;
}
syslog(LOG_NOTICE,
"fetchnews: offered %d, rejected %d, accepted %d, failed %d",
offered, rejected, accepted, failed);
/* write the current timestamp */
lseek(fd, 0, SEEK_SET);
if (write(fd, &stamp, sizeof(stamp)) < sizeof(stamp))
syslog(LOG_ERR, "error writing %s", sfile);
lock_unlock(fd);
close(fd);
quit:
if (psock >= 0) {
prot_printf(pout, "QUIT\r\n");
prot_flush(pout);
/* Flush the incoming buffer */
prot_NONBLOCK(pin);
prot_fill(pin);
/* close/free socket & prot layer */
close(psock);
prot_free(pin);
prot_free(pout);
}
if (ssock >= 0) {
prot_printf(sout, "QUIT\r\n");
prot_flush(sout);
/* Flush the incoming buffer */
prot_NONBLOCK(sin);
prot_fill(sin);
/* close/free socket & prot layer */
close(psock);
prot_free(sin);
prot_free(sout);
}
cyrus_done();
return 0;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Apr 4, 3:10 AM (3 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18822349
Default Alt Text
(11 KB)
Attached To
Mode
R111 cyrus-imapd
Attached
Detach File
Event Timeline