automatic arch-version.h update; CTCP support; helpfile fixes; disk-out-of-space...
authorMichael Poole <mdpoole@troilus.org>
Mon, 29 Mar 2004 21:10:10 +0000 (21:10 +0000)
committerMichael Poole <mdpoole@troilus.org>
Mon, 29 Mar 2004 21:10:10 +0000 (21:10 +0000)
* Add a rule to automatically check arch version and update
arch-version.h when needed

* Implement CTCP response handling messages direct to services.

* Fix grammar error in GIVEOWNERSHIP help entry, fix cross-reference
markup in several ChanServ commands (should underline, not bold, the
"See Also:" link), remove VERSION help entries from modules that no
longer implement that command.

* Check for errors (using setjmp/longjmp) when writing to a saxdb
file, and log the failures.
git-archimport-id: srvx@srvx.net--2004-srvx/srvx--devo--1.3--patch-36

13 files changed:
src/Makefile.am
src/chanserv.help
src/global.help
src/mod-helpserv.c
src/mod-memoserv.help
src/modcmd.c
src/opserv.help
src/proto-bahamut.c
src/proto-p10.c
src/proto.h
src/saxdb.c
src/saxdb.h
src/tools.c

index c31f287bb1350e0edd6ca7abd522abc7e1dc7f8c..f605f8632aff520f6c4029d23274c64420c64885 100644 (file)
@@ -7,13 +7,19 @@ noinst_DATA = chanserv.help global.help modcmd.help nickserv.help opserv.help sa
 EXTRA_DIST = $(noinst_DATA)
 BUILT_SOURCES = arch-version.h
 noinst_HEADERS = arch-version.h
-arch-version.h:
-       @if [ -e $@ ] ; then OLD_REVISION=`cat $@` ; else OLD_REVISION="" ; fi ; \
-       ARCH_REVISION=`tla logs -f | tail -n 1` ; \
-       VERSION_CONTENTS="#define ARCH_VERSION \"$$ARCH_REVISION\"" ; \
-       if [ "z" != "z$$ARCH_REVISION" -a "z$$OLD_REVISION" != "z$$VERSION_CONTENTS" ] ; then \
-           echo "Putting new arch version into $@" ; \
-           echo $$VERSION_CONTENTS > $@ ; \
+
+.PHONY: checkversion
+arch-version.h: checkversion
+checkversion:
+       @tla logs -f >/dev/null || exit 0; \
+       TMPFILE=`mktemp arch-version.h.XXXXXX` || exit 1 ; \
+       echo "#define ARCH_VERSION \"`tla logs -f | tail -n 1`\"" >> $$TMPFILE ; \
+       if diff -q arch-version.h $$TMPFILE >/dev/null 2>&1 ; then \
+           rm $$TMPFILE ; \
+        else \
+           echo "Putting new arch version into arch-version.h" ; \
+           rm -f arch-version.h ; \
+           mv $$TMPFILE arch-version.h ; \
        fi
 
 EXTRA_srvx_SOURCES = proto-bahamut.c proto-common.c proto-p10.c mod-snoop.c mod-memoserv.c mod-helpserv.c mod-sockcheck.c
index b8d59f91d4a7cdd7176df6f947e1ee5c2a214ec1..db953caaacad76f6bc662a1af64db16b16066150 100644 (file)
         "If the note type already exists, it is modified with the new values you specify.",
         "$uSee Also:$u removenote");
 "GIVEOWNERSHIP" ("/msg $C GIVEOWNERSHIP <#channel> <nick|*account>",
-        "Transfer ownership of the channel from you to another user on the channel's userlist.  You are demoted to co-owner, and they are promoted to owner.",
+        "Transfer ownership of the channel from you to another user on the channel's userlist.  You are demoted to co-owner, and he or she is promoted to owner.",
        "You may use *Account instead of Nick as the name argument; the * makes $C use the name of a account directly (useful if the user is not online).",
         "$uSee Also:$u clvl, access, users");
 "CSUSPEND" ("/msg $C CSUSPEND <#channel> [!]<duration> <reason>",
         "$uSee Also:$u unregister, cunsuspend, durations");
 "CUNSUSPEND" ("/msg $C CUNSUSPEND <#channel>",
         "Restores a channel's $b$C$b registration.",
-        "$bSee Also:$b csuspend, unregister");
+        "$uSee Also:$u csuspend, unregister");
 "DELBAN" ("/msg $C DELBAN <#channel> <mask|nick>",
         "Deletes a ban from the channel ban list. This command works for both permanent and timed bans alike.",
         "$uSee Also:$u addban, addtimedban, bans");
         "$uSee Also:$u staff");
 "KICK" ("/msg $C KICK <#channel> <mask|nick> [reason]",
         "Kicks the users matching the given nick or mask with the specified reason. If no reason is provided, a default will be used.",
-        "$bSee Also:$b kickban");
+        "$uSee Also:$u kickban");
 "KICKBAN" ("/msg $C KICKBAN <#channel> <mask|nick> [reason]",
         "Kicks and bans with the specified reason any users with a matching nick or hostmask. If no reason is provided, a default one will be used.",
-        "$bSee Also:$b addban, kick");
+        "$uSee Also:$u addban, kick");
 "MDELCOOWNER" ("/msg $C MDELCOOWNER <#channel> <pattern>",
         "Deletes all coowners with accounts matching the given pattern from the channel user list.",
-        "$bSee Also:$b clist, delcoowner");
+        "$uSee Also:$u clist, delcoowner");
 "MDELMASTER" ("/msg $C MDELMASTER <#channel> <pattern>",
         "Deletes all masters with accounts matching the given pattern from the channel user list.",
-        "$bSee Also:$b mdelban, mdelcoowner, mdelop, mdelowner, mdelpeon");
+        "$uSee Also:$u mdelban, mdelcoowner, mdelop, mdelowner, mdelpeon");
 "MDELOP" ("/msg $C MDELOP <#channel> <pattern>",
         "Deletes all ops with accounts matching the given pattern from the channel user list.");
 "MDELOWNER" ("/msg $C MDELOWNER <#channel> <pattern>",
         "$uSee Also:$u durations");
 "UNBAN" ("/msg $C UNBAN <#channel> <mask|nick>",
         "Unbans the specified nick or hostmask. If a nick is given, $b$C$b determines what hostmask(s) to unban.",
-        "$bSee Also:$b ban, kick, kickban");
+        "$uSee Also:$u ban, kick, kickban");
 "UNBANALL" ("/msg $C UNBANALL <#channel>",
         "Clears the specified channel's banlist. If the channel is omitted, then $bunbanall$b will be done in the channel where the command was given.",
-        "$bSee Also:$b ban, unban, unbanme");
+        "$uSee Also:$u ban, unban, unbanme");
 "UNBANME" ("/msg $C UNBANME <#channel>",
         "Unbans your hostmask from the specified channel.",
-        "$bSee Also:$b ban, unban");
+        "$uSee Also:$u ban, unban");
 "UNREGISTER" ("/msg $C UNREGISTER <#channel> [<confirmation>]",
         "Unregisters a channel that is registered with $b$C$b. $bIMPORTANT$b: Once the channel is unregistered, the userlist $bcannot$b be recovered.",
         "If you are not network staff, you must add a confimation string to the end of your line to confirm the unregistration.  If you leave it out, $C will show the proper confirmation string.",
-        "$bSee Also:$b register");
+        "$uSee Also:$u register");
 "UNSUSPEND" ("/msg $C UNSUSPEND <#channel> <nick|*account>",
         "This restores the target's access to the channel (after it has been suspended).",
         "$uSee Also:$u suspend, deluser");
 "UNVISITED" ("/msg $C UNVISITED [duration] [limit]",
         "Displays up to a certain limit, all channels registered with $b$C$b that have not been visited within a certain duration. If a duration is not provided, a default will be used.",
-        "$bSee Also:$b expire, search, durations");
+        "$uSee Also:$u expire, search, durations");
 "UP" ("/msg $C UP <#channel>",
         "Grants you your normal channel privileges.  If your access in the channel is less than the GiveVoice setting, this does nothing.  Otherwise, if your access is less than the GiveOps setting, $b$C$b will give you voice.  If your access is at least GiveOps, $b$C$b will give you ops.");
 "UPALL" ("/msg $C UPALL",
 "USERS" ("/msg $C USERS <#channel> [mask]",
         "Displays the userlist for the specified channel. If a mask is supplied, only users matching the mask will be shown.",
         "$uSee Also:$u clist, mlist, olist, plist, wlist");
-"VERSION" ("/msg $C VERSION",
-        "Sends you the srvx version and some additional version information that is specific to $b$C$b.");
 "VOICE" ("/msg $C VOICE <#channel> <nick> [nick]...",
         "Voices the specified nick in the specified channel. If the channel is omitted, then $bvoice$b will be done in the channel where the command was given.",
         "$uSee Also:$u devoice");
index 19396d90b4c84b27b43cd5de58a4160851def42b..12824391456acfac992a34e47e45f6ebec3122ff 100644 (file)
@@ -33,5 +33,3 @@
         "$bSTAFF$b:      The message will be sent to helpers and opers.",
         "$bCHANNELS$b:   The message will be sent to all channels.",
         "$bALL$b:        A combination of USERS and CHANNELS.");
-"VERSION" ("/msg $G VERSION",
-        "$bVERSION$b causes $b$G$b to to send you the srvx version and some additional version information that is specific to $b$G$b.");
index 5bf57eb9326ad194f52b465d8121a087f7036ef8..177e11e53708f0a2ef4e479fc9b0bdc4cde4519b 100644 (file)
@@ -482,7 +482,6 @@ static struct {
 static time_t last_stats_update;
 static int shutting_down;
 static FILE *reqlog_f;
-static struct saxdb_context *reqlog_ctx;
 static struct log_type *HS_LOG;
 
 #define CMD_NEED_BOT            0x001
@@ -692,33 +691,38 @@ static struct helpserv_user *GetHSUser(struct helpserv_bot *hs, struct handle_in
 static void helpserv_log_request(struct helpserv_request *req, const char *reason) {
     char key[27+NICKLEN];
     char userhost[USERLEN+HOSTLEN+2];
+    struct saxdb_context *ctx;
+    int res;
 
-    if (!reqlog_ctx || !req)
+    assert(req != NULL);
+    assert(reason != NULL);
+    if (!(ctx = saxdb_open_context(reqlog_f)))
         return;
-    if (!reason)
-        reason = "";
-
     sprintf(key, "%s-" FMT_TIME_T "-%lu", req->hs->helpserv->nick, req->opened, req->id);
-    saxdb_start_record(reqlog_ctx, key, 1);
-    if (req->helper) {
-        saxdb_write_string(reqlog_ctx, KEY_REQUEST_HELPER, req->helper->handle->handle);
-        saxdb_write_int(reqlog_ctx, KEY_REQUEST_ASSIGNED, req->assigned);
-    }
-    if (req->handle) {
-        saxdb_write_string(reqlog_ctx, KEY_REQUEST_HANDLE, req->handle->handle);
-    }
-    if (req->user) {
-        saxdb_write_string(reqlog_ctx, KEY_REQUEST_NICK, req->user->nick);
-        sprintf(userhost, "%s@%s", req->user->ident, req->user->hostname);
-        saxdb_write_string(reqlog_ctx, KEY_REQUEST_USERHOST, userhost);
+    if ((res = setjmp(ctx->jbuf)) != 0) {
+        log_module(HS_LOG, LOG_ERROR, "Unable to log helpserv request: %s.", strerror(res));
+    } else {
+        saxdb_start_record(ctx, key, 1);
+        if (req->helper) {
+            saxdb_write_string(ctx, KEY_REQUEST_HELPER, req->helper->handle->handle);
+            saxdb_write_int(ctx, KEY_REQUEST_ASSIGNED, req->assigned);
+        }
+        if (req->handle) {
+            saxdb_write_string(ctx, KEY_REQUEST_HANDLE, req->handle->handle);
+        }
+        if (req->user) {
+            saxdb_write_string(ctx, KEY_REQUEST_NICK, req->user->nick);
+            sprintf(userhost, "%s@%s", req->user->ident, req->user->hostname);
+            saxdb_write_string(ctx, KEY_REQUEST_USERHOST, userhost);
+        }
+        saxdb_write_int(ctx, KEY_REQUEST_OPENED, req->opened);
+        saxdb_write_int(ctx, KEY_REQUEST_CLOSED, now);
+        saxdb_write_string(ctx, KEY_REQUEST_CLOSEREASON, reason);
+        saxdb_write_string_list(ctx, KEY_REQUEST_TEXT, req->text);
+        saxdb_end_record(ctx);
+        saxdb_close_context(ctx);
+        fflush(reqlog_f);
     }
-    saxdb_write_int(reqlog_ctx, KEY_REQUEST_OPENED, req->opened);
-    saxdb_write_int(reqlog_ctx, KEY_REQUEST_CLOSED, now);
-    saxdb_write_string(reqlog_ctx, KEY_REQUEST_CLOSEREASON, reason);
-    saxdb_write_string_list(reqlog_ctx, KEY_REQUEST_TEXT, req->text);
-    saxdb_end_record(reqlog_ctx);
-
-    fflush(reqlog_f);
 }
 
 /* Searches for a request by number, nick, or account (num|nick|*account).
@@ -3661,20 +3665,13 @@ static void helpserv_conf_read(void) {
     str = database_get_data(conf_node, "user_escape", RECDB_QSTRING);
     helpserv_conf.user_escape = str ? str[0] : '@';
 
-    if (reqlog_ctx) {
-        saxdb_close_context(reqlog_ctx);
-        reqlog_ctx = NULL;
-    }
     if (reqlog_f) {
         fclose(reqlog_f);
         reqlog_f = NULL;
     }
-    if (helpserv_conf.reqlogfile) {
-        if (!(reqlog_f = fopen(helpserv_conf.reqlogfile, "a"))) {
-            log_module(HS_LOG, LOG_ERROR, "Unable to open request logfile (%s): %s", helpserv_conf.reqlogfile, strerror(errno));
-        } else {
-            reqlog_ctx = saxdb_open_context(reqlog_f);
-        }
+    if (helpserv_conf.reqlogfile
+        && !(reqlog_f = fopen(helpserv_conf.reqlogfile, "a"))) {
+        log_module(HS_LOG, LOG_ERROR, "Unable to open request logfile (%s): %s", helpserv_conf.reqlogfile, strerror(errno));
     }
 }
 
@@ -4461,8 +4458,6 @@ static void helpserv_db_cleanup(void) {
     dict_delete(helpserv_reqs_byhand_dict);
     dict_delete(helpserv_users_byhand_dict);
 
-    if (reqlog_ctx)
-        saxdb_close_context(reqlog_ctx);
     if (reqlog_f)
         fclose(reqlog_f);
 }
index 88f30dcfe7e103640307417e59db8d546c5671f8..5ce2e8cf9ec176fac791825a08689beb5b72446e 100644 (file)
@@ -23,9 +23,6 @@
        "/msg $S SET notify <1 or 0>",
        "Decides wether $S should notify you of the messages in your inbox, on authentication with $N AND when someone sends you a new message.");
        
-"VERSION" ("/msg $S VERSION",
-        "Sends you the srvx version and some additional version information that is specific to $b$S$b.");
-        
 "EXPIRY" ("/msg $S EXPIRY ",
          "Sends you the current usage of expiring old messages.");
 
index 218c7c0f436d7d8af02f62edbde78c8ca439114e..557373c66c7f35bae46edf7a8d6123e8f93adc4e 100644 (file)
@@ -36,7 +36,6 @@ static struct pending_template *pending_templates;
 static struct module *modcmd_module;
 static struct modcmd *bind_command, *help_command, *version_command;
 static const struct message_entry msgtab[] = {
-    { "MCMSG_VERSION", "$b"PACKAGE_STRING"$b ("CODENAME"), Built: " __DATE__ ", " __TIME__"." },
     { "MCMSG_BARE_FLAG", "Flag %.*s must be preceded by a + or -." },
     { "MCMSG_UNKNOWN_FLAG", "Unknown module flag %.*s." },
     { "MCMSG_BAD_OPSERV_LEVEL", "Invalid $O access level %s." },
@@ -120,6 +119,7 @@ static const struct message_entry msgtab[] = {
     { "MCMSG_SERVICE_REMOVED", "Service $b%s$b has been deleted." },
     { "MCMSG_FILE_NOT_OPENED", "Unable to open file $b%s$b for writing." },
     { "MCMSG_MESSAGES_DUMPED", "Messages written to $b%s$b." },
+    { "MCMSG_MESSAGE_DUMP_FAILED", "Message dump failed: %s." },
     { "MCMSG_COMMAND_FLAGS", "Command flags are %s (inferred: %s)." },
     { "MCMSG_COMMAND_ACCOUNT_FLAGS", "Requires account flags +%s, prohibits account flags +%s." },
     { "MCMSG_COMMAND_ACCESS_LEVEL", "Requires channel access %d and $O access %d." },
@@ -821,11 +821,63 @@ svccmd_invoke(struct userNode *user, struct service *service, struct chanNode *c
 void
 modcmd_privmsg(struct userNode *user, struct userNode *bot, char *text, int server_qualified) {
     struct service *service;
+
     if (!(service = dict_find(services, bot->nick, NULL))) {
         log_module(MAIN_LOG, LOG_ERROR, "modcmd_privmsg got privmsg for unhandled service %s, unregistering.", bot->nick);
         reg_privmsg_func(bot, NULL);
         return;
     }
+
+    if (text[0] == '\x01') {
+        char *term, response[MAXLEN];
+
+        text++; /* Skip leading ^A. */
+        /* Chop off final ^A. */
+        term = strchr(text, '\x01');
+        if (!term)
+            return;
+        *term = '\0';
+        /* Parse out leading text. */
+        term = strchr(text, ' ');
+        if (term) {
+            *term++ = '\0';
+            if (!*term)
+                term = NULL;
+        }
+        /* No dict lookup since these are so few. */
+        if (!irccasecmp(text, "CLIENTINFO")) {
+            /* Use \001 instead of \x01 because apparently \x01C is
+             * interpreted as ASCII FS (\034, decimal 28, hex 1C).
+             */
+            irc_notice_user(bot, user, "\001CLIENTINFO CLIENTINFO PING TIME USERINFO VERSION\x01");
+        } else if (!irccasecmp(text, "PING")) {
+            if (term) {
+                snprintf(response, sizeof(response), "\x01PONG %s\x01", term);
+                irc_notice_user(bot, user, response);
+            } else {
+                irc_notice_user(bot,user, "\x01PONG\x01");
+            }
+        } else if (!irccasecmp(text, "TIME")) {
+            struct tm tm;
+            localtime_r(&now, &tm);
+            strftime(response, sizeof(response), "\x01TIME %a %b %d %H:%M:%S %Y\x01", &tm);
+            irc_notice_user(bot, user, response);
+        } else if (!irccasecmp(text, "USERINFO")) {
+            snprintf(response, sizeof(response), "\x01USERINFO %s\x01", bot->info);
+            irc_notice_user(bot, user, response);
+        } else if (!irccasecmp(text, "VERSION")) {
+            /* This function provides copyright management information
+             * to end users of srvx. You should not alter, disable or
+             * remove this command or its accessibility to normal IRC
+             * users, except to add copyright information pertaining
+             * to changes you make to srvx.
+             */
+            snprintf(response, sizeof(response), "\x01VERSION %s (%s) %s\x01", PACKAGE_STRING, CODENAME, ARCH_VERSION);
+            irc_notice_user(bot, user, response);
+        }
+        return;
+    }
+
     if (service->msg_hook && service->msg_hook(user, bot, text, server_qualified))
         return;
     svccmd_invoke(user, service, NULL, text, server_qualified);
@@ -1768,6 +1820,7 @@ static MODCMD_FUNC(cmd_dump_messages) {
     struct saxdb_context *ctx;
     dict_iterator_t it;
     FILE *pf;
+    int res;
 
     if (!(pf = fopen(fname, "w"))) {
         reply("MCMSG_FILE_NOT_OPENED", fname);
@@ -1777,21 +1830,29 @@ static MODCMD_FUNC(cmd_dump_messages) {
         reply("MSG_INTERNAL_FAILURE");
         return 0;
     }
-    for (it = dict_first(lang_C->messages); it; it = iter_next(it))
-        saxdb_write_string(ctx, iter_key(it), iter_data(it));
-    saxdb_close_context(ctx);
-    fclose(pf);
-    reply("MCMSG_MESSAGES_DUMPED", fname);
-    return 1;
+    if ((res = setjmp(ctx->jbuf)) != 0) {
+        ctx->complex.used = 0; /* to avoid false assert()s in close */
+        saxdb_close_context(ctx);
+        fclose(pf);
+        reply("MCMSG_MESSAGE_DUMP_FAILED", strerror(res));
+        return 0;
+    } else {
+        for (it = dict_first(lang_C->messages); it; it = iter_next(it))
+            saxdb_write_string(ctx, iter_key(it), iter_data(it));
+        saxdb_close_context(ctx);
+        fclose(pf);
+        reply("MCMSG_MESSAGES_DUMPED", fname);
+        return 1;
+    }
 }
 
 static MODCMD_FUNC(cmd_version) {
     /* This function provides copyright management information to end
      * users of srvx. You should not alter, disable or remove this
-     * command or its accessibility to normal IRC users.
+     * command or its accessibility to normal IRC users, except to add
+     * copyright information pertaining to changes you make to srvx.
      */
-    reply("MCMSG_VERSION");
-    send_message_type(4, user, cmd->parent->bot, "Copyright 2000-2004 srvx Development Team.\nThe srvx Development Team includes Paul Chang, Adrian Dewhurst, Miles Peterson, Michael Poole and others.\nThe srvx Development Team can be reached at http://sf.net/projects/srvx/ or in #srvx on irc.gamesurge.net.");
+    send_message_type(4, user, cmd->parent->bot, "$b"PACKAGE_STRING"$b ("CODENAME"), Built: "__DATE__", "__TIME__".\nCopyright 2000-2004 srvx Development Team.\nThe srvx Development Team includes Paul Chang, Adrian Dewhurst, Miles Peterson, Michael Poole and others.\nThe srvx Development Team can be reached at http://sf.net/projects/srvx/ or in #srvx on irc.gamesurge.net.");
     if ((argc > 1) && !irccasecmp(argv[1], "arch"))
         send_message_type(4, user, cmd->parent->bot, "%s", ARCH_VERSION);
     return 1;
index f5980e7cea56ac4a3b08cfc5760175f7a542f75d..8998f74ba1ec3a45922137fdede14453693d2452 100644 (file)
         "$bWARN$b:       The list of channels with activity warnings.",
         "$bMODULES$b:    Shows loaded modules that implement commands.",
         "$bSERVICES$b:   Shows active service bots.");
-"VERSION" ("/msg $O VERSION ",
-        "Sends you the srvx version and all version information for $b$C$b, $b$O$b, $b$N$b, and $b$G$b.");
 
 "INDEX" "${index}";
 "SEX" ("$bSEX$b",
index e0e9deced79873c4cdfd8f4a68e6c46b55227f26..401fadc5806ef600ff3051cc48b67ac20c1b2edf 100644 (file)
@@ -369,6 +369,11 @@ irc_notice(struct userNode *from, const char *to, const char *message) {
     putsock(":%s NOTICE %s :%s", from->nick, to, message);
 }
 
+void
+irc_notice_user(struct userNode *from, struct userNode *to, const char *message) {
+    putsock(":%s NOTICE %s :%s", from->nick, to->nick, message);
+}
+
 void
 irc_wallchops(UNUSED_ARG(struct userNode *from), UNUSED_ARG(const char *to), UNUSED_ARG(const char *message)) {
 }
index 5a5e5a974e4807b332650fd6e65ac6d6cbe41180..14430fde79d7656fe4221d4826b300f8f0307bd5 100644 (file)
@@ -474,6 +474,12 @@ irc_notice(struct userNode *from, const char *to, const char *message)
     putsock("%s " P10_NOTICE " %s :%s", from->numeric, to, message);
 }
 
+void
+irc_notice_user(struct userNode *from, struct userNode *to, const char *message)
+{
+    putsock("%s " P10_NOTICE " %s :%s", from->numeric, to->numeric, message);
+}
+
 void
 irc_privmsg(struct userNode *from, const char *to, const char *message)
 {
index 09db7c33f845cd74fb10e94cc7d148cb6e46841e..3ed37d56608e62eb796ca055462aaac1eeae472f 100644 (file)
@@ -123,6 +123,7 @@ void irc_squit(struct server *srv, const char *message, const char *service_mess
 /* messages */
 void irc_privmsg(struct userNode *from, const char *to, const char *message);
 void irc_notice(struct userNode *from, const char *to, const char *message);
+void irc_notice_user(struct userNode *from, struct userNode *to, const char *message);
 void irc_wallchops(struct userNode *from, const char *to, const char *message);
 
 /* channel maintenance */
index 61c7e69b7eb388368bf153d470ee039ae75aad6d..2ddd158536a29e1b1c5eee98fefec3e6f5c0235d 100644 (file)
@@ -24,7 +24,6 @@
 #include "saxdb.h"
 #include "timeq.h"
 
-DECLARE_LIST(int_list, int);
 DEFINE_LIST(int_list, int);
 
 struct saxdb {
@@ -39,15 +38,6 @@ struct saxdb {
     struct saxdb *prev;
 };
 
-struct saxdb_context {
-    FILE *output;
-    unsigned int indent;
-    struct int_list complex;
-    jmp_buf jbuf;
-    /* XXX: If jbuf is ever used, places that use saxdb_open_context() and
-     * saxdb_close_context() must be modified to fill it in */
-};
-
 #define COMPLEX(CTX) ((CTX)->complex.used ? ((CTX)->complex.list[(CTX)->complex.used-1]) : 1)
 
 static struct saxdb *last_db;
@@ -65,7 +55,8 @@ saxdb_read_db(struct saxdb *db) {
     assert(db);
     assert(db->filename);
     data = parse_database(db->filename);
-    if (!data) return;
+    if (!data)
+        return;
     if (db->writer == saxdb_mondo_writer) {
         mondo_db = data;
     } else {
@@ -145,7 +136,7 @@ saxdb_write_db(struct saxdb *db) {
     start = time(NULL);
     if ((res = setjmp(ctx.jbuf)) || (res2 = db->writer(&ctx))) {
         if (res) {
-            log_module(MAIN_LOG, LOG_ERROR, "Exception %d caught while writing to %s", res, tmp_fname);
+            log_module(MAIN_LOG, LOG_ERROR, "Error writing to %s: %s", tmp_fname, strerror(res));
         } else {
             log_module(MAIN_LOG, LOG_ERROR, "Internal error %d while writing to %s", res2, tmp_fname);
         }
@@ -188,18 +179,25 @@ saxdb_write_all(void) {
 
     for (it = dict_first(saxdbs); it; it = iter_next(it)) {
         db = iter_data(it);
-        if (!db->mondo_section) saxdb_write_db(db);
+        if (!db->mondo_section)
+            saxdb_write_db(db);
     }
 }
 
-#define saxdb_put_char(DEST, CH)   fputc(CH, (DEST)->output)
-#define saxdb_put_string(DEST, CH) fputs(CH, (DEST)->output)
+#define saxdb_put_char(DEST, CH) do { \
+    if (fputc(CH, (DEST)->output) == EOF) \
+        longjmp((DEST)->jbuf, errno); \
+    } while (0)
+#define saxdb_put_string(DEST, CH) do { \
+    if (fputs(CH, (DEST)->output) == EOF) \
+        longjmp((DEST)->jbuf, errno); \
+    } while (0)
 
 static inline void
 saxdb_put_nchars(struct saxdb_context *dest, const char *name, int len) {
-    while (len--) {
-        fputc(*name++, dest->output);
-    }
+    while (len--)
+        if (fputc(*name++, dest->output) == EOF)
+            longjmp(dest->jbuf, errno);
 }
 
 static void
@@ -209,7 +207,8 @@ saxdb_put_qstring(struct saxdb_context *dest, const char *str) {
     assert(str);
     saxdb_put_char(dest, '"');
     while ((esc = strpbrk(str, "\\\a\b\t\n\v\f\r\""))) {
-        if (esc != str) saxdb_put_nchars(dest, str, esc-str);
+        if (esc != str)
+            saxdb_put_nchars(dest, str, esc-str);
         saxdb_put_char(dest, '\\');
         switch (*esc) {
         case '\a': saxdb_put_char(dest, 'a'); break;
index 9c5786376d75d3ed7949790af4e47354a8320742..bc063c06ba8afc48e92d785659eead02986b66a1 100644 (file)
 
 #include "recdb.h"
 
+DECLARE_LIST(int_list, int);
+
 struct saxdb;
-struct saxdb_context;
+/* This definition should ONLY be used so callers of
+ * saxdb_open_context() can initialize jbuf properly. */
+struct saxdb_context {
+    FILE *output;
+    unsigned int indent;
+    struct int_list complex;
+    jmp_buf jbuf;
+};
+
 
 #define SAXDB_READER(NAME) int NAME(struct dict *db)
 typedef SAXDB_READER(saxdb_reader_func_t);
index 4b852615c8bef349086e2c852e4cc557cdba5997..c2fc94e17a8842ccd3904b249af1bbc24f07ce0e 100644 (file)
@@ -115,7 +115,8 @@ split_line(char *line, int irc_colon, int argv_size, char *argv[])
     int argc = 0;
     int n;
     while (*line && (argc < argv_size)) {
-       while (*line == ' ') *line++ = 0;
+       while (*line == ' ')
+            *line++ = 0;
        if (*line == ':' && irc_colon && argc > 0) {
            /* the rest is a single parameter */
            argv[argc++] = line + 1;
@@ -126,14 +127,14 @@ split_line(char *line, int irc_colon, int argv_size, char *argv[])
        argv[argc++] = line;
        if (argc >= argv_size)
             break;
-       while (*line != ' ' && *line) line++;
+       while (*line != ' ' && *line)
+            line++;
     }
 #ifdef NDEBUG
     n = 0;
 #else
-    for (n=argc; n<argv_size; n++) {
+    for (n=argc; n<argv_size; n++)
         argv[n] = (char*)0xFEEDBEEF;
-    }
 #endif
     return argc;
 }