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
56 static int fileselect(struct dirent *dp);
57 static int printdir(void);
62 lowerit(s_char *buf, int n, s_char *orig)
63 { /* converts a string to lower case */
64 /* lower case output buffer */
65 /* size of output buffer */
71 for (i = 0; i < n && *orig; i++) {
72 *tmp++ = tolower(*orig++);
79 strnccmp(s_char *s1, s_char *s2, int n)
83 for (i = 0; i < n && *s1 && s2; i++) {
99 extern s_char *infodir;
100 #if (!defined linux) && (!defined FBSD) && (!defined __linux__) && (!defined __ppc__)
101 extern s_char *sys_errlist[];
108 s_char filename[1024];
111 if (player->argp[1] == 0 || !*player->argp[1])
114 /* Note that we generate an "all" file now, which contains
115 * this list, so we don't do printdir. */
116 else if (!strcmp(player->argp[1], "all"))
120 * don't let sneaky people go outside the info directory
122 else if (NULL != (bp = rindex(player->argp[1], '/')))
125 bp = player->argp[1];
126 sprintf(filename, "%s/%s", infodir, bp);
127 fp = fopen(filename, "r");
129 int len = strlen(bp);
130 /* may be a "partial" request. */
131 info_dp = opendir(infodir);
133 pr("Can't open info dir \"%s\"\n", infodir);
137 while ((dp = readdir(info_dp)) != 0 && fp == 0) {
138 if (strnccmp(bp, dp->d_name, len) != 0)
140 sprintf(filename, "%s/%s", infodir, dp->d_name);
141 fp = fopen(filename, "r");
145 pr("Sorry, there is no info on %s\n", bp);
149 if (fstat(fileno(fp), &statb) < 0) {
150 pr("Cannot read info page for \"%s\" (%s)\n",
151 dp->d_name, sys_errlist[errno]);
155 if ((statb.st_mode & S_IFREG) == 0) {
156 pr("There is no available information on \"%s\"\n", dp->d_name);
160 pr("Information on: %s Last modification date: %s",
161 bp, ctime(&statb.st_mtime));
162 while (fgets(buf, sizeof(buf), fp) != 0)
173 fileselect(struct dirent *dp)
176 if (*dp->d_name == '.')
179 if ((l = strlen(dp->d_name)) > biggest)
187 alphasort(struct dirent *d1, struct dirent *d2)
189 return strcmp(d1->d_name, d2->d_name);
193 scandir(char *dir, struct dirent ***dpp, int (*select) (), int (*sort) ())
194 /* directory to read */
195 /* directory entry pointer pointer */
200 struct dirent *d, *tmp;
202 d = (struct dirent *)malloc(sizeof(struct dirent) +
203 pathconf(".", _PC_NAME_MAX) + 1);
204 if ((dirp = opendir(dir)) == NULL)
207 *dpp = (struct dirent **)malloc(nsize * sizeof(struct dirent *));
208 if ((*dpp) == NULL) {
213 while ((d = readdir_r(dirp, d)) != NULL) {
214 if (select != NULL && !(*select) (d))
217 (struct dirent *)malloc(sizeof(struct dirent) +
218 strlen(d->d_name) + 1);
221 tmp->d_ino = d->d_ino;
222 tmp->d_reclen = d->d_reclen;
223 strcpy(tmp->d_name, d->d_name);
226 (struct dirent **)realloc((char *)*dpp,
227 nsize * sizeof(struct dirent *));
231 (*dpp)[nents++] = tmp;
234 if (nents > 0 && sort != NULL)
235 qsort(*dpp, nents, sizeof(struct dirent *), sort);
243 #if !defined(solaris) && !defined(ALPHA) && !defined(__linux__)
244 extern int alphasort(const struct dirent *const *,
245 const struct dirent *const *);
247 extern s_char *infodir;
248 static time_t lastmodtime;
250 static struct dirent **dp;
256 if (stat(infodir, &st) == -1)
258 pr("Available topics are:\n");
259 if (lastmodtime < st.st_mtime) {
263 number = scandir(infodir, &dp, fileselect, alphasort);
264 lastmodtime = st.st_mtime;
266 count = 79 / (biggest + 1) - 1;
267 for (i = 0, npl = 0; i < number; i++) {
268 pr("%-*.*s%c", biggest, strlen(dp[i]->d_name),
269 dp[i]->d_name, npl == count ? '\n' : ' ');
284 extern s_char *infodir;
290 s_char filename[1024];
292 long nf, nhf, nl, nlhl, nhl, nll;
296 if (player->argp[1] == 0 || !*player->argp[1]) {
297 pr("Apropos what?\n");
302 if (player->argp[2]) {
303 lhitlim = atoi(player->argp[2]);
308 info_dp = opendir(infodir);
310 pr("Can't open info dir \"%s\"\n", infodir);
314 fbuf = (s_char *)malloc(256);
315 lbuf = (s_char *)malloc(256);
316 lbp = (s_char *)malloc(256);
319 * lower case search string into lbp
321 bp = player->argp[1];
322 lowerit(lbp, 256, bp);
327 nf = nhf = nl = nhl = 0;
329 while ((dp = readdir(info_dp)) != 0) {
330 sprintf(filename, "%s/%s", infodir, dp->d_name);
331 fp = fopen(filename, "r");
335 while (fgets(fbuf, 256, fp)) {
336 lowerit(lbuf, 256, fbuf);
337 if (strstr(lbuf, lbp)) {
339 pr("*** %s ***\n", dp->d_name);
348 * break if too many lines
350 if ((nhl + nlhl) > lhitlim)
369 if ((nhl) > lhitlim) {
370 pr("Limit of %ld lines exceeded\n", lhitlim);
372 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
373 bp, nhf, nf, nhl, nl);
382 extern s_char *infodir;
387 s_char filename[1024];
389 if (player->argp[1] == 0 || !*player->argp[1])
392 /* Note that we generate an "all" file now, which contains
393 * this list, so we don't do printdir. */
394 else if (!strcmp(player->argp[1], "all"))
399 * don't let sneaky people go outside the info directory
401 bp = player->argp[1];
402 if (NULL != (bp2 = rindex(bp, '/')))
404 if (NULL != (bp2 = rindex(bp, '\\')))
406 if (NULL != (bp2 = rindex(bp, ':')))
412 strncpy(filename, infodir, sizeof(filename) - 2);
413 strcat(filename, "//");
414 strncat(filename, bp, sizeof(filename) - 1 - strlen(filename));
415 fp = fopen(filename, "r");
417 /* may be a "partial" request. */
419 WIN32_FIND_DATA fData;
420 int len = strlen(bp);
421 strncat(filename, "*", sizeof(filename) - 1 - strlen(filename));
422 hDir = FindFirstFile(filename, &fData);
423 if (hDir == INVALID_HANDLE_VALUE) {
424 pr("Can't open info dir \"%s\"\n", infodir);
428 if ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) &&
429 (strnccmp(bp, fData.cFileName, len) == 0)) {
430 strncpy(filename, infodir, sizeof(filename) - 2);
431 strcat(filename, "//");
432 strncat(filename, fData.cFileName,
433 sizeof(filename) - 1 - strlen(filename));
434 fp = fopen(filename, "r");
436 } while (!fp && FindNextFile(hDir, &fData));
439 pr("Sorry, there is no info on %s\n", bp);
443 pr("Information on: %s", bp);
444 while (fgets(buf, sizeof(buf), fp) != 0)
454 extern s_char *infodir;
456 WIN32_FIND_DATA fData;
460 s_char filename[1024];
462 strncpy(filename, infodir, sizeof(filename) - 3);
463 strcat(filename, "//*");
465 hDir = FindFirstFile(filename, &fData);
466 if (hDir == INVALID_HANDLE_VALUE) {
470 pr("Available topics are:\n");
472 if (fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) {
473 /* Yes, we could do multi-column work here. */
474 pr("%s\n", fData.cFileName);
476 } while (FindNextFile(hDir, &fData));
486 extern s_char *infodir;
488 WIN32_FIND_DATA fData;
493 s_char filename[1024];
494 long nf, nhf, nl, nlhl, nhl, nll;
498 if (player->argp[1] == 0 || !*player->argp[1]) {
499 pr("Apropos what?\n");
504 if (player->argp[2]) {
505 lhitlim = atoi(player->argp[2]);
510 strncpy(filename, infodir, sizeof(filename) - 3);
511 strcat(filename, "//*");
512 hDir = FindFirstFile(filename, &fData);
513 if (hDir == INVALID_HANDLE_VALUE) {
517 fbuf = (s_char *)malloc(256);
518 lbuf = (s_char *)malloc(256);
519 lbp = (s_char *)malloc(256);
522 * lower case search string into lbp
524 bp = player->argp[1];
525 lowerit(lbp, 256, bp);
530 nf = nhf = nl = nhl = 0;
532 strncpy(filename, infodir, sizeof(filename) - 3);
533 strcat(filename, "//");
534 strncat(filename, fData.cFileName,
535 sizeof(filename) - 1 - strlen(filename));
536 fp = fopen(filename, "r");
540 while (fgets(fbuf, 256, fp)) {
541 lowerit(lbuf, 256, fbuf);
542 if (strstr(lbuf, lbp)) {
544 pr("*** %s ***\n", fData.cFileName);
553 * break if too many lines
555 if ((nhl + nlhl) > lhitlim)
567 } while (FindNextFile(hDir, &fData));
574 if ((nhl) > lhitlim) {
575 pr("Limit of %ld lines exceeded\n", lhitlim);
577 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
578 bp, nhf, nf, nhl, nl);