]> git.pond.sub.org Git - empserver/blob - src/lib/commands/rea.c
37fe828f856a3569c06588c4e339644ec521c5b2
[empserver] / src / lib / commands / rea.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2009, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See files README, COPYING and CREDITS in the root of the source
23  *  tree for related information and legal notices.  It is expected
24  *  that future projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  rea.c: Read telegrams
29  *
30  *  Known contributors to this file:
31  *     Dave Pare
32  *     Doug Hay, 1998
33  *     Steve McClure, 1998-2000
34  *     Ron Koenderink, 2005-2007
35  *     Markus Armbruster, 2009
36  */
37
38 #include <config.h>
39
40 #include <ctype.h>
41 #include <errno.h>
42 #include <stdio.h>
43 #include "commands.h"
44 #include "match.h"
45 #include "misc.h"
46 #include "optlist.h"
47 #include "tel.h"
48
49 static int print_sink(char *, size_t, void *);
50
51 int
52 rea(void)
53 {
54     static char *telnames[] = {
55         /* must follow TEL_ defines in tel.h */
56         "Telegram", "Announcement", "BULLETIN", "Production Report"
57     };
58     char *p;
59     char *mbox;
60     char mbox_buf[256];         /* Maximum path length */
61     struct telstr tgm;
62     FILE *telfp;
63     int teles;
64     int size;
65     char buf[1024];
66     int lasttype;
67     int lastcnum;
68     time_t lastdate;
69     int header;
70     int filelen;
71     char *kind;
72     int n, res;
73     int num = player->cnum;
74     struct natstr *np = getnatp(player->cnum);
75     time_t now;
76     time_t then;
77     time_t delta;
78     int first = 1;
79     int may_delete = 1; /* may messages be deleted? */
80
81     now = time(NULL);
82
83     if (*player->argp[0] == 'w') {
84         kind = "announcement";
85         if (player->argp[1] && isdigit(*player->argp[1])) {
86             delta = days(atoi(player->argp[1]));
87             then = now - delta;
88             may_delete = 0;
89         } else
90             then = np->nat_annotim;
91         mbox = annfil;
92     } else {
93         kind = "telegram";
94         if (player->god && player->argp[1] &&
95             (mineq(player->argp[1], "yes") == ME_MISMATCH) &&
96             (mineq(player->argp[1], "no") == ME_MISMATCH)) {
97             if ((n = natarg(player->argp[1], NULL)) < 0)
98                 return RET_SYN;
99             num = n;
100             may_delete = 0;
101         }
102         mbox = mailbox(mbox_buf, num);
103         clear_telegram_is_new(player->cnum);
104     }
105
106     if (!(telfp = fopen(mbox, "rb+"))) {
107         logerror("telegram file %s", mbox);
108         return RET_FAIL;
109     }
110     teles = 0;
111     fseek(telfp, 0L, SEEK_SET);
112     size = fsize(fileno(telfp));
113   more:
114     lastdate = 0;
115     lastcnum = -1;
116     lasttype = -1;
117     while ((res = tel_read_header(telfp, mbox, &tgm)) > 0) {
118         if (*kind == 'a') {
119             if ((!player->god && (getrejects(tgm.tel_from, np) & REJ_ANNO))
120                 || tgm.tel_date < then) {
121                 res = tel_read_body(telfp, mbox, &tgm, NULL, NULL);
122                 if (res < 0)
123                     break;
124                 continue;
125             }
126         }
127         if (first && *kind == 'a') {
128             pr("\nAnnouncements since %s", ctime(&then));
129             first = 0;
130         }
131         header = 0;
132         if (tgm.tel_type != lasttype || tgm.tel_from != lastcnum)
133             header++;
134         if (abs((int)(tgm.tel_date - (long)lastdate)) > TEL_SECONDS)
135             header++;
136         if (header) {
137             pr("\n> ");
138             lastcnum = tgm.tel_from;
139             lasttype = tgm.tel_type;
140             pr("%s ", telnames[tgm.tel_type]);
141             if ((tgm.tel_type == TEL_NORM) ||
142                 (tgm.tel_type == TEL_ANNOUNCE) ||
143                 (tgm.tel_type == TEL_BULLETIN))
144                 pr("from %s, (#%d)", cname(tgm.tel_from), tgm.tel_from);
145             pr("  dated %s", ctime(&tgm.tel_date));
146             lastdate = tgm.tel_date;
147         }
148         teles++;
149         res = tel_read_body(telfp, mbox, &tgm, print_sink, NULL);
150         if (res < 0)
151             break;
152     }
153     if (res < 0)
154         pr("\n> Mailbox corrupt, tell the deity.\n");
155
156     if (teles > 0 && player->cnum == num && may_delete) {
157         pr("\n");
158         if (teles == 1) {
159             if (chance(0.25))
160                 p = "Forget this one? ";
161             else
162                 p = "Shall I burn it? ";
163         } else {
164             if (chance(0.25))
165                 p = "Into the shredder, boss? ";
166             else
167                 p = "Can I throw away these old love letters? ";
168         }
169         p = getstarg(player->argp[1], p, buf);
170         if (p && *p == 'y') {
171             if ((filelen = fsize(fileno(telfp))) > size) {
172                 pr("Wait a sec!  A new %s has arrived...\n", kind);
173                 /* force stdio to re-read tel file */
174                 (void)fflush(telfp);
175                 (void)fseek(telfp, (long)size, SEEK_SET);
176                 size = filelen;
177                 now = time(NULL);
178                 goto more;
179             }
180             if (*kind == 'a') {
181                 np->nat_annotim = now;
182                 putnat(np);
183             } else {
184                 /* Here, we just re-open the file for "w" only,
185                    and that will wipe the file clean automatically */
186                 (void)fclose(telfp);
187                 telfp = fopen(mbox, "wb");
188             }
189         }
190     }
191     if (teles <= 0) {
192         if (player->cnum == num)
193             pr("No %ss for you at the moment...\n", kind);
194         else
195             pr("No %ss for %s at the moment...\n", kind, cname(num));
196     }
197     (void)fclose(telfp);
198     if (np->nat_flags & NF_INFORM) {
199         pr_inform(player, "\n");
200         np->nat_tgms = 0;
201         putnat(np);
202     }
203     return RET_OK;
204 }
205
206 /*
207  * Print first telegram in file FNAME.
208  */
209 int
210 show_first_tel(char *fname)
211 {
212     FILE *fp;
213     struct telstr tgm;
214
215     if ((fp = fopen(fname, "rb")) == NULL) {
216         if (errno == ENOENT)
217             return 0;
218         else {
219             logerror("Could not open %s.\n", fname);
220             return -1;
221         }
222     }
223     if (tel_read_header(fp, fname, &tgm) < 0)
224         return -1;
225     if (tel_read_body(fp, fname, &tgm, print_sink, NULL) < 0)
226         return -1;
227     fclose(fp);
228     return 0;
229 }
230
231 static int
232 print_sink(char *chunk, size_t sz, void *arg)
233 {
234     uprnf(chunk);
235     return 0;
236 }