]> git.pond.sub.org Git - empserver/blob - src/lib/commands/info.c
Remove a bunch of redundant casts.
[empserver] / src / lib / commands / info.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2005, 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 the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  info.c: display an info page
29  * 
30  *  Known contributors to this file:
31  *     Dave Pare, 1986
32  *     Mike Wise, 1997 - added apropos and case insensitivity
33  *     Doug Hay, 1998
34  *     Steve McClure, 1998-2000
35  */
36
37 #include "misc.h"
38 #include "player.h"
39 #include <errno.h>
40 #include <string.h>
41 #include <stdio.h>
42 #include <sys/stat.h>
43 #if !defined(_WIN32)
44 #include <dirent.h>
45 #else
46 #include <windows.h>
47 #endif
48 #include "commands.h"
49 #include "optlist.h"
50
51 static s_char *
52 lowerit(s_char *buf, int n, s_char *orig)
53 {                               /* converts a string to lower case */
54     /* lower case output buffer */
55     /* size of output buffer */
56     /* input strig */
57     int i;
58     s_char *tmp;
59     tmp = buf;
60     memset(buf, 0, n);
61     for (i = 0; i < n && *orig; i++) {
62         *tmp++ = tolower(*orig++);
63     }
64     return buf;
65 }
66
67 #if !defined(_WIN32)
68
69 int
70 info(void)
71 {
72     s_char buf[255];
73     FILE *fp;
74     s_char *name;
75     s_char *tmp_name;
76     struct stat statb;
77     struct dirent *dp;
78     s_char filename[1024];
79     s_char last[256];
80     DIR *info_dp;
81     int nmatch = 0;
82     int width = 0;
83     char sep;
84  
85     name = player->argp[1];
86     if (name) {
87         /*
88          * don't let sneaky people go outside the info directory
89          */
90         if (NULL != (tmp_name = strrchr(name, '/')))
91             name = tmp_name + 1;
92     }
93     if (!name || !*name)
94         name = "TOP";
95  
96     snprintf(filename, sizeof(filename), "%s/%s", infodir, name);
97     fp = fopen(filename, "r");
98     if (fp == NULL) {
99         int len = strlen(name);
100         /* may be a "partial" request.  */
101         info_dp = opendir(infodir);
102         if (info_dp == 0) {
103             pr("Can't open info dir\n");
104             logerror("Can't open info dir \"%s\"\n", infodir);
105             return RET_SYS;
106         }
107
108         while ((dp = readdir(info_dp)) != 0) {
109             if (strncasecmp(name, dp->d_name, strlen(name)) != 0)
110                 continue;
111             nmatch++;
112             if (nmatch == 1) {
113                 snprintf(last, sizeof(last), "%s", dp->d_name);
114             } else {
115                 if (nmatch == 2) {
116                     pr("`%s' is ambiguous.  The following topics match:\n%s",
117                         name, last);
118                     width = strlen(last);
119                 }
120                 width += 2 + strlen(dp->d_name);
121                 sep = ' ';
122                 if (width > 75) {
123                     sep = '\n';
124                     width = strlen(dp->d_name);
125                 }
126                 pr(",%c%s", sep, dp->d_name);
127             }
128         }
129         closedir(info_dp);
130         if (nmatch == 0) {
131             pr("Sorry, there is no info on %s\n", name);
132             return RET_FAIL;
133         } else if (nmatch > 1) {
134             pr(".\n");
135             return RET_FAIL;
136         }
137         snprintf(filename, sizeof(filename), "%s/%s", infodir,
138                  last);
139         fp = fopen(filename, "r");
140         if (fp == NULL) {
141             pr("Error reading info file for %s\n", name);
142             logerror("Cannot open for \"%s\" info file (%s)",
143                      filename, strerror(errno));
144             return RET_FAIL;
145         }
146     }
147     if (fstat(fileno(fp), &statb) < 0) {
148         pr("Error reading info file for %s\n", name);
149         logerror("Cannot fstat for \"%s\" info file (%s)",
150                  filename, strerror(errno));
151         fclose(fp);
152         return RET_SYS;
153     }
154     if ((statb.st_mode & S_IFREG) == 0) {
155         pr("Error reading info file for %s\n", name);
156         logerror("The info file \"%s\" is not regular file\n", filename);
157         fclose(fp);
158         return RET_SYS;
159     }
160     pr("Information on:  %s    Last modification date: %s",
161        name, ctime(&statb.st_mtime));
162     while (fgets(buf, sizeof(buf), fp) != 0)
163         pr("%s", buf);
164     (void)fclose(fp);
165     return RET_OK;
166 }
167
168 int
169 apro(void)
170 {
171     FILE *fp;
172     s_char *name, *lbp;
173     s_char *fbuf;
174     s_char *lbuf;
175     struct dirent *dp;
176     s_char filename[1024];
177     DIR *info_dp;
178     long nf, nhf, nl, nlhl, nhl, nll;
179     int alreadyhit;
180     int lhitlim;
181     struct stat statb;
182
183     if (player->argp[1] == 0 || !*player->argp[1]) {
184         pr("Apropos what?\n");
185         return RET_FAIL;
186     }
187
188     lhitlim = 100;
189     if (player->argp[2]) {
190         lhitlim = atoi(player->argp[2]);
191         if (lhitlim <= 0)
192             lhitlim = 100;
193     }
194
195     info_dp = opendir(infodir);
196     if (info_dp == NULL) {
197         pr("Can't open info dir \n");
198         logerror("Can't open info dir \"%s\"", infodir);
199         return RET_SYS;
200     }
201
202     fbuf = malloc(256);
203     lbuf = malloc(256);
204     lbp = malloc(256);
205
206     /*
207      *  lower case search string into lbp
208      */
209     name = player->argp[1];
210     lowerit(lbp, 256, name);
211
212     /*
213      *  search
214      */
215     nf = nhf = nl = nhl = 0;
216     while ((dp = readdir(info_dp)) != 0) {
217         snprintf(filename, sizeof(filename), "%s/%s", infodir,
218             dp->d_name);
219         fp = fopen(filename, "r");
220         alreadyhit = 0;
221         nll = nlhl = 0;
222         if (fp != NULL) {
223             if (fstat(fileno(fp), &statb) < 0) {
224                 logerror("Cannot stat for \"%s\" info file (%s)",
225                          filename, strerror(errno));
226                 fclose(fp);
227                 continue;
228             }
229             if ((statb.st_mode & S_IFREG) == 0) {
230                 logerror("The info file \"%s\" is not regular file\n",
231                          filename);
232                 fclose(fp);
233                 continue;
234             }
235             while (fgets(fbuf, 256, fp)) {
236                 lowerit(lbuf, 256, fbuf);
237                 if (strstr(lbuf, lbp)) {
238                     if (!alreadyhit) {
239                         pr("*** %s ***\n", dp->d_name);
240                         alreadyhit = 1;
241                         nhf++;
242                     }
243                     fbuf[74] = '\n';
244                     fbuf[75] = 0;
245                     pr("   %s", fbuf);
246                     nlhl++;
247                     /*
248                      * break if too many lines
249                      */
250                     if ((nhl + nlhl) > lhitlim)
251                         break;
252                 }
253                 nll++;
254             }
255             fclose(fp);
256         }
257         nhl += nlhl;
258         nl += nll;
259         nf++;
260         if (nhl > lhitlim)
261             break;
262     }
263     closedir(info_dp);
264
265     free(fbuf);
266     free(lbuf);
267     free(lbp);
268
269     if ((nhl) > lhitlim) {
270         pr("Limit of %d lines exceeded\n", lhitlim);
271     }
272     pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
273        name, nhf, nf, nhl, nl);
274     return RET_OK;
275 }
276
277 #else
278
279 int
280 info(void)
281 {
282     s_char buf[255];
283     FILE *fp;
284     s_char *name;
285     s_char *tmp_name;
286     s_char filename[1024];
287     s_char last[256];
288     int nmatch = 0;
289     int width = 0;
290     char sep;
291
292     name = player->argp[1];
293     if (name) {
294         /*
295          * don't let sneaky people go outside the info directory
296          */
297         if (NULL != (tmp_name = strrchr(name, '/')))
298             name = tmp_name + 1;
299         if (NULL != (tmp_name = strrchr(name, '\\')))
300             name = tmp_name + 1;
301         if (NULL != (tmp_name = strrchr(name, ':')))
302             name = tmp_name + 1;
303     }
304     if (!name || !*name)
305         name = "TOP";
306
307     _snprintf(filename, sizeof(filename) - 1, "%s\\%s", infodir, name);
308     fp = fopen(filename, "rb");
309     if (fp == NULL) {
310         /* may be a "partial" request.  */
311         HANDLE hDir;
312         WIN32_FIND_DATA fData;
313         int len = strlen(name);
314         strcat(filename, "*");
315         hDir = FindFirstFile(filename, &fData);
316         if (hDir == INVALID_HANDLE_VALUE) {
317             switch (GetLastError()) {
318             case ERROR_FILE_NOT_FOUND:
319                 pr("Sorry, there is no info on %s\n", name);
320                 return RET_FAIL;
321                 break;
322             case ERROR_PATH_NOT_FOUND:
323                 pr("Can't open info dir\n");
324                 logerror("Can't open info dir \"%s\"", infodir);
325                 break;
326             default:
327                 pr("Error reading info dir\n");
328                 logerror("Error (%d) reading info dir(%s)\\file(%s)",
329                     infodir, filename, GetLastError());
330             }
331             return RET_SYS;
332         }
333         do {
334             if ((fData.dwFileAttributes != (DWORD)-1) &&
335                 ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) ||
336                  (fData.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE) ||
337                  (fData.dwFileAttributes == FILE_ATTRIBUTE_READONLY)) &&
338                 (strncasecmp(name, fData.cFileName, strlen(name)) == 0)) {
339                 nmatch++;
340                 if (nmatch == 1) {
341                     _snprintf(last, sizeof(last), "%s", fData.cFileName);
342                 } else {
343                     if (nmatch == 2) {
344                         pr("`%s' is ambiguous.  The following topics match:\n%s",
345                             name, last);
346                         width = strlen(last);
347                     }
348                     width += 2 + strlen(fData.cFileName);
349                     sep = ' ';
350                     if (width > 75) {
351                         sep = '\n';
352                         width = strlen(fData.cFileName);
353                     }
354                     pr(",%c%s", sep, fData.cFileName);
355                 }
356             }
357         } while (FindNextFile(hDir, &fData));
358         FindClose(hDir);
359         if (nmatch == 0) {
360             pr("Sorry, there is no info on %s\n", name);
361             return RET_FAIL;
362         } else if (nmatch > 1) {
363             pr(".\n");
364             return RET_FAIL;
365         }
366         _snprintf(filename, sizeof(filename), "%s/%s",
367                   infodir, last);
368         fp = fopen(filename, "rb");
369         if (fp == NULL) {
370             pr("Error reading info file for %s\n", name);
371             logerror("Cannot open for \"%s\" info file (%s)",
372                      filename, strerror(errno));
373             return RET_FAIL;
374         }
375     }
376     else {
377         DWORD fAttrib = GetFileAttributes(filename);
378         if ((fAttrib == (DWORD)-1) || /* INVALID_FILE_ATTRIBUTES */
379             (fAttrib != FILE_ATTRIBUTE_NORMAL) &&
380             (fAttrib != FILE_ATTRIBUTE_ARCHIVE) &&
381             (fAttrib != FILE_ATTRIBUTE_READONLY)) {
382             pr("Error reading info file for %s\n", name);
383             logerror("The info file \"%s\" is not regular file\n",
384                      filename);
385             fclose(fp);
386             return RET_SYS;
387         }
388     }
389
390     pr("Information on:  %s", name);
391     while (fgets(buf, sizeof(buf), fp) != 0)
392         pr("%s", buf);
393     (void)fclose(fp);
394     return RET_OK;
395 }
396
397 int
398 apro(void)
399 {
400     HANDLE hDir;
401     WIN32_FIND_DATA fData;
402     FILE *fp;
403     s_char *name, *lbp;
404     s_char *fbuf;
405     s_char *lbuf;
406     s_char filename[1024];
407     long nf, nhf, nl, nlhl, nhl, nll;
408     int alreadyhit;
409     int lhitlim;
410
411     if (player->argp[1] == 0 || !*player->argp[1]) {
412         pr("Apropos what?\n");
413         return RET_FAIL;
414     }
415
416     lhitlim = 100;
417     if (player->argp[2]) {
418         lhitlim = atoi(player->argp[2]);
419         if (lhitlim <= 0)
420             lhitlim = 100;
421     }
422
423     _snprintf(filename, sizeof(filename), "%s\\*",infodir);
424     hDir = FindFirstFile(filename, &fData);
425     if (hDir == INVALID_HANDLE_VALUE) {
426         if (GetLastError() == ERROR_PATH_NOT_FOUND) {
427             pr("Can't open info dir\n");
428             logerror("Can't open info dir \"%s\"", infodir);
429         } else {
430             pr("Error reading info dir\n");
431             logerror("Error (%d) reading info dir(%s)\\file(%s)",
432                 infodir, filename, GetLastError());
433         }
434         return RET_SYS;
435     }
436
437     fbuf = malloc(256);
438     lbuf = malloc(256);
439     lbp = malloc(256);
440
441     /*
442      *  lower case search string into lbp
443      */
444     name = player->argp[1];
445     lowerit(lbp, 256, name);
446
447     /*
448      *  search
449      */
450     nf = nhf = nl = nhl = 0;
451     do {
452         if ((fData.dwFileAttributes != (DWORD)-1) &&
453             ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) ||
454              (fData.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE) ||
455              (fData.dwFileAttributes == FILE_ATTRIBUTE_READONLY))) {
456             _snprintf(filename, sizeof(filename), "%s\\%s", infodir,
457                       fData.cFileName);
458             fp = fopen(filename, "rb");
459             alreadyhit = 0;
460             nll = nlhl = 0;
461             if (fp != NULL) {
462                 while (fgets(fbuf, 256, fp)) {
463                     lowerit(lbuf, 256, fbuf);
464                     if (strstr(lbuf, lbp)) {
465                         if (!alreadyhit) {
466                             pr("*** %s ***\n", fData.cFileName);
467                             alreadyhit = 1;
468                             nhf++;
469                         }
470                         fbuf[74] = '\n';
471                         fbuf[75] = 0;
472                         pr("   %s", fbuf);
473                         nlhl++;
474                         /*
475                          * break if too many lines
476                          */
477                         if ((nhl + nlhl) > lhitlim)
478                             break;
479                     }
480                     nll++;
481                 }
482                 fclose(fp);
483             }
484             nhl += nlhl;
485             nl += nll;
486             nf++;
487             if (nhl > lhitlim)
488                 break;
489         }
490     } while (FindNextFile(hDir, &fData));
491     FindClose(hDir);
492
493     free(fbuf);
494     free(lbuf);
495     free(lbp);
496
497     if ((nhl) > lhitlim) {
498         pr("Limit of %ld lines exceeded\n", lhitlim);
499     }
500     pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
501        name, nhf, nf, nhl, nl);
502     return RET_OK;
503 }
504
505 #endif