src/lib/subs/wu.c

Go to the documentation of this file.
00001 /*
00002  *  Empire - A multi-player, client/server Internet based war game.
00003  *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
00004  *                           Ken Stevens, Steve McClure
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  *  ---
00021  *
00022  *  See files README, COPYING and CREDITS in the root of the source
00023  *  tree for related information and legal notices.  It is expected
00024  *  that future projects/authors will amend these files as needed.
00025  *
00026  *  ---
00027  *
00028  *  wu.c: Write a telegram to a user from another
00029  * 
00030  *  Known contributors to this file:
00031  *     Steve McClure, 2000
00032  */
00033 
00034 #include <config.h>
00035 
00036 #include <fcntl.h>
00037 #include <stdarg.h>
00038 #include <sys/uio.h>
00039 #include <unistd.h>
00040 #include "file.h"
00041 #include "misc.h"
00042 #include "nat.h"
00043 #include "optlist.h"
00044 #include "player.h"
00045 #include "prototypes.h"
00046 #include "server.h"
00047 #include "tel.h"
00048 
00049 static struct telstr last_tel[MAXNOC];
00050 
00051 void
00052 clear_telegram_is_new(natid to)
00053 {
00054     last_tel[to].tel_type = 0;
00055     last_tel[to].tel_from = 0;
00056     last_tel[to].tel_date = 0;
00057 }
00058 
00059 /*
00060  * telegram_is_new counts new telegrams the same as read_telegrams in 
00061  * lib/commands/mail.c and lib/commands/rea.c
00062  */
00063 
00064 static int
00065 telegram_is_new(natid to, struct telstr *tel)
00066 {
00067     int is_new = 0;
00068 
00069     is_new |= tel->tel_type != last_tel[to].tel_type;
00070     is_new |= tel->tel_from != last_tel[to].tel_from;
00071     is_new |= !update_running && /* updates can take a long time */
00072         abs(tel->tel_date - last_tel[to].tel_date) > TEL_SECONDS;
00073 
00074     last_tel[to].tel_type = tel->tel_type;
00075     last_tel[to].tel_from = tel->tel_from;
00076     last_tel[to].tel_date = tel->tel_date;
00077 
00078     return is_new;
00079 }
00080 
00081 /*
00082  * Send a telegram from FROM to TO.
00083  * Format text to send using printf-style FORMAT and optional
00084  * arguments.  It is plain ASCII.
00085  * If running from the update, telegram type is TEL_UPDATE.
00086  * Else if FROM is a deity, type is TEL_BULLETIN.
00087  * Else it is TEL_NORM.
00088  * Return 0 on success, -1 on error.
00089  */
00090 int
00091 wu(natid from, natid to, char *format, ...)
00092 {
00093     struct natstr *np;
00094     va_list ap;
00095     char buf[4096];
00096 
00097     va_start(ap, format);
00098     (void)vsprintf(buf, format, ap);
00099     va_end(ap);
00100     np = getnatp(from);
00101     if (update_running)
00102         return typed_wu(from, to, buf, TEL_UPDATE);
00103     else if (np->nat_stat == STAT_GOD)
00104         return typed_wu(from, to, buf, TEL_BULLETIN);
00105     else
00106         return typed_wu(from, to, buf, TEL_NORM);
00107 }
00108 
00109 /*
00110  * Send a telegram from FROM to TO.
00111  * MESSAGE is the text to send, in UTF-8.
00112  * TYPE is the telegram type.
00113  * Return 0 on success, -1 on error.
00114  */
00115 int
00116 typed_wu(natid from, natid to, char *message, int type)
00117 {
00118     int len;
00119     struct telstr tel;
00120     struct natstr *np;
00121     struct iovec iov[2];
00122     int fd;
00123     char box[1024];
00124     int write_ok = 0;
00125     int new_tele = 0;
00126     struct player *other;
00127 
00128     if (type == TEL_ANNOUNCE)
00129         strcpy(box, annfil);
00130     else
00131         mailbox(box, to);
00132 
00133     if (type != TEL_ANNOUNCE)
00134         if ((np = getnatp(to)) == 0 || np->nat_stat < STAT_SANCT)
00135             return -1;
00136 #if !defined(_WIN32)
00137     if ((fd = open(box, O_WRONLY | O_APPEND, 0)) < 0) {
00138 #else
00139     if ((fd = open(box, O_WRONLY | O_APPEND | O_BINARY, 0)) < 0) {
00140 #endif
00141         logerror("telegram 'open' of %s (#%d) failed", box, to);
00142         return -1;
00143     }
00144     tel.tel_from = from;
00145     (void)time(&tel.tel_date);
00146     len = strlen(message);
00147     if (CANT_HAPPEN(len > MAXTELSIZE)) {
00148         len = MAXTELSIZE;
00149         message[len] = 0;
00150     }
00151     tel.tel_length = len;
00152     tel.tel_type = type;
00153     iov[0].iov_base = &tel;
00154     iov[0].iov_len = sizeof(tel);
00155     iov[1].iov_base = message;
00156     iov[1].iov_len = len;
00157     if (writev(fd, iov, 2) < (int)(iov[0].iov_len + iov[1].iov_len)) {
00158         logerror("telegram 'write' to #%d failed", to);
00159     } else
00160         write_ok = 1;
00161 
00162     if (close(fd) == -1) {
00163         logerror("telegram 'write' to #%d failed to close.", to);
00164     } else if (write_ok && type == TEL_ANNOUNCE) {
00165         for (to = 0; NULL != (np = getnatp(to)); to++) {
00166             if (np->nat_stat < STAT_SANCT)
00167                 continue;
00168             if (!player->god && (getrejects(from, np) & REJ_ANNO))
00169                 continue;
00170             np->nat_ann++;
00171             putnat(np);
00172         }
00173     } else if (write_ok) {
00174         new_tele = telegram_is_new(to, &tel);
00175         np->nat_tgms += new_tele || np->nat_tgms == 0;
00176         putnat(np);
00177 
00178         if (new_tele && np->nat_flags & NF_INFORM) {
00179             if (NULL != (other = getplayer(to))) {
00180                 if (np->nat_tgms == 1)
00181                     pr_inform(other, "[new tele]\n");
00182                 else
00183                     pr_inform(other, "[%d new teles]\n", np->nat_tgms);
00184             }
00185         }
00186     }
00187 
00188     return 0;
00189 }

Generated on Fri Mar 28 11:01:16 2008 for empserver by  doxygen 1.5.2