src/lib/commands/info.c

Go to the documentation of this file.
00001 /*
00002  *  Empire - A multi-player, client/server Internet based war game.
00003  *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
00004  *                           Ken Stevens, Steve McClure
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  *  ---
00021  *
00022  *  See files README, COPYING and CREDITS in the root of the source
00023  *  tree for related information and legal notices.  It is expected
00024  *  that future projects/authors will amend these files as needed.
00025  *
00026  *  ---
00027  *
00028  *  info.c: display an info page
00029  * 
00030  *  Known contributors to this file:
00031  *     Dave Pare, 1986
00032  *     Mike Wise, 1997 - added apropos and case insensitivity
00033  *     Doug Hay, 1998
00034  *     Steve McClure, 1998-2000
00035  *     Ron Koenderink, 2004
00036  */
00037 
00038 #include <config.h>
00039 
00040 #include <ctype.h>
00041 #include <errno.h>
00042 #include <sys/stat.h>
00043 #include <stdio.h>
00044 #if !defined(_WIN32)
00045 #include <dirent.h>
00046 #else
00047 #include <windows.h>
00048 #endif
00049 #include "commands.h"
00050 #include "optlist.h"
00051 
00052 static char *
00053 lowerit(char *buf, int n, char *orig)
00054 {                               /* converts a string to lower case */
00055     /* lower case output buffer */
00056     /* size of output buffer */
00057     /* input strig */
00058     int i;
00059     for (i = 0; i < n - 1 && orig[i]; i++)
00060         buf[i] = tolower(orig[i]);
00061     buf[i] = 0;
00062     return buf;
00063 }
00064 
00065 #if !defined(_WIN32)
00066 
00067 int
00068 info(void)
00069 {
00070     char buf[255];
00071     FILE *fp;
00072     char *name;
00073     char *tmp_name;
00074     struct stat statb;
00075     struct dirent *dp;
00076     char filename[1024];
00077     char last[256];
00078     DIR *info_dp;
00079     int nmatch = 0;
00080     int width = 0;
00081     char sep;
00082  
00083     name = player->argp[1];
00084     if (name) {
00085         /*
00086          * don't let sneaky people go outside the info directory
00087          */
00088         if (NULL != (tmp_name = strrchr(name, '/')))
00089             name = tmp_name + 1;
00090     }
00091     if (!name || !*name)
00092         name = "TOP";
00093  
00094     snprintf(filename, sizeof(filename), "%s/%s", infodir, name);
00095     fp = fopen(filename, "r");
00096     if (fp == NULL) {
00097         /* may be a "partial" request.  */
00098         info_dp = opendir(infodir);
00099         if (info_dp == 0) {
00100             pr("Can't open info dir\n");
00101             logerror("Can't open info dir \"%s\"\n", infodir);
00102             return RET_SYS;
00103         }
00104 
00105         while ((dp = readdir(info_dp)) != 0) {
00106             if (strncasecmp(name, dp->d_name, strlen(name)) != 0)
00107                 continue;
00108             nmatch++;
00109             if (nmatch == 1) {
00110                 snprintf(last, sizeof(last), "%s", dp->d_name);
00111             } else {
00112                 if (nmatch == 2) {
00113                     pr("`%s' is ambiguous.  The following topics match:\n%s",
00114                         name, last);
00115                     width = strlen(last);
00116                 }
00117                 width += 2 + strlen(dp->d_name);
00118                 sep = ' ';
00119                 if (width > 75) {
00120                     sep = '\n';
00121                     width = strlen(dp->d_name);
00122                 }
00123                 pr(",%c%s", sep, dp->d_name);
00124             }
00125         }
00126         closedir(info_dp);
00127         if (nmatch == 0) {
00128             pr("Sorry, there is no info on %s\n", name);
00129             return RET_FAIL;
00130         } else if (nmatch > 1) {
00131             pr(".\n");
00132             return RET_FAIL;
00133         }
00134         snprintf(filename, sizeof(filename), "%s/%s", infodir,
00135                  last);
00136         fp = fopen(filename, "r");
00137         if (fp == NULL) {
00138             pr("Error reading info file for %s\n", name);
00139             logerror("Cannot open for \"%s\" info file (%s)",
00140                      filename, strerror(errno));
00141             return RET_FAIL;
00142         }
00143     }
00144     if (fstat(fileno(fp), &statb) < 0) {
00145         pr("Error reading info file for %s\n", name);
00146         logerror("Cannot fstat for \"%s\" info file (%s)",
00147                  filename, strerror(errno));
00148         fclose(fp);
00149         return RET_SYS;
00150     }
00151     if ((statb.st_mode & S_IFREG) == 0) {
00152         pr("Error reading info file for %s\n", name);
00153         logerror("The info file \"%s\" is not regular file\n", filename);
00154         fclose(fp);
00155         return RET_SYS;
00156     }
00157     pr("Information on:  %s    Last modification date: %s",
00158        name, ctime(&statb.st_mtime));
00159     while (fgets(buf, sizeof(buf), fp) != 0)
00160         pr("%s", buf);
00161     (void)fclose(fp);
00162     return RET_OK;
00163 }
00164 
00165 int
00166 apro(void)
00167 {
00168     FILE *fp;
00169     char *name, *lbp;
00170     char *fbuf;
00171     char *lbuf;
00172     struct dirent *dp;
00173     char filename[1024];
00174     DIR *info_dp;
00175     long nf, nhf, nl, nlhl, nhl, nll;
00176     int alreadyhit;
00177     int lhitlim;
00178     struct stat statb;
00179 
00180     if (player->argp[1] == 0 || !*player->argp[1]) {
00181         pr("Apropos what?\n");
00182         return RET_FAIL;
00183     }
00184 
00185     lhitlim = 100;
00186     if (player->argp[2]) {
00187         lhitlim = atoi(player->argp[2]);
00188         if (lhitlim <= 0)
00189             lhitlim = 100;
00190     }
00191 
00192     info_dp = opendir(infodir);
00193     if (info_dp == NULL) {
00194         pr("Can't open info dir \n");
00195         logerror("Can't open info dir \"%s\"", infodir);
00196         return RET_SYS;
00197     }
00198 
00199     fbuf = malloc(256);
00200     lbuf = malloc(256);
00201     lbp = malloc(256);
00202 
00203     /*
00204      *  lower case search string into lbp
00205      */
00206     name = player->argp[1];
00207     lowerit(lbp, 256, name);
00208 
00209     /*
00210      *  search
00211      */
00212     nf = nhf = nl = nhl = 0;
00213     while ((dp = readdir(info_dp)) != 0) {
00214         if (dp->d_name[0] == '.')
00215             continue;
00216         snprintf(filename, sizeof(filename), "%s/%s", infodir,
00217                  dp->d_name);
00218         fp = fopen(filename, "r");
00219         alreadyhit = 0;
00220         nll = nlhl = 0;
00221         if (fp != NULL) {
00222             if (fstat(fileno(fp), &statb) < 0) {
00223                 logerror("Cannot stat for \"%s\" info file (%s)",
00224                          filename, strerror(errno));
00225                 fclose(fp);
00226                 continue;
00227             }
00228             if ((statb.st_mode & S_IFREG) == 0) {
00229                 logerror("The info file \"%s\" is not regular file\n",
00230                          filename);
00231                 fclose(fp);
00232                 continue;
00233             }
00234             while (fgets(fbuf, 256, fp)) {
00235                 lowerit(lbuf, 256, fbuf);
00236                 if (strstr(lbuf, lbp)) {
00237                     if (!alreadyhit) {
00238                         pr("*** %s ***\n", dp->d_name);
00239                         alreadyhit = 1;
00240                         nhf++;
00241                     }
00242                     fbuf[74] = '\n';
00243                     fbuf[75] = 0;
00244                     pr("   %s", fbuf);
00245                     nlhl++;
00246                     /*
00247                      * break if too many lines
00248                      */
00249                     if ((nhl + nlhl) > lhitlim)
00250                         break;
00251                 }
00252                 nll++;
00253             }
00254             fclose(fp);
00255         }
00256         nhl += nlhl;
00257         nl += nll;
00258         nf++;
00259         if (nhl > lhitlim)
00260             break;
00261     }
00262     closedir(info_dp);
00263 
00264     free(fbuf);
00265     free(lbuf);
00266     free(lbp);
00267 
00268     if ((nhl) > lhitlim) {
00269         pr("Limit of %d lines exceeded\n", lhitlim);
00270     }
00271     pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
00272        name, nhf, nf, nhl, nl);
00273     return RET_OK;
00274 }
00275 
00276 #else  /* _WIN32 */
00277 
00278 int
00279 info(void)
00280 {
00281     char buf[255];
00282     FILE *fp;
00283     char *name;
00284     char *tmp_name;
00285     char filename[1024];
00286     char last[256];
00287     int nmatch = 0;
00288     int width = 0;
00289     char sep;
00290 
00291     name = player->argp[1];
00292     if (name) {
00293         /*
00294          * don't let sneaky people go outside the info directory
00295          */
00296         if (NULL != (tmp_name = strrchr(name, '/')))
00297             name = tmp_name + 1;
00298         if (NULL != (tmp_name = strrchr(name, '\\')))
00299             name = tmp_name + 1;
00300         if (NULL != (tmp_name = strrchr(name, ':')))
00301             name = tmp_name + 1;
00302     }
00303     if (!name || !*name)
00304         name = "TOP";
00305 
00306     snprintf(filename, sizeof(filename) - 1, "%s\\%s", infodir, name);
00307     fp = fopen(filename, "rb");
00308     if (fp == NULL) {
00309         /* may be a "partial" request.  */
00310         HANDLE hDir;
00311         WIN32_FIND_DATA fData;
00312         strcat(filename, "*");
00313         hDir = FindFirstFile(filename, &fData);
00314         if (hDir == INVALID_HANDLE_VALUE) {
00315             switch (GetLastError()) {
00316             case ERROR_FILE_NOT_FOUND:
00317                 pr("Sorry, there is no info on %s\n", name);
00318                 return RET_FAIL;
00319                 break;
00320             case ERROR_PATH_NOT_FOUND:
00321                 pr("Can't open info dir\n");
00322                 logerror("Can't open info dir \"%s\"", infodir);
00323                 break;
00324             default:
00325                 pr("Error reading info dir\n");
00326                 logerror("Error (%lu) reading info dir(%s)\\file(%s)",
00327                     GetLastError(), infodir, filename);
00328             }
00329             return RET_SYS;
00330         }
00331         do {
00332             if ((fData.dwFileAttributes != (DWORD)-1) &&
00333                 ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) ||
00334                  (fData.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE) ||
00335                  (fData.dwFileAttributes == FILE_ATTRIBUTE_READONLY)) &&
00336                 (strncasecmp(name, fData.cFileName, strlen(name)) == 0)) {
00337                 nmatch++;
00338                 if (nmatch == 1) {
00339                     snprintf(last, sizeof(last), "%s", fData.cFileName);
00340                 } else {
00341                     if (nmatch == 2) {
00342                         pr("`%s' is ambiguous.  The following topics match:\n%s",
00343                             name, last);
00344                         width = strlen(last);
00345                     }
00346                     width += 2 + strlen(fData.cFileName);
00347                     sep = ' ';
00348                     if (width > 75) {
00349                         sep = '\n';
00350                         width = strlen(fData.cFileName);
00351                     }
00352                     pr(",%c%s", sep, fData.cFileName);
00353                 }
00354             }
00355         } while (FindNextFile(hDir, &fData));
00356         FindClose(hDir);
00357         if (nmatch == 0) {
00358             pr("Sorry, there is no info on %s\n", name);
00359             return RET_FAIL;
00360         } else if (nmatch > 1) {
00361             pr(".\n");
00362             return RET_FAIL;
00363         }
00364         snprintf(filename, sizeof(filename), "%s/%s",
00365                   infodir, last);
00366         fp = fopen(filename, "rb");
00367         if (fp == NULL) {
00368             pr("Error reading info file for %s\n", name);
00369             logerror("Cannot open for \"%s\" info file (%s)",
00370                      filename, strerror(errno));
00371             return RET_FAIL;
00372         }
00373     }
00374     else {
00375         DWORD fAttrib = GetFileAttributes(filename);
00376         if ((fAttrib == (DWORD)-1) || /* INVALID_FILE_ATTRIBUTES */
00377             ((fAttrib != FILE_ATTRIBUTE_NORMAL) &&
00378              (fAttrib != FILE_ATTRIBUTE_ARCHIVE) &&
00379              (fAttrib != FILE_ATTRIBUTE_READONLY))) {
00380             pr("Error reading info file for %s\n", name);
00381             logerror("The info file \"%s\" is not regular file\n",
00382                      filename);
00383             fclose(fp);
00384             return RET_SYS;
00385         }
00386     }
00387 
00388     pr("Information on:  %s", name);
00389     while (fgets(buf, sizeof(buf), fp) != 0)
00390         pr("%s", buf);
00391     (void)fclose(fp);
00392     return RET_OK;
00393 }
00394 
00395 int
00396 apro(void)
00397 {
00398     HANDLE hDir;
00399     WIN32_FIND_DATA fData;
00400     FILE *fp;
00401     char *name, *lbp;
00402     char *fbuf;
00403     char *lbuf;
00404     char filename[1024];
00405     long nf, nhf, nl, nlhl, nhl, nll;
00406     int alreadyhit;
00407     int lhitlim;
00408 
00409     if (player->argp[1] == 0 || !*player->argp[1]) {
00410         pr("Apropos what?\n");
00411         return RET_FAIL;
00412     }
00413 
00414     lhitlim = 100;
00415     if (player->argp[2]) {
00416         lhitlim = atoi(player->argp[2]);
00417         if (lhitlim <= 0)
00418             lhitlim = 100;
00419     }
00420 
00421     snprintf(filename, sizeof(filename), "%s\\*",infodir);
00422     hDir = FindFirstFile(filename, &fData);
00423     if (hDir == INVALID_HANDLE_VALUE) {
00424         if (GetLastError() == ERROR_PATH_NOT_FOUND) {
00425             pr("Can't open info dir\n");
00426             logerror("Can't open info dir \"%s\"", infodir);
00427         } else {
00428             pr("Error reading info dir\n");
00429             logerror("Error (%lu) reading info dir(%s)\\file(%s)",
00430                 GetLastError(), infodir, filename);
00431         }
00432         return RET_SYS;
00433     }
00434 
00435     fbuf = malloc(256);
00436     lbuf = malloc(256);
00437     lbp = malloc(256);
00438 
00439     /*
00440      *  lower case search string into lbp
00441      */
00442     name = player->argp[1];
00443     lowerit(lbp, 256, name);
00444 
00445     /*
00446      *  search
00447      */
00448     nf = nhf = nl = nhl = 0;
00449     do {
00450         if ((fData.dwFileAttributes != (DWORD)-1) &&
00451             ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) ||
00452              (fData.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE) ||
00453              (fData.dwFileAttributes == FILE_ATTRIBUTE_READONLY))) {
00454             snprintf(filename, sizeof(filename), "%s\\%s", infodir,
00455                       fData.cFileName);
00456             fp = fopen(filename, "rb");
00457             alreadyhit = 0;
00458             nll = nlhl = 0;
00459             if (fp != NULL) {
00460                 while (fgets(fbuf, 256, fp)) {
00461                     lowerit(lbuf, 256, fbuf);
00462                     if (strstr(lbuf, lbp)) {
00463                         if (!alreadyhit) {
00464                             pr("*** %s ***\n", fData.cFileName);
00465                             alreadyhit = 1;
00466                             nhf++;
00467                         }
00468                         fbuf[74] = '\n';
00469                         fbuf[75] = 0;
00470                         pr("   %s", fbuf);
00471                         nlhl++;
00472                         /*
00473                          * break if too many lines
00474                          */
00475                         if ((nhl + nlhl) > lhitlim)
00476                             break;
00477                     }
00478                     nll++;
00479                 }
00480                 fclose(fp);
00481             }
00482             nhl += nlhl;
00483             nl += nll;
00484             nf++;
00485             if (nhl > lhitlim)
00486                 break;
00487         }
00488     } while (FindNextFile(hDir, &fData));
00489     FindClose(hDir);
00490 
00491     free(fbuf);
00492     free(lbuf);
00493     free(lbp);
00494 
00495     if ((nhl) > lhitlim) {
00496         pr("Limit of %d lines exceeded\n", lhitlim);
00497     }
00498     pr("Found %s in %ld of %ld files and in %ld of %ld lines\n",
00499        name, nhf, nf, nhl, nl);
00500     return RET_OK;
00501 }
00502 
00503 #endif  /* _WIN32 */

Generated on Fri Mar 28 11:01:12 2008 for empserver by  doxygen 1.5.2