# 2.11BSD#431 - /usr/src/usr.sbin/sendmail/src/srvrsmtp.c

##### Functions

    help              X
    iswiz             X
    runinchild        X
    smtp              X

##### Variables

    WizWord           X

##### Macros

    CMDDATA           X
    CMDDBGDEBUG       X
    CMDDBGKILL        X
    CMDDBGQSHOW       X
    CMDDBGWIZ         X
    CMDERROR          X
    CMDHELO           X
    CMDHELP           X
    CMDMAIL           X
    CMDNOOP           X
    CMDONEX           X
    CMDQUIT           X
    CMDRCPT           X
    CMDRSET           X
    CMDVERB           X
    CMDVRFY           X
    EX_QUIT           X

##### struct's

    cmd               X

       1: /*
       2: **  Sendmail
       3: **  Copyright (c) 1983  Eric P. Allman
       4: **  Berkeley, California
       5: **
       6: **  Copyright (c) 1983 Regents of the University of California.
       7: **  All rights reserved.  The Berkeley software License Agreement
       8: **  specifies the terms and conditions for redistribution.
       9: */
      10:
      11:
      12: # include <errno.h>
      13: # include "sendmail.h"
      14: # include <signal.h>
      15:
      16: # ifndef SMTP
      17: #if !defined(lint) && !defined(NOSCCS)
      18: static char SccsId[] = "@(#)srvrsmtp.c 5.18.1 (2.11BSD GTE) 7/15/94 (no SMTP)";
      19: # endif
      20: # else SMTP
      21:
      22: #if !defined(lint) && !defined(NOSCCS)
      23: static char SccsId[] = "@(#)srvrsmtp.c	5.18.1 (2.11BSD GTE) 7/15/94";
      24: # endif
      25:
      26: /*
      27: **  SMTP -- run the SMTP protocol.
      28: **
      29: **	Parameters:
      30: **		none.
      31: **
      32: **	Returns:
      33: **		never.
      34: **
      35: **	Side Effects:
      36: **		Reads commands from the input channel and processes
      37: **			them.
      38: */
      39:
      40: struct cmd
      41: {
      42:     char    *cmdname;   /* command name */
      43:     int cmdcode;    /* internal code, see below */
      44: };
      45:
      46: /* values for cmdcode */
      47: # define CMDERROR   0   /* bad command */
      48: # define CMDMAIL    1   /* mail -- designate sender */
      49: # define CMDRCPT    2   /* rcpt -- designate recipient */
      50: # define CMDDATA    3   /* data -- send message text */
      51: # define CMDRSET    4   /* rset -- reset state */
      52: # define CMDVRFY    5   /* vrfy -- verify address */
      53: # define CMDHELP    6   /* help -- give usage info */
      54: # define CMDNOOP    7   /* noop -- do nothing */
      55: # define CMDQUIT    8   /* quit -- close connection and die */
      56: # define CMDHELO    9   /* helo -- be polite */
      57: # define CMDDBGQSHOW    10  /* showq -- show send queue (DEBUG) */
      58: # define CMDDBGDEBUG    11  /* debug -- set debug mode */
      59: # define CMDVERB    12  /* verb -- go into verbose mode */
      60: # define CMDDBGKILL 13  /* kill -- kill sendmail */
      61: # define CMDDBGWIZ  14  /* wiz -- become a wizard */
      62: # define CMDONEX    15  /* onex -- sending one transaction only */
      63:
      64: static struct cmd   CmdTab[] =
      65: {
      66:     "mail",     CMDMAIL,
      67:     "rcpt",     CMDRCPT,
      68:     "data",     CMDDATA,
      69:     "rset",     CMDRSET,
      70:     "vrfy",     CMDVRFY,
      71:     "expn",     CMDVRFY,
      72:     "help",     CMDHELP,
      73:     "noop",     CMDNOOP,
      74:     "quit",     CMDQUIT,
      75:     "helo",     CMDHELO,
      76:     "verb",     CMDVERB,
      77:     "onex",     CMDONEX,
      78: # ifdef DEBUG
      79:     "showq",    CMDDBGQSHOW,
      80:     "debug",    CMDDBGDEBUG,
      81: # endif DEBUG
      82: # ifdef WIZ
      83:     "kill",     CMDDBGKILL,
      84: # endif WIZ
      85:     "wiz",      CMDDBGWIZ,
      86:     NULL,       CMDERROR,
      87: };
      88:
      89: # ifdef WIZ
      90: bool    IsWiz = FALSE;          /* set if we are a wizard */
      91: char    *WizWord;           /* the wizard word to compare against */
      92: # endif WIZ
      93: bool    InChild = FALSE;        /* true if running in a subprocess */
      94: bool    OneXact = FALSE;        /* one xaction only this run */
      95:
      96: #define EX_QUIT     22      /* special code for QUIT command */
      97:
      98: smtp()
      99: {
     100:     register char *p;
     101:     register struct cmd *c;
     102:     char *cmd;
     103:     extern char *skipword();
     104:     extern bool sameword();
     105:     bool hasmail;           /* mail command received */
     106:     auto ADDRESS *vrfyqueue;
     107:     ADDRESS *a;
     108:     char inp[MAXLINE];
     109:     char cmdbuf[100];
     110:     extern tick();
     111:     extern bool iswiz();
     112:     extern char *arpadate();
     113:     extern char *macvalue();
     114:     extern ADDRESS *recipient();
     115:     extern ENVELOPE BlankEnvelope;
     116:     extern ENVELOPE *newenvelope();
     117:
     118:     hasmail = FALSE;
     119:     if (OutChannel != stdout)
     120:     {
     121:         /* arrange for debugging output to go to remote host */
     122:         (void) close(1);
     123:         (void) dup(fileno(OutChannel));
     124:     }
     125:     settime();
     126:     if (RealHostName != NULL)
     127:     {
     128:         CurHostName = RealHostName;
     129:         setproctitle("srvrsmtp %s", CurHostName);
     130:     }
     131:     else
     132:     {
     133:         /* this must be us!! */
     134:         CurHostName = MyHostName;
     135:     }
     136:     expand("\001e", inp, &inp[sizeof inp], CurEnv);
     137:     message("220", inp);
     138:     SmtpPhase = "startup";
     139:     for (;;)
     140:     {
     141:         /* arrange for backout */
     142:         if (setjmp(TopFrame) > 0 && InChild)
     143:             finis();
     144:         QuickAbort = FALSE;
     145:         HoldErrs = FALSE;
     146:
     147:         /* setup for the read */
     148:         CurEnv->e_to = NULL;
     149:         Errors = 0;
     150:         (void) fflush(stdout);
     151:
     152:         /* read the input line */
     153:         p = sfgets(inp, sizeof inp, InChannel);
     154:
     155:         /* handle errors */
     156:         if (p == NULL)
     157:         {
     158:             /* end of file, just die */
     159:             message("421", "%s Lost input channel to %s",
     160:                 MyHostName, CurHostName);
     161:             finis();
     162:         }
     163:
     164:         /* clean up end of line */
     165:         fixcrlf(inp, TRUE);
     166:
     167:         /* echo command to transcript */
     168:         if (CurEnv->e_xfp != NULL)
     169:             fprintf(CurEnv->e_xfp, "<<< %s\n", inp);
     170:
     171:         /* break off command */
     172:         for (p = inp; isspace(*p); p++)
     173:             continue;
     174:         cmd = p;
     175:         for (cmd = cmdbuf; *p != '\0' && !isspace(*p); )
     176:             *cmd++ = *p++;
     177:         *cmd = '\0';
     178:
     179:         /* throw away leading whitespace */
     180:         while (isspace(*p))
     181:             p++;
     182:
     183:         /* decode command */
     184:         for (c = CmdTab; c->cmdname != NULL; c++)
     185:         {
     186:             if (sameword(c->cmdname, cmdbuf))
     187:                 break;
     188:         }
     189:
     190:         /* process command */
     191:         switch (c->cmdcode)
     192:         {
     193:           case CMDHELO:     /* hello -- introduce yourself */
     194:             SmtpPhase = "HELO";
     195:             setproctitle("%s: %s", CurHostName, inp);
     196:             if (sameword(p, MyHostName))
     197:             {
     198:                 /* connected to an echo server */
     199:                 message("553", "%s I refuse to talk to myself",
     200:                     MyHostName);
     201:                 break;
     202:             }
     203:             if (RealHostName != NULL && !sameword(p, RealHostName))
     204:             {
     205:                 char hostbuf[MAXNAME];
     206:
     207:                 (void) sprintf(hostbuf, "%s (%s)", p, RealHostName);
     208:                 define('s', newstr(hostbuf), CurEnv);
     209:             }
     210:             else
     211:                 define('s', newstr(p), CurEnv);
     212:             message("250", "%s Hello %s, pleased to meet you",
     213:                 MyHostName, p);
     214:             break;
     215:
     216:           case CMDMAIL:     /* mail -- designate sender */
     217:             SmtpPhase = "MAIL";
     218:
     219:             /* force a sending host even if no HELO given */
     220:             if (RealHostName != NULL && macvalue('s', CurEnv) == NULL)
     221:                 define('s', RealHostName, CurEnv);
     222:
     223:             /* check for validity of this command */
     224:             if (hasmail)
     225:             {
     226:                 message("503", "Sender already specified");
     227:                 break;
     228:             }
     229:             if (InChild)
     230:             {
     231:                 syserr("Nested MAIL command");
     232:                 exit(0);
     233:             }
     234:
     235:             /* fork a subprocess to process this command */
     236:             if (runinchild("SMTP-MAIL") > 0)
     237:                 break;
     238:             initsys();
     239:             setproctitle("%s %s: %s", CurEnv->e_id,
     240:                 CurHostName, inp);
     241:
     242:             /* child -- go do the processing */
     243:             p = skipword(p, "from");
     244:             if (p == NULL)
     245:                 break;
     246:             setsender(p);
     247:             if (Errors == 0)
     248:             {
     249:                 message("250", "Sender ok");
     250:                 hasmail = TRUE;
     251:             }
     252:             else if (InChild)
     253:                 finis();
     254:             break;
     255:
     256:           case CMDRCPT:     /* rcpt -- designate recipient */
     257:             SmtpPhase = "RCPT";
     258:             setproctitle("%s %s: %s", CurEnv->e_id,
     259:                 CurHostName, inp);
     260:             if (setjmp(TopFrame) > 0)
     261:             {
     262:                 CurEnv->e_flags &= ~EF_FATALERRS;
     263:                 break;
     264:             }
     265:             QuickAbort = TRUE;
     266:             p = skipword(p, "to");
     267:             if (p == NULL)
     268:                 break;
     269:             a = parseaddr(p, (ADDRESS *) NULL, 1, '\0');
     270:             if (a == NULL)
     271:                 break;
     272:             a->q_flags |= QPRIMARY;
     273:             a = recipient(a, &CurEnv->e_sendqueue);
     274:             if (Errors != 0)
     275:                 break;
     276:
     277:             /* no errors during parsing, but might be a duplicate */
     278:             CurEnv->e_to = p;
     279:             if (!bitset(QBADADDR, a->q_flags))
     280:                 message("250", "Recipient ok");
     281:             else
     282:             {
     283:                 /* punt -- should keep message in ADDRESS.... */
     284:                 message("550", "Addressee unknown");
     285:             }
     286:             CurEnv->e_to = NULL;
     287:             break;
     288:
     289:           case CMDDATA:     /* data -- text of mail */
     290:             SmtpPhase = "DATA";
     291:             if (!hasmail)
     292:             {
     293:                 message("503", "Need MAIL command");
     294:                 break;
     295:             }
     296:             else if (CurEnv->e_nrcpts <= 0)
     297:             {
     298:                 message("503", "Need RCPT (recipient)");
     299:                 break;
     300:             }
     301:
     302:             /* collect the text of the message */
     303:             SmtpPhase = "collect";
     304:             setproctitle("%s %s: %s", CurEnv->e_id,
     305:                 CurHostName, inp);
     306:             collect(TRUE);
     307:             if (Errors != 0)
     308:                 break;
     309:
     310:             /*
     311: 			**  Arrange to send to everyone.
     312: 			**	If sending to multiple people, mail back
     313: 			**		errors rather than reporting directly.
     314: 			**	In any case, don't mail back errors for
     315: 			**		anything that has happened up to
     316: 			**		now (the other end will do this).
     317: 			**	Truncate our transcript -- the mail has gotten
     318: 			**		to us successfully, and if we have
     319: 			**		to mail this back, it will be easier
     320: 			**		on the reader.
     321: 			**	Then send to everyone.
     322: 			**	Finally give a reply code.  If an error has
     323: 			**		already been given, don't mail a
     324: 			**		message back.
     325: 			**	We goose error returns by clearing error bit.
     326: 			*/
     327:
     328:             SmtpPhase = "delivery";
     329:             if (CurEnv->e_nrcpts != 1)
     330:             {
     331:                 HoldErrs = TRUE;
     332:                 ErrorMode = EM_MAIL;
     333:             }
     334:             CurEnv->e_flags &= ~EF_FATALERRS;
     335:             CurEnv->e_xfp = freopen(queuename(CurEnv, 'x'), "w", CurEnv->e_xfp);
     336:
     337:             /* send to all recipients */
     338:             sendall(CurEnv, SM_DEFAULT);
     339:             CurEnv->e_to = NULL;
     340:
     341:             /* save statistics */
     342:             markstats(CurEnv, (ADDRESS *) NULL);
     343:
     344:             /* issue success if appropriate and reset */
     345:             if (Errors == 0 || HoldErrs)
     346:                 message("250", "Ok");
     347:             else
     348:                 CurEnv->e_flags &= ~EF_FATALERRS;
     349:
     350:             /* if in a child, pop back to our parent */
     351:             if (InChild)
     352:                 finis();
     353:
     354:             /* clean up a bit */
     355:             hasmail = 0;
     356:             dropenvelope(CurEnv);
     357:             CurEnv = newenvelope(CurEnv);
     358:             CurEnv->e_flags = BlankEnvelope.e_flags;
     359:             break;
     360:
     361:           case CMDRSET:     /* rset -- reset state */
     362:             message("250", "Reset state");
     363:             if (InChild)
     364:                 finis();
     365:             break;
     366:
     367:           case CMDVRFY:     /* vrfy -- verify address */
     368:             if (runinchild("SMTP-VRFY") > 0)
     369:                 break;
     370:             setproctitle("%s: %s", CurHostName, inp);
     371:             vrfyqueue = NULL;
     372:             QuickAbort = TRUE;
     373:             sendtolist(p, (ADDRESS *) NULL, &vrfyqueue);
     374:             if (Errors != 0)
     375:             {
     376:                 if (InChild)
     377:                     finis();
     378:                 break;
     379:             }
     380:             while (vrfyqueue != NULL)
     381:             {
     382:                 register ADDRESS *a = vrfyqueue->q_next;
     383:                 char *code;
     384:
     385:                 while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags))
     386:                     a = a->q_next;
     387:
     388:                 if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags))
     389:                 {
     390:                     if (a != NULL)
     391:                         code = "250-";
     392:                     else
     393:                         code = "250";
     394:                     if (vrfyqueue->q_fullname == NULL)
     395:                         message(code, "<%s>", vrfyqueue->q_paddr);
     396:                     else
     397:                         message(code, "%s <%s>",
     398:                             vrfyqueue->q_fullname, vrfyqueue->q_paddr);
     399:                 }
     400:                 else if (a == NULL)
     401:                     message("554", "Self destructive alias loop");
     402:                 vrfyqueue = a;
     403:             }
     404:             if (InChild)
     405:                 finis();
     406:             break;
     407:
     408:           case CMDHELP:     /* help -- give user info */
     409:             if (*p == '\0')
     410:                 p = "SMTP";
     411:             help(p);
     412:             break;
     413:
     414:           case CMDNOOP:     /* noop -- do nothing */
     415:             message("200", "OK");
     416:             break;
     417:
     418:           case CMDQUIT:     /* quit -- leave mail */
     419:             message("221", "%s closing connection", MyHostName);
     420:             if (InChild)
     421:                 ExitStat = EX_QUIT;
     422:             finis();
     423:
     424:           case CMDVERB:     /* set verbose mode */
     425:             Verbose = TRUE;
     426:             SendMode = SM_DELIVER;
     427:             message("200", "Verbose mode");
     428:             break;
     429:
     430:           case CMDONEX:     /* doing one transaction only */
     431:             OneXact = TRUE;
     432:             message("200", "Only one transaction");
     433:             break;
     434:
     435: # ifdef DEBUG
     436:           case CMDDBGQSHOW: /* show queues */
     437:             printf("Send Queue=");
     438:             printaddr(CurEnv->e_sendqueue, TRUE);
     439:             break;
     440:
     441:           case CMDDBGDEBUG: /* set debug mode */
     442:             tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
     443:             tTflag(p);
     444:             message("200", "Debug set");
     445:             break;
     446: # endif DEBUG
     447:
     448: # ifdef WIZ
     449:           case CMDDBGKILL:  /* kill the parent */
     450:             if (!iswiz())
     451:                 break;
     452:             if (kill(MotherPid, SIGTERM) >= 0)
     453:                 message("200", "Mother is dead");
     454:             else
     455:                 message("500", "Can't kill Mom");
     456:             break;
     457:
     458:           case CMDDBGWIZ:   /* become a wizard */
     459:             if (WizWord != NULL)
     460:             {
     461:                 char seed[3];
     462:                 extern char *crypt();
     463:
     464:                 (void) strncpy(seed, WizWord, 2);
     465:                 if (strcmp(WizWord, crypt(p, seed)) == 0)
     466:                 {
     467:                     IsWiz = TRUE;
     468:                     message("200", "Please pass, oh mighty wizard");
     469:                     break;
     470:                 }
     471:             }
     472:             message("500", "You are no wizard!");
     473:             break;
     474:
     475: # else WIZ
     476:           case CMDDBGWIZ:   /* try to become a wizard */
     477:             message("500", "You wascal wabbit!  Wandering wizards won't win!");
     478:             break;
     479: # endif WIZ
     480:
     481:           case CMDERROR:    /* unknown command */
     482:             message("500", "Command unrecognized");
     483:             break;
     484:
     485:           default:
     486:             syserr("smtp: unknown code %d", c->cmdcode);
     487:             break;
     488:         }
     489:     }
     490: }
     491: /*
     492: **  SKIPWORD -- skip a fixed word.
     493: **
     494: **	Parameters:
     495: **		p -- place to start looking.
     496: **		w -- word to skip.
     497: **
     498: **	Returns:
     499: **		p following w.
     500: **		NULL on error.
     501: **
     502: **	Side Effects:
     503: **		clobbers the p data area.
     504: */
     505:
     506: static char *
     507: skipword(p, w)
     508:     register char *p;
     509:     char *w;
     510: {
     511:     register char *q;
     512:     extern bool sameword();
     513:
     514:     /* find beginning of word */
     515:     while (isspace(*p))
     516:         p++;
     517:     q = p;
     518:
     519:     /* find end of word */
     520:     while (*p != '\0' && *p != ':' && !isspace(*p))
     521:         p++;
     522:     while (isspace(*p))
     523:         *p++ = '\0';
     524:     if (*p != ':')
     525:     {
     526:       syntax:
     527:         message("501", "Syntax error");
     528:         Errors++;
     529:         return (NULL);
     530:     }
     531:     *p++ = '\0';
     532:     while (isspace(*p))
     533:         p++;
     534:
     535:     /* see if the input word matches desired word */
     536:     if (!sameword(q, w))
     537:         goto syntax;
     538:
     539:     return (p);
     540: }
     541: /*
     542: **  HELP -- implement the HELP command.
     543: **
     544: **	Parameters:
     545: **		topic -- the topic we want help for.
     546: **
     547: **	Returns:
     548: **		none.
     549: **
     550: **	Side Effects:
     551: **		outputs the help file to message output.
     552: */
     553:
     554: help(topic)
     555:     char *topic;
     556: {
     557:     register FILE *hf;
     558:     int len;
     559:     char buf[MAXLINE];
     560:     bool noinfo;
     561:
     562:     if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL)
     563:     {
     564:         /* no help */
     565:         errno = 0;
     566:         message("502", "HELP not implemented");
     567:         return;
     568:     }
     569:
     570:     len = strlen(topic);
     571:     makelower(topic);
     572:     noinfo = TRUE;
     573:
     574:     while (fgets(buf, sizeof buf, hf) != NULL)
     575:     {
     576:         if (strncmp(buf, topic, len) == 0)
     577:         {
     578:             register char *p;
     579:
     580:             p = index(buf, '\t');
     581:             if (p == NULL)
     582:                 p = buf;
     583:             else
     584:                 p++;
     585:             fixcrlf(p, TRUE);
     586:             message("214-", p);
     587:             noinfo = FALSE;
     588:         }
     589:     }
     590:
     591:     if (noinfo)
     592:         message("504", "HELP topic unknown");
     593:     else
     594:         message("214", "End of HELP info");
     595:     (void) fclose(hf);
     596: }
     597: /*
     598: **  ISWIZ -- tell us if we are a wizard
     599: **
     600: **	If not, print a nasty message.
     601: **
     602: **	Parameters:
     603: **		none.
     604: **
     605: **	Returns:
     606: **		TRUE if we are a wizard.
     607: **		FALSE if we are not a wizard.
     608: **
     609: **	Side Effects:
     610: **		Prints a 500 exit stat if we are not a wizard.
     611: */
     612:
     613: #ifdef WIZ
     614:
     615: bool
     616: iswiz()
     617: {
     618:     if (!IsWiz)
     619:         message("500", "Mere mortals musn't mutter that mantra");
     620:     return (IsWiz);
     621: }
     622:
     623: #endif WIZ
     624: /*
     625: **  RUNINCHILD -- return twice -- once in the child, then in the parent again
     626: **
     627: **	Parameters:
     628: **		label -- a string used in error messages
     629: **
     630: **	Returns:
     631: **		zero in the child
     632: **		one in the parent
     633: **
     634: **	Side Effects:
     635: **		none.
     636: */
     637:
     638: runinchild(label)
     639:     char *label;
     640: {
     641:     int childpid;
     642:
     643:     if (!OneXact)
     644:     {
     645:         childpid = dofork();
     646:         if (childpid < 0)
     647:         {
     648:             syserr("%s: cannot fork", label);
     649:             return (1);
     650:         }
     651:         if (childpid > 0)
     652:         {
     653:             auto int st;
     654:
     655:             /* parent -- wait for child to complete */
     656:             st = waitfor(childpid);
     657:             if (st == -1)
     658:                 syserr("%s: lost child", label);
     659:
     660:             /* if we exited on a QUIT command, complete the process */
     661:             if (st == (EX_QUIT << 8))
     662:                 finis();
     663:
     664:             return (1);
     665:         }
     666:         else
     667:         {
     668:             /* child */
     669:             InChild = TRUE;
     670:             QuickAbort = FALSE;
     671:             clearenvelope(CurEnv, FALSE);
     672:         }
     673:     }
     674:
     675:     /* open alias database */
     676:     initaliases(AliasFile, FALSE);
     677:
     678:     return (0);
     679: }
     680:
     681: # endif SMTP

#### Defined functions

help defined in line 554; used 1 times

- in line 411

iswiz defined in line 615; used 2 times

- in line 111, 450

runinchild defined in line 638; used 2 times

- in line 236, 368

skipword defined in line 506; used 3 times

- in line 103, 243, 266

smtp defined in line 98; used 1 times

- in /usr/src/usr.sbin/sendmail/src/main.c line 659

#### Defined variables

CmdTab defined in line 64; used 1 times

- in line 184

SccsId defined in line 23; never used
WizWord defined in line 91; used 4 times

- in line 459-465(3)
- in /usr/src/usr.sbin/sendmail/src/readcf.c line 883

#### Defined struct's

cmd defined in line 40; used 4 times

- in line 64(2), 101(2)

#### Defined macros

CMDDATA defined in line 50; used 1 times

- in line 68

CMDDBGDEBUG defined in line 58; used 1 times

- in line 80

CMDDBGKILL defined in line 60; used 1 times

- in line 83

CMDDBGQSHOW defined in line 57; used 1 times

- in line 79

CMDDBGWIZ defined in line 61; used 1 times

- in line 85

CMDERROR defined in line 47; used 1 times

- in line 86

CMDHELO defined in line 56; used 1 times

- in line 75

CMDHELP defined in line 53; used 1 times

- in line 72

CMDMAIL defined in line 48; used 1 times

- in line 66

CMDNOOP defined in line 54; used 1 times

- in line 73

CMDONEX defined in line 62; used 1 times

- in line 77

CMDQUIT defined in line 55; used 1 times

- in line 74

CMDRCPT defined in line 49; used 1 times

- in line 67

CMDRSET defined in line 51; used 1 times

- in line 69

CMDVERB defined in line 59; used 1 times

- in line 76

CMDVRFY defined in line 52; used 2 times

- in line 70-71(2)

EX_QUIT defined in line 96; used 2 times

- in line 421, 661

Last modified: 1994-07-16 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2883 |