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

#### Defined functions

help defined in line 563; used 1 times

- in line 421

iswiz defined in line 624; used 2 times

- in line 119, 460

runinchild defined in line 647; used 2 times

- in line 245, 378

skipword defined in line 516; used 3 times

- in line 111, 253, 276

smtp defined in line 106; used 1 times

- in /usr/src/usr.sbin/sendmail.MX/src/main.c line 655

#### Defined variables

CmdTab defined in line 70; used 1 times

- in line 193

WizWord defined in line 100; used 4 times

- in line 469-475(3)
- in /usr/src/usr.sbin/sendmail.MX/src/readcf.c line 885

sccsid defined in line 23; never used

#### Defined struct's

cmd defined in line 46; used 4 times

- in line 70(2), 109(2)

#### Defined macros

CMDDATA defined in line 56; used 1 times

- in line 74

CMDDBGDEBUG defined in line 64; used 1 times

- in line 87

CMDDBGKILL defined in line 66; used 1 times

- in line 91

CMDDBGQSHOW defined in line 63; used 1 times

- in line 85

CMDDBGWIZ defined in line 67; used 1 times

- in line 93

CMDERROR defined in line 53; used 1 times

- in line 94

CMDHELO defined in line 62; used 1 times

- in line 81

CMDHELP defined in line 59; used 1 times

- in line 78

CMDMAIL defined in line 54; used 1 times

- in line 72

CMDNOOP defined in line 60; used 1 times

- in line 79

CMDONEX defined in line 68; used 1 times

- in line 83

CMDQUIT defined in line 61; used 1 times

- in line 80

CMDRCPT defined in line 55; used 1 times

- in line 73

CMDRSET defined in line 57; used 1 times

- in line 75

CMDVERB defined in line 65; used 1 times

- in line 82

CMDVRFY defined in line 58; used 2 times

- in line 76-77(2)

EX_QUIT defined in line 104; used 2 times

- in line 431, 670

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