# 2.11BSD#431 - /usr/src/games/warp/intrp.c

##### Functions

    dointerp          X
    filexp            X
    getrealname       X
    interp            X
    intrp_init        X
    skipinterp        X

##### Variables

    hostname          X
    uts               X

##### Macros

    HOSTNAME          X

       1: /* $Header: /usr/src/games/warp/RCS/intrp.c,v 1.3.2 97/10/2 22:40:37 games Exp $
       2:  *
       3:  * $Log:	intrp.c,v $
       4:  * Revision 7.0.2  93/12/31  23:40:37  games
       5:  * Removed shortnames.h for new version of 2.11BSD
       6:  *
       7:  * Revision 7.0.1.2a  87/07/03  00:56:37  games
       8:  * Included shortnames.h for 2.10BSD
       9:  *
      10:  * Revision 7.0.1.2  86/12/12  16:59:04  lwall
      11:  * Baseline for net release.
      12:  *
      13:  * Revision 7.0.1.1  86/10/16  10:51:43  lwall
      14:  * Added Damage.  Fixed random bugs.
      15:  *
      16:  * Revision 7.0  86/10/08  15:12:19  lwall
      17:  * Split into separate files.  Added amoebas and pirates.
      18:  *
      19:  */
      20:
      21: #include "EXTERN.h"
      22: #include "warp.h"
      23: #include "sig.h"
      24: #include "util.h"
      25: #include "term.h"
      26: #include "INTERN.h"
      27: #include "intrp.h"
      28: #include <unistd.h>
      29:
      30: /* name of this host */
      31: #ifdef GETHOSTNAME
      32:     char *hostname;
      33: #   undef HOSTNAME
      34: #   define HOSTNAME hostname
      35: #else /* !GETHOSTNAME */
      36: #   ifdef DOUNAME
      37: #	include <sys/utsname.h>
      38:     struct utsname uts;
      39: #	undef HOSTNAME
      40: #	define HOSTNAME uts.nodename
      41: #   else /* !DOUNAME */
      42: #	ifdef PHOSTNAME
      43:         char *hostname;
      44: #	    undef HOSTNAME
      45: #	    define HOSTNAME hostname
      46: #	else /* !PHOSTNAME */
      47: #	    ifdef WHOAMI
      48: #		undef HOSTNAME
      49: #		define HOSTNAME sysname
      50: #	    endif /* WHOAMI */
      51: #	endif /* PHOSTNAME */
      52: #   endif /* DOUNAME */
      53: #endif /* GETHOSTNAME */
      54:
      55: #ifdef TILDENAME
      56: static char *tildename = Nullch;
      57: static char *tildedir = Nullch;
      58: #endif
      59:
      60: char *dointerp();
      61: char *getrealname();
      62: #ifdef CONDSUB
      63: char *skipinterp();
      64: #endif
      65:
      66: static void abort_interp();
      67:
      68: void
      69: intrp_init(tcbuf)
      70: char *tcbuf;
      71: {
      72:
      73:     /* get environmental stuff */
      74:
      75:     /* get home directory */
      76:
      77:     homedir = getenv("HOME");
      78:     if (homedir == Nullch)
      79:     homedir = getenv("LOGDIR");
      80:
      81:     dotdir = getval("DOTDIR",homedir);
      82:
      83:     /* get login name */
      84:
      85:     logname = getenv("USER");
      86:     if (logname == Nullch)
      87:     logname = getenv("LOGNAME");
      88: #ifdef GETLOGIN
      89:     if (logname == Nullch)
      90:     logname = savestr(getlogin());
      91: #endif
      92:
      93:     /* get the real name of the person (%N) */
      94:     /* Must be done after logname is read in because BERKNAMES uses that */
      95:
      96:     strcpy(tcbuf,getrealname(getuid()));
      97:     realname = savestr(tcbuf);
      98:
      99:     /* name of this host (%H) */
     100:
     101: #ifdef GETHOSTNAME
     102:     gethostname(buf,sizeof buf);
     103:     hostname = savestr(buf);
     104: #else
     105: #ifdef DOUNAME
     106:     /* get sysname */
     107:     uname(&uts);
     108: #else
     109: #ifdef PHOSTNAME
     110:     {
     111:     FILE *popen();
     112:     FILE *pipefp = popen(PHOSTNAME,"r");
     113:
     114:     if (pipefp == Nullfp) {
     115:         printf("Can't find hostname\r\n");
     116:         sig_catcher(0);
     117:     }
     118:     Fgets(buf,sizeof buf,pipefp);
     119:     buf[strlen(buf)-1] = '\0';  /* wipe out newline */
     120:     hostname = savestr(buf);
     121:     pclose(pipefp);
     122:     }
     123: #endif
     124: #endif
     125: #endif
     126:     if (index(HOSTNAME,'.'))
     127:     hostname = savestr(HOSTNAME);
     128:     else {
     129:     char hname[128];
     130:
     131:     strcpy(hname,HOSTNAME);
     132:     strcat(hname,MYDOMAIN);
     133:     hostname=savestr(hname);
     134:     }
     135:     warplib = savestr(filexp(WARPLIB));
     136:
     137:     if (scorespec)          /* that getwd below takes ~1/3 sec. */
     138:     return;             /* and we do not need it for -s */
     139:     (void) getwd(tcbuf);        /* find working directory name */
     140:     origdir = savestr(tcbuf);       /* and remember it */
     141: }
     142:
     143: /* expand filename via %, ~, and $ interpretation */
     144: /* returns pointer to static area */
     145: /* Note that there is a 1-deep cache of ~name interpretation */
     146:
     147: char *
     148: filexp(s)
     149: Reg1 char *s;
     150: {
     151:     static char filename[CBUFLEN];
     152:     char scrbuf[CBUFLEN];
     153:     Reg2 char *d;
     154:
     155: #ifdef DEBUGGING
     156:     if (debug & DEB_FILEXP)
     157:     printf("< %s\r\n",s);
     158: #endif
     159:     interp(filename, (sizeof filename), s);         /* interpret any % escapes */
     160: #ifdef DEBUGGING
     161:     if (debug & DEB_FILEXP)
     162:     printf("%% %s\r\n",filename);
     163: #endif
     164:     s = filename;
     165:     if (*s == '~') {    /* does destination start with ~? */
     166:     if (!*(++s) || *s == '/') {
     167:         Sprintf(scrbuf,"%s%s",homedir,s);
     168:                 /* swap $HOME for it */
     169: #ifdef DEBUGGING
     170:     if (debug & DEB_FILEXP)
     171:     printf("~ %s\r\n",scrbuf);
     172: #endif
     173:         strcpy(filename,scrbuf);
     174:     }
     175:     else {
     176: #ifdef TILDENAME
     177:         for (d=scrbuf; isalnum(*s); s++,d++)
     178:         *d = *s;
     179:         *d = '\0';
     180:         if (tildedir && strEQ(tildename,scrbuf)) {
     181:         strcpy(scrbuf,tildedir);
     182:         strcat(scrbuf, s);
     183:         strcpy(filename, scrbuf);
     184: #ifdef DEBUGGING
     185:         if (debug & DEB_FILEXP)
     186:             printf("r %s %s\r\n",tildename,tildedir);
     187: #endif
     188:         }
     189:         else {
     190:         if (tildename) {
     191:             free(tildename);
     192:             free(tildedir);
     193:         }
     194:         tildedir = Nullch;
     195:         tildename = savestr(scrbuf);
     196: #ifdef GETPWENT     /* getpwnam() is not the paragon of efficiency */
     197:         {
     198:             struct passwd *getpwnam();
     199:             struct passwd *pwd = getpwnam(tildename);
     200:
     201:             Sprintf(scrbuf,"%s%s",pwd->pw_dir,s);
     202:             tildedir = savestr(pwd->pw_dir);
     203:             strcpy(filename,scrbuf);
     204: #ifdef GETPWENT
     205:             endpwent();
     206: #endif
     207:         }
     208: #else           /* this will run faster, and is less D space */
     209:         {   /* just be sure LOGDIRFIELD is correct */
     210:             FILE *pfp = fopen("/etc/passwd","r");
     211:             char tmpbuf[512];
     212:             int i;
     213:
     214:             if (pfp == Nullfp) {
     215:             printf(cantopen,"passwd");
     216:             sig_catcher(0);
     217:             }
     218:             while (fgets(tmpbuf,512,pfp) != Nullch) {
     219:             d = cpytill(scrbuf,tmpbuf,':');
     220: #ifdef DEBUGGING
     221:             if (debug & DEB_FILEXP)
     222:                 printf("p %s\r\n",tmpbuf);
     223: #endif
     224:             if (strEQ(scrbuf,tildename)) {
     225:                 for (i=LOGDIRFIELD-2; i; i--) {
     226:                 if (d)
     227:                     d = index(d+1,':');
     228:                 }
     229:                 if (d) {
     230:                 Cpytill(scrbuf,d+1,':');
     231:                 tildedir = savestr(scrbuf);
     232:                 strcat(scrbuf,s);
     233:                 strcpy(filename,scrbuf);
     234:                 }
     235:                 break;
     236:             }
     237:             }
     238:             Fclose(pfp);
     239:         }
     240: #endif
     241:         }
     242: #else /* !TILDENAME */
     243: #ifdef VERBOSE
     244:         IF(verbose)
     245:         fputs("~loginname not implemented.\r\n",stdout);
     246:         ELSE
     247: #endif
     248: #ifdef TERSE
     249:         fputs("~login not impl.\r\n",stdout);
     250: #endif
     251: #endif
     252:     }
     253:     }
     254:     else if (*s == '$') {   /* starts with some env variable? */
     255:     d = scrbuf;
     256:     *d++ = '%';
     257:     if (s[1] == '{')
     258:         strcpy(d,s+2);
     259:     else {
     260:         *d++ = '{';
     261:         for (s++; isalnum(*s); s++) *d++ = *s;
     262:                 /* skip over token */
     263:         *d++ = '}';
     264:         strcpy(d,s);
     265:     }
     266: #ifdef DEBUGGING
     267:     if (debug & DEB_FILEXP)
     268:         printf("$ %s\r\n",scrbuf);
     269: #endif
     270:     interp(filename, (sizeof filename), scrbuf);
     271:                     /* this might do some extra '%'s but */
     272:                     /* that is how the Mercedes Benz */
     273:     }
     274: #ifdef DEBUGGING
     275:     if (debug & DEB_FILEXP)
     276:     printf("> %s\r\n",filename);
     277: #endif
     278:     return filename;
     279: }
     280:
     281: #ifdef CONDSUB
     282: /* skip interpolations */
     283:
     284: char *
     285: skipinterp(pattern,stoppers)
     286: Reg1 char *pattern;
     287: char *stoppers;
     288: {
     289:
     290:     while (*pattern && (!stoppers || !index(stoppers,*pattern))) {
     291: #ifdef DEBUGGING
     292:     if (debug & 8)
     293:         printf("skipinterp till %s at %s\r\n",stoppers?stoppers:"",pattern);
     294: #endif
     295:     if (*pattern == '%' && pattern[1]) {
     296:         switch (*++pattern) {
     297:         case '{':
     298:         for (pattern++; *pattern && *pattern != '}'; pattern++)
     299:             if (*pattern == '\\')
     300:             pattern++;
     301:         break;
     302: #ifdef CONDSUB
     303:         case '(': {
     304:         pattern = skipinterp(pattern+1,"!=");
     305:         if (!*pattern)
     306:             goto getout;
     307:         for (pattern++; *pattern && *pattern != '?'; pattern++)
     308:             if (*pattern == '\\')
     309:             pattern++;
     310:         if (!*pattern)
     311:             goto getout;
     312:         pattern = skipinterp(pattern+1,":)");
     313:         if (*pattern == ':')
     314:             pattern = skipinterp(pattern+1,")");
     315:         break;
     316:         }
     317: #endif
     318: #ifdef BACKTICK
     319:         case '`': {
     320:         pattern = skipinterp(pattern+1,"`");
     321:         break;
     322:         }
     323: #endif
     324: #ifdef PROMPTTTY
     325:         case '"':
     326:         pattern = skipinterp(pattern+1,"\"");
     327:         break;
     328: #endif
     329:         default:
     330:         break;
     331:         }
     332:         pattern++;
     333:     }
     334:     else {
     335:         if (*pattern == '^' && pattern[1])
     336:         pattern += 2;
     337:         else if (*pattern == '\\' && pattern[1])
     338:         pattern += 2;
     339:         else
     340:         pattern++;
     341:     }
     342:     }
     343: getout:
     344:     return pattern;         /* where we left off */
     345: }
     346: #endif
     347:
     348: /* interpret interpolations */
     349:
     350: char *
     351: dointerp(dest,destsize,pattern,stoppers)
     352: Reg1 char *dest;
     353: Reg2 int destsize;
     354: Reg3 char *pattern;
     355: char *stoppers;
     356: {
     357:     Reg4 char *s;
     358:     Reg5 int i;
     359:     char scrbuf[512];
     360:     bool upper = FALSE;
     361:     bool lastcomp = FALSE;
     362:     int metabit = 0;
     363:
     364:     while (*pattern && (!stoppers || !index(stoppers,*pattern))) {
     365: #ifdef DEBUGGING
     366:     if (debug & 8)
     367:         printf("dointerp till %s at %s\r\n",stoppers?stoppers:"",pattern);
     368: #endif
     369:     if (*pattern == '%' && pattern[1]) {
     370:         upper = FALSE;
     371:         lastcomp = FALSE;
     372:         for (s=Nullch; !s; ) {
     373:         switch (*++pattern) {
     374:         case '^':
     375:             upper = TRUE;
     376:             break;
     377:         case '_':
     378:             lastcomp = TRUE;
     379:             break;
     380:         case '{':
     381:             pattern = cpytill(scrbuf,pattern+1,'}');
     382:             if (s = index(scrbuf,'-'))
     383:             *s++ = '\0';
     384:             else
     385:             s = nullstr;
     386:             s = getval(scrbuf,s);
     387:             break;
     388: #ifdef CONDSUB
     389:         case '(': {
     390:             char rch;
     391:             bool matched;
     392:
     393:             pattern = dointerp(dest,destsize,pattern+1,"!=");
     394:             rch = *pattern;
     395:             if (rch == '!')
     396:             pattern++;
     397:             if (*pattern != '=')
     398:             goto getout;
     399:             pattern = cpytill(scrbuf,pattern+1,'?');
     400:             if (!*pattern)
     401:             goto getout;
     402:             if (*scrbuf == '^' && scrbuf[strlen(scrbuf)-1] == '$') {
     403:             scrbuf[strlen(scrbuf)-1] = '\0';
     404:             matched = strEQ(scrbuf+1,dest);
     405:             }
     406:             else
     407:             matched = instr(dest,scrbuf) != Nullch;
     408:             if (matched==(rch == '=')) {
     409:             pattern = dointerp(dest,destsize,pattern+1,":)");
     410:             if (*pattern == ':')
     411:                 pattern = skipinterp(pattern+1,")");
     412:             }
     413:             else {
     414:             pattern = skipinterp(pattern+1,":)");
     415:             if (*pattern == ':')
     416:                 pattern++;
     417:             pattern = dointerp(dest,destsize,pattern,")");
     418:             }
     419:             s = dest;
     420:             break;
     421:         }
     422: #endif
     423: #ifdef BACKTICK
     424:         case '`': {
     425:             FILE *pipefp, *popen();
     426:
     427:             pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"`");
     428:             pipefp = popen(scrbuf,"r");
     429:             if (pipefp != Nullfp) {
     430:             int len;
     431:
     432:             len = fread(scrbuf,sizeof(char),(sizeof scrbuf)-1,
     433:                 pipefp);
     434:             scrbuf[len] = '\0';
     435:             pclose(pipefp);
     436:             }
     437:             else {
     438:             printf("\r\nCan't run %s\r\n",scrbuf);
     439:             *scrbuf = '\0';
     440:             }
     441:             for (s=scrbuf; *s; s++) {
     442:             if (*s == '\n') {
     443:                 if (s[1])
     444:                 *s = ' ';
     445:                 else
     446:                 *s = '\0';
     447:             }
     448:             }
     449:             s = scrbuf;
     450:             break;
     451:         }
     452: #endif
     453: #ifdef PROMPTTTY
     454:         case '"':
     455:             pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"\"");
     456:             fputs(scrbuf,stdout);
     457:             resetty();
     458:             gets(scrbuf);
     459:             crmode();
     460:             raw();
     461:             noecho();
     462:             nonl();
     463:             s = scrbuf;
     464:             break;
     465: #endif
     466:         case '~':
     467:             s = homedir;
     468:             break;
     469:         case '.':
     470:             s = dotdir;
     471:             break;
     472:         case '$':
     473:             s = scrbuf;
     474:             Sprintf(s,"%d",getpid());
     475:             break;
     476:         case 'H':           /* host name */
     477:             s = hostname;
     478:             break;
     479:         case 'L':           /* login id */
     480:             s = logname;
     481:             break;
     482:         case 'N':           /* full name */
     483:             s = getval("NAME",realname);
     484:             break;
     485:         case 'O':
     486:             s = origdir;
     487:             break;
     488:         case 'p':
     489:             s = cwd;
     490:             break;
     491:         case 'X':           /* warp library */
     492:             s = warplib;
     493:             break;
     494:         default:
     495:             if (--destsize <= 0)
     496:             abort_interp();
     497:             *dest++ = *pattern | metabit;
     498:             s = nullstr;
     499:             break;
     500:         }
     501:         }
     502:         if (!s)
     503:         s = nullstr;
     504:         pattern++;
     505:         if (upper || lastcomp) {
     506:         char *t;
     507:
     508:         if (s != scrbuf) {
     509:             Safecpy(scrbuf,s,(sizeof scrbuf));
     510:             s = scrbuf;
     511:         }
     512:         if (upper || !(t=rindex(s,'/')))
     513:             t = s;
     514:         while (*t && !isalpha(*t))
     515:             t++;
     516:         if (islower(*t))
     517:             *t = toupper(*t);
     518:         }
     519:         i = metabit;        /* maybe get into register */
     520:         if (s == dest) {
     521:         while (*dest) {
     522:             if (--destsize <= 0)
     523:             abort_interp();
     524:             *dest++ |= i;
     525:         }
     526:         }
     527:         else {
     528:         while (*s) {
     529:             if (--destsize <= 0)
     530:             abort_interp();
     531:             *dest++ = *s++ | i;
     532:         }
     533:         }
     534:     }
     535:     else {
     536:         if (--destsize <= 0)
     537:         abort_interp();
     538:         if (*pattern == '^' && pattern[1]) {
     539:         ++pattern;          /* skip uparrow */
     540:         i = *pattern;       /* get char into a register */
     541:         if (i == '?')
     542:             *dest++ = '\177' | metabit;
     543:         else if (i == '(') {
     544:             metabit = 0200;
     545:             destsize++;
     546:         }
     547:         else if (i == ')') {
     548:             metabit = 0;
     549:             destsize++;
     550:         }
     551:         else
     552:             *dest++ = i & 037 | metabit;
     553:         pattern++;
     554:         }
     555:         else if (*pattern == '\\' && pattern[1]) {
     556:         ++pattern;          /* skip backslash */
     557:         i = *pattern;       /* get char into a register */
     558:
     559:         /* this used to be a switch but the if may save space */
     560:
     561:         if (i >= '0' && i <= '7') {
     562:             i = 1;
     563:             while (i < 01000 && *pattern >= '0' && *pattern <= '7') {
     564:             i <<= 3;
     565:             i += *pattern++ - '0';
     566:             }
     567:             *dest++ = i & 0377 | metabit;
     568:             --pattern;
     569:         }
     570:         else if (i == 'b')
     571:             *dest++ = '\b' | metabit;
     572:         else if (i == 'f')
     573:             *dest++ = '\f' | metabit;
     574:         else if (i == 'n')
     575:             *dest++ = '\n' | metabit;
     576:         else if (i == 'r')
     577:             *dest++ = '\r' | metabit;
     578:         else if (i == 't')
     579:             *dest++ = '\t' | metabit;
     580:         else
     581:             *dest++ = i | metabit;
     582:         pattern++;
     583:         }
     584:         else
     585:         *dest++ = *pattern++ | metabit;
     586:     }
     587:     }
     588:     *dest = '\0';
     589: getout:
     590:     return pattern;         /* where we left off */
     591: }
     592:
     593: void
     594: interp(dest,destsize,pattern)
     595: char *dest;
     596: int destsize;
     597: char *pattern;
     598: {
     599:     (void) dointerp(dest,destsize,pattern,Nullch);
     600: #ifdef DEBUGGING
     601:     if (debug & DEB_FILEXP)
     602:     fputs(dest,stdout);
     603: #endif
     604: }
     605:
     606: /* get the person's real name from /etc/passwd */
     607: /* (string is overwritten, so it must be copied) */
     608:
     609: char *
     610: getrealname(uid)
     611: int uid;
     612: {
     613:     char *s, *c;
     614:
     615: #ifdef PASSNAMES
     616:     struct passwd *pwd = getpwuid(uid);
     617:
     618:     s = pwd->pw_gecos;
     619: #ifdef BERKNAMES
     620: #ifdef BERKJUNK
     621:     while (*s && !isalnum(*s) && *s != '&') s++;
     622: #endif
     623:     if ((c = index(s, ',')) != Nullch)
     624:     *c = '\0';
     625:     if ((c = index(s, ';')) != Nullch)
     626:     *c = '\0';
     627:     s = cpytill(buf,s,'&');
     628:     if (*s == '&') {            /* whoever thought this one up was */
     629:     c = buf + strlen(buf);      /* in the middle of the night */
     630:     strcat(c,logname);      /* before the morning after */
     631:     strcat(c,s+1);
     632:     if (islower(*c))
     633:         *c = toupper(*c);       /* gack and double gack */
     634:     }
     635: #else
     636:     if ((c = index(s, '(')) != Nullch)
     637:     *c = '\0';
     638:     if ((c = index(s, '-')) != Nullch)
     639:     s = c;
     640:     strcpy(buf,tmpbuf);
     641: #endif
     642:     endpwent();
     643:     return buf;             /* return something static */
     644: #else
     645:     if ((tmpfp=fopen(filexp(FULLNAMEFILE),"r")) != Nullfp) {
     646:     Fgets(buf,sizeof buf,tmpfp);
     647:     Fclose(tmpfp);
     648:     }
     649:     else {
     650:     resetty();
     651:     printf("What is your name? ");
     652:     Fgets(buf,(sizeof buf),stdin);
     653:     crmode();
     654:     raw();
     655:     noecho();
     656:     nonl();
     657:     if (fork())
     658:         wait(0);
     659:     else {
     660:         setuid(getuid());
     661:         if ((tmpfp = fopen(filexp(FULLNAMEFILE),"w")) == NULL)
     662:         exit(1);
     663:         fprintf(tmpfp, "%s\n", buf);
     664:         Fclose(tmpfp);
     665:         exit(0);
     666:     }
     667:     }
     668:     buf[strlen(buf)-1] = '\0';
     669:     return buf;
     670: #endif
     671: }
     672:
     673: static void
     674: abort_interp()
     675: {
     676:     fputs("\r\n% interp buffer overflow!\r\n",stdout);
     677:     sig_catcher(0);
     678: }

#### Defined functions

abort_interp defined in line 673; used 5 times

- in line 66, 496, 523, 530, 537

dointerp defined in line 350; used 9 times

- in line 60, 393, 409, 417, 427, 455, 599
- in /usr/src/games/warp/intrp.h line 21
- in /usr/src/games/warp/term.c line 340

filexp defined in line 147; used 5 times

- in line 135, 645, 661
- in /usr/src/games/warp/intrp.h line 20
- in /usr/src/games/warp/term.c line 312

getrealname defined in line 609; used 3 times

- in line 61, 96
- in /usr/src/games/warp/intrp.h line 23

interp defined in line 593; used 6 times

- in line 159, 270
- in /usr/src/games/warp/intrp.h line 22
- in /usr/src/games/warp/score.c line 52-57(2)
- in /usr/src/games/warp/term.c line 812

intrp_init defined in line 68; used 2 times

- in /usr/src/games/warp/intrp.h line 19
- in /usr/src/games/warp/warp.c line 302

skipinterp defined in line 284; used 8 times

- in line 63, 304, 312-314(2), 320, 326, 411-414(2)

#### Defined variables

hostname defined in line 43; used 7 times

- in line 34, 45, 103, 120, 127, 133, 477

tildedir defined in line 57; used 7 times

- in line 180-186(3), 192-194(2), 202, 231

tildename defined in line 56; used 7 times

- in line 180, 186-199(5), 224

uts defined in line 38; used 2 times

- in line 40, 107

#### Defined macros

HOSTNAME defined in line 49; used 7 times

- in line 33, 39-48(3), 126-131(3)

Last modified: 1997-10-03 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1838 |