|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 23105 (0x5a41) Types: TextFile Names: »smtpsrvr.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z« └─⟦e5a54fb17⟧ └─⟦this⟧ »pp-5.0/Chans/smtp/smtpsrvr.c«
/* smtpsrvr.c: server for smtp requests */ # ifndef lint static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Chans/smtp/RCS/smtpsrvr.c,v 5.0 90/09/20 15:54:32 pp Exp Locker: pp $"; # endif /* * $Header: /cs/research/pp/hubris/pp-beta/Chans/smtp/RCS/smtpsrvr.c,v 5.0 90/09/20 15:54:32 pp Exp Locker: pp $ * * $Log: smtpsrvr.c,v $ * Revision 5.0 90/09/20 15:54:32 pp * rcsforce : 5.0 public release * */ #include "head.h" #include "prm.h" #include "q.h" #include "dl.h" #include <isode/cmd_srch.h> #include <signal.h> #include <sys/stat.h> #include <netinet/in.h> #include <sys/socket.h> #include <netdb.h> #include <errno.h> /* -- external variables -- */ extern char *hdr_822_bp, *ia5_bp; extern char *ctime(), *quedfldir, *postmaster; extern time_t time(); extern ADDR *adr_new (); #if sparc && defined(__GNUC__) /* work around bug in gcc 1.37 sparc version */ #define inet_ntoa myinet_ntoa static char *myinet_ntoa (in) struct in_addr in; { static char buf[80]; (void) sprintf (buf, "%d.%d.%d.%d", (in.s_addr >> 24) & 0xff, (in.s_addr >> 16) & 0xff, (in.s_addr >> 8 ) & 0xff, (in.s_addr ) & 0xff); return buf; } #else extern char *inet_ntoa (); #endif /* -- internal definitions -- */ #define BUFL 8096 /* -- length of buf -- */ #define CNULL '\0' /* -- null -- */ #define CR '\r' /* -- carriage return -- */ #define LF '\n' /* -- line feed -- */ #define NTIMEOUT 300 /* -- 5 minute timeout on net I/O -- */ /* -- internal variables -- */ static char buf [BUFL], /* -- for general usage -- */ *getline(), netbuf [BUFL], /* -- contains the valid characters -- */ *adrfix(), *arg, /* -- 0 if no arg - pts to comm param -- */ *channel = "smtp", *netptr = netbuf, /* -- next char to come out of netbuf -- */ *progname, *sender = NULLCP, *them, *realthem, *us; static int hellod = 0, nstimeout = 30, dont_mung = 0, /* -- used by getline() to limit munging -- */ net_count = 0, /* -- no of valid characters in netbuf -- */ no_recip = 0; /* -- no of valid recipients accepted -- */ CHAN *chanptr, *ch_nm2struct(); extern CMD_TABLE qtbl_con_type[]; static void byebye (), pprestart (), ppbegin (), ppstart (), netreply (), rset (); static void initialise (), dispatch (); static char *official (); /* -------------------------------------------------------------- . . . C o m m a n d D i s p a t c h T a b l e . . . * ------------------------------------------------------------ */ static void data (), helo (), help (), mail (), confirm (), quit (), rcpt (), vrfy (), expn (); static struct comarr /* -- the command table -- */ { char *cmdname; /* -- ascii name -- */ void (*cmdfunc)(); /* -- cmd func to call -- */ } commands [] = { "data", data, "helo", helo, "help", help, "mail", mail, "noop", confirm, "quit", quit, "rcpt", rcpt, "rset", rset, "vrfy", vrfy, "expn", expn, NULLCP, NULL }; static char usage[] = "Usage: smtp [-t timeout] channel"; main (argc, argv) int argc; char **argv; { char replybuf [128]; char *cp; int isnumeric; int opt; extern char *optarg; extern int optind; progname = argv [0]; sys_init (progname); (void) chdir (quedfldir); signal (SIGQUIT,SIG_IGN); signal (SIGTERM,quit); while ((opt = getopt (argc, argv, "t:")) != EOF) { switch (opt) { case 't': nstimeout = atoi (optarg); break; default: fprintf (stderr, "bad switch -%c: %s\n", opt, usage); PP_OPER (NULLCP, ("Bad argument -%c: %s", opt, usage)); exit (1); } } argc -= optind; argv += optind; #ifdef NAMESERVER ns_settimeo (nstimeout); /* don't wait forever! */ #endif if (argc != 1) { PP_OPER (NULLCP, ("smtpsrvr - no channel given!")); exit (NOTOK); } channel = *argv; /* -- find out who you are I might even believe you. -- */ if ((chanptr = ch_nm2struct (channel)) == NULLCHAN) { PP_LOG (LLOG_EXCEPTIONS, ("unknown channe: %s", channel)); (void) sprintf (replybuf, "421 %s: channel '%s' is unknown to PP. (Complain to: %s)\r\n", us, channel, postmaster); netreply (replybuf); exit (NOTOK); } channel = chanptr -> ch_name; rename_log (channel); initialise (); /* fill in us & them */ /* SEK - force validation of IP address */ for (isnumeric = TRUE, cp=them; *cp++ != '\0';) if (!isdigit(*cp) && *cp != '.' && *cp != '\0') { isnumeric = FALSE; break; } if (isnumeric && lexequ (chanptr -> ch_info, "sloppy") != 0) { PP_LOG (LLOG_FATAL, ("can't lookup '%s'", them)); (void) sprintf (replybuf, "421 %s: PP cannot resolve your address. '%s' (Help from: %s)\r\n", us, them, postmaster); netreply (replybuf); exit (NOTOK); } PP_NOTICE (("Connection from %s channel %s", realthem, channel)); ppbegin (); /* -- say we're listening -- */ (void) sprintf (replybuf, "220 %s PP Here - Pleased to meet you (Complaints/bugs to: %s)\r\n", us, postmaster); netreply (replybuf); while (cp = getline()) { PP_LOG (LLOG_PDUS, ("<- %s", buf)); dispatch (buf); } byebye (net_count < 0 ? 1 : 0); } /* --------------------- Static Routines ------------------------------- */ static void dispatch (str) char *str; { register struct comarr *comp; for (comp = commands;comp->cmdname != NULL; comp ++) { if (strcmp (str, comp->cmdname) == 0) { (*comp->cmdfunc)(); /* call comm proc */ return; } } PP_LOG (LLOG_EXCEPTIONS, ("Unknown command: %s", buf)); netreply ("500 Unknown or unimplemented command\r\n"); } static void initialise () { int i; char workarea[BUFSIZ]; struct sockaddr_in rmtaddr; int len; struct hostent *hp; if (gethostname (workarea, sizeof workarea) == -1) PP_SLOG (LLOG_EXCEPTIONS, "gethostname", ("Can't find out who I am")); us = official (workarea); if(us == NULLCP) { PP_OPER (NULLCP, ("Cannot find 'official' name of host '%s'\n", workarea)); exit(-1); } len = sizeof rmtaddr; if (getpeername (0, &rmtaddr, &len) != 0) { PP_OPER ("getpeername", ("Can't figure out who called us")); exit (-1); } for (i = 0 ; i < 4 ; i++) { hp = gethostbyaddr((char *)&rmtaddr.sin_addr, sizeof(rmtaddr.sin_addr), AF_INET); #ifdef NAMESERVER if(hp != NULL) #endif break; } if (hp == NULL) { (void) strcpy(workarea, inet_ntoa(rmtaddr.sin_addr)); them = strdup (workarea); PP_OPER (NULLCP, ("lookup failed for address '%s'", workarea)); } else them = strdup (hp->h_name); realthem = them; } /* name: getline() function: - get commands from the standard input terminated by <cr><lf>. - afix a pointer (arg) to any arguments passed. - ignore carriage returns. - map UPPER case to lower case. - manage the netptr and net_count variables. algorithm: while we havent received a line feed and buffer not full if net_count is zero or less get more data from net error: return 0 check for delimiter character null terminate first string set arg pointer to next character check for carriage return ignore it if looking at command name convert upper case to lower case if command line (not mail) null terminate last token manage netptr returns: 0 for EOF -1 when an error occurs on network connection ptr to last character (null) in command line variables: dont_mung net_count netptr buf --------------------------------------------------------------------------- */ static char *getline() { register char *inp; /* -- input pointer in netbuf -- */ static char *outp; /* -- output pointer in buf -- */ register int c; /* -- temporary char -- */ inp = netptr; outp = buf; arg = NULLCP; do { if (--net_count <= 0) { if (timeout (NTIMEOUT)) { PP_SLOG (LLOG_EXCEPTIONS, "read", ("%s net input", realthem)); return (NULLCP); } net_count = read (0, netbuf, sizeof netbuf); timeout (0); if (net_count == 0) /* -- EOF -- */ return NULLCP; if (net_count < 0) { /* -- error -- */ PP_SLOG (LLOG_EXCEPTIONS, "read", ("%s net input", realthem)); return NULLCP; } inp = netbuf; } c = *inp++ & 0377; if (c == '\r' || /* -- ignore CR -- */ c >= 0200) /* -- or any telnet codes that -- */ continue; /* -- try to sneak through -- */ if (dont_mung == 0 && arg == NULL) { /* -- if char is a delim afix token -- */ if (c == ' ' || c == ',') { c = CNULL; /* -- make null term'ed -- */ arg = outp + 1; /* -- set arg ptr -- */ } else if (isupper (c)) /* -- do case mapping (UPPER -> lower) -- */ c = tolower(c); } *outp++ = c; } while (c != '\n' && outp < &buf [BUFL]); if (dont_mung == 0) *--outp = 0; /* -- null term the last token -- */ /* -- scan off blanks in argument -- */ if (arg) { while (*arg == ' ') arg++; if (*arg == '\0') arg = 0; /* -- if all blanks, no argument -- */ } if (dont_mung == 0) PP_DBG (("'%s', '%s'", buf, arg == 0 ? "<noarg>" : arg)); /* -- reset netptr for next trip in -- */ netptr = inp; /* -- return success -- */ return (outp); } /* The helo command */ static void helo() { char replybuf [128]; char *cp; if (arg == NULLCP || *arg == 0) { PP_LOG (LLOG_EXCEPTIONS, ("No argument to HELO")); netreply ("501 No argument to HELO\r\n"); return; } compress (arg, arg); for (cp = arg; *cp; cp++) { switch (*cp) { case '\\': cp++; break; case '[': while (*cp && *cp != ']') cp ++; break; default: if (isascii(*cp) && (!iscntrl(*cp) && !isspace (*cp))) break; /* fall */ case '(': case ')': case '<': case '>': case '@': case ',': case ';': case ':': case '"': PP_LOG (LLOG_EXCEPTIONS, ("Bad character '%c' in domain name '%s'", *cp, arg)); netreply ("501 Bad hostname in HELO.\r\n"); return; } } hellod ++; if (lexequ (arg, them) != 0) { (void) sprintf (replybuf, "250 %s: You are bluffing - `%s` expected\r\n", us, them); PP_NOTICE (("%s claims to be %s", realthem, arg)); } else (void) sprintf (replybuf, "250 %s: Looks good to me\r\n", us); netreply (replybuf); } /* handle the MAIL command ("MAIL from:<user@host>") */ static void mail() { static Q_struct qstruct; Q_struct *qp = &qstruct; ADDR *ap; char replybuf [128]; RP_Buf thereply; LIST_BPT *new; if (hellod == 0) { PP_LOG (LLOG_EXCEPTIONS, ("Expecting a HELO command")); hellod ++; /* MH breaks this! */ } if (arg == 0 || *arg == 0) { PP_LOG (LLOG_EXCEPTIONS, ("No argument to MAIL supplied")); netreply ("501 No argument supplied\r\n"); return; } else if (sender) { PP_LOG (LLOG_EXCEPTIONS, ("MAIL command already supplied")); netreply ("503 MAIL command already accepted\r\n"); return; } else if (!prefix ("from:", arg)) { PP_LOG (LLOG_EXCEPTIONS, ("No sender given in MAIL")); netreply ("501 No sender named\r\n"); return; } /* -- Scan FROM: parts of arg -- */ sender = index (arg, ':') + 1; sender = adrfix (sender); q_init (qp); new = list_bpt_new (hdr_822_bp); list_bpt_add (&qp -> encodedinfo.eit_types, new); new = list_bpt_new (ia5_bp); list_bpt_add (&qp -> encodedinfo.eit_types, new); qp -> inbound = list_rchan_new (them, chanptr -> ch_name); ppstart (); if (rp_isbad (io_wrq (qp, &thereply))) { PP_LOG (LLOG_EXCEPTIONS, ("Can't write Q struct %s", thereply.rp_line)); netreply ("451 Temporary problem initialising\r\n"); pprestart (); return; } if (sender == NULLCP || *sender == NULL) sender = postmaster; PP_NOTICE (("Sender %s", sender)); ap = adr_new (sender, AD_822_TYPE, 0); (void) io_wadr (ap, AD_ORIGINATOR, &thereply); adr_tfree (ap); switch (thereply.rp_val) { case RP_BHST: thereply.rp_val = RP_NDEL; break; } if (rp_gbval (thereply.rp_val) == RP_BNO) { PP_LOG (LLOG_EXCEPTIONS, ("Can't write sender address %s [PERM]", thereply.rp_line)); (void) sprintf (replybuf, "501 %s\r\n", thereply.rp_line); netreply (replybuf); pprestart(); } else if (rp_gbval (thereply.rp_val) == RP_BTNO) { PP_LOG (LLOG_EXCEPTIONS, ("Can't write sender address %s [TEMP]", thereply.rp_line)); (void) sprintf (replybuf, "451 %s\r\n", thereply.rp_line); netreply (replybuf); pprestart(); } else netreply ("250 OK\r\n"); no_recip = 0; } /* The RCPT command ("RCPT TO:<forward-path>") */ static void rcpt() { RP_Buf thereply; register char *p; char replybuf [128]; ADDR *ap; /* -- parse destination arg -- */ if (hellod == 0) { PP_LOG (LLOG_EXCEPTIONS, ("Expecting a HELO command")); hellod ++; /* MH bug */ } if (sender == NULLCP) { PP_LOG (LLOG_EXCEPTIONS, ("RCPT but no MAIL")); netreply ("503 You must give a MAIL command first\r\n"); return; } else if (arg == NULLCP || !prefix ("to:", arg)) { PP_LOG (LLOG_EXCEPTIONS, ("No recipient named in RCPT")); netreply ("501 No recipient named.\r\n"); return; } p = index (arg, ':') + 1; p = adrfix (p); if (p == NULLCP || *p == NULL) { PP_LOG (LLOG_EXCEPTIONS, ("No recipient in RCPT")); netreply ("501 No recipient named.\r\n"); return; } PP_NOTICE (("Recipient Address '%s'", p)); ap = adr_new (p, AD_822_TYPE, no_recip + 1); (void) io_wadr (ap, AD_RECIPIENT, &thereply); adr_tfree (ap); if (thereply.rp_val == RP_BHST || rp_gbval (thereply.rp_val) == RP_BNO) { PP_LOG (LLOG_EXCEPTIONS, ("Problems writing address %s [PERM]", thereply.rp_line)); (void) sprintf (replybuf, "550 %s\r\n", thereply.rp_line); netreply (replybuf); } else if (rp_gbval (thereply.rp_val) == RP_BTNO) { PP_LOG (LLOG_EXCEPTIONS, ("Problems writing address %s [TEMP]", thereply.rp_line)); (void) sprintf (replybuf, "451 %s\r\n", thereply.rp_line); netreply (replybuf); } else { netreply ("250 Recipient OK.\r\n"); no_recip++; } } /*---------------------------------------------------------------------------- ADDRFIX() -- This function takes the SMTP "path" and removes the leading and trailing "<>"'s which would make the address illegal to RFC822 mailers. Note that although the specification states that the angle brackets are required, we will accept addresses without them. (DPK@BRL, 4 Jan 83) ----------------------------------------------------------------------------*/ static char *adrfix (addrp) char *addrp; { register char *cp; PP_TRACE (("adrfix %s", addrp)); if (cp = index (addrp, '<')) { addrp = ++cp; if (cp = rindex (addrp, '>')) *cp = 0; } compress (addrp, addrp); PP_TRACE (("adrfix(): '%s'", addrp)); return (addrp); } #ifdef notdef static int isblank (line) char *line; { for (cp = line; *cp; cp ++) switch (*cp) { case ' ': case 't': case '\r': break; case '\n': return 1; default: return 0; } return 1; } #endif /* The DATA command. Send text to Submit. */ static void data() { char tbuf[LINESIZE]; struct rp_bufstruct thereply; struct timeval data_time; register char *p, *bufptr; int errflg, werrflg, size = 0, doing_header = 1; errflg = 0; werrflg = 0; timer_start (&data_time); if (no_recip == 0) { PP_LOG (LLOG_EXCEPTIONS, ("No recipients for DATA")); netreply ("503 No recipients have been specified.\r\n"); return; } if (rp_isbad (io_adend(&thereply))) { PP_LOG (LLOG_EXCEPTIONS, ("Bad address end %s", thereply.rp_line)); netreply ("451 Unknown mail system trouble.\r\n"); return; } if (rp_isbad (io_tinit (&thereply)) || rp_isbad (io_tpart (hdr_822_bp, FALSE, &thereply))) { PP_LOG (LLOG_EXCEPTIONS, ("Bad text init %s", thereply.rp_line)); netreply ("451 Unknown text initialisation failure.\r\n"); return; } netreply ("354 Enter Mail, end by a line with only '.'\r\n"); dont_mung = 1; /* -- tell getline only to drop cr -- */ PP_TRACE (("body of message")); while (1) { /* -- forever -- */ if ((p = getline()) == 0) { p = "\n***Sender closed connection***\n"; errflg++; break; } if (p == (char *)NOTOK) { p = "\n***Error on net connection***\n"; if (!errflg++) PP_LOG (LLOG_EXCEPTIONS, ("netread error from host %s", realthem)); break; } /* -- are we done? -- */ if (buf [0] == '.') if (buf [1] == '\n') break; /* -- yep -- */ else bufptr = &buf [1]; /* -- skip leading . -- */ else bufptr = &buf [0]; /* -- If write err occurs, stop writing but keep reading -- */ if (!werrflg) { size += p-bufptr; if (doing_header && buf [0] == '\n') { /* do we need to go convert into body parts ?? */ doing_header = 0; if (rp_isbad (io_tdend (&thereply))) { PP_LOG (LLOG_EXCEPTIONS, ("io_tdend - %s", thereply.rp_line)); netreply ("451 Data input problem.\r\n"); return; } (void) sprintf (tbuf, "1.%s", ia5_bp); if (rp_isbad (io_tpart (tbuf, FALSE, &thereply))) { PP_LOG (LLOG_EXCEPTIONS, ("io_tpart - %s", thereply.rp_line)); netreply ("451 Body input failure.\r\n"); return; } } else if (rp_isbad (io_tdata (bufptr, (p-bufptr)))) { werrflg++; PP_LOG (LLOG_EXCEPTIONS, ("error from submit")); } } } if (doing_header) { (void) sprintf (tbuf, "1.%s", ia5_bp); if (rp_isbad (io_tdend (&thereply)) || rp_isbad (io_tpart (tbuf, FALSE, &thereply))) { netreply ("451 Data Input problem.\r\n"); return; } } dont_mung = 0; /* -- set getline to normal operation -- */ PP_TRACE (("Finished receiving text.")); timer_end (&data_time, size, "Data Received"); if (werrflg) { netreply ("451-Mail trouble (write error to mailsystem)\r\n"); netreply ("451 Please try again later.\r\n"); byebye (1); } if (errflg) byebye (1); if (rp_isbad (io_tdend (&thereply))) { PP_LOG (LLOG_EXCEPTIONS, ("io_tdend - %s", thereply.rp_line)); netreply ("451 Data termination problems.\r\n"); return; } (void) io_tend (&thereply); if (rp_isgood (rp_gval (thereply.rp_val))) { (void) sprintf (buf, "250 %s\r\n", thereply.rp_line); netreply (buf); } else if (rp_gbval (thereply.rp_val) == RP_BNO) { PP_LOG (LLOG_EXCEPTIONS, ("io_tend failed %s", thereply.rp_line)); (void) sprintf (buf, "554 %s\r\n", thereply.rp_line); netreply (buf); return; } else { PP_LOG (LLOG_EXCEPTIONS, ("io_tend failed %s", thereply.rp_line)); (void) sprintf (buf, "451 %s\r\n", thereply.rp_line); netreply (buf); return; } PP_NOTICE (("<<< Message received from %s (%d recipients, %d bytes)", realthem, no_recip, size)); sender = NULLCP; no_recip = 0; } /* The RSET command */ static void rset() { pprestart (); confirm(); } static void pprestart () { io_end (NOTOK); ppbegin (); } static void ppbegin () { RP_Buf reply; if (rp_isbad (io_init(&reply))) { PP_LOG (LLOG_EXCEPTIONS, ("can't reinitialize mail system [%s]", reply.rp_line)); netreply ("421 Server can't initialize mail system (PP)\r\n"); byebye (2); } sender = NULLCP; no_recip = 0; } static void ppstart() { RP_Buf reply; struct prm_vars prm; prm_init (&prm); if (rp_isbad (io_wprm (&prm, &reply))) { PP_LOG (LLOG_EXCEPTIONS, ("can't set parameters [%s]", reply.rp_line)); netreply ("421 Server can't initialize mail system (PP)\r\n"); byebye (2); } no_recip = 0; } /* The QUIT command */ static void quit() { time_t timenow; PP_NOTICE (("smtp server quit")); time (&timenow); (void) sprintf (buf, "221 %s says goodbye to %s at %.19s.\r\n", us, them, ctime (&timenow)); netreply (buf); byebye (0); } static void byebye (retval) int retval; { /* if (retval == OK) mm_sbend(); */ if (rp_isbad (retval)) PP_LOG (LLOG_EXCEPTIONS, ("Smtp server aborting")); io_end (retval == 0 ? OK : NOTOK); exit (retval); } /* Reply that the current command has been logged and noted */ static void confirm() { netreply ("250 OK\r\n"); } /* The help command gives a list of valid commands */ static void help() { register int i; register struct comarr *p; char replybuf [128]; netreply ("214-The following commands are accepted:\r\n214-"); for (p=commands, i=1; p->cmdname; p++, i++) { (void) sprintf (replybuf, "%s%s", p->cmdname, ((i%10) ? " " : "\r\n214-" )); netreply (replybuf); } (void) sprintf (replybuf, "\r\n214 Send complaints/bugs to: %s\r\n", postmaster); netreply (replybuf); } /* vrfy - attempt to verify user is OK */ static void vrfy () { RP_Buf rp; ADDR *adr; char buffer[BUFSIZ]; if (hellod == 0) { PP_LOG (LLOG_EXCEPTIONS, ("Expecting a HELO command")); hellod ++; /* MH bug */ } if (arg == NULLCP || *arg == 0) { PP_LOG (LLOG_EXCEPTIONS, ("No argument to VRFY command")); netreply ("501 No argument supplied\r\n"); return; } adr = adr_new (arg, AD_822_TYPE, 0); if (rp_isbad (ad_parse (adr, &rp, CH_USA_PREF))) { PP_LOG (LLOG_EXCEPTIONS, ("Failed to VRFY '%s' [%s]", arg, rp.rp_line)); (void) sprintf (buffer, "550 User unknown [%s]\r\n", rp.rp_line); netreply (buffer); } else { (void) sprintf (buffer, "250 %s\r\n", adr -> ad_type == AD_822_TYPE ? adr -> ad_r822adr : adr -> ad_r400adr); netreply (buffer); } adr_free (adr); } static void expn () { dl *list; Name *np; struct stat statbuf; char buffer[BUFSIZ]; if (hellod == 0) { PP_LOG (LLOG_EXCEPTIONS, ("Expecting a HELO command")); hellod ++; /* MH bug */ } if (arg == NULLCP || *arg == 0) { PP_LOG (LLOG_EXCEPTIONS, ("No argument to VRFY command")); netreply ("501 No argument supplied\r\n"); return; } switch (tb_getdl (arg, &list, OK)) { case DONE: PP_NOTICE (("No such list %s", arg)); netreply ("550 No such list\r\n"); return; case NOTOK: PP_LOG (LLOG_EXCEPTIONS, ("Error locating list %s", arg)); netreply ("550 List Error\r\n"); return; } if (list -> dl_file == NULLCP || stat (list -> dl_file, &statbuf) == NOTOK || (statbuf.st_mode & (~S_IFMT)) == SECRMODE) { netreply ("550 Access Denied to you\r\n"); dl_free (list); return; } for (np = list -> dl_list; np; np = np -> next) { (void) sprintf (buffer, "250%c%s\r\n", np -> next == NULL ? ' ' : '-', np -> name); netreply (buffer); } dl_free (list); } /* Send appropriate ascii responses over the network connection. */ static void netreply (str) char *str; { PP_LOG (LLOG_PDUS, ("-> %s", str)); if (timeout (NTIMEOUT)) byebye (1); if (write (1, str, strlen (str)) < 0) { timeout (0); PP_SLOG (LLOG_EXCEPTIONS, "write", ("(netreply) in writing [%s]", str)); byebye (1); } timeout (0); PP_TRACE (("%s", str)); } static char *official (name) char *name; { struct hostent *hp; int i; for(i = 0 ; i < 10 ; i++){ hp = gethostbyname(name); #ifdef NAMESERVER if(hp != NULL) #endif break; PP_TRACE (("Timeout looking up %s", name)); if(i > 2) sleep(i*2); } return hp == NULL ? NULLCP : strdup (hp -> h_name); }