# 2.11BSD#431 - /usr/src/ucb/rlogin.c

##### Functions

    catchild          X
    doit              X
    done              X
    echo              X
    lostpeer          X
    main              X
    mode              X
    oob               X
    prf               X
    reader            X
    sendwindow        X
    sigwinch          X
    stop              X
    writer            X
    writeroob         X

##### Variables

    child             X
    cmdchar           X
    copyright         X
    deferase          X
    defflags          X
    defkill           X
    deflflags         X
    defltc            X
    deftc             X
    dosigwinch        X
    eight             X
    litout            X
    name              X
    noltc             X
    notc              X
    ppid              X
    rcvbuf            X
    rcvcnt            X
    rcvstate          X
    rcvtop            X
    rem               X
    speeds            X
    term              X
    winsize           X

##### Macros

    CRLF              X
    READING           X
    TIOCPKT_WINDOW    X
    WRITING           X
    sigmask           X

##### struct's

    winsize           X

       1: /*
       2:  * Copyright (c) 1983 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  */
       6:
       7: #if !defined(lint) && defined(DOSCCS)
       8: char copyright[] =
       9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
      10:  All rights reserved.\n";
      11:
      12: static char sccsid[] = "@(#)rlogin.c	5.10.1 (2.11BSD) 1997/3/28";
      13: #endif
      14:
      15: /*
      16:  * rlogin - remote login
      17:  */
      18: #include <sys/param.h>
      19: #include <sys/errno.h>
      20: #include <sys/file.h>
      21: #include <sys/socket.h>
      22: #include <sys/wait.h>
      23:
      24: #include <netinet/in.h>
      25:
      26: #include <stdio.h>
      27: #include <sgtty.h>
      28: #include <errno.h>
      29: #include <pwd.h>
      30: #include <signal.h>
      31: #include <setjmp.h>
      32: #include <netdb.h>
      33:
      34: # ifndef TIOCPKT_WINDOW
      35: # define TIOCPKT_WINDOW 0x80
      36: # endif TIOCPKT_WINDOW
      37:
      38: char    *index(), *rindex(), *malloc(), *getenv();
      39: struct  passwd *getpwuid();
      40: char    *name;
      41: int rem;
      42: char    cmdchar = '~';
      43: int eight;
      44: int litout;
      45: char    *speeds[] =
      46:     { "0", "50", "75", "110", "134", "150", "200", "300",
      47:       "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
      48: char    term[256] = "network";
      49: extern  int errno;
      50: int lostpeer();
      51: int dosigwinch = 0;
      52: #ifndef sigmask
      53: #define sigmask(m)  (1L << ((m)-1))
      54: #endif
      55: #ifdef sun
      56: struct  ttysize winsize;
      57: struct winsize {
      58:     unsigned short ws_row, ws_col;
      59:     unsigned short ws_xpixel, ws_ypixel;
      60: };
      61: #else sun
      62: struct  winsize winsize;
      63: #endif sun
      64: int sigwinch(), oob();
      65:
      66: main(argc, argv)
      67:     int argc;
      68:     char **argv;
      69: {
      70:     char *host, *cp;
      71:     struct sgttyb ttyb;
      72:     struct passwd *pwd;
      73:     struct servent *sp;
      74:     int uid, options = 0;
      75:     long oldmask;
      76:     int on = 1;
      77:
      78:     host = rindex(argv[0], '/');
      79:     if (host)
      80:         host++;
      81:     else
      82:         host = argv[0];
      83:     argv++, --argc;
      84:     if (!strcmp(host, "rlogin"))
      85:         host = *argv++, --argc;
      86: another:
      87:     if (argc > 0 && !strcmp(*argv, "-d")) {
      88:         argv++, argc--;
      89:         options |= SO_DEBUG;
      90:         goto another;
      91:     }
      92:     if (argc > 0 && !strcmp(*argv, "-l")) {
      93:         argv++, argc--;
      94:         if (argc == 0)
      95:             goto usage;
      96:         name = *argv++; argc--;
      97:         goto another;
      98:     }
      99:     if (argc > 0 && !strncmp(*argv, "-e", 2)) {
     100:         cmdchar = argv[0][2];
     101:         argv++, argc--;
     102:         goto another;
     103:     }
     104:     if (argc > 0 && !strcmp(*argv, "-8")) {
     105:         eight = 1;
     106:         argv++, argc--;
     107:         goto another;
     108:     }
     109:     if (argc > 0 && !strcmp(*argv, "-L")) {
     110:         litout = 1;
     111:         argv++, argc--;
     112:         goto another;
     113:     }
     114:     if (host == 0)
     115:         goto usage;
     116:     if (argc > 0)
     117:         goto usage;
     118:     pwd = getpwuid(getuid());
     119:     if (pwd == 0) {
     120:         fprintf(stderr, "Who are you?\n");
     121:         exit(1);
     122:     }
     123:     sp = getservbyname("login", "tcp");
     124:     if (sp == 0) {
     125:         fprintf(stderr, "rlogin: login/tcp: unknown service\n");
     126:         exit(2);
     127:     }
     128:     cp = getenv("TERM");
     129:     if (cp)
     130:         strcpy(term, cp);
     131:     if (ioctl(0, TIOCGETP, &ttyb) == 0) {
     132:         strcat(term, "/");
     133:         strcat(term, speeds[ttyb.sg_ospeed]);
     134:     }
     135: #ifdef sun
     136:     (void) ioctl(0, TIOCGSIZE, &winsize);
     137: #else sun
     138:     (void) ioctl(0, TIOCGWINSZ, &winsize);
     139: #endif sun
     140:     signal(SIGPIPE, lostpeer);
     141:     signal(SIGURG, oob);
     142:     oldmask = sigblock(sigmask(SIGURG));
     143:         rem = rcmd(&host, sp->s_port, pwd->pw_name,
     144:         name ? name : pwd->pw_name, term, 0);
     145:         if (rem < 0)
     146:                 exit(1);
     147:     if (options & SO_DEBUG &&
     148:         setsockopt(rem, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0)
     149:         perror("rlogin: setsockopt (SO_DEBUG)");
     150:     uid = getuid();
     151:     if (setuid(uid) < 0) {
     152:         perror("rlogin: setuid");
     153:         exit(1);
     154:     }
     155:     doit(oldmask);
     156:     /*NOTREACHED*/
     157: usage:
     158:     fprintf(stderr,
     159:         "usage: rlogin host [ -ex ] [ -l username ] [ -8 ] [ -L ]\n");
     160:     exit(1);
     161: }
     162:
     163: #define CRLF "\r\n"
     164:
     165: int child;
     166: int catchild();
     167: int writeroob();
     168:
     169: int defflags;
     170: int deflflags;
     171: char    deferase, defkill;
     172: struct  tchars deftc;
     173: struct  ltchars defltc;
     174: struct  tchars notc =   { -1, -1, -1, -1, -1, -1 };
     175: struct  ltchars noltc = { -1, -1, -1, -1, -1, -1 };
     176:
     177: doit(oldmask)
     178:     long oldmask;
     179: {
     180:     int exit();
     181:     struct sgttyb sb;
     182:
     183:     ioctl(0, TIOCGETP, (char *)&sb);
     184:     defflags = sb.sg_flags & (ECHO | CRMOD | XTABS);
     185:     deferase = sb.sg_erase;
     186:     defkill = sb.sg_kill;
     187:     ioctl(0, TIOCLGET, (char *)&deflflags);
     188:     ioctl(0, TIOCGETC, (char *)&deftc);
     189:     notc.t_startc = deftc.t_startc;
     190:     notc.t_stopc = deftc.t_stopc;
     191:     ioctl(0, TIOCGLTC, (char *)&defltc);
     192:     signal(SIGINT, SIG_IGN);
     193:     signal(SIGHUP, exit);
     194:     signal(SIGQUIT, exit);
     195:     child = fork();
     196:     if (child == -1) {
     197:         perror("rlogin: fork");
     198:         done(1);
     199:     }
     200:     if (child == 0) {
     201:         mode(1);
     202:         sigsetmask(oldmask);
     203:         if (reader() == 0) {
     204:             prf("Connection closed.");
     205:             exit(0);
     206:         }
     207:         sleep(1);
     208:         prf("\007Connection closed.");
     209:         exit(3);
     210:     }
     211:     signal(SIGURG, writeroob);
     212:     sigsetmask(oldmask);
     213:     signal(SIGCHLD, catchild);
     214:     writer();
     215:     prf("Closed connection.");
     216:     done(0);
     217: }
     218:
     219: done(status)
     220:     int status;
     221: {
     222:
     223:     mode(0);
     224:     if (child > 0 && kill(child, SIGKILL) >= 0)
     225:         wait((int *)0);
     226:     exit(status);
     227: }
     228:
     229: /*
     230:  * This is called when the reader process gets the out-of-band (urgent)
     231:  * request to turn on the window-changing protocol.
     232:  */
     233: writeroob()
     234: {
     235:
     236:     if (dosigwinch == 0) {
     237:         sendwindow();
     238:         signal(SIGWINCH, sigwinch);
     239:     }
     240:     dosigwinch = 1;
     241: }
     242:
     243: catchild()
     244: {
     245:     union wait status;
     246:     int pid;
     247:
     248: again:
     249:     pid = wait3(&status, WNOHANG|WUNTRACED, 0);
     250:     if (pid == 0)
     251:         return;
     252:     /*
     253: 	 * if the child (reader) dies, just quit
     254: 	 */
     255:     if (pid < 0 || pid == child && !WIFSTOPPED(status))
     256:         done(status.w_termsig | status.w_retcode);
     257:     goto again;
     258: }
     259:
     260: /*
     261:  * writer: write to remote: 0 -> line.
     262:  * ~.	terminate
     263:  * ~^Z	suspend rlogin process.
     264:  * ~^Y  suspend rlogin process, but leave reader alone.
     265:  */
     266: writer()
     267: {
     268:     char c;
     269:     register n;
     270:     register bol = 1;               /* beginning of line */
     271:     register local = 0;
     272:
     273:     for (;;) {
     274:         n = read(0, &c, 1);
     275:         if (n <= 0) {
     276:             if (n < 0 && errno == EINTR)
     277:                 continue;
     278:             break;
     279:         }
     280:         /*
     281: 		 * If we're at the beginning of the line
     282: 		 * and recognize a command character, then
     283: 		 * we echo locally.  Otherwise, characters
     284: 		 * are echo'd remotely.  If the command
     285: 		 * character is doubled, this acts as a
     286: 		 * force and local echo is suppressed.
     287: 		 */
     288:         if (bol) {
     289:             bol = 0;
     290:             if (c == cmdchar) {
     291:                 bol = 0;
     292:                 local = 1;
     293:                 continue;
     294:             }
     295:         } else if (local) {
     296:             local = 0;
     297:             if (c == '.' || c == deftc.t_eofc) {
     298:                 echo(c);
     299:                 break;
     300:             }
     301:             if (c == defltc.t_suspc || c == defltc.t_dsuspc) {
     302:                 bol = 1;
     303:                 echo(c);
     304:                 stop(c);
     305:                 continue;
     306:             }
     307:             if (c != cmdchar)
     308:                 write(rem, &cmdchar, 1);
     309:         }
     310:         if (write(rem, &c, 1) == 0) {
     311:             prf("line gone");
     312:             break;
     313:         }
     314:         bol = c == defkill || c == deftc.t_eofc ||
     315:             c == deftc.t_intrc || c == defltc.t_suspc ||
     316:             c == '\r' || c == '\n';
     317:     }
     318: }
     319:
     320: echo(c)
     321: register char c;
     322: {
     323:     char buf[8];
     324:     register char *p = buf;
     325:
     326:     c &= 0177;
     327:     *p++ = cmdchar;
     328:     if (c < ' ') {
     329:         *p++ = '^';
     330:         *p++ = c + '@';
     331:     } else if (c == 0177) {
     332:         *p++ = '^';
     333:         *p++ = '?';
     334:     } else
     335:         *p++ = c;
     336:     *p++ = '\r';
     337:     *p++ = '\n';
     338:     write(1, buf, p - buf);
     339: }
     340:
     341: stop(cmdc)
     342:     char cmdc;
     343: {
     344:     mode(0);
     345:     signal(SIGCHLD, SIG_IGN);
     346:     kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
     347:     signal(SIGCHLD, catchild);
     348:     mode(1);
     349:     sigwinch();         /* check for size changes */
     350: }
     351:
     352: #ifdef sun
     353: sigwinch()
     354: {
     355:     struct ttysize ws;
     356:
     357:     if (dosigwinch && ioctl(0, TIOCGSIZE, &ws) == 0 &&
     358:         bcmp(&ws, &winsize, sizeof (ws))) {
     359:         winsize = ws;
     360:         sendwindow();
     361:     }
     362: }
     363:
     364: #else sun
     365: sigwinch()
     366: {
     367:     struct winsize ws;
     368:
     369:     if (dosigwinch && ioctl(0, TIOCGWINSZ, &ws) == 0 &&
     370:         bcmp(&ws, &winsize, sizeof (ws))) {
     371:         winsize = ws;
     372:         sendwindow();
     373:     }
     374: }
     375: #endif
     376:
     377: /*
     378:  * Send the window size to the server via the magic escape
     379:  */
     380: sendwindow()
     381: {
     382:     char obuf[4 + sizeof (struct winsize)];
     383:     struct winsize *wp = (struct winsize *)(obuf+4);
     384:
     385:     obuf[0] = 0377;
     386:     obuf[1] = 0377;
     387:     obuf[2] = 's';
     388:     obuf[3] = 's';
     389: #ifdef sun
     390:     wp->ws_row = htons(winsize.ts_lines);
     391:     wp->ws_col = htons(winsize.ts_cols);
     392:     wp->ws_xpixel = 0;
     393:     wp->ws_ypixel = 0;
     394: #else sun
     395:     wp->ws_row = htons(winsize.ws_row);
     396:     wp->ws_col = htons(winsize.ws_col);
     397:     wp->ws_xpixel = htons(winsize.ws_xpixel);
     398:     wp->ws_ypixel = htons(winsize.ws_ypixel);
     399: #endif sun
     400:     (void) write(rem, obuf, sizeof(obuf));
     401: }
     402:
     403: /*
     404:  * reader: read from remote: line -> 1
     405:  */
     406: #define READING 1
     407: #define WRITING 2
     408:
     409: char    rcvbuf[8 * 1024];
     410: int rcvcnt;
     411: int rcvstate;
     412: int ppid;
     413: jmp_buf rcvtop;
     414:
     415: oob()
     416: {
     417:     int out = FWRITE, atmark, n;
     418:     int rcvd = 0;
     419:     char waste[BUFSIZ], mark;
     420:     struct sgttyb sb;
     421:
     422:     while (recv(rem, &mark, 1, MSG_OOB) < 0)
     423:         switch (errno) {
     424:
     425:         case EWOULDBLOCK:
     426:             /*
     427: 			 * Urgent data not here yet.
     428: 			 * It may not be possible to send it yet
     429: 			 * if we are blocked for output
     430: 			 * and our input buffer is full.
     431: 			 */
     432:             if (rcvcnt < sizeof(rcvbuf)) {
     433:                 n = read(rem, rcvbuf + rcvcnt,
     434:                     sizeof(rcvbuf) - rcvcnt);
     435:                 if (n <= 0)
     436:                     return;
     437:                 rcvd += n;
     438:             } else {
     439:                 n = read(rem, waste, sizeof(waste));
     440:                 if (n <= 0)
     441:                     return;
     442:             }
     443:             continue;
     444:
     445:         default:
     446:             return;
     447:     }
     448:     if (mark & TIOCPKT_WINDOW) {
     449:         /*
     450: 		 * Let server know about window size changes
     451: 		 */
     452:         kill(ppid, SIGURG);
     453:     }
     454:     if (!eight && (mark & TIOCPKT_NOSTOP)) {
     455:         ioctl(0, TIOCGETP, (char *)&sb);
     456:         sb.sg_flags &= ~CBREAK;
     457:         sb.sg_flags |= RAW;
     458:         ioctl(0, TIOCSETN, (char *)&sb);
     459:         notc.t_stopc = -1;
     460:         notc.t_startc = -1;
     461:         ioctl(0, TIOCSETC, (char *)&notc);
     462:     }
     463:     if (!eight && (mark & TIOCPKT_DOSTOP)) {
     464:         ioctl(0, TIOCGETP, (char *)&sb);
     465:         sb.sg_flags &= ~RAW;
     466:         sb.sg_flags |= CBREAK;
     467:         ioctl(0, TIOCSETN, (char *)&sb);
     468:         notc.t_stopc = deftc.t_stopc;
     469:         notc.t_startc = deftc.t_startc;
     470:         ioctl(0, TIOCSETC, (char *)&notc);
     471:     }
     472:     if (mark & TIOCPKT_FLUSHWRITE) {
     473:         ioctl(1, TIOCFLUSH, (char *)&out);
     474:         for (;;) {
     475:             if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
     476:                 perror("ioctl");
     477:                 break;
     478:             }
     479:             if (atmark)
     480:                 break;
     481:             n = read(rem, waste, sizeof (waste));
     482:             if (n <= 0)
     483:                 break;
     484:         }
     485:         /*
     486: 		 * Don't want any pending data to be output,
     487: 		 * so clear the recv buffer.
     488: 		 * If we were hanging on a write when interrupted,
     489: 		 * don't want it to restart.  If we were reading,
     490: 		 * restart anyway.
     491: 		 */
     492:         rcvcnt = 0;
     493:         longjmp(rcvtop, 1);
     494:     }
     495:     /*
     496: 	 * If we filled the receive buffer while a read was pending,
     497: 	 * longjmp to the top to restart appropriately.  Don't abort
     498: 	 * a pending write, however, or we won't know how much was written.
     499: 	 */
     500:     if (rcvd && rcvstate == READING)
     501:         longjmp(rcvtop, 1);
     502: }
     503:
     504: /*
     505:  * reader: read from remote: line -> 1
     506:  */
     507: reader()
     508: {
     509: #if !defined(BSD) || BSD < 43
     510:     int pid = -getpid();
     511: #else
     512:     int pid = getpid();
     513: #endif
     514:     int n, remaining;
     515:     char *bufp = rcvbuf;
     516:
     517:     signal(SIGTTOU, SIG_IGN);
     518:     fcntl(rem, F_SETOWN, pid);
     519:     ppid = getppid();
     520:     (void) setjmp(rcvtop);
     521:     for (;;) {
     522:         while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
     523:             rcvstate = WRITING;
     524:             n = write(1, bufp, remaining);
     525:             if (n < 0) {
     526:                 if (errno != EINTR)
     527:                     return (-1);
     528:                 continue;
     529:             }
     530:             bufp += n;
     531:         }
     532:         bufp = rcvbuf;
     533:         rcvcnt = 0;
     534:         rcvstate = READING;
     535:         rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf));
     536:         if (rcvcnt == 0)
     537:             return (0);
     538:         if (rcvcnt < 0) {
     539:             if (errno == EINTR)
     540:                 continue;
     541:             perror("read");
     542:             return (-1);
     543:         }
     544:     }
     545: }
     546:
     547: mode(f)
     548: {
     549:     struct tchars *tc;
     550:     struct ltchars *ltc;
     551:     struct sgttyb sb;
     552:     int lflags;
     553:
     554:     ioctl(0, TIOCGETP, (char *)&sb);
     555:     ioctl(0, TIOCLGET, (char *)&lflags);
     556:     switch (f) {
     557:
     558:     case 0:
     559:         sb.sg_flags &= ~(CBREAK|RAW|XTABS);
     560:         sb.sg_flags |= defflags;
     561:         tc = &deftc;
     562:         ltc = &defltc;
     563:         sb.sg_kill = defkill;
     564:         sb.sg_erase = deferase;
     565:         lflags = deflflags;
     566:         break;
     567:
     568:     case 1:
     569:         sb.sg_flags |= (eight ? RAW : CBREAK);
     570:         sb.sg_flags &= ~defflags;
     571:         sb.sg_flags &= ~XTABS;
     572:         tc = &notc;
     573:         ltc = &noltc;
     574:         sb.sg_kill = sb.sg_erase = -1;
     575:         if (litout)
     576:             lflags |= LLITOUT;
     577:         break;
     578:
     579:     default:
     580:         return;
     581:     }
     582:     ioctl(0, TIOCSLTC, (char *)ltc);
     583:     ioctl(0, TIOCSETC, (char *)tc);
     584:     ioctl(0, TIOCSETN, (char *)&sb);
     585:     ioctl(0, TIOCLSET, (char *)&lflags);
     586: }
     587:
     588: /*VARARGS*/
     589: prf(f, a1, a2, a3, a4, a5)
     590:     char *f;
     591: {
     592:     fprintf(stderr, f, a1, a2, a3, a4, a5);
     593:     fprintf(stderr, CRLF);
     594: }
     595:
     596: lostpeer()
     597: {
     598:     signal(SIGPIPE, SIG_IGN);
     599:     prf("\007Connection closed.");
     600:     done(1);
     601: }

#### Defined functions

catchild defined in line 243; used 3 times

- in line 166, 213, 347

doit defined in line 177; used 1 times

- in line 155

done defined in line 219; used 4 times

- in line 198, 216, 256, 600

echo defined in line 320; used 2 times

- in line 298-303(2)

lostpeer defined in line 596; used 2 times

- in line 50, 140

main defined in line 66; never used
mode defined in line 547; used 4 times

- in line 201, 223, 344-348(2)

oob defined in line 415; used 2 times

- in line 64, 141

prf defined in line 589; used 5 times

- in line 204-208(2), 215, 311, 599

reader defined in line 507; used 1 times

- in line 203

sendwindow defined in line 380; used 3 times

- in line 237, 360, 372

sigwinch defined in line 365; used 3 times

- in line 64, 238, 349

stop defined in line 341; used 1 times

- in line 304

writer defined in line 266; used 1 times

- in line 214

writeroob defined in line 233; used 2 times

- in line 167, 211

#### Defined variables

child defined in line 165; used 6 times

- in line 195-200(3), 224(2), 255

cmdchar defined in line 42; used 5 times

- in line 100, 290, 307-308(2), 327

copyright defined in line 8; never used
deferase defined in line 171; used 2 times

- in line 185, 564

defflags defined in line 169; used 3 times

- in line 184, 560, 570

defkill defined in line 171; used 3 times

- in line 186, 314, 563

deflflags defined in line 170; used 2 times

- in line 187, 565

defltc defined in line 173; used 6 times

- in line 191, 301(2), 315, 346, 562

deftc defined in line 172; used 9 times

- in line 188-190(3), 297, 314-315(2), 468-469(2), 561

dosigwinch defined in line 51; used 4 times

- in line 236-240(2), 357, 369

eight defined in line 43; used 4 times

- in line 105, 454, 463, 569

litout defined in line 44; used 2 times

- in line 110, 575

name defined in line 40; used 3 times

- in line 96, 144(2)

noltc defined in line 175; used 1 times

- in line 573

notc defined in line 174; used 9 times

- in line 189-190(2), 459-461(3), 468-470(3), 572

ppid defined in line 412; used 2 times

- in line 452, 519

rcvbuf defined in line 409; used 8 times

- in line 432-434(3), 515, 522, 532-535(3)

rcvcnt defined in line 410; used 9 times

- in line 432-434(3), 492, 522, 533-538(4)

rcvstate defined in line 411; used 3 times

- in line 500, 523, 534

rcvtop defined in line 413; used 3 times

- in line 493, 501, 520

rem defined in line 41; used 13 times

- in line 143-148(3), 308-310(2), 400, 422, 433, 439, 475, 481, 518, 535

sccsid defined in line 12; never used
speeds defined in line 45; used 1 times

- in line 133

term defined in line 48; used 4 times

- in line 130-133(3), 144

winsize defined in line 62; used 12 times

- in line 136-138(2), 358-359(2), 370-371(2), 390-398(6)

#### Defined struct's

winsize defined in line 57; used 10 times

- in line 62(2), 367(2), 382-383(6)

#### Defined macros

CRLF defined in line 163; used 1 times

- in line 593

READING defined in line 406; used 2 times

- in line 500, 534

TIOCPKT_WINDOW defined in line 35; used 2 times

- in line 34, 448

WRITING defined in line 407; used 1 times

- in line 523

sigmask defined in line 53; used 2 times

- in line 52, 142

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