Here it is, the new thread interface.
[citadel.git] / citadel / modules / network / serv_network.c
index 8885e5d812360db07701ea09186de91735f830e5..ad8618406e351ed120894159016974d340e04942 100644 (file)
@@ -48,6 +48,7 @@
 #include <sys/wait.h>
 #include <string.h>
 #include <limits.h>
+#include <libcitadel.h>
 #include "citadel.h"
 #include "server.h"
 #include "citserver.h"
@@ -58,7 +59,6 @@
 #include "policy.h"
 #include "database.h"
 #include "msgbase.h"
-#include "tools.h"
 #include "internet_addressing.h"
 #include "serv_network.h"
 #include "clientsocket.h"
@@ -366,7 +366,11 @@ void cmd_gnet(char *argbuf) {
        char buf[SIZ];
        FILE *fp;
 
-       if (CtdlAccessCheck(ac_room_aide)) return;
+       if ( (CC->room.QRflags & QR_MAILBOX) && (CC->user.usernum == atol(CC->room.QRname)) ) {
+               /* users can edit the netconfigs for their own mailbox rooms */
+       }
+       else if (CtdlAccessCheck(ac_room_aide)) return;
+
        assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir);
        cprintf("%d Network settings for room #%ld <%s>\n",
                LISTING_FOLLOWS,
@@ -389,11 +393,15 @@ void cmd_snet(char *argbuf) {
        char tempfilename[SIZ];
        char filename[SIZ];
        char buf[SIZ];
-       FILE *fp;
+       FILE *fp, *newfp;
 
        unbuffer_output();
 
-       if (CtdlAccessCheck(ac_room_aide)) return;
+       if ( (CC->room.QRflags & QR_MAILBOX) && (CC->user.usernum == atol(CC->room.QRname)) ) {
+               /* users can edit the netconfigs for their own mailbox rooms */
+       }
+       else if (CtdlAccessCheck(ac_room_aide)) return;
+
        CtdlMakeTempFileName(tempfilename, sizeof tempfilename);
        assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir);
 
@@ -411,15 +419,23 @@ void cmd_snet(char *argbuf) {
        }
        fclose(fp);
 
-       /* Now copy the temp file to its permanent location
-        * (We use /bin/mv instead of link() because they may be on
-        * different filesystems)
+       /* Now copy the temp file to its permanent location.
+        * (We copy instead of link because they may be on different filesystems)
         */
-       unlink(filename);
-       snprintf(buf, sizeof buf, "/bin/mv %s %s", tempfilename, filename);
        begin_critical_section(S_NETCONFIGS);
-       system(buf);
+       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);
+       }
        end_critical_section(S_NETCONFIGS);
+       unlink(tempfilename);
 }
 
 
@@ -454,7 +470,7 @@ void network_deliver_digest(struct SpoolControl *sc) {
        snprintf(buf, sizeof buf, "[%s]", CC->room.QRname);
        msg->cm_fields['U'] = strdup(buf);
        sprintf(buf, "room_%s@%s", CC->room.QRname, config.c_fqdn);
-       for (i=0; i<strlen(buf); ++i) {
+       for (i=0; buf[i]; ++i) {
                if (isspace(buf[i])) buf[i]='_';
                buf[i] = tolower(buf[i]);
        }
@@ -612,7 +628,7 @@ void network_spool_msg(long msgnum, void *userdata) {
                        snprintf(msg->cm_fields['R'], 256,
                                "room_%s@%s", CC->room.QRname,
                                config.c_fqdn);
-                       for (i=0; i<strlen(msg->cm_fields['R']); ++i) {
+                       for (i=0; msg->cm_fields['R'][i]; ++i) {
                                if (isspace(msg->cm_fields['R'][i])) {
                                        msg->cm_fields['R'][i] = '_';
                                }
@@ -702,7 +718,7 @@ void network_spool_msg(long msgnum, void *userdata) {
                                snprintf(msg->cm_fields['F'], SIZ,
                                        "room_%s@%s", CC->room.QRname,
                                        config.c_fqdn);
-                               for (i=0; i<strlen(msg->cm_fields['F']); ++i) {
+                               for (i=0; msg->cm_fields['F'][i]; ++i) {
                                        if (isspace(msg->cm_fields['F'][i])) {
                                                msg->cm_fields['F'][i] = '_';
                                        }
@@ -973,7 +989,7 @@ void network_spoolout_room(char *room_to_spool) {
        /* If we wrote a digest, deliver it and then close it */
        snprintf(buf, sizeof buf, "room_%s@%s",
                CC->room.QRname, config.c_fqdn);
-       for (i=0; i<strlen(buf); ++i) {
+       for (i=0; buf[i]; ++i) {
                buf[i] = tolower(buf[i]);
                if (isspace(buf[i])) buf[i] = '_';
        }
@@ -1340,13 +1356,12 @@ void network_process_buffer(char *buffer, long size) {
        unsigned char firstbyte;
        unsigned char lastbyte;
 
-       /* Validate just a little bit.  First byte should be FF and
-        * last byte should be 00.
-        */
-       memcpy(&firstbyte, &buffer[0], 1);
-       memcpy(&lastbyte, &buffer[size-1], 1);
+       /* 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) ) {
-               lprintf(CTDL_ERR, "Corrupt message!  Ignoring.\n");
+               lprintf(CTDL_ERR, "Corrupt message ignored.  Length=%ld, firstbyte = %d, lastbyte = %d\n",
+                       size, firstbyte, lastbyte);
                return;
        }
 
@@ -1435,6 +1450,7 @@ void network_process_buffer(char *buffer, long size) {
         * connected that it's inevitable.)
         */
        if (network_usetable(msg) != 0) {
+               CtdlFreeMessage(msg);
                return;
        }
 
@@ -1531,12 +1547,13 @@ void network_process_file(char *filename) {
 
        fp = fopen(filename, "rb");
        if (fp == NULL) {
-               lprintf(CTDL_CRIT, "Error opening %s: %s\n",
-                       filename, strerror(errno));
+               lprintf(CTDL_CRIT, "Error opening %s: %s\n", filename, strerror(errno));
                return;
        }
 
-       lprintf(CTDL_INFO, "network: processing <%s>\n", filename);
+       fseek(fp, 0L, SEEK_END);
+       lprintf(CTDL_INFO, "network: processing %ld bytes from %s\n", ftell(fp), filename);
+       rewind(fp);
 
        /* Look for messages in the data stream and break them out */
        while (ch = getc(fp), ch >= 0) {
@@ -1644,17 +1661,19 @@ void network_purge_spoolout(void) {
  * receive network spool from the remote system
  */
 void receive_spool(int sock, char *remote_nodename) {
-       long download_len;
-       long bytes_received;
+       long download_len = 0L;
+       long bytes_received = 0L;
+       long bytes_copied = 0L;
        char buf[SIZ];
        static char pbuf[IGNET_PACKET_SIZE];
        char tempfilename[PATH_MAX];
+       char filename[PATH_MAX];
        long plen;
-       FILE *fp;
+       FILE *fp, *newfp;
 
        CtdlMakeTempFileName(tempfilename, sizeof tempfilename);
        if (sock_puts(sock, "NDOP") < 0) return;
-       if (sock_gets(sock, buf) < 0) return;
+       if (sock_getln(sock, buf, sizeof buf) < 0) return;
        lprintf(CTDL_DEBUG, "<%s\n", buf);
        if (buf[0] != '2') {
                return;
@@ -1679,14 +1698,14 @@ void receive_spool(int sock, char *remote_nodename) {
                        unlink(tempfilename);
                        return;
                }
-               if (sock_gets(sock, buf) < 0) {
+               if (sock_getln(sock, buf, sizeof buf) < 0) {
                        fclose(fp);
                        unlink(tempfilename);
                        return;
                }
                if (buf[0] == '6') {
                        plen = extract_long(&buf[4], 0);
-                       if (sock_read(sock, pbuf, plen) < 0) {
+                       if (sock_read(sock, pbuf, plen, 1) < 0) {
                                fclose(fp);
                                unlink(tempfilename);
                                return;
@@ -1701,23 +1720,46 @@ void receive_spool(int sock, char *remote_nodename) {
                unlink(tempfilename);
                return;
        }
-       if (sock_gets(sock, buf) < 0) {
+       if (sock_getln(sock, buf, sizeof buf) < 0) {
                unlink(tempfilename);
                return;
        }
-       if (download_len > 0)
-               lprintf(CTDL_NOTICE, "Received %ld octets from <%s>",
-                               download_len, remote_nodename);
-       lprintf(CTDL_DEBUG, "%s", buf);
-       /* TODO: make move inline. forking is verry expensive. */
-       snprintf(buf, 
-                        sizeof buf, 
-                        "mv %s %s/%s.%ld",
-                        tempfilename, 
+       if (download_len > 0) {
+               lprintf(CTDL_NOTICE, "Received %ld octets from <%s>\n", download_len, remote_nodename);
+       }
+       lprintf(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)
+        */
+       begin_critical_section(S_NETSPOOL);
+       snprintf(filename, 
+                        sizeof filename, 
+                        "%s/%s.%ld",
                         ctdl_netin_dir,
                         remote_nodename, 
-                        (long) getpid());
-       system(buf);
+                        (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;
+                               }
+                               fread(buf, plen, 1, fp);
+                               fwrite(buf, plen, 1, newfp);
+                               bytes_copied += plen;
+                       }
+                       fclose(newfp);
+               }
+               fclose(fp);
+       }
+       end_critical_section(S_NETSPOOL);
+       unlink(tempfilename);
 }
 
 
@@ -1735,7 +1777,7 @@ void transmit_spool(int sock, char *remote_nodename)
        char sfname[128];
 
        if (sock_puts(sock, "NUOP") < 0) return;
-       if (sock_gets(sock, buf) < 0) return;
+       if (sock_getln(sock, buf, sizeof buf) < 0) return;
        lprintf(CTDL_DEBUG, "<%s\n", buf);
        if (buf[0] != '2') {
                return;
@@ -1762,7 +1804,7 @@ void transmit_spool(int sock, char *remote_nodename)
                                close(fd);
                                return;
                        }
-                       if (sock_gets(sock, buf) < 0) {
+                       if (sock_getln(sock, buf, sizeof buf) < 0) {
                                close(fd);
                                return;
                        }
@@ -1784,7 +1826,7 @@ void transmit_spool(int sock, char *remote_nodename)
 ABORTUPL:
        close(fd);
        if (sock_puts(sock, "UCLS 1") < 0) return;
-       if (sock_gets(sock, buf) < 0) return;
+       if (sock_getln(sock, buf, sizeof buf) < 0) return;
        lprintf(CTDL_NOTICE, "Sent %ld octets to <%s>\n",
                        bytes_written, remote_nodename);
        lprintf(CTDL_DEBUG, "<%s\n", buf);
@@ -1817,14 +1859,14 @@ void network_poll_node(char *node, char *secret, char *host, char *port) {
        lprintf(CTDL_DEBUG, "Connected!\n");
 
        /* Read the server greeting */
-       if (sock_gets(sock, buf) < 0) goto bail;
+       if (sock_getln(sock, buf, sizeof buf) < 0) goto bail;
        lprintf(CTDL_DEBUG, ">%s\n", buf);
 
        /* Identify ourselves */
        snprintf(buf, sizeof buf, "NETP %s|%s", config.c_nodename, secret);
        lprintf(CTDL_DEBUG, "<%s\n", buf);
        if (sock_puts(sock, buf) <0) goto bail;
-       if (sock_gets(sock, buf) < 0) goto bail;
+       if (sock_getln(sock, buf, sizeof buf) < 0) goto bail;
        lprintf(CTDL_DEBUG, ">%s\n", buf);
        if (buf[0] != '2') goto bail;
 
@@ -2070,13 +2112,17 @@ int network_room_handler (struct ctdlroom *room)
  */
 CTDL_MODULE_INIT(network)
 {
-       create_spool_dirs();
-       CtdlRegisterProtoHook(cmd_gnet, "GNET", "Get network config");
-       CtdlRegisterProtoHook(cmd_snet, "SNET", "Set network config");
-       CtdlRegisterProtoHook(cmd_netp, "NETP", "Identify as network poller");
-       CtdlRegisterProtoHook(cmd_nsyn, "NSYN", "Synchronize room to node");
-       CtdlRegisterSessionHook(network_do_queue, EVT_TIMER);
-        CtdlRegisterRoomHook(network_room_handler);
+       if (!threading)
+       {
+               create_spool_dirs();
+               CtdlRegisterProtoHook(cmd_gnet, "GNET", "Get network config");
+               CtdlRegisterProtoHook(cmd_snet, "SNET", "Set network config");
+               CtdlRegisterProtoHook(cmd_netp, "NETP", "Identify as network poller");
+               CtdlRegisterProtoHook(cmd_nsyn, "NSYN", "Synchronize room to node");
+               CtdlRegisterSessionHook(network_do_queue, EVT_TIMER);
+               CtdlRegisterRoomHook(network_room_handler);
+               CtdlRegisterCleanupHook(destroy_network_queue_room);
+       }
 
        /* return our Subversion id for the Log */
        return "$Id$";