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 static time_t lastmodtime;
240 static struct dirent **dp;
246 if (stat(infodir, &st) == -1)
248 pr("Available topics are:\n");
249 if (lastmodtime < st.st_mtime) {
253 number = scandir(infodir, &dp, fileselect, alphasort);
254 lastmodtime = st.st_mtime;
256 count = 79 / (biggest + 1) - 1;
257 for (i = 0, npl = 0; i < number; i++) {
258 pr("%-*.*s%c", biggest, strlen(dp[i]->d_name),
259 dp[i]->d_name, npl == count ? '\n' : ' ');
279 s_char filename[1024];
281 long nf, nhf, nl, nlhl, nhl, nll;
285 if (player->argp[1] == 0 || !*player->argp[1]) {
286 pr("Apropos what?\n");
291 if (player->argp[2]) {
292 lhitlim = atoi(player->argp[2]);
297 info_dp = opendir(infodir);
299 pr("Can't open info dir \"%s\"\n", infodir);
303 fbuf = (s_char *)malloc(256);
304 lbuf = (s_char *)malloc(256);
305 lbp = (s_char *)malloc(256);
308 * lower case search string into lbp
310 bp = player->argp[1];
311 lowerit(lbp, 256, bp);
316 nf = nhf = nl = nhl = 0;
318 while ((dp = readdir(info_dp)) != 0) {
319 sprintf(filename, "%s/%s", infodir, dp->d_name);
320 fp = fopen(filename, "r");
324 while (fgets(fbuf, 256, fp)) {
325 lowerit(lbuf, 256, fbuf);
326 if (strstr(lbuf, lbp)) {
328 pr("*** %s ***\n", dp->d_name);
337 * break if too many lines
339 if ((nhl + nlhl) > lhitlim)
358 if ((nhl) > lhitlim) {
359 pr("Limit of %ld lines exceeded\n", lhitlim);
361 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
362 bp, nhf, nf, nhl, nl);
375 s_char filename[1024];
377 if (player->argp[1] == 0 || !*player->argp[1])
380 /* Note that we generate an "all" file now, which contains
381 * this list, so we don't do printdir. */
382 else if (!strcmp(player->argp[1], "all"))
387 * don't let sneaky people go outside the info directory
389 bp = player->argp[1];
390 if (NULL != (bp2 = strrchr(bp, '/')))
392 if (NULL != (bp2 = strrchr(bp, '\\')))
394 if (NULL != (bp2 = strrchr(bp, ':')))
400 strncpy(filename, infodir, sizeof(filename) - 2);
401 strcat(filename, "//");
402 strncat(filename, bp, sizeof(filename) - 1 - strlen(filename));
403 fp = fopen(filename, "r");
405 /* may be a "partial" request. */
407 WIN32_FIND_DATA fData;
408 int len = strlen(bp);
409 strncat(filename, "*", sizeof(filename) - 1 - strlen(filename));
410 hDir = FindFirstFile(filename, &fData);
411 if (hDir == INVALID_HANDLE_VALUE) {
412 pr("Can't open info dir \"%s\"\n", infodir);
416 if ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) &&
417 (strnccmp(bp, fData.cFileName, len) == 0)) {
418 strncpy(filename, infodir, sizeof(filename) - 2);
419 strcat(filename, "//");
420 strncat(filename, fData.cFileName,
421 sizeof(filename) - 1 - strlen(filename));
422 fp = fopen(filename, "r");
424 } while (!fp && FindNextFile(hDir, &fData));
427 pr("Sorry, there is no info on %s\n", bp);
431 pr("Information on: %s", bp);
432 while (fgets(buf, sizeof(buf), fp) != 0)
443 WIN32_FIND_DATA fData;
447 s_char filename[1024];
449 strncpy(filename, infodir, sizeof(filename) - 3);
450 strcat(filename, "//*");
452 hDir = FindFirstFile(filename, &fData);
453 if (hDir == INVALID_HANDLE_VALUE) {
457 pr("Available topics are:\n");
459 if (fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) {
460 /* Yes, we could do multi-column work here. */
461 pr("%s\n", fData.cFileName);
463 } while (FindNextFile(hDir, &fData));
474 WIN32_FIND_DATA fData;
479 s_char filename[1024];
480 long nf, nhf, nl, nlhl, nhl, nll;
484 if (player->argp[1] == 0 || !*player->argp[1]) {
485 pr("Apropos what?\n");
490 if (player->argp[2]) {
491 lhitlim = atoi(player->argp[2]);
496 strncpy(filename, infodir, sizeof(filename) - 3);
497 strcat(filename, "//*");
498 hDir = FindFirstFile(filename, &fData);
499 if (hDir == INVALID_HANDLE_VALUE) {
503 fbuf = (s_char *)malloc(256);
504 lbuf = (s_char *)malloc(256);
505 lbp = (s_char *)malloc(256);
508 * lower case search string into lbp
510 bp = player->argp[1];
511 lowerit(lbp, 256, bp);
516 nf = nhf = nl = nhl = 0;
518 strncpy(filename, infodir, sizeof(filename) - 3);
519 strcat(filename, "//");
520 strncat(filename, fData.cFileName,
521 sizeof(filename) - 1 - strlen(filename));
522 fp = fopen(filename, "r");
526 while (fgets(fbuf, 256, fp)) {
527 lowerit(lbuf, 256, fbuf);
528 if (strstr(lbuf, lbp)) {
530 pr("*** %s ***\n", fData.cFileName);
539 * break if too many lines
541 if ((nhl + nlhl) > lhitlim)
553 } while (FindNextFile(hDir, &fData));
560 if ((nhl) > lhitlim) {
561 pr("Limit of %ld lines exceeded\n", lhitlim);
563 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
564 bp, nhf, nf, nhl, nl);