2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
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.
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.
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
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.
28 * info.c: display an info page
30 * Known contributors to this file:
32 * Mike Wise, 1997 - added apropos and case insensitivity
34 * Steve McClure, 1998-2000
55 static int fileselect(struct dirent *dp);
56 static int printdir(void);
61 lowerit(s_char *buf, int n, s_char *orig)
64 { /* converts a string to lower case */
65 /* lower case output buffer */
66 /* size of output buffer */
72 for (i = 0; i < n && *orig; i++) {
73 *tmp++ = tolower(*orig++);
80 strnccmp(s_char *s1, s_char *s2, int n)
84 for (i = 0; i < n && *s1 && s2; i++) {
101 extern s_char *infodir;
102 #if (!defined linux) && (!defined FBSD) && (!defined __linux__) && (!defined __ppc__)
103 extern s_char *sys_errlist[];
110 s_char filename[1024];
113 if (player->argp[1] == 0 || !*player->argp[1])
116 /* Note that we generate an "all" file now, which contains
117 * this list, so we don't do printdir. */
118 else if (!strcmp(player->argp[1], "all"))
122 * don't let sneaky people go outside the info directory
124 else if (NULL != (bp = rindex(player->argp[1], '/')))
127 bp = player->argp[1];
128 sprintf(filename, "%s/%s", infodir, bp);
129 fp = fopen(filename, "r");
131 int len = strlen(bp);
132 /* may be a "partial" request. */
133 info_dp = opendir(infodir);
135 pr("Can't open info dir \"%s\"\n", infodir);
139 while ((dp = readdir(info_dp)) != 0 && fp == 0) {
140 if (strnccmp(bp, dp->d_name, len) != 0)
142 sprintf(filename, "%s/%s", infodir, dp->d_name);
143 fp = fopen(filename, "r");
147 pr("Sorry, there is no info on %s\n", bp);
151 if (fstat(fileno(fp), &statb) < 0) {
152 pr("Cannot read info page for \"%s\" (%s)\n",
153 dp->d_name, sys_errlist[errno]);
157 if ((statb.st_mode & S_IFREG) == 0) {
158 pr("There is no available information on \"%s\"\n", dp->d_name);
162 pr("Information on: %s Last modification date: %s",
163 bp, ctime(&statb.st_mtime));
164 while (fgets(buf, sizeof(buf), fp) != 0)
175 fileselect(struct dirent *dp)
178 if (*dp->d_name == '.')
181 if ((l = strlen(dp->d_name)) > biggest)
189 alphasort(struct dirent *d1, struct dirent *d2)
191 return strcmp(d1->d_name, d2->d_name);
195 scandir(char *dir, struct dirent ***dpp, int (*select) (), int (*sort) ())
196 /* directory to read */
197 /* directory entry pointer pointer */
202 struct dirent *d, *tmp;
204 d = (struct dirent *)malloc(sizeof(struct dirent) +
205 pathconf(".", _PC_NAME_MAX) + 1);
206 if ((dirp = opendir(dir)) == NULL)
209 *dpp = (struct dirent **)malloc(nsize * sizeof(struct dirent *));
210 if ((*dpp) == NULL) {
215 while ((d = readdir_r(dirp, d)) != NULL) {
216 if (select != NULL && !(*select) (d))
219 (struct dirent *)malloc(sizeof(struct dirent) +
220 strlen(d->d_name) + 1);
223 tmp->d_ino = d->d_ino;
224 tmp->d_reclen = d->d_reclen;
225 strcpy(tmp->d_name, d->d_name);
228 (struct dirent **)realloc((char *)*dpp,
229 nsize * sizeof(struct dirent *));
233 (*dpp)[nents++] = tmp;
236 if (nents > 0 && sort != NULL)
237 qsort(*dpp, nents, sizeof(struct dirent *), sort);
245 #if !defined(solaris) && !defined(ALPHA) && !defined(__linux__)
246 extern int alphasort(const struct dirent *const *,
247 const struct dirent *const *);
249 extern s_char *infodir;
250 static time_t lastmodtime;
252 static struct dirent **dp;
258 if (stat(infodir, &st) == -1)
260 pr("Available topics are:\n");
261 if (lastmodtime < st.st_mtime) {
265 number = scandir(infodir, &dp, fileselect, alphasort);
266 lastmodtime = st.st_mtime;
268 count = 79 / (biggest + 1) - 1;
269 for (i = 0, npl = 0; i < number; i++) {
270 pr("%-*.*s%c", biggest, strlen(dp[i]->d_name),
271 dp[i]->d_name, npl == count ? '\n' : ' ');
286 extern s_char *infodir;
292 s_char filename[1024];
294 long nf, nhf, nl, nlhl, nhl, nll;
298 if (player->argp[1] == 0 || !*player->argp[1]) {
299 pr("Apropos what?\n");
304 if (player->argp[2]) {
305 lhitlim = atoi(player->argp[2]);
310 info_dp = opendir(infodir);
312 pr("Can't open info dir \"%s\"\n", infodir);
316 fbuf = (s_char *)malloc(256);
317 lbuf = (s_char *)malloc(256);
318 lbp = (s_char *)malloc(256);
321 * lower case search string into lbp
323 bp = player->argp[1];
324 lowerit(lbp, 256, bp);
329 nf = nhf = nl = nhl = 0;
331 while ((dp = readdir(info_dp)) != 0) {
332 sprintf(filename, "%s/%s", infodir, dp->d_name);
333 fp = fopen(filename, "r");
337 while (fgets(fbuf, 256, fp)) {
338 lowerit(lbuf, 256, fbuf);
339 if (strstr(lbuf, lbp)) {
341 pr("*** %s ***\n", dp->d_name);
350 * break if too many lines
352 if ((nhl + nlhl) > lhitlim)
371 if ((nhl) > lhitlim) {
372 pr("Limit of %ld lines exceeded\n", lhitlim);
374 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
375 bp, nhf, nf, nhl, nl);
385 extern s_char *infodir;
390 s_char filename[1024];
392 if (player->argp[1] == 0 || !*player->argp[1])
395 /* Note that we generate an "all" file now, which contains
396 * this list, so we don't do printdir. */
397 else if (!strcmp(player->argp[1], "all"))
402 * don't let sneaky people go outside the info directory
404 bp = player->argp[1];
405 if (NULL != (bp2 = rindex(bp, '/')))
407 if (NULL != (bp2 = rindex(bp, '\\')))
409 if (NULL != (bp2 = rindex(bp, ':')))
415 strncpy(filename, infodir, sizeof(filename) - 2);
416 strcat(filename, "//");
417 strncat(filename, bp, sizeof(filename) - 1 - strlen(filename));
418 fp = fopen(filename, "r");
420 /* may be a "partial" request. */
422 WIN32_FIND_DATA fData;
423 int len = strlen(bp);
424 strncat(filename, "*", sizeof(filename) - 1 - strlen(filename));
425 hDir = FindFirstFile(filename, &fData);
426 if (hDir == INVALID_HANDLE_VALUE) {
427 pr("Can't open info dir \"%s\"\n", infodir);
431 if ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) &&
432 (strnccmp(bp, fData.cFileName, len) == 0)) {
433 strncpy(filename, infodir, sizeof(filename) - 2);
434 strcat(filename, "//");
435 strncat(filename, fData.cFileName,
436 sizeof(filename) - 1 - strlen(filename));
437 fp = fopen(filename, "r");
439 } while (!fp && FindNextFile(hDir, &fData));
442 pr("Sorry, there is no info on %s\n", bp);
446 pr("Information on: %s", bp);
447 while (fgets(buf, sizeof(buf), fp) != 0)
457 extern s_char *infodir;
459 WIN32_FIND_DATA fData;
463 s_char filename[1024];
465 strncpy(filename, infodir, sizeof(filename) - 3);
466 strcat(filename, "//*");
468 hDir = FindFirstFile(filename, &fData);
469 if (hDir == INVALID_HANDLE_VALUE) {
473 pr("Available topics are:\n");
475 if (fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) {
476 /* Yes, we could do multi-column work here. */
477 pr("%s\n", fData.cFileName);
479 } while (FindNextFile(hDir, &fData));
489 extern s_char *infodir;
491 WIN32_FIND_DATA fData;
496 s_char filename[1024];
497 long nf, nhf, nl, nlhl, nhl, nll;
501 if (player->argp[1] == 0 || !*player->argp[1]) {
502 pr("Apropos what?\n");
507 if (player->argp[2]) {
508 lhitlim = atoi(player->argp[2]);
513 strncpy(filename, infodir, sizeof(filename) - 3);
514 strcat(filename, "//*");
515 hDir = FindFirstFile(filename, &fData);
516 if (hDir == INVALID_HANDLE_VALUE) {
520 fbuf = (s_char *)malloc(256);
521 lbuf = (s_char *)malloc(256);
522 lbp = (s_char *)malloc(256);
525 * lower case search string into lbp
527 bp = player->argp[1];
528 lowerit(lbp, 256, bp);
533 nf = nhf = nl = nhl = 0;
535 strncpy(filename, infodir, sizeof(filename) - 3);
536 strcat(filename, "//");
537 strncat(filename, fData.cFileName,
538 sizeof(filename) - 1 - strlen(filename));
539 fp = fopen(filename, "r");
543 while (fgets(fbuf, 256, fp)) {
544 lowerit(lbuf, 256, fbuf);
545 if (strstr(lbuf, lbp)) {
547 pr("*** %s ***\n", fData.cFileName);
556 * break if too many lines
558 if ((nhl + nlhl) > lhitlim)
570 } while (FindNextFile(hDir, &fData));
577 if ((nhl) > lhitlim) {
578 pr("Limit of %ld lines exceeded\n", lhitlim);
580 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
581 bp, nhf, nf, nhl, nl);