2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2021, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure, Markus Armbruster
6 * Empire 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 3 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, see <http://www.gnu.org/licenses/>.
21 * See files README, COPYING and CREDITS in the root of the source
22 * tree for related information and legal notices. It is expected
23 * that future projects/authors will amend these files as needed.
27 * info.c: display an info page
29 * Known contributors to this file:
31 * Mike Wise, 1997 - added apropos and case insensitivity
33 * Steve McClure, 1998-2000
34 * Ron Koenderink, 2004
53 lowerit(char *buf, int n, char *orig)
54 { /* converts a string to lower case */
55 /* lower case output buffer */
56 /* size of output buffer */
59 for (i = 0; i < n - 1 && orig[i]; i++)
60 buf[i] = tolower(orig[i]);
83 name = player->argp[1];
86 * don't let sneaky people go outside the info directory
88 if (NULL != (tmp_name = strrchr(name, '/')))
94 snprintf(filename, sizeof(filename), "%s/%s", infodir, name);
95 fp = fopen(filename, "r");
97 /* may be a "partial" request. */
98 info_dp = opendir(infodir);
100 pr("Can't open info dir\n");
101 logerror("Can't open info dir \"%s\"\n", infodir);
105 while ((dp = readdir(info_dp))) {
106 if (strncasecmp(name, dp->d_name, strlen(name)) != 0)
110 snprintf(last, sizeof(last), "%s", dp->d_name);
113 pr("`%s' is ambiguous. The following topics match:\n%s",
115 width = strlen(last);
117 width += 2 + strlen(dp->d_name);
121 width = strlen(dp->d_name);
123 pr(",%c%s", sep, dp->d_name);
128 pr("Sorry, there is no info on %s\n", name);
130 } else if (nmatch > 1) {
134 snprintf(filename, sizeof(filename), "%s/%s", infodir, last);
135 fp = fopen(filename, "r");
137 pr("Error reading info file for %s\n", name);
138 logerror("Cannot open for \"%s\" info file (%s)",
139 filename, strerror(errno));
143 if (fstat(fileno(fp), &statb) < 0) {
144 pr("Error reading info file for %s\n", name);
145 logerror("Cannot fstat for \"%s\" info file (%s)",
146 filename, strerror(errno));
150 if (!S_ISREG(statb.st_mode)) {
151 pr("Error reading info file for %s\n", name);
152 logerror("The info file \"%s\" is not regular file\n", filename);
157 while (fgets(buf, sizeof(buf), fp))
173 long nf, nhf, nl, nlhl, nhl, nll;
178 if (!player->argp[1] || !*player->argp[1]) {
179 pr("Apropos what?\n");
184 if (player->argp[2]) {
185 lhitlim = atoi(player->argp[2]);
190 info_dp = opendir(infodir);
191 if (info_dp == NULL) {
192 pr("Can't open info dir\n");
193 logerror("Can't open info dir \"%s\"", infodir);
202 * lower case search string into lbp
204 name = player->argp[1];
205 lowerit(lbp, 256, name);
210 nf = nhf = nl = nhl = 0;
211 while ((dp = readdir(info_dp))) {
212 if (dp->d_name[0] == '.')
214 snprintf(filename, sizeof(filename), "%s/%s", infodir, dp->d_name);
215 fp = fopen(filename, "r");
219 if (fstat(fileno(fp), &statb) < 0) {
220 logerror("Cannot stat for \"%s\" info file (%s)",
221 filename, strerror(errno));
225 if (!S_ISREG(statb.st_mode)) {
226 logerror("The info file \"%s\" is not regular file\n",
231 while (fgets(fbuf, 256, fp)) {
232 lowerit(lbuf, 256, fbuf);
233 if (strstr(lbuf, lbp)) {
235 pr("*** %s ***\n", dp->d_name);
244 * break if too many lines
246 if ((nhl + nlhl) > lhitlim)
265 if ((nhl) > lhitlim) {
266 pr("Limit of %d lines exceeded\n", lhitlim);
268 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
269 name, nhf, nf, nhl, nl);
288 name = player->argp[1];
291 * don't let sneaky people go outside the info directory
293 if (NULL != (tmp_name = strrchr(name, '/')))
295 if (NULL != (tmp_name = strrchr(name, '\\')))
297 if (NULL != (tmp_name = strrchr(name, ':')))
303 snprintf(filename, sizeof(filename) - 1, "%s\\%s", infodir, name);
304 fp = fopen(filename, "rb");
306 /* may be a "partial" request. */
308 WIN32_FIND_DATA fData;
309 strcat(filename, "*");
310 hDir = FindFirstFile(filename, &fData);
311 if (hDir == INVALID_HANDLE_VALUE) {
312 switch (GetLastError()) {
313 case ERROR_FILE_NOT_FOUND:
314 pr("Sorry, there is no info on %s\n", name);
316 case ERROR_PATH_NOT_FOUND:
317 pr("Can't open info dir\n");
318 logerror("Can't open info dir \"%s\"", infodir);
321 pr("Error reading info dir\n");
322 logerror("Error (%lu) reading info dir(%s)\\file(%s)",
323 GetLastError(), infodir, filename);
328 if ((fData.dwFileAttributes != (DWORD)-1) &&
329 ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) ||
330 (fData.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE) ||
331 (fData.dwFileAttributes == FILE_ATTRIBUTE_READONLY)) &&
332 (strncasecmp(name, fData.cFileName, strlen(name)) == 0)) {
335 snprintf(last, sizeof(last), "%s", fData.cFileName);
338 pr("`%s' is ambiguous. The following topics match:\n%s",
340 width = strlen(last);
342 width += 2 + strlen(fData.cFileName);
346 width = strlen(fData.cFileName);
348 pr(",%c%s", sep, fData.cFileName);
351 } while (FindNextFile(hDir, &fData));
354 pr("Sorry, there is no info on %s\n", name);
356 } else if (nmatch > 1) {
360 snprintf(filename, sizeof(filename), "%s/%s", infodir, last);
361 fp = fopen(filename, "rb");
363 pr("Error reading info file for %s\n", name);
364 logerror("Cannot open for \"%s\" info file (%s)",
365 filename, strerror(errno));
369 DWORD fAttrib = GetFileAttributes(filename);
370 if ((fAttrib == (DWORD)-1) || /* INVALID_FILE_ATTRIBUTES */
371 ((fAttrib != FILE_ATTRIBUTE_NORMAL) &&
372 (fAttrib != FILE_ATTRIBUTE_ARCHIVE) &&
373 (fAttrib != FILE_ATTRIBUTE_READONLY))) {
374 pr("Error reading info file for %s\n", name);
375 logerror("The info file \"%s\" is not regular file\n",
382 while (fgets(buf, sizeof(buf), fp) != 0)
392 WIN32_FIND_DATA fData;
398 long nf, nhf, nl, nlhl, nhl, nll;
402 if (player->argp[1] == 0 || !*player->argp[1]) {
403 pr("Apropos what?\n");
408 if (player->argp[2]) {
409 lhitlim = atoi(player->argp[2]);
414 snprintf(filename, sizeof(filename), "%s\\*", infodir);
415 hDir = FindFirstFile(filename, &fData);
416 if (hDir == INVALID_HANDLE_VALUE) {
417 if (GetLastError() == ERROR_PATH_NOT_FOUND) {
418 pr("Can't open info dir\n");
419 logerror("Can't open info dir \"%s\"", infodir);
421 pr("Error reading info dir\n");
422 logerror("Error (%lu) reading info dir(%s)\\file(%s)",
423 GetLastError(), infodir, filename);
433 * lower case search string into lbp
435 name = player->argp[1];
436 lowerit(lbp, 256, name);
441 nf = nhf = nl = nhl = 0;
443 if ((fData.dwFileAttributes != (DWORD)-1) &&
444 ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) ||
445 (fData.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE) ||
446 (fData.dwFileAttributes == FILE_ATTRIBUTE_READONLY))) {
447 snprintf(filename, sizeof(filename), "%s\\%s", infodir,
449 fp = fopen(filename, "rb");
453 while (fgets(fbuf, 256, fp)) {
454 lowerit(lbuf, 256, fbuf);
455 if (strstr(lbuf, lbp)) {
457 pr("*** %s ***\n", fData.cFileName);
466 * break if too many lines
468 if ((nhl + nlhl) > lhitlim)
481 } while (FindNextFile(hDir, &fData));
488 if ((nhl) > lhitlim) {
489 pr("Limit of %d lines exceeded\n", lhitlim);
491 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
492 name, nhf, nf, nhl, nl);