home *** CD-ROM | disk | FTP | other *** search
- /*
- * smtp -- client, send mail to remote smtp server
- * Set up for 4.2BSD networking system.
- * Adapted for System V by jv@mh.nl.
- * TODO:
- * better mapping of error numbers.
- * allow multiple recipients (maybe)
- * send stuff from cmds.h instead of hard-coded here
- */
-
- #define USAGE "usage: %s [-h helohost] targethost sender recipient\n"
-
- #include "smtp.h"
- #include <sys/uio.h> /* needed for socket.h */
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
-
-
- #ifndef SERVNAME
- #define SERVNAME "smtp" /* service we wanna talk to */
- #endif
-
- char *progname;
- int debug = 0;
- extern char hostname[];
- extern char hostdomain[];
- char *sendhost = hostdomain;
- FILE *sfi, *sfo;
- char *host = "None";
- char *strcat(), *strcpy();
- static char *makedomain();
-
- #ifdef HOOTING
- extern int hooting; /* in netio */
- #endif
-
- /*
- * main - parse arguments and handle options
- */
- main(argc, argv)
- int argc;
- char *argv[];
- {
- register int c;
- int errflg = 0;
- extern int optind;
- extern char *optarg;
- char *sender, *recip;
-
- progname = argv[0];
- getmynames ();
-
- while ((c = getopt(argc, argv, "dh:")) != EOF)
- switch (c) {
- case 'd':
- ++debug;
- break;
- case 'h': /* alternate sending host */
- sendhost = optarg;
- break;
- case '?':
- default:
- errflg++;
- break;
- }
- if (errflg || (argc - optind) < 3) {
- (void) fprintf(stderr, USAGE, progname);
- bomb(E_USAGE);
- }
- host = argv[optind++];
- sender = makedomain(argv[optind++], sendhost);
- recip = makedomain(argv[optind++], host);
-
- setup(); /* open connection */
-
-
- #ifdef HOOTING
- hooting = 1;
- #endif
- /* hold the conversation */
-
- converse(sender, recip, sfi, sfo, stdin);
- (void) sleep(5); /* drain? */
-
- if (sfo!=NULL)
- (void) fclose(sfo);
- if (sfi!=NULL)
- (void) fclose(sfi);
-
- return 0;
- }
-
- /*
- * setup -- setup tcp/ip connection to/from server
- */
- setup()
- {
- struct hostent *hp;
- struct servent *sp;
- struct sockaddr_in sin;
- int s;
- extern int errno;
-
- (void) bzero((char *)&sin, sizeof(sin));
-
- if ((hp = gethostbyname(host)) == (struct hostent *) NULL) {
- (void) fprintf(stderr, "unknown host (%s).\n", host);
- bomb(E_NOHOST);
- }
-
- (void) bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
-
- if ((sp = getservbyname (SERVNAME, "tcp")) == NULL) {
- (void)fprintf(stderr,"unknown service TCP/%s\n", SERVNAME);
- bomb(E_OSFILE);
- }
- sin.sin_port = sp->s_port;
- sin.sin_family = hp->h_addrtype;
-
- if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("setup - socket");
- bomb(E_CANTOPEN);
- }
-
- if (connect(s, (struct sockaddr *) &sin, sizeof (sin)) < 0) {
- perror("setup - connect");
- /*
- * check for conditions that (we think) are temporary;
- * try them later; bomb utterly on all others.
- */
- if (errno == ETIMEDOUT || errno == ECONNREFUSED ||
- errno == EHOSTDOWN || errno == EHOSTUNREACH)
- bomb(E_TEMPFAIL);
- else
- bomb(E_CANTOPEN);
- }
-
- if (((sfi = fdopen(s, "r")) == (FILE *) NULL) ||
- ((sfo = fdopen(s, "w")) == (FILE *) NULL)) {
- perror("setup - fdopen");
- bomb(E_CANTOPEN);
- }
- /* setbuf(sfi, (char *) 0);*/
- }
-
- /*
- * bomb(code) - exit program, map smtp error code into mailsystem code
- * Codes with E_ are defined in miscerrs.h.
- * Codes with EX_ are from <sysexits.h>
- * Lines with FOO are placeholders until we decrypt more appropriate codes.
- */
- bomb(code)
- int code;
- {
- if (sfi != NULL)
- (void) fclose(sfi);
- if (sfo != NULL)
- (void) fclose(sfo);
-
- #ifdef EX_OK
- switch(code) {
- case 451: /* host not responding */
- code = EX_UNAVAILABLE; /* service unavailable */
- break;
- case 550:
- code = EX_NOUSER; /* addressee unknown */
- break;
- case 501: /* syntax error in address */
- case 554: /* */
- code = EX_DATAERR; /* data format error */
- break;
- case E_IOERR:
- code = EX_IOERR; /* input/output error */
- break;
- case E_NOHOST:
- code = EX_NOHOST; /* host name unknown */
- break;
- case E_OSFILE: /* no "smtp" -> /etc/services f'd */
- code = EX_OSFILE; /* critical OS file missing */
- break;
- case E_USAGE:
- code = EX_USAGE; /* command line usage error */
- break;
- case E_TEMPFAIL:
- code = EX_TEMPFAIL; /* temp failure; user can retry */
- break;
- #if 0
- case FOO:
- code = EX_OSERR; /* system error (e.g., can't fork) */
- break;
- case FOO:
- code = EX_NOINPUT; /* cannot open input */
- break;
- case FOO:
- code = EX_CANTCREAT; /* can't create (user) output file */
- break;
- case FOO:
- code = EX_PROTOCOL; /* remote error in protocol */
- break;
- case FOO:
- code = EX_NOPERM; /* permission denied */
- break;
- #endif /* NOTDEF */
- default: /* can't happen? */
- code = EX_SOFTWARE; /* internal software error */
- break;
- }
-
- #else /* has no sysexits */
- code = 1;
- #endif
-
- (void) exit (code);
- }
-
- static char *
- makedomain(addr, domain)
- char *addr, *domain;
- {
- char *rval;
- extern char *index(), *malloc();
-
- if (index(addr, '@') != 0)
- return addr;
-
- if ((rval = malloc(strlen(addr) + strlen(domain) + 2)) == 0)
- #ifdef EX_SOFTWARE
- bomb(EX_SOFTWARE); /* can't happen! */
- #else
- bomb (3);
- #endif
- sprintf(rval, "%s@%s", addr, domain);
- return rval;
- }
-