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);
60 lowerit(s_char *buf, int n, s_char *orig)
61 { /* converts a string to lower case */
62 /* lower case output buffer */
63 /* size of output buffer */
69 for (i = 0; i < n && *orig; i++) {
70 *tmp++ = tolower(*orig++);
76 strnccmp(s_char *s1, s_char *s2, int n)
80 for (i = 0; i < n && *s1 && s2; i++) {
101 s_char filename[1024];
104 if (player->argp[1] == 0 || !*player->argp[1])
107 /* Note that we generate an "all" file now, which contains
108 * this list, so we don't do printdir. */
109 else if (!strcmp(player->argp[1], "all"))
113 * don't let sneaky people go outside the info directory
115 else if (NULL != (bp = strrchr(player->argp[1], '/')))
118 bp = player->argp[1];
119 sprintf(filename, "%s/%s", infodir, bp);
120 fp = fopen(filename, "r");
122 int len = strlen(bp);
123 /* may be a "partial" request. */
124 info_dp = opendir(infodir);
126 pr("Can't open info dir \"%s\"\n", infodir);
130 while ((dp = readdir(info_dp)) != 0 && fp == 0) {
131 if (strnccmp(bp, dp->d_name, len) != 0)
133 sprintf(filename, "%s/%s", infodir, dp->d_name);
134 fp = fopen(filename, "r");
138 pr("Sorry, there is no info on %s\n", bp);
142 if (fstat(fileno(fp), &statb) < 0) {
143 pr("Cannot read info page for \"%s\" (%s)\n",
144 dp->d_name, strerror(errno));
148 if ((statb.st_mode & S_IFREG) == 0) {
149 pr("There is no available information on \"%s\"\n", dp->d_name);
153 pr("Information on: %s Last modification date: %s",
154 bp, ctime(&statb.st_mtime));
155 while (fgets(buf, sizeof(buf), fp) != 0)
165 fileselect(struct dirent *dp)
168 if (*dp->d_name == '.')
171 if ((l = strlen(dp->d_name)) > biggest)
178 alphasort(struct dirent *d1, struct dirent *d2)
180 return strcmp(d1->d_name, d2->d_name);
184 scandir(char *dir, struct dirent ***dpp, int (*select) (), int (*sort) ())
185 /* directory to read */
186 /* directory entry pointer pointer */
191 struct dirent *d, *tmp;
193 d = (struct dirent *)malloc(sizeof(struct dirent) +
194 pathconf(".", _PC_NAME_MAX) + 1);
195 if ((dirp = opendir(dir)) == NULL)
198 *dpp = (struct dirent **)malloc(nsize * sizeof(struct dirent *));
199 if ((*dpp) == NULL) {
204 while ((d = readdir_r(dirp, d)) != NULL) {
205 if (select != NULL && !(*select) (d))
208 (struct dirent *)malloc(sizeof(struct dirent) +
209 strlen(d->d_name) + 1);
212 tmp->d_ino = d->d_ino;
213 tmp->d_reclen = d->d_reclen;
214 strcpy(tmp->d_name, d->d_name);
217 (struct dirent **)realloc((char *)*dpp,
218 nsize * sizeof(struct dirent *));
222 (*dpp)[nents++] = tmp;
225 if (nents > 0 && sort != NULL)
226 qsort(*dpp, nents, sizeof(struct dirent *), sort);
234 #if !defined(solaris) && !defined(ALPHA) && !defined(__linux__)
235 extern int alphasort(const struct dirent *const *,
236 const struct dirent *const *);
238 extern s_char *infodir;
239 static time_t lastmodtime;
241 static struct dirent **dp;
247 if (stat(infodir, &st) == -1)
249 pr("Available topics are:\n");
250 if (lastmodtime < st.st_mtime) {
254 number = scandir(infodir, &dp, fileselect, alphasort);
255 lastmodtime = st.st_mtime;
257 count = 79 / (biggest + 1) - 1;
258 for (i = 0, npl = 0; i < number; i++) {
259 pr("%-*.*s%c", biggest, strlen(dp[i]->d_name),
260 dp[i]->d_name, npl == count ? '\n' : ' ');
280 s_char filename[1024];
282 long nf, nhf, nl, nlhl, nhl, nll;
286 if (player->argp[1] == 0 || !*player->argp[1]) {
287 pr("Apropos what?\n");
292 if (player->argp[2]) {
293 lhitlim = atoi(player->argp[2]);
298 info_dp = opendir(infodir);
300 pr("Can't open info dir \"%s\"\n", infodir);
304 fbuf = (s_char *)malloc(256);
305 lbuf = (s_char *)malloc(256);
306 lbp = (s_char *)malloc(256);
309 * lower case search string into lbp
311 bp = player->argp[1];
312 lowerit(lbp, 256, bp);
317 nf = nhf = nl = nhl = 0;
319 while ((dp = readdir(info_dp)) != 0) {
320 sprintf(filename, "%s/%s", infodir, dp->d_name);
321 fp = fopen(filename, "r");
325 while (fgets(fbuf, 256, fp)) {
326 lowerit(lbuf, 256, fbuf);
327 if (strstr(lbuf, lbp)) {
329 pr("*** %s ***\n", dp->d_name);
338 * break if too many lines
340 if ((nhl + nlhl) > lhitlim)
359 if ((nhl) > lhitlim) {
360 pr("Limit of %ld lines exceeded\n", lhitlim);
362 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
363 bp, nhf, nf, nhl, nl);
372 extern s_char *infodir;
377 s_char filename[1024];
379 if (player->argp[1] == 0 || !*player->argp[1])
382 /* Note that we generate an "all" file now, which contains
383 * this list, so we don't do printdir. */
384 else if (!strcmp(player->argp[1], "all"))
389 * don't let sneaky people go outside the info directory
391 bp = player->argp[1];
392 if (NULL != (bp2 = strrchr(bp, '/')))
394 if (NULL != (bp2 = strrchr(bp, '\\')))
396 if (NULL != (bp2 = strrchr(bp, ':')))
402 strncpy(filename, infodir, sizeof(filename) - 2);
403 strcat(filename, "//");
404 strncat(filename, bp, sizeof(filename) - 1 - strlen(filename));
405 fp = fopen(filename, "r");
407 /* may be a "partial" request. */
409 WIN32_FIND_DATA fData;
410 int len = strlen(bp);
411 strncat(filename, "*", sizeof(filename) - 1 - strlen(filename));
412 hDir = FindFirstFile(filename, &fData);
413 if (hDir == INVALID_HANDLE_VALUE) {
414 pr("Can't open info dir \"%s\"\n", infodir);
418 if ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) &&
419 (strnccmp(bp, fData.cFileName, len) == 0)) {
420 strncpy(filename, infodir, sizeof(filename) - 2);
421 strcat(filename, "//");
422 strncat(filename, fData.cFileName,
423 sizeof(filename) - 1 - strlen(filename));
424 fp = fopen(filename, "r");
426 } while (!fp && FindNextFile(hDir, &fData));
429 pr("Sorry, there is no info on %s\n", bp);
433 pr("Information on: %s", bp);
434 while (fgets(buf, sizeof(buf), fp) != 0)
444 extern s_char *infodir;
446 WIN32_FIND_DATA fData;
450 s_char filename[1024];
452 strncpy(filename, infodir, sizeof(filename) - 3);
453 strcat(filename, "//*");
455 hDir = FindFirstFile(filename, &fData);
456 if (hDir == INVALID_HANDLE_VALUE) {
460 pr("Available topics are:\n");
462 if (fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) {
463 /* Yes, we could do multi-column work here. */
464 pr("%s\n", fData.cFileName);
466 } while (FindNextFile(hDir, &fData));
476 extern s_char *infodir;
478 WIN32_FIND_DATA fData;
483 s_char filename[1024];
484 long nf, nhf, nl, nlhl, nhl, nll;
488 if (player->argp[1] == 0 || !*player->argp[1]) {
489 pr("Apropos what?\n");
494 if (player->argp[2]) {
495 lhitlim = atoi(player->argp[2]);
500 strncpy(filename, infodir, sizeof(filename) - 3);
501 strcat(filename, "//*");
502 hDir = FindFirstFile(filename, &fData);
503 if (hDir == INVALID_HANDLE_VALUE) {
507 fbuf = (s_char *)malloc(256);
508 lbuf = (s_char *)malloc(256);
509 lbp = (s_char *)malloc(256);
512 * lower case search string into lbp
514 bp = player->argp[1];
515 lowerit(lbp, 256, bp);
520 nf = nhf = nl = nhl = 0;
522 strncpy(filename, infodir, sizeof(filename) - 3);
523 strcat(filename, "//");
524 strncat(filename, fData.cFileName,
525 sizeof(filename) - 1 - strlen(filename));
526 fp = fopen(filename, "r");
530 while (fgets(fbuf, 256, fp)) {
531 lowerit(lbuf, 256, fbuf);
532 if (strstr(lbuf, lbp)) {
534 pr("*** %s ***\n", fData.cFileName);
543 * break if too many lines
545 if ((nhl + nlhl) > lhitlim)
557 } while (FindNextFile(hDir, &fData));
564 if ((nhl) > lhitlim) {
565 pr("Limit of %ld lines exceeded\n", lhitlim);
567 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
568 bp, nhf, nf, nhl, nl);