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
51 lowerit(char *buf, int n, char *orig)
52 { /* converts a string to lower case */
53 /* lower case output buffer */
54 /* size of output buffer */
57 for (i = 0; i < n - 1 && orig[i]; i++)
58 buf[i] = tolower(orig[i]);
81 name = player->argp[1];
84 * don't let sneaky people go outside the info directory
86 if (NULL != (tmp_name = strrchr(name, '/')))
92 snprintf(filename, sizeof(filename), "%s/%s", infodir, name);
93 fp = fopen(filename, "r");
95 /* may be a "partial" request. */
96 info_dp = opendir(infodir);
98 pr("Can't open info dir\n");
99 logerror("Can't open info dir \"%s\"\n", infodir);
103 while ((dp = readdir(info_dp))) {
104 if (strncasecmp(name, dp->d_name, strlen(name)) != 0)
108 snprintf(last, sizeof(last), "%s", dp->d_name);
111 pr("`%s' is ambiguous. The following topics match:\n%s",
113 width = strlen(last);
115 width += 2 + strlen(dp->d_name);
119 width = strlen(dp->d_name);
121 pr(",%c%s", sep, dp->d_name);
126 pr("Sorry, there is no info on %s\n", name);
128 } else if (nmatch > 1) {
132 snprintf(filename, sizeof(filename), "%s/%s", infodir, last);
133 fp = fopen(filename, "r");
135 pr("Error reading info file for %s\n", name);
136 logerror("Cannot open for \"%s\" info file (%s)",
137 filename, strerror(errno));
141 if (fstat(fileno(fp), &statb) < 0) {
142 pr("Error reading info file for %s\n", name);
143 logerror("Cannot fstat for \"%s\" info file (%s)",
144 filename, strerror(errno));
148 if (!S_ISREG(statb.st_mode)) {
149 pr("Error reading info file for %s\n", name);
150 logerror("The info file \"%s\" is not regular file\n", filename);
155 while (fgets(buf, sizeof(buf), fp))
171 long nf, nhf, nl, nlhl, nhl, nll;
176 if (!player->argp[1] || !*player->argp[1]) {
177 pr("Apropos what?\n");
182 if (player->argp[2]) {
183 lhitlim = atoi(player->argp[2]);
188 info_dp = opendir(infodir);
189 if (info_dp == NULL) {
190 pr("Can't open info dir\n");
191 logerror("Can't open info dir \"%s\"", infodir);
200 * lower case search string into lbp
202 name = player->argp[1];
203 lowerit(lbp, 256, name);
208 nf = nhf = nl = nhl = 0;
209 while ((dp = readdir(info_dp))) {
210 if (dp->d_name[0] == '.')
212 snprintf(filename, sizeof(filename), "%s/%s", infodir, dp->d_name);
213 fp = fopen(filename, "r");
217 if (fstat(fileno(fp), &statb) < 0) {
218 logerror("Cannot stat for \"%s\" info file (%s)",
219 filename, strerror(errno));
223 if (!S_ISREG(statb.st_mode)) {
224 logerror("The info file \"%s\" is not regular file\n",
229 while (fgets(fbuf, 256, fp)) {
230 lowerit(lbuf, 256, fbuf);
231 if (strstr(lbuf, lbp)) {
233 pr("*** %s ***\n", dp->d_name);
242 * break if too many lines
244 if ((nhl + nlhl) > lhitlim)
263 if ((nhl) > lhitlim) {
264 pr("Limit of %d lines exceeded\n", lhitlim);
266 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
267 name, nhf, nf, nhl, nl);
286 name = player->argp[1];
289 * don't let sneaky people go outside the info directory
291 if (NULL != (tmp_name = strrchr(name, '/')))
293 if (NULL != (tmp_name = strrchr(name, '\\')))
295 if (NULL != (tmp_name = strrchr(name, ':')))
301 snprintf(filename, sizeof(filename) - 1, "%s\\%s", infodir, name);
302 fp = fopen(filename, "rb");
304 /* may be a "partial" request. */
306 WIN32_FIND_DATA fData;
307 strcat(filename, "*");
308 hDir = FindFirstFile(filename, &fData);
309 if (hDir == INVALID_HANDLE_VALUE) {
310 switch (GetLastError()) {
311 case ERROR_FILE_NOT_FOUND:
312 pr("Sorry, there is no info on %s\n", name);
314 case ERROR_PATH_NOT_FOUND:
315 pr("Can't open info dir\n");
316 logerror("Can't open info dir \"%s\"", infodir);
319 pr("Error reading info dir\n");
320 logerror("Error (%lu) reading info dir(%s)\\file(%s)",
321 GetLastError(), infodir, filename);
326 if ((fData.dwFileAttributes != (DWORD)-1) &&
327 ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) ||
328 (fData.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE) ||
329 (fData.dwFileAttributes == FILE_ATTRIBUTE_READONLY)) &&
330 (strncasecmp(name, fData.cFileName, strlen(name)) == 0)) {
333 snprintf(last, sizeof(last), "%s", fData.cFileName);
336 pr("`%s' is ambiguous. The following topics match:\n%s",
338 width = strlen(last);
340 width += 2 + strlen(fData.cFileName);
344 width = strlen(fData.cFileName);
346 pr(",%c%s", sep, fData.cFileName);
349 } while (FindNextFile(hDir, &fData));
352 pr("Sorry, there is no info on %s\n", name);
354 } else if (nmatch > 1) {
358 snprintf(filename, sizeof(filename), "%s/%s", infodir, last);
359 fp = fopen(filename, "rb");
361 pr("Error reading info file for %s\n", name);
362 logerror("Cannot open for \"%s\" info file (%s)",
363 filename, strerror(errno));
367 DWORD fAttrib = GetFileAttributes(filename);
368 if ((fAttrib == (DWORD)-1) || /* INVALID_FILE_ATTRIBUTES */
369 ((fAttrib != FILE_ATTRIBUTE_NORMAL) &&
370 (fAttrib != FILE_ATTRIBUTE_ARCHIVE) &&
371 (fAttrib != FILE_ATTRIBUTE_READONLY))) {
372 pr("Error reading info file for %s\n", name);
373 logerror("The info file \"%s\" is not regular file\n",
380 while (fgets(buf, sizeof(buf), fp) != 0)
390 WIN32_FIND_DATA fData;
396 long nf, nhf, nl, nlhl, nhl, nll;
400 if (player->argp[1] == 0 || !*player->argp[1]) {
401 pr("Apropos what?\n");
406 if (player->argp[2]) {
407 lhitlim = atoi(player->argp[2]);
412 snprintf(filename, sizeof(filename), "%s\\*", infodir);
413 hDir = FindFirstFile(filename, &fData);
414 if (hDir == INVALID_HANDLE_VALUE) {
415 if (GetLastError() == ERROR_PATH_NOT_FOUND) {
416 pr("Can't open info dir\n");
417 logerror("Can't open info dir \"%s\"", infodir);
419 pr("Error reading info dir\n");
420 logerror("Error (%lu) reading info dir(%s)\\file(%s)",
421 GetLastError(), infodir, filename);
431 * lower case search string into lbp
433 name = player->argp[1];
434 lowerit(lbp, 256, name);
439 nf = nhf = nl = nhl = 0;
441 if ((fData.dwFileAttributes != (DWORD)-1) &&
442 ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) ||
443 (fData.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE) ||
444 (fData.dwFileAttributes == FILE_ATTRIBUTE_READONLY))) {
445 snprintf(filename, sizeof(filename), "%s\\%s", infodir,
447 fp = fopen(filename, "rb");
451 while (fgets(fbuf, 256, fp)) {
452 lowerit(lbuf, 256, fbuf);
453 if (strstr(lbuf, lbp)) {
455 pr("*** %s ***\n", fData.cFileName);
464 * break if too many lines
466 if ((nhl + nlhl) > lhitlim)
479 } while (FindNextFile(hDir, &fData));
486 if ((nhl) > lhitlim) {
487 pr("Limit of %d lines exceeded\n", lhitlim);
489 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
490 name, nhf, nf, nhl, nl);