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);
61 lowerit(s_char *buf, int n, s_char *orig) /* converts a string to lower case */
62 /* lower case output buffer */
63 /* size of output buffer */
70 for ( i=0; i<n && *orig; i++ ){
71 *tmp++ = tolower(*orig++);
78 strnccmp(s_char *s1, s_char *s2, int n)
82 for ( i=0; i<n && *s1 && s2; i++ ){
86 else if (c1<c2) return -1;
97 extern s_char *infodir;
98 #if (!defined linux) && (!defined FBSD) && (!defined __linux__) && (!defined __ppc__)
99 extern s_char *sys_errlist[];
106 s_char filename[1024];
109 if (player->argp[1] == 0 || !*player->argp[1])
112 /* Note that we generate an "all" file now, which contains
113 * this list, so we don't do printdir. */
114 else if (!strcmp(player->argp[1], "all"))
118 * don't let sneaky people go outside the info directory
120 else if (NULL != (bp = rindex(player->argp[1], '/')))
123 bp = player->argp[1];
124 sprintf(filename, "%s/%s", infodir, bp);
125 fp = fopen(filename, "r");
127 int len = strlen(bp);
128 /* may be a "partial" request. */
129 info_dp = opendir(infodir);
131 pr("Can't open info dir \"%s\"\n", infodir);
135 while ((dp = readdir(info_dp)) != 0 && fp == 0) {
136 if (strnccmp(bp, dp->d_name, len) != 0)
138 sprintf(filename, "%s/%s", infodir, dp->d_name);
139 fp = fopen(filename, "r");
143 pr("Sorry, there is no info on %s\n", bp);
147 if (fstat(fileno(fp), &statb) < 0) {
148 pr("Cannot read info page for \"%s\" (%s)\n",
149 dp->d_name, sys_errlist[errno]);
153 if ((statb.st_mode & S_IFREG) == 0) {
154 pr("There is no available information on \"%s\"\n",
159 pr("Information on: %s Last modification date: %s",
160 bp, ctime(&statb.st_mtime));
161 while (fgets(buf, sizeof(buf), fp) != 0)
172 fileselect(struct dirent *dp)
175 if (*dp->d_name == '.')
178 if ((l = strlen (dp->d_name)) > biggest)
186 alphasort(struct dirent *d1, struct dirent *d2)
188 return strcmp(d1->d_name, d2->d_name);
192 scandir(char *dir, struct dirent ***dpp, int (*select)(), int (*sort)())
193 /* directory to read */
194 /* directory entry pointer pointer */
199 struct dirent *d, *tmp;
201 d = (struct dirent *)malloc(sizeof(struct dirent) + pathconf(".", _PC_NAME_MAX) +1);
202 if ( (dirp = opendir(dir)) == NULL)
205 *dpp = (struct dirent **)malloc(nsize * sizeof(struct dirent *));
206 if ( (*dpp) == NULL )
212 while ( (d = readdir_r(dirp, d)) != NULL)
214 if ( select != NULL && !(*select)(d) )
216 tmp = (struct dirent *)malloc(sizeof(struct dirent) + strlen(d->d_name) + 1);
219 tmp->d_ino = d->d_ino;
220 tmp->d_reclen = d->d_reclen;
221 strcpy(tmp->d_name, d->d_name);
224 *dpp = (struct dirent **)realloc((char *)*dpp, nsize * sizeof(struct dirent *));
228 (*dpp)[nents++] = tmp;
231 if (nents > 0 && sort != NULL )
232 qsort(*dpp, nents, sizeof(struct dirent *), sort);
240 #if !defined(solaris) && !defined(ALPHA) && !defined(__linux__)
241 extern int alphasort(const struct dirent *const *, const struct dirent *const *);
243 extern s_char *infodir;
244 static time_t lastmodtime;
246 static struct dirent **dp;
252 if (stat(infodir, &st) == -1)
254 pr("Available topics are:\n");
255 if (lastmodtime < st.st_mtime) {
259 number = scandir(infodir, &dp, fileselect, alphasort);
260 lastmodtime = st.st_mtime;
262 count = 79 / (biggest + 1) - 1;
263 for(i = 0, npl = 0; i < number; i++) {
264 pr("%-*.*s%c", biggest, strlen (dp[i]->d_name),
265 dp[i]->d_name, npl == count ? '\n' : ' ');
280 extern s_char *infodir;
286 s_char filename[1024];
288 long nf,nhf,nl,nlhl,nhl,nll;
292 if (player->argp[1] == 0 || !*player->argp[1]) {
293 pr("Apropos what?\n");
298 if (player->argp[2] ) {
299 lhitlim = atoi(player->argp[2]);
300 if (lhitlim<=0) lhitlim = 100;
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) break;
354 if (nhl>lhitlim) break;
363 pr("Limit of %ld lines exceeded\n",lhitlim);
365 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
366 bp, nhf,nf, nhl,nl );
376 extern s_char *infodir;
381 s_char filename[1024];
383 if (player->argp[1] == 0 || !*player->argp[1])
386 /* Note that we generate an "all" file now, which contains
387 * this list, so we don't do printdir. */
388 else if (!strcmp(player->argp[1], "all"))
393 * don't let sneaky people go outside the info directory
395 bp = player->argp[1];
396 if (NULL != (bp2 = rindex(bp, '/')))
398 if (NULL != (bp2 = rindex(bp, '\\')))
400 if (NULL != (bp2 = rindex(bp, ':')))
406 strncpy(filename, infodir, sizeof(filename)-2);
407 strcat(filename, "//");
408 strncat(filename, bp, sizeof(filename)-1-strlen(filename));
409 fp = fopen(filename, "r");
411 /* may be a "partial" request. */
413 WIN32_FIND_DATA fData;
414 int len = strlen(bp);
415 strncat(filename, "*", sizeof(filename)-1-strlen(filename));
416 hDir = FindFirstFile(filename, &fData);
417 if (hDir == INVALID_HANDLE_VALUE) {
418 pr("Can't open info dir \"%s\"\n", infodir);
422 if ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) &&
423 (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)
469 /* Yes, we could do multi-column work here. */
470 pr("%s\n", fData.cFileName);
472 } while (FindNextFile(hDir, &fData));
482 extern s_char *infodir;
484 WIN32_FIND_DATA fData;
489 s_char filename[1024];
490 long nf,nhf,nl,nlhl,nhl,nll;
494 if (player->argp[1] == 0 || !*player->argp[1]) {
495 pr("Apropos what?\n");
500 if (player->argp[2] ) {
501 lhitlim = atoi(player->argp[2]);
502 if (lhitlim<=0) lhitlim = 100;
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) break;
559 if (nhl>lhitlim) break;
560 } while (FindNextFile(hDir, &fData));
568 pr("Limit of %ld lines exceeded\n",lhitlim);
570 pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
571 bp, nhf,nf, nhl,nl );