From 54c2d8ef501c09178be9c3a36d4234e156d8a458 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Sun, 23 Jan 2000 21:25:46 +0000 Subject: [PATCH] * Temporary hack to ig_tcp_server() to listen on an arbitrary port if the one specified is not bindable (for development only) * Added SM_DONT_BUMP_REF flag to CtdlSaveMsgPointerInRoom() to be used only in very specific and special situations * Generate delivery instructions when outbound SMTP mail is created from within Citadel (as opposed to being from the SMTP module) --- citadel/ChangeLog | 9 ++ citadel/Makefile.in | 4 +- citadel/clientsocket.c | 184 +++++++++++++++++++++++++++++++++++++++++ citadel/clientsocket.h | 16 ++++ citadel/msgbase.c | 52 +++++++----- citadel/msgbase.h | 2 + citadel/sysconfig.h | 4 +- citadel/sysdep.c | 11 ++- 8 files changed, 257 insertions(+), 25 deletions(-) create mode 100644 citadel/clientsocket.c create mode 100644 citadel/clientsocket.h diff --git a/citadel/ChangeLog b/citadel/ChangeLog index 1d0925f80..8260a195f 100644 --- a/citadel/ChangeLog +++ b/citadel/ChangeLog @@ -1,4 +1,12 @@ $Log$ +Revision 1.451 2000/01/23 21:25:45 ajc +* Temporary hack to ig_tcp_server() to listen on an arbitrary port if the + one specified is not bindable (for development only) +* Added SM_DONT_BUMP_REF flag to CtdlSaveMsgPointerInRoom() to be used only + in very specific and special situations +* Generate delivery instructions when outbound SMTP mail is created from + within Citadel (as opposed to being from the SMTP module) + Revision 1.450 2000/01/23 05:22:41 ajc * Coded up some more of the SMTP-sender (still not done) @@ -1578,3 +1586,4 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant Fri Jul 10 1998 Art Cancro * Initial CVS import + diff --git a/citadel/Makefile.in b/citadel/Makefile.in index 9f8d3537c..c526414b2 100644 --- a/citadel/Makefile.in +++ b/citadel/Makefile.in @@ -73,7 +73,7 @@ SOURCES=aidepost.c citadel.c citmail.c citserver.c client_chat.c commands.c \ whobbs.c sendcommand.c mime_parser.c base64.c qpdecode.c getutline.c \ auth.c chkpwd.c client_icq.c html.c vcard.c serv_upgrade.c \ serv_smtp.c serv_pop3.c internet_addressing.c parsedate.c genstamp.c \ - domain.c + domain.c clientsocket.c DEP_FILES=$(SOURCES:.c=.d) @@ -110,7 +110,7 @@ SERV_OBJS = citserver.ro user_ops.ro support.ro room_ops.ro file_ops.ro \ msgbase.ro config.ro sysdep.ro locate_host.ro housekeeping.ro \ database.ro control.ro logging.ro policy.ro dynloader.ro tools.ro \ mime_parser.ro html.ro internet_addressing.ro \ - parsedate.ro genstamp.ro \ + parsedate.ro genstamp.ro clientsocket.ro \ $(AUTH) $(LIBOBJS:.o=.ro) citserver: $(SERV_OBJS) diff --git a/citadel/clientsocket.c b/citadel/clientsocket.c new file mode 100644 index 000000000..710df1a3f --- /dev/null +++ b/citadel/clientsocket.c @@ -0,0 +1,184 @@ +/* + * $Id$ + * + * This module handles client-side sockets opened by the Citadel server (for + * the client side of Internet protocols, etc.) It does _not_ handle client + * sockets for the Citadel client; for that you must look in ipc_c_tcp.c + * (which, uncoincidentally, bears a striking similarity to this file). + * + */ + +#include "sysdep.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "citadel.h" +#ifndef HAVE_SNPRINTF +#include "snprintf.h" +#endif +#include "sysdep_decls.h" + +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif + +int sock_connect(char *host, char *service, char *protocol) +{ + struct hostent *phe; + struct servent *pse; + struct protoent *ppe; + struct sockaddr_in sin; + int s, type; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + + pse = getservbyname(service, protocol); + if (pse) { + sin.sin_port = pse->s_port; + } else if ((sin.sin_port = htons((u_short) atoi(service))) == 0) { + lprintf(3, "Can't get %s service entry: %s\n", + service, strerror(errno)); + return(-1); + } + phe = gethostbyname(host); + if (phe) { + memcpy(&sin.sin_addr, phe->h_addr, phe->h_length); + } else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) { + lprintf(3, "Can't get %s host entry: %s\n", + host, strerror(errno)); + return(-1); + } + if ((ppe = getprotobyname(protocol)) == 0) { + lprintf(3, "Can't get %s protocol entry: %s\n", + protocol, strerror(errno)); + return(-1); + } + if (!strcmp(protocol, "udp")) { + type = SOCK_DGRAM; + } else { + type = SOCK_STREAM; + } + + s = socket(PF_INET, type, ppe->p_proto); + if (s < 0) { + lprintf(3, "Can't create socket: %s\n", strerror(errno)); + return(-1); + } + +/* FIX ... the alarm clock is a problem for multithreaded programs because all + * threads receive the signal. + signal(SIGALRM, timeout); + alarm(30); + */ + + if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + lprintf(3, "can't connect to %s.%s: %s\n", + host, service, strerror(errno)); + return(-1); + } +/* + alarm(0); + signal(SIGALRM, SIG_IGN); + */ + + return (s); +} + +/* + * sock_read() - input binary data from socket. + * Returns the number of bytes read, or -1 for error. + */ +int sock_read(int sock, char *buf, int bytes) +{ + int len, rlen; + + len = 0; + while (len < bytes) { + rlen = read(sock, &buf[len], bytes - len); + if (rlen < 1) { + return (-1); + } + len = len + rlen; + } + return (len); +} + + +/* + * sock_write() - send binary to server. + * Returns the number of bytes written, or -1 for error. + */ +int sock_write(int sock, char *buf, int nbytes) +{ + int bytes_written = 0; + int retval; + while (bytes_written < nbytes) { + retval = write(sock, &buf[bytes_written], + nbytes - bytes_written); + if (retval < 1) { + return (-1); + } + bytes_written = bytes_written + retval; + } + return (bytes_written); +} + + +/* + * Input string from socket - implemented in terms of sock_read() + * + */ +int sock_gets(int sock, char *buf) +{ + int i; + + /* Read one character at a time. + */ + for (i = 0;; i++) { + if (sock_read(sock, &buf[i], 1) < 0) return(-1); + if (buf[i] == '\n' || i == 255) + break; + } + + /* If we got a long line, discard characters until the newline. + */ + if (i == 255) + while (buf[i] != '\n') + if (sock_read(sock, &buf[i], 1) < 0) return(-1); + + /* Strip any trailing CR and LF characters. + */ + while ( (strlen(buf)>0) + && ((buf[strlen(buf)-1]==13) + || (buf[strlen(buf)-1]==10)) ) { + buf[strlen(buf)-1] = 0; + } + return(strlen(buf)); +} + + +/* + * sock_puts() - send line to server - implemented in terms of serv_write() + * Returns the number of bytes written, or -1 for error. + */ +int sock_puts(int sock, char *buf) +{ + int i, j; + + i = sock_write(sock, buf, strlen(buf)); + if (i<0) return(i); + j = sock_write(sock, "\n", 1); + if (j<0) return(j); + return(i+j); +} diff --git a/citadel/clientsocket.h b/citadel/clientsocket.h new file mode 100644 index 000000000..0185fdf24 --- /dev/null +++ b/citadel/clientsocket.h @@ -0,0 +1,16 @@ +/* + * $Id$ + * + * Header file for TCP client socket library + */ + +int sock_connect(char *host, char *service, char *protocol); +int sock_read(int sock, char *buf, int bytes); +int sock_write(int sock, *buf, int nbytes); +int *sock_gets(int sock, *buf); +int sock_puts(int sock, *buf); + +/* + * This looks dumb, but it's being done for future portability + */ +#define sock_close(sock) close(sock) diff --git a/citadel/msgbase.c b/citadel/msgbase.c index bd118964f..755743d19 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -1320,7 +1320,9 @@ int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int flags) { getroom(&CC->quickroom, hold_rm); /* Bump the reference count for this message. */ - AdjRefCount(msgid, +1); + if ((flags & SM_DONT_BUMP_REF)==0) { + AdjRefCount(msgid, +1); + } /* Return success. */ if (msg != NULL) CtdlFreeMessage(msg); @@ -1531,6 +1533,7 @@ long CtdlSaveMsg(struct CtdlMessage *msg, /* message to save */ static int seqnum = 1; struct CtdlMessage *imsg; char *instr; + long imsgid; lprintf(9, "CtdlSaveMsg() called\n"); if (is_valid_message(msg) == 0) return(-1); /* self check */ @@ -1670,7 +1673,6 @@ long CtdlSaveMsg(struct CtdlMessage *msg, /* message to save */ /* Now figure out where to store the pointers */ lprintf(9, "Storing pointers\n"); - /* If this is being done by the networker delivering a private * message, we want to BYPASS saving the sender's copy (because there * is no local sender; it would otherwise go to the Trashcan). @@ -1682,23 +1684,6 @@ long CtdlSaveMsg(struct CtdlMessage *msg, /* message to save */ /* For internet mail, drop a copy in the outbound queue room */ if (mailtype == MES_INTERNET) { CtdlSaveMsgPointerInRoom(SMTP_SPOOLOUT_ROOM, newmsgid, 0); - - /* And generate delivery instructions */ - lprintf(9, "Generating delivery instructions\n"); - instr = mallok(2048); - sprintf(instr, - "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n" - "remote|%s|0||\n", - SPOOLMIME, newmsgid, time(NULL), recipient ); - - imsg = mallok(sizeof(struct CtdlMessage)); - memset(imsg, 0, sizeof(struct CtdlMessage)); - imsg->cm_magic = CTDLMESSAGE_MAGIC; - imsg->cm_anon_type = MES_NORMAL; - imsg->cm_format_type = FMT_RFC822; - imsg->cm_fields['M'] = instr; - CtdlSaveMsg(imsg, "", SMTP_SPOOLOUT_ROOM, MES_LOCAL, 1); - CtdlFreeMessage(imsg); } /* Bump this user's messages posted counter. */ @@ -1727,6 +1712,32 @@ long CtdlSaveMsg(struct CtdlMessage *msg, /* message to save */ if (strcasecmp(hold_rm, CC->quickroom.QRname)) getroom(&CC->quickroom, hold_rm); + /* For internet mail, generate delivery instructions + * (Yes, this is recursive! Deal with it!) + */ + if (mailtype == MES_INTERNET) { + lprintf(9, "Generating delivery instructions\n"); + instr = mallok(2048); + sprintf(instr, + "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n" + "remote|%s|0||\n", + SPOOLMIME, newmsgid, time(NULL), recipient ); + + imsg = mallok(sizeof(struct CtdlMessage)); + memset(imsg, 0, sizeof(struct CtdlMessage)); + imsg->cm_magic = CTDLMESSAGE_MAGIC; + imsg->cm_anon_type = MES_NORMAL; + imsg->cm_format_type = FMT_RFC822; + imsg->cm_fields['M'] = instr; + imsgid = send_message(imsg, 1, NULL); + if (imsgid >= 0L) { + CtdlSaveMsgPointerInRoom(SMTP_SPOOLOUT_ROOM, + imsgid, + SM_DONT_BUMP_REF); + } + CtdlFreeMessage(imsg); + } + return(newmsgid); } @@ -2377,10 +2388,11 @@ void AdjRefCount(long msgnum, int incr) */ begin_critical_section(S_SUPPMSGMAIN); GetSuppMsgInfo(&smi, msgnum); + lprintf(9, "Ref count for message <%ld> before write is <%d>\n", + msgnum, smi.smi_refcount); smi.smi_refcount += incr; PutSuppMsgInfo(&smi); end_critical_section(S_SUPPMSGMAIN); - lprintf(9, "Ref count for message <%ld> after write is <%d>\n", msgnum, smi.smi_refcount); diff --git a/citadel/msgbase.h b/citadel/msgbase.h index 9e55685b5..51e104ff9 100644 --- a/citadel/msgbase.h +++ b/citadel/msgbase.h @@ -14,6 +14,8 @@ */ #define SM_VERIFY_GOODNESS 1 /* Verify this is a real msg number */ #define SM_DO_REPL_CHECK 2 /* Perform replication checks */ +#define SM_DONT_BUMP_REF 3 /* Don't bump reference count + (use with extreme care!!!!!!) */ /* diff --git a/citadel/sysconfig.h b/citadel/sysconfig.h index 3ce4597f8..198f7e557 100644 --- a/citadel/sysconfig.h +++ b/citadel/sysconfig.h @@ -83,8 +83,8 @@ * These define what port to listen on for various services. * FIX ... put this in a programmable config somewhere */ -#define POP3_PORT 1110 -#define SMTP_PORT 2525 +#define POP3_PORT 110 +#define SMTP_PORT 25 /* diff --git a/citadel/sysdep.c b/citadel/sysdep.c index 35a3d8f43..6bde9f396 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -285,7 +285,16 @@ int ig_tcp_server(int port_number, int queue_len) if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { lprintf(1, "citserver: Can't bind: %s\n", strerror(errno)); - return(-1); + sin.sin_port = 0; + if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + lprintf(1, "citserver: Can't bind: %s\n", + strerror(errno)); + return(-1); + } + else { + lprintf(1, "bind to alternate port %d ok\n", + htons(sin.sin_port) ); + } } if (listen(s, queue_len) < 0) { -- 2.30.2