X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fnetwork%2Fserv_network.c;h=eae59f394c1d1a99566e90d31c2b55e7e16fa33b;hb=f1ee61891901850ebbdee1e9440b363dc6df540a;hp=5740feaa045534cdefd88d5add734ab1a04139c4;hpb=95a200d4c65532f812b5d3fc471513751e7fa7cf;p=citadel.git diff --git a/citadel/modules/network/serv_network.c b/citadel/modules/network/serv_network.c index 5740feaa0..eae59f394 100644 --- a/citadel/modules/network/serv_network.c +++ b/citadel/modules/network/serv_network.c @@ -1,6 +1,4 @@ /* - * $Id$ - * * This module handles shared rooms, inter-Citadel mail, and outbound * mailing list processing. * @@ -57,6 +55,13 @@ # include # endif #endif +#ifdef HAVE_SYSCALL_H +# include +#else +# if HAVE_SYS_SYSCALL_H +# include +# endif +#endif #include #include @@ -68,7 +73,6 @@ #include "support.h" #include "config.h" #include "user_ops.h" -#include "policy.h" #include "database.h" #include "msgbase.h" #include "internet_addressing.h" @@ -217,7 +221,7 @@ int network_usetable(struct CtdlMessage *msg) { cdbut = cdb_fetch(CDB_USETABLE, msgid, strlen(msgid)); if (cdbut != NULL) { cdb_free(cdbut); - CtdlLogPrintf(CTDL_DEBUG, "network_usetable() : we already have %s\n", msgid); + syslog(LOG_DEBUG, "network_usetable() : we already have %s\n", msgid); return(1); } @@ -319,7 +323,7 @@ int is_valid_node(char *nexthop, char *secret, char *node) { * First try the neighbor nodes */ if (working_ignetcfg == NULL) { - CtdlLogPrintf(CTDL_ERR, "working_ignetcfg is NULL!\n"); + syslog(LOG_ERR, "working_ignetcfg is NULL!\n"); if (nexthop != NULL) { strcpy(nexthop, ""); } @@ -367,7 +371,7 @@ int is_valid_node(char *nexthop, char *secret, char *node) { /* * If we get to this point, the supplied node name is bogus. */ - CtdlLogPrintf(CTDL_ERR, "Invalid node name <%s>\n", node); + syslog(LOG_ERR, "Invalid node name <%s>\n", node); return(-1); } @@ -406,8 +410,11 @@ void cmd_gnet(char *argbuf) { void cmd_snet(char *argbuf) { char tempfilename[PATH_MAX]; char filename[PATH_MAX]; - char buf[SIZ]; - FILE *fp, *newfp; + int TmpFD; + StrBuf *Line; + struct stat StatBuf; + long len; + int rc; unbuffer_output(); @@ -416,40 +423,67 @@ void cmd_snet(char *argbuf) { } else if (CtdlAccessCheck(ac_room_aide)) return; - CtdlMakeTempFileName(tempfilename, sizeof tempfilename); - assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir); + len = assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir); + memcpy(tempfilename, filename, len + 1); - fp = fopen(tempfilename, "w"); - if (fp == NULL) { - cprintf("%d Cannot open %s: %s\n", + memset(&StatBuf, 0, sizeof(struct stat)); + if ((stat(filename, &StatBuf) == -1) || (StatBuf.st_size == 0)) + StatBuf.st_size = 80; /* Not there or empty? guess 80 chars line. */ + + sprintf(tempfilename + len, ".%d", CC->cs_pid); + errno = 0; + TmpFD = open(tempfilename, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); + + if ((TmpFD > 0) && (errno == 0)) + { + char *tmp = malloc(StatBuf.st_size * 2); + memset(tmp, ' ', StatBuf.st_size * 2); + rc = write(TmpFD, tmp, StatBuf.st_size * 2); + free(tmp); + if ((rc <= 0) || (rc != StatBuf.st_size * 2)) + { + close(TmpFD); + cprintf("%d Unable to allocate the space required for %s: %s\n", + ERROR + INTERNAL_ERROR, + tempfilename, + strerror(errno)); + unlink(tempfilename); + return; + } + lseek(TmpFD, SEEK_SET, 0); + } + else { + cprintf("%d Unable to allocate the space required for %s: %s\n", ERROR + INTERNAL_ERROR, tempfilename, strerror(errno)); + unlink(tempfilename); + return; } + Line = NewStrBuf(); cprintf("%d %s\n", SEND_LISTING, tempfilename); - while (client_getln(buf, sizeof buf) >= 0 && strcmp(buf, "000")) { - fprintf(fp, "%s\n", buf); + + len = 0; + while (rc = CtdlClientGetLine(Line), + (rc >= 0)) + { + if ((rc == 3) && (strcmp(ChrPtr(Line), "000") == 0)) + break; + StrBufAppendBufPlain(Line, HKEY("\n"), 0); + write(TmpFD, ChrPtr(Line), StrLength(Line)); + len += StrLength(Line); } - fclose(fp); + FreeStrBuf(&Line); + ftruncate(TmpFD, len); + close(TmpFD); /* Now copy the temp file to its permanent location. * (We copy instead of link because they may be on different filesystems) */ begin_critical_section(S_NETCONFIGS); - fp = fopen(tempfilename, "r"); - if (fp != NULL) { - newfp = fopen(filename, "w"); - if (newfp != NULL) { - while (fgets(buf, sizeof buf, fp) != NULL) { - fprintf(newfp, "%s", buf); - } - fclose(newfp); - } - fclose(fp); - } + rename(tempfilename, filename); end_critical_section(S_NETCONFIGS); - unlink(tempfilename); } @@ -528,7 +562,7 @@ void network_deliver_digest(SpoolControl *sc) { recps = malloc(recps_len); if (recps == NULL) { - CtdlLogPrintf(CTDL_EMERG, "Cannot allocate %ld bytes for recps...\n", (long)recps_len); + syslog(LOG_EMERG, "Cannot allocate %ld bytes for recps...\n", (long)recps_len); abort(); } @@ -583,7 +617,7 @@ void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc) { recps = malloc(recps_len); if (recps == NULL) { - CtdlLogPrintf(CTDL_EMERG, "Cannot allocate %ld bytes for recps...\n", (long)recps_len); + syslog(LOG_EMERG, "Cannot allocate %ld bytes for recps...\n", (long)recps_len); abort(); } @@ -648,7 +682,22 @@ void network_spool_msg(long msgnum, void *userdata) { */ msg = CtdlFetchMessage(msgnum, 1); if (msg != NULL) { - + int len, rlen; + char *pCh; + + if (msg->cm_fields['V'] == NULL){ + /* local message, no enVelope */ + StrBuf *Buf; + Buf = NewStrBuf(); + StrBufAppendBufPlain(Buf, msg->cm_fields['O'], -1, 0); + StrBufAppendBufPlain(Buf, HKEY("@"), 0); + StrBufAppendBufPlain(Buf, config.c_fqdn, -1, 0); + + msg->cm_fields['K'] = SmashStrBuf(&Buf); + } + else { + msg->cm_fields['K'] = strdup (msg->cm_fields['V']); + } /* Set the 'List-ID' header */ if (msg->cm_fields['L'] != NULL) { free(msg->cm_fields['L']); @@ -665,24 +714,37 @@ void network_spool_msg(long msgnum, void *userdata) { if (msg->cm_fields['U'] == NULL) { msg->cm_fields['U'] = strdup("(no subject)"); } - snprintf(buf, sizeof buf, "[%s] %s", CC->room.QRname, msg->cm_fields['U']); - free(msg->cm_fields['U']); - msg->cm_fields['U'] = strdup(buf); + + len = strlen(msg->cm_fields['U']); + rlen = strlen(CC->room.QRname); + pCh = strstr(msg->cm_fields['U'], CC->room.QRname); + if ((pCh == NULL) || + (*(pCh + rlen) != ']') || + (pCh == msg->cm_fields['U']) || + (*(pCh - 1) != '[') + ) + { + char *pBuff; - /* Set the recipient of the list message to the - * email address of the room itself. - * FIXME ... I want to be able to pick any address - */ - if (msg->cm_fields['R'] != NULL) { - free(msg->cm_fields['R']); + rlen += len + 4; + pBuff = malloc (rlen * sizeof(char)); + + snprintf(pBuff, rlen, "[%s] %s", CC->room.QRname, msg->cm_fields['U']); + free(msg->cm_fields['U']); + msg->cm_fields['U'] = pBuff; } - msg->cm_fields['R'] = malloc(256); - snprintf(msg->cm_fields['R'], 256, - "room_%s@%s", CC->room.QRname, - config.c_fqdn); - for (i=0; msg->cm_fields['R'][i]; ++i) { - if (isspace(msg->cm_fields['R'][i])) { - msg->cm_fields['R'][i] = '_'; + /* else we won't modify the buffer, since the roomname is already here. */ + + /* if we don't already have a 'reply to' field, put our roomname in. */ + if (msg->cm_fields['K'] == NULL) { + msg->cm_fields['K'] = malloc(256); + snprintf(msg->cm_fields['K'], 256, + "room_%s@%s", CC->room.QRname, + config.c_fqdn); + for (i=0; msg->cm_fields['K'][i]; ++i) { + if (isspace(msg->cm_fields['K'][i])) { + msg->cm_fields['K'][i] = '_'; + } } } @@ -716,20 +778,17 @@ void network_spool_msg(long msgnum, void *userdata) { fprintf(sc->digestfp, "Subject: %s\n", msg->cm_fields['U']); } - CC->redirect_buffer = malloc(SIZ); - CC->redirect_len = 0; - CC->redirect_alloc = SIZ; - + CC->redirect_buffer = NewStrBufPlain(NULL, SIZ); + safestrncpy(CC->preferred_formats, "text/plain", sizeof CC->preferred_formats); CtdlOutputPreLoadedMsg(msg, MT_CITADEL, HEADERS_NONE, 0, 0, 0); - striplt(CC->redirect_buffer); - fprintf(sc->digestfp, "\n%s\n", CC->redirect_buffer); + StrBufTrim(CC->redirect_buffer); + fwrite(HKEY("\n"), 1, sc->digestfp); + fwrite(SKEY(CC->redirect_buffer), 1, sc->digestfp); + fwrite(HKEY("\n"), 1, sc->digestfp); - free(CC->redirect_buffer); - CC->redirect_buffer = NULL; - CC->redirect_len = 0; - CC->redirect_alloc = 0; + FreeStrBuf(&CC->redirect_buffer); sc->num_msgs_spooled += 1; free(msg); @@ -836,24 +895,24 @@ void network_spool_msg(long msgnum, void *userdata) { /* Check for valid node name */ if (is_valid_node(NULL, NULL, mptr->remote_nodename) != 0) { - CtdlLogPrintf(CTDL_ERR, "Invalid node <%s>\n", mptr->remote_nodename); + syslog(LOG_ERR, "Invalid node <%s>\n", mptr->remote_nodename); send = 0; } /* Check for split horizon */ - CtdlLogPrintf(CTDL_DEBUG, "Path is %s\n", msg->cm_fields['P']); + syslog(LOG_DEBUG, "Path is %s\n", msg->cm_fields['P']); bang = num_tokens(msg->cm_fields['P'], '!'); if (bang > 1) for (i=0; i<(bang-1); ++i) { extract_token(buf, msg->cm_fields['P'], i, '!', sizeof buf); - CtdlLogPrintf(CTDL_DEBUG, "Compare <%s> to <%s>\n", + syslog(LOG_DEBUG, "Compare <%s> to <%s>\n", buf, mptr->remote_nodename) ; if (!strcasecmp(buf, mptr->remote_nodename)) { send = 0; - CtdlLogPrintf(CTDL_DEBUG, "Not sending to %s\n", + syslog(LOG_DEBUG, "Not sending to %s\n", mptr->remote_nodename); } else { - CtdlLogPrintf(CTDL_DEBUG, "Sending to %s\n", mptr->remote_nodename); + syslog(LOG_DEBUG, "Sending to %s\n", mptr->remote_nodename); } } @@ -878,11 +937,14 @@ void network_spool_msg(long msgnum, void *userdata) { serialize_message(&sermsg, msg); if (sermsg.len > 0) { - /* write it to the spool file */ - snprintf(filename, sizeof filename,"%s/%s", - ctdl_netout_dir, - mptr->remote_nodename); - CtdlLogPrintf(CTDL_DEBUG, "Appending to %s\n", filename); + /* write it to a spool file */ + snprintf(filename, sizeof filename,"%s/%s@%lx%x", + ctdl_netout_dir, + mptr->remote_nodename, + time(NULL), + rand() + ); + syslog(LOG_DEBUG, "Appending to %s\n", filename); fp = fopen(filename, "ab"); if (fp != NULL) { fwrite(sermsg.ser, @@ -890,7 +952,7 @@ void network_spool_msg(long msgnum, void *userdata) { fclose(fp); } else { - CtdlLogPrintf(CTDL_ERR, "%s: %s\n", filename, strerror(errno)); + syslog(LOG_ERR, "%s: %s\n", filename, strerror(errno)); } /* free the serialized version */ @@ -939,31 +1001,31 @@ int read_spoolcontrol_file(SpoolControl **scc, char *filename) buf[strlen(buf)-1] = 0; extract_token(instr, buf, 0, '|', sizeof instr); - if (!strcasecmp(instr, "lastsent")) { + if (!strcasecmp(instr, strof(lastsent))) { sc->lastsent = extract_long(buf, 1); } - else if (!strcasecmp(instr, "listrecp")) { + else if (!strcasecmp(instr, strof(listrecp))) { nptr = (namelist *) malloc(sizeof(namelist)); nptr->next = sc->listrecps; extract_token(nptr->name, buf, 1, '|', sizeof nptr->name); sc->listrecps = nptr; } - else if (!strcasecmp(instr, "participate")) { + else if (!strcasecmp(instr, strof(participate))) { nptr = (namelist *) malloc(sizeof(namelist)); nptr->next = sc->participates; extract_token(nptr->name, buf, 1, '|', sizeof nptr->name); sc->participates = nptr; } - else if (!strcasecmp(instr, "digestrecp")) { + else if (!strcasecmp(instr, strof(digestrecp))) { nptr = (namelist *) malloc(sizeof(namelist)); nptr->next = sc->digestrecps; extract_token(nptr->name, buf, 1, '|', sizeof nptr->name); sc->digestrecps = nptr; } - else if (!strcasecmp(instr, "ignet_push_share")) { + else if (!strcasecmp(instr, strof(ignet_push_share))) { extract_token(nodename, buf, 1, '|', sizeof nodename); extract_token(roomname, buf, 2, '|', sizeof roomname); mptr = (maplist *) malloc(sizeof(maplist)); @@ -978,12 +1040,12 @@ int read_spoolcontrol_file(SpoolControl **scc, char *filename) * timestamps. */ skipthisline = 0; - if (!strncasecmp(buf, "subpending|", 11)) { + if (!strncasecmp(buf, strof(subpending)"|", 11)) { if (time(NULL) - extract_long(buf, 4) > EXP) { skipthisline = 1; } } - if (!strncasecmp(buf, "unsubpending|", 13)) { + if (!strncasecmp(buf, strof(unsubpending)"|", 13)) { if (time(NULL) - extract_long(buf, 3) > EXP) { skipthisline = 1; } @@ -1040,60 +1102,97 @@ void free_spoolcontrol_struct(SpoolControl **scc) int writenfree_spoolcontrol_file(SpoolControl **scc, char *filename) { - FILE *fp; + char tempfilename[PATH_MAX]; + int TmpFD; SpoolControl *sc; namelist *nptr = NULL; maplist *mptr = NULL; + long len; + time_t unixtime; + struct timeval tv; + long reltid; /* if we don't have SYS_gettid, use "random" value */ + StrBuf *Cfg; + int rc; + + len = strlen(filename); + memcpy(tempfilename, filename, len + 1); + +#if defined(HAVE_SYSCALL_H) && defined (SYS_gettid) + reltid = syscall(SYS_gettid); +#endif + gettimeofday(&tv, NULL); + /* Promote to time_t; types differ on some OSes (like darwin) */ + unixtime = tv.tv_sec; + + sprintf(tempfilename + len, ".%ld-%ld", reltid, unixtime); sc = *scc; - fp = fopen(filename, "w"); - if (fp == NULL) { - CtdlLogPrintf(CTDL_CRIT, "ERROR: cannot open %s: %s\n", + errno = 0; + TmpFD = open(tempfilename, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); + Cfg = NewStrBuf(); + if ((TmpFD < 0) || (errno != 0)) { + syslog(LOG_CRIT, "ERROR: cannot open %s: %s\n", filename, strerror(errno)); free_spoolcontrol_struct(scc); + unlink(tempfilename); } else { - fprintf(fp, "lastsent|%ld\n", sc->lastsent); - + fchown(TmpFD, config.c_ctdluid, 0); + StrBufAppendPrintf(Cfg, "lastsent|%ld\n", sc->lastsent); + /* Write out the listrecps while freeing from memory at the * same time. Am I clever or what? :) */ while (sc->listrecps != NULL) { - fprintf(fp, "listrecp|%s\n", sc->listrecps->name); + StrBufAppendPrintf(Cfg, "listrecp|%s\n", sc->listrecps->name); nptr = sc->listrecps->next; free(sc->listrecps); sc->listrecps = nptr; } /* Do the same for digestrecps */ while (sc->digestrecps != NULL) { - fprintf(fp, "digestrecp|%s\n", sc->digestrecps->name); + StrBufAppendPrintf(Cfg, "digestrecp|%s\n", sc->digestrecps->name); nptr = sc->digestrecps->next; free(sc->digestrecps); sc->digestrecps = nptr; } /* Do the same for participates */ while (sc->participates != NULL) { - fprintf(fp, "participate|%s\n", sc->participates->name); + StrBufAppendPrintf(Cfg, "participate|%s\n", sc->participates->name); nptr = sc->participates->next; free(sc->participates); sc->participates = nptr; } while (sc->ignet_push_shares != NULL) { - fprintf(fp, "ignet_push_share|%s", sc->ignet_push_shares->remote_nodename); + StrBufAppendPrintf(Cfg, "ignet_push_share|%s", sc->ignet_push_shares->remote_nodename); if (!IsEmptyStr(sc->ignet_push_shares->remote_roomname)) { - fprintf(fp, "|%s", sc->ignet_push_shares->remote_roomname); + StrBufAppendPrintf(Cfg, "|%s", sc->ignet_push_shares->remote_roomname); } - fprintf(fp, "\n"); + StrBufAppendPrintf(Cfg, "\n"); mptr = sc->ignet_push_shares->next; free(sc->ignet_push_shares); sc->ignet_push_shares = mptr; } if (sc->misc != NULL) { - fwrite(sc->misc, strlen(sc->misc), 1, fp); + StrBufAppendBufPlain(Cfg, sc->misc, -1, 0); } free(sc->misc); - fclose(fp); + rc = write(TmpFD, ChrPtr(Cfg), StrLength(Cfg)); + if ((rc >=0 ) && (rc == StrLength(Cfg))) + { + close(TmpFD); + rename(tempfilename, filename); + } + else { + syslog(LOG_EMERG, + "unable to write %s; [%s]; not enough space on the disk?\n", + tempfilename, + strerror(errno)); + close(TmpFD); + unlink(tempfilename); + } + FreeStrBuf(&Cfg); free(sc); *scc=NULL; } @@ -1144,7 +1243,7 @@ void network_spoolout_room(char *room_to_spool) { * queued for networking and then deleted before it can happen. */ if (CtdlGetRoom(&CC->room, room_to_spool) != 0) { - CtdlLogPrintf(CTDL_CRIT, "ERROR: cannot load <%s>\n", room_to_spool); + syslog(LOG_CRIT, "ERROR: cannot load <%s>\n", room_to_spool); return; } @@ -1157,7 +1256,7 @@ void network_spoolout_room(char *room_to_spool) { end_critical_section(S_NETCONFIGS); return; } - CtdlLogPrintf(CTDL_INFO, "Networking started for <%s>\n", CC->room.QRname); + syslog(LOG_INFO, "Networking started for <%s>\n", CC->room.QRname); /* If there are digest recipients, we have to build a digest */ if (sc->digestrecps != NULL) { @@ -1189,7 +1288,7 @@ void network_spoolout_room(char *room_to_spool) { } /* Now rewrite the config file */ - writenfree_spoolcontrol_file (&sc, filename); + writenfree_spoolcontrol_file(&sc, filename); end_critical_section(S_NETCONFIGS); } @@ -1253,7 +1352,7 @@ int network_sync_to(char *target_node) { /* Concise cleanup because we know there's only one node in the sc */ free(sc.ignet_push_shares); - CtdlLogPrintf(CTDL_NOTICE, "Synchronized %d messages to <%s>\n", + syslog(LOG_NOTICE, "Synchronized %d messages to <%s>\n", num_spooled, target_node); return(num_spooled); } @@ -1372,7 +1471,7 @@ void network_bounce(struct CtdlMessage *msg, char *reason) { static int serialnum = 0; size_t size; - CtdlLogPrintf(CTDL_DEBUG, "entering network_bounce()\n"); + syslog(LOG_DEBUG, "entering network_bounce()\n"); if (msg == NULL) return; @@ -1461,7 +1560,7 @@ void network_bounce(struct CtdlMessage *msg, char *reason) { /* Clean up */ if (valid != NULL) free_recipients(valid); CtdlFreeMessage(msg); - CtdlLogPrintf(CTDL_DEBUG, "leaving network_bounce()\n"); + syslog(LOG_DEBUG, "leaving network_bounce()\n"); } @@ -1485,13 +1584,13 @@ void network_process_buffer(char *buffer, long size) { unsigned char firstbyte; unsigned char lastbyte; - CtdlLogPrintf(CTDL_DEBUG, "network_process_buffer() processing %ld bytes\n", size); + syslog(LOG_DEBUG, "network_process_buffer() processing %ld bytes\n", size); /* Validate just a little bit. First byte should be FF and * last byte should be 00. */ firstbyte = buffer[0]; lastbyte = buffer[size-1]; if ( (firstbyte != 255) || (lastbyte != 0) ) { - CtdlLogPrintf(CTDL_ERR, "Corrupt message ignored. Length=%ld, firstbyte = %d, lastbyte = %d\n", + syslog(LOG_ERR, "Corrupt message ignored. Length=%ld, firstbyte = %d, lastbyte = %d\n", size, firstbyte, lastbyte); return; } @@ -1541,19 +1640,21 @@ void network_process_buffer(char *buffer, long size) { strcpy(nexthop, msg->cm_fields['D']); } snprintf(filename, - sizeof filename, - "%s/%s", - ctdl_netout_dir, - nexthop); - CtdlLogPrintf(CTDL_DEBUG, "Appending to %s\n", filename); + sizeof filename, + "%s/%s@%lx%x", + ctdl_netout_dir, + nexthop, + time(NULL), + rand() + ); + syslog(LOG_DEBUG, "Appending to %s\n", filename); fp = fopen(filename, "ab"); if (fp != NULL) { - fwrite(sermsg.ser, - sermsg.len, 1, fp); + fwrite(sermsg.ser, sermsg.len, 1, fp); fclose(fp); } else { - CtdlLogPrintf(CTDL_ERR, "%s: %s\n", filename, strerror(errno)); + syslog(LOG_ERR, "%s: %s\n", filename, strerror(errno)); } free(sermsg.ser); CtdlFreeMessage(msg); @@ -1604,7 +1705,7 @@ void network_process_buffer(char *buffer, long size) { "Please check the address and try sending the message again.\n"); msg = NULL; free_recipients(recp); - CtdlLogPrintf(CTDL_DEBUG, "Bouncing message due to invalid recipient address.\n"); + syslog(LOG_DEBUG, "Bouncing message due to invalid recipient address.\n"); return; } strcpy(target_room, ""); /* no target room if mail */ @@ -1673,12 +1774,12 @@ void network_process_file(char *filename) { fp = fopen(filename, "rb"); if (fp == NULL) { - CtdlLogPrintf(CTDL_CRIT, "Error opening %s: %s\n", filename, strerror(errno)); + syslog(LOG_CRIT, "Error opening %s: %s\n", filename, strerror(errno)); return; } fseek(fp, 0L, SEEK_END); - CtdlLogPrintf(CTDL_INFO, "network: processing %ld bytes from %s\n", ftell(fp), filename); + syslog(LOG_INFO, "network: processing %ld bytes from %s\n", ftell(fp), filename); rewind(fp); /* Look for messages in the data stream and break them out */ @@ -1721,11 +1822,11 @@ void network_do_spoolin(void) { */ if (stat(ctdl_netin_dir, &statbuf)) return; if (statbuf.st_mtime == last_spoolin_mtime) { - CtdlLogPrintf(CTDL_DEBUG, "network: nothing in inbound queue\n"); + syslog(LOG_DEBUG, "network: nothing in inbound queue\n"); return; } last_spoolin_mtime = statbuf.st_mtime; - CtdlLogPrintf(CTDL_DEBUG, "network: processing inbound queue\n"); + syslog(LOG_DEBUG, "network: processing inbound queue\n"); /* * Ok, there's something interesting in there, so scan it. @@ -1736,10 +1837,11 @@ void network_do_spoolin(void) { while (d = readdir(dp), d != NULL) { if ((strcmp(d->d_name, ".")) && (strcmp(d->d_name, ".."))) { snprintf(filename, - sizeof filename, - "%s/%s", - ctdl_netin_dir, - d->d_name); + sizeof filename, + "%s/%s", + ctdl_netin_dir, + d->d_name + ); network_process_file(filename); } } @@ -1748,15 +1850,60 @@ void network_do_spoolin(void) { } /* - * Delete any files in the outbound queue that were intended - * to be sent to nodes which no longer exist. + * Step 1: consolidate files in the outbound queue into one file per neighbor node + * Step 2: delete any files in the outbound queue that were for neighbors who no longer exist. */ -void network_purge_spoolout(void) { +void network_consolidate_spoolout(void) { DIR *dp; struct dirent *d; char filename[PATH_MAX]; + char cmd[PATH_MAX]; char nexthop[256]; int i; + char *ptr; + + /* Step 1: consolidate files in the outbound queue into one file per neighbor node */ + dp = opendir(ctdl_netout_dir); + if (dp == NULL) return; + while (d = readdir(dp), d != NULL) { + if ( + (strcmp(d->d_name, ".")) + && (strcmp(d->d_name, "..")) + && (strchr(d->d_name, '@') != NULL) + ) { + safestrncpy(nexthop, d->d_name, sizeof nexthop); + ptr = strchr(nexthop, '@'); + if (ptr) *ptr = 0; + + snprintf(filename, + sizeof filename, + "%s/%s", + ctdl_netout_dir, + d->d_name + ); + + syslog(LOG_DEBUG, "Consolidate %s to %s\n", filename, nexthop); + if (network_talking_to(nexthop, NTT_CHECK)) { + syslog(LOG_DEBUG, + "Currently online with %s - skipping for now\n", + nexthop + ); + } + else { + network_talking_to(nexthop, NTT_ADD); + snprintf(cmd, sizeof cmd, "/bin/cat %s >>%s/%s && /bin/rm -f %s", + filename, + ctdl_netout_dir, nexthop, + filename + ); + system(cmd); + network_talking_to(nexthop, NTT_REMOVE); + } + } + } + closedir(dp); + + /* Step 2: delete any files in the outbound queue that were for neighbors who no longer exist */ dp = opendir(ctdl_netout_dir); if (dp == NULL) return; @@ -1764,11 +1911,15 @@ void network_purge_spoolout(void) { while (d = readdir(dp), d != NULL) { if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; + ptr = strchr(d->d_name, '@'); + if (d != NULL) + continue; snprintf(filename, - sizeof filename, - "%s/%s", - ctdl_netout_dir, - d->d_name); + sizeof filename, + "%s/%s", + ctdl_netout_dir, + d->d_name + ); strcpy(nexthop, ""); i = is_valid_node(nexthop, NULL, d->d_name); @@ -1786,37 +1937,55 @@ void network_purge_spoolout(void) { /* * receive network spool from the remote system */ -void receive_spool(int sock, char *remote_nodename) { - size_t siz; - long download_len = 0L; - long bytes_received = 0L; - long bytes_copied = 0L; +void receive_spool(int *sock, char *remote_nodename) { + int download_len = 0L; + int bytes_received = 0L; char buf[SIZ]; - static char pbuf[IGNET_PACKET_SIZE]; char tempfilename[PATH_MAX]; - char filename[PATH_MAX]; - long plen; - FILE *fp, *newfp; + char permfilename[PATH_MAX]; + int plen; + FILE *fp; + + snprintf(tempfilename, + sizeof tempfilename, + "%s/%s.%lx%x", + ctdl_nettmp_dir, + remote_nodename, + time(NULL), + rand() + ); + + snprintf(permfilename, + sizeof permfilename, + "%s/%s.%lx%x", + ctdl_netin_dir, + remote_nodename, + time(NULL), + rand() + ); - CtdlMakeTempFileName(tempfilename, sizeof tempfilename); if (sock_puts(sock, "NDOP") < 0) return; if (sock_getln(sock, buf, sizeof buf) < 0) return; - CtdlLogPrintf(CTDL_DEBUG, "<%s\n", buf); + syslog(LOG_DEBUG, "<%s\n", buf); if (buf[0] != '2') { return; } + download_len = extract_long(&buf[4], 0); + if (download_len <= 0) { + return; + } bytes_received = 0L; fp = fopen(tempfilename, "w"); if (fp == NULL) { - CtdlLogPrintf(CTDL_CRIT, "cannot open download file locally: %s\n", - strerror(errno)); + syslog(LOG_CRIT, "Cannot create %s: %s\n", tempfilename, strerror(errno)); return; } + syslog(LOG_DEBUG, "Expecting to transfer %d bytes\n", download_len); while (bytes_received < download_len) { - /** + /* * If shutting down we can exit here and unlink the temp file. * this shouldn't loose us any messages. */ @@ -1826,10 +1995,12 @@ void receive_spool(int sock, char *remote_nodename) { unlink(tempfilename); return; } - snprintf(buf, sizeof buf, "READ %ld|%ld", - bytes_received, - ((download_len - bytes_received > IGNET_PACKET_SIZE) - ? IGNET_PACKET_SIZE : (download_len - bytes_received))); + snprintf(buf, sizeof buf, "READ %d|%d", + bytes_received, + ((download_len - bytes_received > IGNET_PACKET_SIZE) + ? IGNET_PACKET_SIZE : (download_len - bytes_received)) + ); + if (sock_puts(sock, buf) < 0) { fclose(fp); unlink(tempfilename); @@ -1840,71 +2011,56 @@ void receive_spool(int sock, char *remote_nodename) { unlink(tempfilename); return; } + if (buf[0] == '6') { - plen = extract_long(&buf[4], 0); - if (sock_read(sock, pbuf, plen, 1) < 0) { + plen = extract_int(&buf[4], 0); + StrBuf *pbuf = NewStrBuf(); + if (socket_read_blob(sock, pbuf, plen, CLIENT_TIMEOUT) != plen) { + syslog(LOG_INFO, "Short read from peer; aborting.\n"); fclose(fp); unlink(tempfilename); + FreeStrBuf(&pbuf); return; } - fwrite((char *) pbuf, plen, 1, fp); - bytes_received = bytes_received + plen; + fwrite(ChrPtr(pbuf), plen, 1, fp); + bytes_received += plen; + FreeStrBuf(&pbuf); } } fclose(fp); - /** Last chance for shutdown exit */ + + /* Last chance for shutdown exit */ if (CtdlThreadCheckStop()) { unlink(tempfilename); return; } + if (sock_puts(sock, "CLOS") < 0) { unlink(tempfilename); return; } - /** + + /* * From here on we must complete or messages will get lost */ if (sock_getln(sock, buf, sizeof buf) < 0) { unlink(tempfilename); return; } - if (download_len > 0) { - CtdlLogPrintf(CTDL_NOTICE, "Received %ld octets from <%s>\n", download_len, remote_nodename); - } - CtdlLogPrintf(CTDL_DEBUG, "%s\n", buf); - - /* Now copy the temp file to its permanent location. - * (We copy instead of link because they may be on different filesystems) + + syslog(LOG_DEBUG, "%s\n", buf); + + /* + * Now move the temp file to its permanent location. */ - begin_critical_section(S_NETSPOOL); - snprintf(filename, - sizeof filename, - "%s/%s.%ld", - ctdl_netin_dir, - remote_nodename, - (long) getpid() - ); - fp = fopen(tempfilename, "r"); - if (fp != NULL) { - newfp = fopen(filename, "w"); - if (newfp != NULL) { - bytes_copied = 0L; - while (bytes_copied < download_len) { - plen = download_len - bytes_copied; - if (plen > sizeof buf) { - plen = sizeof buf; - } - siz = fread(buf, plen, 1, fp); - fwrite(buf, plen, 1, newfp); - bytes_copied += plen; - } - fclose(newfp); - } - fclose(fp); + if (link(tempfilename, permfilename) != 0) { + syslog(LOG_ALERT, "Could not link %s to %s: %s\n", + tempfilename, permfilename, strerror(errno) + ); } - end_critical_section(S_NETSPOOL); + unlink(tempfilename); } @@ -1913,7 +2069,7 @@ void receive_spool(int sock, char *remote_nodename) { /* * transmit network spool to the remote system */ -void transmit_spool(int sock, char *remote_nodename) +void transmit_spool(int *sock, char *remote_nodename) { char buf[SIZ]; char pbuf[4096]; @@ -1924,20 +2080,20 @@ void transmit_spool(int sock, char *remote_nodename) if (sock_puts(sock, "NUOP") < 0) return; if (sock_getln(sock, buf, sizeof buf) < 0) return; - CtdlLogPrintf(CTDL_DEBUG, "<%s\n", buf); + syslog(LOG_DEBUG, "<%s\n", buf); if (buf[0] != '2') { return; } snprintf(sfname, sizeof sfname, - "%s/%s", - ctdl_netout_dir, - remote_nodename); + "%s/%s", + ctdl_netout_dir, + remote_nodename + ); fd = open(sfname, O_RDONLY); if (fd < 0) { if (errno != ENOENT) { - CtdlLogPrintf(CTDL_CRIT, "cannot open upload file locally: %s\n", - strerror(errno)); + syslog(LOG_CRIT, "cannot open %s: %s\n", sfname, strerror(errno)); } return; } @@ -1945,7 +2101,7 @@ void transmit_spool(int sock, char *remote_nodename) while (plen = (long) read(fd, pbuf, IGNET_PACKET_SIZE), plen > 0L) { bytes_to_write = plen; while (bytes_to_write > 0L) { - /** Exit if shutting down */ + /* Exit if shutting down */ if (CtdlThreadCheckStop()) { close(fd); @@ -1963,8 +2119,7 @@ void transmit_spool(int sock, char *remote_nodename) } thisblock = atol(&buf[4]); if (buf[0] == '7') { - if (sock_write(sock, pbuf, - (int) thisblock) < 0) { + if (sock_write(sock, pbuf, (int) thisblock) < 0) { close(fd); return; } @@ -1978,20 +2133,21 @@ void transmit_spool(int sock, char *remote_nodename) ABORTUPL: close(fd); - /** Last chance for shutdown exit */ + + /* Last chance for shutdown exit */ if(CtdlThreadCheckStop()) return; if (sock_puts(sock, "UCLS 1") < 0) return; - /** + + /* * From here on we must complete or messages will get lost */ if (sock_getln(sock, buf, sizeof buf) < 0) return; - CtdlLogPrintf(CTDL_NOTICE, "Sent %ld octets to <%s>\n", - bytes_written, remote_nodename); - CtdlLogPrintf(CTDL_DEBUG, "<%s\n", buf); + syslog(LOG_NOTICE, "Sent %ld octets to <%s>\n", bytes_written, remote_nodename); + syslog(LOG_DEBUG, "<%s\n", buf); if (buf[0] == '2') { - CtdlLogPrintf(CTDL_DEBUG, "Removing <%s>\n", sfname); + syslog(LOG_DEBUG, "Removing <%s>\n", sfname); unlink(sfname); } } @@ -2006,50 +2162,64 @@ void network_poll_node(char *node, char *secret, char *host, char *port) { char buf[SIZ]; char err_buf[SIZ]; char connected_to[SIZ]; + CitContext *CCC=CC; if (network_talking_to(node, NTT_CHECK)) return; network_talking_to(node, NTT_ADD); - CtdlLogPrintf(CTDL_NOTICE, "Connecting to <%s> at %s:%s\n", node, host, port); + syslog(LOG_DEBUG, "network: polling <%s>\n", node); + syslog(LOG_NOTICE, "Connecting to <%s> at %s:%s\n", node, host, port); - sock = sock_connect(host, port, "tcp"); + sock = sock_connect(host, port); if (sock < 0) { - CtdlLogPrintf(CTDL_ERR, "Could not connect: %s\n", strerror(errno)); + syslog(LOG_ERR, "Could not connect: %s\n", strerror(errno)); network_talking_to(node, NTT_REMOVE); return; } - CtdlLogPrintf(CTDL_DEBUG, "Connected!\n"); + syslog(LOG_DEBUG, "Connected!\n"); + CCC->SBuf.Buf = NewStrBuf(); + CCC->sMigrateBuf = NewStrBuf(); + CCC->SBuf.ReadWritePointer = NULL; /* Read the server greeting */ - if (sock_getln(sock, buf, sizeof buf) < 0) goto bail; - CtdlLogPrintf(CTDL_DEBUG, ">%s\n", buf); + if (sock_getln(&sock, buf, sizeof buf) < 0) goto bail; + syslog(LOG_DEBUG, ">%s\n", buf); /* Check that the remote is who we think it is and warn the Aide if not */ extract_token (connected_to, buf, 1, ' ', sizeof connected_to); if (strcmp(connected_to, node)) { - snprintf (err_buf, sizeof(err_buf), "Connected to node \"%s\" but I was expecting to connect to node \"%s\".", connected_to, node); - CtdlLogPrintf(CTDL_ERR, "%s\n", err_buf); + snprintf(err_buf, sizeof(err_buf), + "Connected to node \"%s\" but I was expecting to connect to node \"%s\".", + connected_to, node + ); + syslog(LOG_ERR, "%s\n", err_buf); CtdlAideMessage(err_buf, "Network error"); } else { /* We're talking to the correct node. Now identify ourselves. */ snprintf(buf, sizeof buf, "NETP %s|%s", config.c_nodename, secret); - CtdlLogPrintf(CTDL_DEBUG, "<%s\n", buf); - if (sock_puts(sock, buf) <0) goto bail; - if (sock_getln(sock, buf, sizeof buf) < 0) goto bail; - CtdlLogPrintf(CTDL_DEBUG, ">%s\n", buf); - if (buf[0] != '2') goto bail; + syslog(LOG_DEBUG, "<%s\n", buf); + if (sock_puts(&sock, buf) <0) goto bail; + if (sock_getln(&sock, buf, sizeof buf) < 0) goto bail; + syslog(LOG_DEBUG, ">%s\n", buf); + if (buf[0] != '2') { + goto bail; + } /* At this point we are authenticated. */ if (!CtdlThreadCheckStop()) - receive_spool(sock, node); + receive_spool(&sock, node); if (!CtdlThreadCheckStop()) - transmit_spool(sock, node); + transmit_spool(&sock, node); } - sock_puts(sock, "QUIT"); -bail: sock_close(sock); + sock_puts(&sock, "QUIT"); +bail: + FreeStrBuf(&CCC->SBuf.Buf); + FreeStrBuf(&CCC->sMigrateBuf); + if (sock != -1) + sock_close(sock); network_talking_to(node, NTT_REMOVE); } @@ -2071,7 +2241,7 @@ void network_poll_other_citadel_nodes(int full_poll) { char spoolfile[256]; if (working_ignetcfg == NULL) { - CtdlLogPrintf(CTDL_DEBUG, "No nodes defined - not polling\n"); + syslog(LOG_DEBUG, "network: no neighbor nodes are configured - not polling.\n"); return; } @@ -2089,10 +2259,11 @@ void network_poll_other_citadel_nodes(int full_poll) { poll = full_poll; if (poll == 0) { snprintf(spoolfile, - sizeof spoolfile, - "%s/%s", - ctdl_netout_dir, - node); + sizeof spoolfile, + "%s/%s", + ctdl_netout_dir, + node + ); if (access(spoolfile, R_OK) == 0) { poll = 1; } @@ -2113,17 +2284,21 @@ void network_poll_other_citadel_nodes(int full_poll) { */ void create_spool_dirs(void) { if ((mkdir(ctdl_spool_dir, 0700) != 0) && (errno != EEXIST)) - CtdlLogPrintf(CTDL_EMERG, "unable to create directory [%s]: %s", ctdl_spool_dir, strerror(errno)); + syslog(LOG_EMERG, "unable to create directory [%s]: %s", ctdl_spool_dir, strerror(errno)); if (chown(ctdl_spool_dir, CTDLUID, (-1)) != 0) - CtdlLogPrintf(CTDL_EMERG, "unable to set the access rights for [%s]: %s", ctdl_spool_dir, strerror(errno)); + syslog(LOG_EMERG, "unable to set the access rights for [%s]: %s", ctdl_spool_dir, strerror(errno)); if ((mkdir(ctdl_netin_dir, 0700) != 0) && (errno != EEXIST)) - CtdlLogPrintf(CTDL_EMERG, "unable to create directory [%s]: %s", ctdl_netin_dir, strerror(errno)); + syslog(LOG_EMERG, "unable to create directory [%s]: %s", ctdl_netin_dir, strerror(errno)); if (chown(ctdl_netin_dir, CTDLUID, (-1)) != 0) - CtdlLogPrintf(CTDL_EMERG, "unable to set the access rights for [%s]: %s", ctdl_netin_dir, strerror(errno)); + syslog(LOG_EMERG, "unable to set the access rights for [%s]: %s", ctdl_netin_dir, strerror(errno)); + if ((mkdir(ctdl_nettmp_dir, 0700) != 0) && (errno != EEXIST)) + syslog(LOG_EMERG, "unable to create directory [%s]: %s", ctdl_nettmp_dir, strerror(errno)); + if (chown(ctdl_nettmp_dir, CTDLUID, (-1)) != 0) + syslog(LOG_EMERG, "unable to set the access rights for [%s]: %s", ctdl_nettmp_dir, strerror(errno)); if ((mkdir(ctdl_netout_dir, 0700) != 0) && (errno != EEXIST)) - CtdlLogPrintf(CTDL_EMERG, "unable to create directory [%s]: %s", ctdl_netout_dir, strerror(errno)); + syslog(LOG_EMERG, "unable to create directory [%s]: %s", ctdl_netout_dir, strerror(errno)); if (chown(ctdl_netout_dir, CTDLUID, (-1)) != 0) - CtdlLogPrintf(CTDL_EMERG, "unable to set the access rights for [%s]: %s", ctdl_netout_dir, strerror(errno)); + syslog(LOG_EMERG, "unable to set the access rights for [%s]: %s", ctdl_netout_dir, strerror(errno)); } @@ -2135,15 +2310,10 @@ void create_spool_dirs(void) { * * Run through the rooms doing various types of network stuff. */ -void *network_do_queue(void *args) { +void network_do_queue(void) { static time_t last_run = 0L; struct RoomProcList *ptr; int full_processing = 1; - struct CitContext networkerCC; - - /* Give the networker its own private CitContext */ - CtdlFillSystemContext(&networkerCC, "network"); - citthread_setspecific(MyConKey, (void *)&networkerCC ); /* * Run the full set of processing tasks no more frequently @@ -2151,7 +2321,9 @@ void *network_do_queue(void *args) { */ if ( (time(NULL) - last_run) < config.c_net_freq ) { full_processing = 0; - CtdlLogPrintf(CTDL_DEBUG, "Network full processing in %ld seconds.\n", config.c_net_freq - (time(NULL)- last_run)); + syslog(LOG_DEBUG, "Network full processing in %ld seconds.\n", + config.c_net_freq - (time(NULL)- last_run) + ); } /* @@ -2160,7 +2332,9 @@ void *network_do_queue(void *args) { * don't really require extremely fine granularity here, we'll do it * with a static variable instead. */ - if (doing_queue) return NULL; + if (doing_queue) { + return; + } doing_queue = 1; /* Load the IGnet Configuration into memory */ @@ -2183,12 +2357,12 @@ void *network_do_queue(void *args) { * Go ahead and run the queue */ if (full_processing && !CtdlThreadCheckStop()) { - CtdlLogPrintf(CTDL_DEBUG, "network: loading outbound queue\n"); + syslog(LOG_DEBUG, "network: loading outbound queue\n"); CtdlForEachRoom(network_queue_room, NULL); } if (rplist != NULL) { - CtdlLogPrintf(CTDL_DEBUG, "network: running outbound queue\n"); + syslog(LOG_DEBUG, "network: running outbound queue\n"); while (rplist != NULL && !CtdlThreadCheckStop()) { char spoolroomname[ROOMNAMELEN]; safestrncpy(spoolroomname, rplist->name, sizeof spoolroomname); @@ -2214,8 +2388,9 @@ void *network_do_queue(void *args) { } /* If there is anything in the inbound queue, process it */ - if (!CtdlThreadCheckStop()) + if (!CtdlThreadCheckStop()) { network_do_spoolin(); + } /* Save the network map back to disk */ write_network_map(); @@ -2224,20 +2399,15 @@ void *network_do_queue(void *args) { free_filter_list(filterlist); filterlist = NULL; - network_purge_spoolout(); + network_consolidate_spoolout(); - CtdlLogPrintf(CTDL_DEBUG, "network: queue run completed\n"); + syslog(LOG_DEBUG, "network: queue run completed\n"); if (full_processing) { last_run = time(NULL); } doing_queue = 0; - if (!CtdlThreadCheckStop()) // Only reschedule if system is not stopping - CtdlThreadSchedule("IGnet Network", CTDLTHREAD_BIGSTACK, network_do_queue, NULL, time(NULL) + 60); - else - CtdlLogPrintf(CTDL_DEBUG, "network: Task STOPPED.\n"); - return NULL; } @@ -2259,12 +2429,6 @@ void cmd_netp(char *cmdbuf) extract_token(node, cmdbuf, 0, '|', sizeof node); extract_token(pass, cmdbuf, 1, '|', sizeof pass); - if (doing_queue) { - CtdlLogPrintf(CTDL_WARNING, "Network node <%s> refused - spooling\n", node); - cprintf("%d spooling - try again in a few minutes\n", ERROR + RESOURCE_BUSY); - return; - } - /* load the IGnet Configuration to check node validity */ load_working_ignetcfg(); v = is_valid_node(nexthop, secret, node); @@ -2274,7 +2438,7 @@ void cmd_netp(char *cmdbuf) "An unknown Citadel server called \"%s\" attempted to connect from %s [%s].\n", node, CC->cs_host, CC->cs_addr ); - CtdlLogPrintf(CTDL_WARNING, err_buf); + syslog(LOG_WARNING, err_buf); cprintf("%d authentication failed\n", ERROR + PASSWORD_REQUIRED); CtdlAideMessage(err_buf, "IGNet Networking."); return; @@ -2285,21 +2449,21 @@ void cmd_netp(char *cmdbuf) "A Citadel server at %s [%s] failed to authenticate as network node \"%s\".\n", CC->cs_host, CC->cs_addr, node ); - CtdlLogPrintf(CTDL_WARNING, err_buf); + syslog(LOG_WARNING, err_buf); cprintf("%d authentication failed\n", ERROR + PASSWORD_REQUIRED); CtdlAideMessage(err_buf, "IGNet Networking."); return; } if (network_talking_to(node, NTT_CHECK)) { - CtdlLogPrintf(CTDL_WARNING, "Duplicate session for network node <%s>", node); + syslog(LOG_WARNING, "Duplicate session for network node <%s>", node); cprintf("%d Already talking to %s right now\n", ERROR + RESOURCE_BUSY, node); return; } safestrncpy(CC->net_node, node, sizeof CC->net_node); network_talking_to(node, NTT_ADD); - CtdlLogPrintf(CTDL_NOTICE, "Network node <%s> logged in from %s [%s]\n", + syslog(LOG_NOTICE, "Network node <%s> logged in from %s [%s]\n", CC->net_node, CC->cs_host, CC->cs_addr ); cprintf("%d authenticated as network node '%s'\n", CIT_OK, CC->net_node); @@ -2312,6 +2476,24 @@ int network_room_handler (struct ctdlroom *room) return 0; } +void *ignet_thread(void *arg) { + struct CitContext ignet_thread_CC; + + syslog(LOG_DEBUG, "ignet_thread() initializing\n"); + CtdlFillSystemContext(&ignet_thread_CC, "IGnet Queue"); + citthread_setspecific(MyConKey, (void *)&ignet_thread_CC); + + while (!CtdlThreadCheckStop()) { + network_do_queue(); + CtdlThreadSleep(60); + } + + CtdlClearSystemContext(); + return(NULL); +} + + + /* * Module entry point @@ -2325,11 +2507,9 @@ CTDL_MODULE_INIT(network) CtdlRegisterProtoHook(cmd_snet, "SNET", "Set network config"); CtdlRegisterProtoHook(cmd_netp, "NETP", "Identify as network poller"); CtdlRegisterProtoHook(cmd_nsyn, "NSYN", "Synchronize room to node"); - CtdlRegisterRoomHook(network_room_handler); + CtdlRegisterRoomHook(network_room_handler); CtdlRegisterCleanupHook(destroy_network_queue_room); + CtdlThreadCreate("SMTP Send", CTDLTHREAD_BIGSTACK, ignet_thread, NULL); } - else - CtdlThreadSchedule("IGnet Network", CTDLTHREAD_BIGSTACK, network_do_queue, NULL, 0); - /* return our Subversion id for the Log */ - return "$Id$"; + return "network"; }