1 | /*
2 | * $Log: tm_xpress.c,v $
3 | * Revision 1.7 2004/05/18 02:05:31 nzmb
4 | * Fixed wrong e-mail title and compiler warning in send_diary() function.
5 | *
6 | * Revision 1.6 2003/07/18 01:24:07 nzmb
7 | * Changed it so the "diary" command by itself defaults to "diary record"
8 | *
9 | * Revision 1.5 2003/07/12 01:48:43 nzmb
10 | * Master now gets notified when a player enters a new diary entry.
11 | *
12 | * Revision 1.4 2003/06/29 21:37:43 nzmb
13 | * Made EOG draw entries broadcasted at the end of the game.
14 | *
15 | * Revision 1.3 2003/06/22 04:10:23 nzmb
16 | * Added code to allow users to record diary entries, read them, and delete them
17 | * if they make a mistake. The diaries will be broadcast when the games end (this
18 | * part is not as of now, yet written).
19 | *
20 | * Revision 1.2 2002/07/17 11:48:11 millis
21 | * Added Log to header
22 | *
23 | */
24 |
25 | /*
26 | * tm_xpress.c -- Tim Miller's extended press functionality. Will include
27 | * EOG diarys and szine style press published at deadline.
28 | */
29 |
30 | #include <stdio.h>
31 | #include <stdlib.h>
32 | #include <string.h>
33 | #include <unistd.h>
34 | #include <sys/stat.h>
35 |
36 | #include "dip.h"
37 | #include "mail.h"
38 | #include "functions.h"
39 |
40 | void new_diary_entry(void);
41 | void list_entries(void);
42 | void read_entry(int entry);
43 | void delete_entry(int entry);
44 | int get_numentries(char *gamename, char pabbr);
45 |
46 | int process_ppress(void)
47 | {
48 | char pfilename[1000];
49 | char b;
50 |
51 | /* see if this is even allowed */
52 | if(!(dipent.x2flags & X2F_POSTALPRESS))
53 | {
54 | fprintf(rfp,"Postal press is not allowed. Skipping:\n");
55 | ppress_skip = 1;
56 | return 1;
57 | }
58 |
59 | /* this is cool -- open up the press file */
60 | sprintf(pfilename,"%s%s/ppress-%s", GAME_DIR, dipent.name, dipent.phase);
61 | if((ppfp = fopen(pfilename, "a")) == NULL)
62 | {
63 | fprintf(log_fp, "Error opening ppress file %s.\n", pfilename);
64 | bailout(E_FATAL);
65 | }
66 |
67 | ppress_read = 1;
68 | broadcast_master_only = 1;
69 | b = dipent.pl[dipent.players[player].power];
70 | fprintf(mbfp,"%s as %c in %s submitted press:\n", raddr,
71 | b, dipent.name);
72 | fprintf(ppfp,"\nPress from %c:\n", b);
73 | fprintf(rfp, "\nAppending to press file:\n");
74 | sprintf(subjectline, "%s:%s - %s postal press recorded", JUDGE_CODE,
75 | dipent.name, dipent.phase);
76 | return 0;
77 | }
78 |
79 | void process_diary(char *cmd)
80 | {
81 | char *ch, *tmp = NULL;
82 | int read = 0; /* read a specified entry */
83 | int delete = 0; /* delete a specified entry */
84 | int entry = -1; /* number of entry to perform action on */
85 | int record = 0;
86 |
87 | if(cmd[0] == '\0')
88 | record++;
89 | ch = strchr(cmd,'\n');
90 | if(ch)
91 | *ch = '\0'; /* remove any newline */
92 |
93 | ch = strchr(cmd, ' ');
94 | if(ch)
95 | {
96 | tmp = ch + 1;
97 | *ch = '\0'; /* make the first arg its own null terminated string */
98 | }
99 |
100 | if(record || !strcasecmp(cmd, "record"))
101 | {
102 | /* record a new diary entry */
103 | new_diary_entry();
104 | broadcast_master_only = 1;
105 | sprintf(subjectline, "%s:%s - %s New diary entry from %c",
106 | JUDGE_CODE, dipent.name, dipent.phase,
107 | dipent.pl[dipent.players[player].power]);
108 | return;
109 | }
110 | if(!strcasecmp(cmd, "list"))
111 | {
112 | /* list previously made entries */
113 | list_entries();
114 | return;
115 | }
116 | if(!strcasecmp(cmd, "read"))
117 | read++;
118 | else if(!strcasecmp(cmd, "delete"))
119 | delete++;
120 | else {
121 | fprintf(rfp,"Bad diary option %s.\n",cmd);
122 | fprintf(rfp,"Skipping following message...\n");
123 | diary_skip++;
124 | return;
125 | }
126 |
127 | if(!ch)
128 | {
129 | fprintf(rfp, "You must specify an entry number to %s.\n\n", cmd);
130 | return;
131 | }
132 |
133 | entry = (int)strtol(tmp,NULL,10);
134 | if(entry < 0)
135 | {
136 | fprintf(rfp,"Bad entry %s.\n", tmp);
137 | return;
138 | }
139 |
140 | if(read)
141 | read_entry(entry);
142 | if(delete)
143 | delete_entry(entry);
144 | }
145 |
146 | void new_diary_entry(void)
147 | {
148 | int next_entry;
149 | char fname[512];
150 | char pabbr = dipent.pl[dipent.players[player].power];
151 |
152 | next_entry = get_numentries(dipent.name, pabbr);
153 | if(next_entry < 0)
154 | {
155 | fprintf(rfp,"Error: could not open new diary entry.\n\n");
156 | diary_skip++;
157 | return;
158 | }
159 |
160 | /* determine the new entry file & open it */
161 | sprintf(fname,"%s%s/diary-%c-%d", GAME_DIR, dipent.name,
162 | pabbr, next_entry);
163 | diaryfp = fopen(fname, "w");
164 | if(!diaryfp)
165 | {
166 | fprintf(log_fp, "Could not open diary file %s!\n", fname);
167 | fflush(log_fp);
168 | bailout(E_FATAL);
169 | }
170 |
171 | fprintf(rfp, "Recording new diary entry #%d...\n\n", next_entry);
172 | fprintf(diaryfp, "Diary entry from %s in %s for phase %s:\n\n\n",
173 | powers[dipent.players[player].power], dipent.name,
174 | dipent.phase);
175 | diary_read = 1;
176 | }
177 |
178 | void read_entry(int entry)
179 | {
180 | char entryfname[512];
181 | char line[1000];
182 | FILE *diary_read;
183 |
184 | sprintf(entryfname,"%s%s/diary-%c-%d", GAME_DIR, dipent.name,
185 | dipent.pl[dipent.players[player].power], entry);
186 | diary_read = fopen(entryfname, "r");
187 | if(!diary_read)
188 | {
189 | fprintf(rfp, "Cannot open diary entry #%d -- ", entry);
190 | fprintf(rfp, "perhaps said entry doesn't exist?\n\n");
191 | return;
192 | }
193 |
194 | fprintf(rfp, "Reading entry %d ... \n\n", entry);
195 | while(fgets(line, sizeof line, diary_read))
196 | fprintf(rfp,"%s", line);
197 | fprintf(rfp, "\n\nEnd of entry\n\n");
198 | }
199 |
200 | void delete_entry(int entry)
201 | {
202 | char pabbr, cmd[512];
203 |
204 | pabbr = dipent.pl[dipent.players[player].power];
205 | if(entry < 0 || entry >= get_numentries(dipent.name, pabbr))
206 | {
207 | fprintf(rfp,"Cannot delete diary entry %d -- no such entry.\n\n", entry);
208 | return;
209 | }
210 |
211 | sprintf(cmd,"rm -f %s%s/diary-%c-%d", GAME_DIR, dipent.name,
212 | pabbr, entry);
213 | system(cmd);
214 | fprintf(rfp, "Diary entry %d removed.\n\n", entry);
215 | }
216 |
217 | void list_entries(void)
218 | {
219 | int nentries, i;
220 | char pabbr;
221 | struct stat statbuf;
222 | struct tm *mod_tm;
223 | char fname[1000];
224 | char *months[] = {"Non", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
225 |
226 | pabbr = dipent.pl[dipent.players[player].power];
227 | nentries = get_numentries(dipent.name, pabbr);
228 | if(nentries < 0)
229 | {
230 | fprintf(rfp,"Error fetching number of entries!\n");
231 | } else if(nentries == 0) {
232 | fprintf(rfp,"You haven't made any diary entries!\n");
233 | } else {
234 | fprintf(rfp,"\nExisting diary entries:\n\n");
235 | for(i = 0; i < nentries; i++)
236 | {
237 | sprintf(fname,"%s%s/diary-%c-%d", GAME_DIR,
238 | dipent.name, pabbr, i);
239 | if(stat(fname, &statbuf) != -1)
240 | {
241 | mod_tm = localtime(&(statbuf.st_mtime));
242 | fprintf(rfp, "Entry #%d: modified %s %d, %d %02d:%02d\n",
243 | i, months[mod_tm->tm_mon + 1],
244 | mod_tm->tm_mday, 1900 + mod_tm->tm_year,
245 | mod_tm->tm_hour, mod_tm->tm_min);
246 | }
247 | else
248 | {
249 | nentries++;
250 | }
251 | }
252 | fprintf(rfp,"\n\n");
253 | }
254 | }
255 |
256 | int get_numentries(char *gamename, char pabbr)
257 | {
258 | char command[1000];
259 | char nstring[256];
260 | FILE *cmdpipe;
261 | int nentries = -1;
262 |
263 | sprintf(command,"ls %s%s/diary-%c* | wc -w",
264 | GAME_DIR, gamename, pabbr);
265 | cmdpipe = popen(command, "r");
266 | if(cmdpipe)
267 | {
268 | fread(nstring, 1, 255, cmdpipe);
269 | pclose(cmdpipe);
270 |
271 | if(strstr(nstring, "No such file"))
272 | nentries = 0;
273 | else
274 | nentries = (int)strtol(nstring, NULL, 10);
275 | }
276 |
277 | return nentries;
278 | }
279 |
280 | void send_diary(void)
281 | {
282 | /*
283 | * send each diary out at the end of the game.
284 | */
285 | int i, j, k, ndiaries;
286 | char subjectln[256];
287 | char diary_fl[256];
288 | char line[1000];
289 | char pabbr;
290 | struct stat sbuf;
291 |
292 | for(i = 0; i < dipent.n; i++)
293 | {
294 | /*
295 | * cycle through all the players who may have
296 | * left diaries
297 | */
298 | if(dipent.players[i].power < 0)
299 | continue;
300 | pabbr = dipent.pl[dipent.players[i].power];
301 | ndiaries = get_numentries(dipent.name, pabbr);
302 | if(ndiaries < 0)
303 | /* error don't send anything */
304 | ndiaries = 0;
305 |
306 | for(j = 0; j < ndiaries; j++)
307 | {
308 | /* send all diaries */
309 | sprintf(subjectln, "%s:%s diary #%d from %c",
310 | JUDGE_CODE, dipent.name, j, pabbr);
311 | sprintf(diary_fl, "%s%s/diary-%c-%d", GAME_DIR,
312 | dipent.name, pabbr, j);
313 | if(stat(diary_fl, &sbuf) == -1)
314 | {
315 | ndiaries++;
316 | continue;
317 | }
318 |
319 | for(k = 0; k < dipent.n; k++)
320 | {
321 | /* to everyone */
322 | if(dipent.players[k].power < 0)
323 | continue;
324 | sprintf(line, "%s %s \"%s\" %s", SMAIL_CMD,
325 | diary_fl, subjectln, dipent.players[k].address);
326 | execute(line);
327 | }
328 | }
329 | }
330 | }