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
54 static int fileselect(struct dirent *dp);
55 static int printdir(void);
59 lowerit(s_char *buf, int n, s_char *orig)
60 { /* converts a string to lower case */
61 /* lower case output buffer */
62 /* size of output buffer */
68 for (i = 0; i < n && *orig; i++) {
69 *tmp++ = tolower(*orig++);
75 strnccmp(s_char *s1, s_char *s2, int n)
79 for (i = 0; i < n && *s1 && s2; i++) {
95 extern s_char *infodir;
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' : ' ');
275 extern s_char *infodir;
281 s_char filename[1024];
283 long nf, nhf, nl, nlhl, nhl, nll;
287 if (player->argp[1] == 0 || !*player->argp[1]) {
288 pr("Apropos what?\n");
293 if (player->argp[2]) {
294 lhitlim = atoi(player->argp[2]);
299 info_dp = opendir(infodir);
301 pr("Can't open info dir \"%s\"\n", infodir);
305 fbuf = (s_char *)malloc(256);
306 lbuf = (s_char *)malloc(256);
307 lbp = (s_char *)malloc(256);
310 * lower case search string into lbp
312 bp = player->argp[1];
313 lowerit(lbp, 256, bp);
318 nf = nhf = nl = nhl = 0;
320 while ((dp = readdir(info_dp)) != 0) {
321 sprintf(filename, "%s/%s", infodir, dp->d_name);
322 fp = fopen(filename, "r");
326 while (fgets(fbuf, 256, fp)) {
327 lowerit(lbuf, 256, fbuf);
328 if (strstr(lbuf, lbp)) {
330 pr("*** %s ***\n", dp->d_name);
339 * break if too many lines
341 if ((nhl + nlhl) > lhitlim)
360 if ((nhl) > lhitlim) {
361 pr("Limit of %ld lines exceeded\n", lhitlim);
363 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
364 bp, nhf, nf, nhl, nl);
373 extern s_char *infodir;
378 s_char filename[1024];
380 if (player->argp[1] == 0 || !*player->argp[1])
383 /* Note that we generate an "all" file now, which contains
384 * this list, so we don't do printdir. */
385 else if (!strcmp(player->argp[1], "all"))
390 * don't let sneaky people go outside the info directory
392 bp = player->argp[1];
393 if (NULL != (bp2 = strrchr(bp, '/')))
395 if (NULL != (bp2 = strrchr(bp, '\\')))
397 if (NULL != (bp2 = strrchr(bp, ':')))
403 strncpy(filename, infodir, sizeof(filename) - 2);
404 strcat(filename, "//");
405 strncat(filename, bp, sizeof(filename) - 1 - strlen(filename));
406 fp = fopen(filename, "r");
408 /* may be a "partial" request. */
410 WIN32_FIND_DATA fData;
411 int len = strlen(bp);
412 strncat(filename, "*", sizeof(filename) - 1 - strlen(filename));
413 hDir = FindFirstFile(filename, &fData);
414 if (hDir == INVALID_HANDLE_VALUE) {
415 pr("Can't open info dir \"%s\"\n", infodir);
419 if ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) &&
420 (strnccmp(bp, fData.cFileName, len) == 0)) {
421 strncpy(filename, infodir, sizeof(filename) - 2);
422 strcat(filename, "//");
423 strncat(filename, fData.cFileName,
424 sizeof(filename) - 1 - strlen(filename));
425 fp = fopen(filename, "r");
427 } while (!fp && FindNextFile(hDir, &fData));
430 pr("Sorry, there is no info on %s\n", bp);
434 pr("Information on: %s", bp);
435 while (fgets(buf, sizeof(buf), fp) != 0)
445 extern s_char *infodir;
447 WIN32_FIND_DATA fData;
451 s_char filename[1024];
453 strncpy(filename, infodir, sizeof(filename) - 3);
454 strcat(filename, "//*");
456 hDir = FindFirstFile(filename, &fData);
457 if (hDir == INVALID_HANDLE_VALUE) {
461 pr("Available topics are:\n");
463 if (fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) {
464 /* Yes, we could do multi-column work here. */
465 pr("%s\n", fData.cFileName);
467 } while (FindNextFile(hDir, &fData));
477 extern s_char *infodir;
479 WIN32_FIND_DATA fData;
484 s_char filename[1024];
485 long nf, nhf, nl, nlhl, nhl, nll;
489 if (player->argp[1] == 0 || !*player->argp[1]) {
490 pr("Apropos what?\n");
495 if (player->argp[2]) {
496 lhitlim = atoi(player->argp[2]);
501 strncpy(filename, infodir, sizeof(filename) - 3);
502 strcat(filename, "//*");
503 hDir = FindFirstFile(filename, &fData);
504 if (hDir == INVALID_HANDLE_VALUE) {
508 fbuf = (s_char *)malloc(256);
509 lbuf = (s_char *)malloc(256);
510 lbp = (s_char *)malloc(256);
513 * lower case search string into lbp
515 bp = player->argp[1];
516 lowerit(lbp, 256, bp);
521 nf = nhf = nl = nhl = 0;
523 strncpy(filename, infodir, sizeof(filename) - 3);
524 strcat(filename, "//");
525 strncat(filename, fData.cFileName,
526 sizeof(filename) - 1 - strlen(filename));
527 fp = fopen(filename, "r");
531 while (fgets(fbuf, 256, fp)) {
532 lowerit(lbuf, 256, fbuf);
533 if (strstr(lbuf, lbp)) {
535 pr("*** %s ***\n", fData.cFileName);
544 * break if too many lines
546 if ((nhl + nlhl) > lhitlim)
558 } while (FindNextFile(hDir, &fData));
565 if ((nhl) > lhitlim) {
566 pr("Limit of %ld lines exceeded\n", lhitlim);
568 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
569 bp, nhf, nf, nhl, nl);