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);
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++);
77 strnccmp(s_char *s1, s_char *s2, int n)
81 for (i = 0; i < n && *s1 && s2; i++) {
97 extern s_char *infodir;
103 s_char filename[1024];
106 if (player->argp[1] == 0 || !*player->argp[1])
109 /* Note that we generate an "all" file now, which contains
110 * this list, so we don't do printdir. */
111 else if (!strcmp(player->argp[1], "all"))
115 * don't let sneaky people go outside the info directory
117 else if (NULL != (bp = rindex(player->argp[1], '/')))
120 bp = player->argp[1];
121 sprintf(filename, "%s/%s", infodir, bp);
122 fp = fopen(filename, "r");
124 int len = strlen(bp);
125 /* may be a "partial" request. */
126 info_dp = opendir(infodir);
128 pr("Can't open info dir \"%s\"\n", infodir);
132 while ((dp = readdir(info_dp)) != 0 && fp == 0) {
133 if (strnccmp(bp, dp->d_name, len) != 0)
135 sprintf(filename, "%s/%s", infodir, dp->d_name);
136 fp = fopen(filename, "r");
140 pr("Sorry, there is no info on %s\n", bp);
144 if (fstat(fileno(fp), &statb) < 0) {
145 pr("Cannot read info page for \"%s\" (%s)\n",
146 dp->d_name, strerror(errno));
150 if ((statb.st_mode & S_IFREG) == 0) {
151 pr("There is no available information on \"%s\"\n", dp->d_name);
155 pr("Information on: %s Last modification date: %s",
156 bp, ctime(&statb.st_mtime));
157 while (fgets(buf, sizeof(buf), fp) != 0)
168 fileselect(struct dirent *dp)
171 if (*dp->d_name == '.')
174 if ((l = strlen(dp->d_name)) > biggest)
182 alphasort(struct dirent *d1, struct dirent *d2)
184 return strcmp(d1->d_name, d2->d_name);
188 scandir(char *dir, struct dirent ***dpp, int (*select) (), int (*sort) ())
189 /* directory to read */
190 /* directory entry pointer pointer */
195 struct dirent *d, *tmp;
197 d = (struct dirent *)malloc(sizeof(struct dirent) +
198 pathconf(".", _PC_NAME_MAX) + 1);
199 if ((dirp = opendir(dir)) == NULL)
202 *dpp = (struct dirent **)malloc(nsize * sizeof(struct dirent *));
203 if ((*dpp) == NULL) {
208 while ((d = readdir_r(dirp, d)) != NULL) {
209 if (select != NULL && !(*select) (d))
212 (struct dirent *)malloc(sizeof(struct dirent) +
213 strlen(d->d_name) + 1);
216 tmp->d_ino = d->d_ino;
217 tmp->d_reclen = d->d_reclen;
218 strcpy(tmp->d_name, d->d_name);
221 (struct dirent **)realloc((char *)*dpp,
222 nsize * sizeof(struct dirent *));
226 (*dpp)[nents++] = tmp;
229 if (nents > 0 && sort != NULL)
230 qsort(*dpp, nents, sizeof(struct dirent *), sort);
238 #if !defined(solaris) && !defined(ALPHA) && !defined(__linux__)
239 extern int alphasort(const struct dirent *const *,
240 const struct dirent *const *);
242 extern s_char *infodir;
243 static time_t lastmodtime;
245 static struct dirent **dp;
251 if (stat(infodir, &st) == -1)
253 pr("Available topics are:\n");
254 if (lastmodtime < st.st_mtime) {
258 number = scandir(infodir, &dp, fileselect, alphasort);
259 lastmodtime = st.st_mtime;
261 count = 79 / (biggest + 1) - 1;
262 for (i = 0, npl = 0; i < number; i++) {
263 pr("%-*.*s%c", biggest, strlen(dp[i]->d_name),
264 dp[i]->d_name, npl == count ? '\n' : ' ');
279 extern s_char *infodir;
285 s_char filename[1024];
287 long nf, nhf, nl, nlhl, nhl, nll;
291 if (player->argp[1] == 0 || !*player->argp[1]) {
292 pr("Apropos what?\n");
297 if (player->argp[2]) {
298 lhitlim = atoi(player->argp[2]);
303 info_dp = opendir(infodir);
305 pr("Can't open info dir \"%s\"\n", infodir);
309 fbuf = (s_char *)malloc(256);
310 lbuf = (s_char *)malloc(256);
311 lbp = (s_char *)malloc(256);
314 * lower case search string into lbp
316 bp = player->argp[1];
317 lowerit(lbp, 256, bp);
322 nf = nhf = nl = nhl = 0;
324 while ((dp = readdir(info_dp)) != 0) {
325 sprintf(filename, "%s/%s", infodir, dp->d_name);
326 fp = fopen(filename, "r");
330 while (fgets(fbuf, 256, fp)) {
331 lowerit(lbuf, 256, fbuf);
332 if (strstr(lbuf, lbp)) {
334 pr("*** %s ***\n", dp->d_name);
343 * break if too many lines
345 if ((nhl + nlhl) > lhitlim)
364 if ((nhl) > lhitlim) {
365 pr("Limit of %ld lines exceeded\n", lhitlim);
367 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
368 bp, nhf, nf, nhl, nl);
377 extern s_char *infodir;
382 s_char filename[1024];
384 if (player->argp[1] == 0 || !*player->argp[1])
387 /* Note that we generate an "all" file now, which contains
388 * this list, so we don't do printdir. */
389 else if (!strcmp(player->argp[1], "all"))
394 * don't let sneaky people go outside the info directory
396 bp = player->argp[1];
397 if (NULL != (bp2 = rindex(bp, '/')))
399 if (NULL != (bp2 = rindex(bp, '\\')))
401 if (NULL != (bp2 = rindex(bp, ':')))
407 strncpy(filename, infodir, sizeof(filename) - 2);
408 strcat(filename, "//");
409 strncat(filename, bp, sizeof(filename) - 1 - strlen(filename));
410 fp = fopen(filename, "r");
412 /* may be a "partial" request. */
414 WIN32_FIND_DATA fData;
415 int len = strlen(bp);
416 strncat(filename, "*", sizeof(filename) - 1 - strlen(filename));
417 hDir = FindFirstFile(filename, &fData);
418 if (hDir == INVALID_HANDLE_VALUE) {
419 pr("Can't open info dir \"%s\"\n", infodir);
423 if ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) &&
424 (strnccmp(bp, fData.cFileName, len) == 0)) {
425 strncpy(filename, infodir, sizeof(filename) - 2);
426 strcat(filename, "//");
427 strncat(filename, fData.cFileName,
428 sizeof(filename) - 1 - strlen(filename));
429 fp = fopen(filename, "r");
431 } while (!fp && FindNextFile(hDir, &fData));
434 pr("Sorry, there is no info on %s\n", bp);
438 pr("Information on: %s", bp);
439 while (fgets(buf, sizeof(buf), fp) != 0)
449 extern s_char *infodir;
451 WIN32_FIND_DATA fData;
455 s_char filename[1024];
457 strncpy(filename, infodir, sizeof(filename) - 3);
458 strcat(filename, "//*");
460 hDir = FindFirstFile(filename, &fData);
461 if (hDir == INVALID_HANDLE_VALUE) {
465 pr("Available topics are:\n");
467 if (fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) {
468 /* Yes, we could do multi-column work here. */
469 pr("%s\n", fData.cFileName);
471 } while (FindNextFile(hDir, &fData));
481 extern s_char *infodir;
483 WIN32_FIND_DATA fData;
488 s_char filename[1024];
489 long nf, nhf, nl, nlhl, nhl, nll;
493 if (player->argp[1] == 0 || !*player->argp[1]) {
494 pr("Apropos what?\n");
499 if (player->argp[2]) {
500 lhitlim = atoi(player->argp[2]);
505 strncpy(filename, infodir, sizeof(filename) - 3);
506 strcat(filename, "//*");
507 hDir = FindFirstFile(filename, &fData);
508 if (hDir == INVALID_HANDLE_VALUE) {
512 fbuf = (s_char *)malloc(256);
513 lbuf = (s_char *)malloc(256);
514 lbp = (s_char *)malloc(256);
517 * lower case search string into lbp
519 bp = player->argp[1];
520 lowerit(lbp, 256, bp);
525 nf = nhf = nl = nhl = 0;
527 strncpy(filename, infodir, sizeof(filename) - 3);
528 strcat(filename, "//");
529 strncat(filename, fData.cFileName,
530 sizeof(filename) - 1 - strlen(filename));
531 fp = fopen(filename, "r");
535 while (fgets(fbuf, 256, fp)) {
536 lowerit(lbuf, 256, fbuf);
537 if (strstr(lbuf, lbp)) {
539 pr("*** %s ***\n", fData.cFileName);
548 * break if too many lines
550 if ((nhl + nlhl) > lhitlim)
562 } while (FindNextFile(hDir, &fData));
569 if ((nhl) > lhitlim) {
570 pr("Limit of %ld lines exceeded\n", lhitlim);
572 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
573 bp, nhf, nf, nhl, nl);