📄 daemon.c
字号:
** port -- the port number to connect to.** outfile -- a pointer to a place to put the outfile** descriptor.** infile -- ditto for infile.**** Returns:** An exit code telling whether the connection could be** made and if not why not.**** Side Effects:** On an error, global <errno> is set describing the error.** A previously existing connection will be reused.** Previously cached data will be used to find the host** and determine its status. This cache is updated** with the host's current status.*/makeconnection(host, port, outfile, infile) char *host; u_short port; FILE **outfile; FILE **infile;{ register struct hostinfo *hp; extern char *inet_ntoa(); int s; struct sockaddr_in addr; /* Remember who we're talking to, for error messages */ RealHostName = newstr(host); /* ** Determine the address of the host. ** If we have tried to connect before and failed, don't try, ** Unless this is the last attempt. */ setproctitle("%s To %s", CurEnv->e_id, RealHostName); AlreadyKnown = FALSE; hp = lookuphost(host); errno = 0; if (!hp->h_exists) return (EX_NOHOST); if (hp->h_down && (curtime() < CurEnv->e_ctime + TimeOut)) { errno = hp->h_errno; /* for a better message */ return (EX_TEMPFAIL); } addr.sin_family = AF_INET; addr.sin_addr = hp->h_addrlist[hp->h_index]; /* ** Determine the port number. */ if (port != 0) addr.sin_port = htons(port); else addr.sin_port = htons(IPPORT_SMTP); if (!hp->h_open || hp->h_port != port) { s = openhost(hp, addr); if (s != EX_OK) return s; } *outfile = fdopen(hp->h_fd, "w"); *infile = fdopen(dup(hp->h_fd), "r"); return (EX_OK);}intopenhost(hp, addr) struct hostinfo *hp; struct sockaddr_in addr;{ register int s; int error_code; int on = 1; /* ** Try to actually open the connection. */# ifdef DEBUG if (tTd(16, 1)) printf("openhost (%x)\n", hp->h_addrlist[hp->h_index].s_addr);# endif DEBUG if (hp->h_addrlist[hp->h_index].s_addr == INADDR_ANY) /* * restart the address list search if we hit the end, * otherwise use the last one that worked. */ hp->h_index = 0; for ( ;*(int *)&(hp->h_addrlist[hp->h_index]);hp->h_index++) { addr.sin_addr = hp->h_addrlist[hp->h_index]; s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { error_code = errno; /* Save errno for <failure> */ syserr("makeconnection: no socket"); errno = error_code; /* Save errno for <failure> */ goto failure; }# ifdef DEBUG if (tTd(16, 1)) printf("makeconnection: %d\n", s); /* turn on network debugging? */ if (tTd(16, 14)) { int on = 1; (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); }# endif DEBUG if (Verbose) { printf("Trying %s... ", inet_ntoa(addr.sin_addr) ); fflush(stdout); } (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, on, sizeof(on)); if (CurEnv->e_xfp) (void) fflush(CurEnv->e_xfp); errno = 0; /* for debugging */ hp->h_tried = 1; /* We are trying to connect */ if (connect(s, &addr, sizeof addr) < 0) { /* failure, decide if temporary or not */ failure: error_code = errno; (void) close(s); /* Free the socket */ if (Verbose) printf("%s\r\n", errstring(error_code) ); errno = error_code; switch (errno) { case ETIMEDOUT: errno = EHOSTDOWN; /* for a better message */ case EISCONN: case EINPROGRESS: case EALREADY: case EADDRINUSE: case EHOSTDOWN: case ENETDOWN: case ENETRESET: case ENOBUFS: case ECONNREFUSED: case ECONNRESET: case EHOSTUNREACH: case ENETUNREACH: case EPERM: /* there are others, I'm sure..... */ continue; default: return (EX_UNAVAILABLE); } } if (Verbose) printf(" connected.\r\n"); /* connection ok, put it into canonical form */ host_from_fd[s] = hp; /* Create cross reference pointer */ hp->h_port = addr.sin_port; hp->h_fd = s; /* Save file descriptor */ hp->h_open = 1; /* And indicate that it's open */ return (EX_OK); } hp->h_down = 1; /* Mark down host */ hp->h_errno = errno; /* ** Note that the down flag is never turned off. ** We depend on sendmail's exiting to throw away ** this information. It should apply to one ** queue run only. */ return (EX_TEMPFAIL);}/*** CLOSECONNECTION -- mark an open connection as closed.**** Parameters:** fd -- the file descriptor of the connection.**** Returns:** none.**** Side Effects:** Marks the host (which had a connection opened via** makeconnection()) as not having a current connection.** Note that this does not actually close the file** descriptor. That's the caller's responsibility.** Also frees the memory allocated by RealHostName in the** "newstr()" call above; otherwise queue runners are swap hogs.*/closeconnection(fd) int fd;{ register struct hostinfo *hp; if (fd < NOFILE) { hp = host_from_fd[fd]; if (hp != NULL && hp->h_open) { hp->h_open = 0; } host_from_fd[fd] = NULL; if (RealHostName && RealHostName[0] != '\0') { free(RealHostName); RealHostName = ""; } }}/*** MYHOSTNAME -- return the name of this host.**** Parameters:** hostbuf -- a place to return the name of this host.** size -- the size of hostbuf.**** Returns:** A list of aliases for this host.**** Side Effects:** none.*/char **myhostname(hostbuf, size) char hostbuf[]; int size;{ extern struct hostent *gethostbyname(); struct hostent *hp; static char *nicknames[MAXATOM]; register char **avp, *thisname; int s, n; struct ifconf ifc; struct ifreq *ifr; char interfacebuf[1024]; if (gethostname(hostbuf, size) < 0) { (void) strcpy(hostbuf, "localhost"); } hp = gethostbyname(hostbuf); if (hp == NULL) return (NULL); (void) strncpy(hostbuf, hp->h_name, size-1); for (avp=nicknames;*hp->h_aliases;) *avp++ = *hp->h_aliases++; *avp = NULL; s = socket(AF_INET, SOCK_DGRAM, 0); if (s == -1) return (nicknames); ifc.ifc_len = sizeof(interfacebuf); ifc.ifc_buf = interfacebuf; if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) return (nicknames); ifr = ifc.ifc_req; for (n = ifc.ifc_len/sizeof (struct ifreq); n > 0; n--, ifr++) { char thisbuf[256]; if (ifr->ifr_addr.sa_family != AF_INET) continue; (void) sprintf(thisbuf, "[%s]", inet_ntoa( ((struct sockaddr_in *)(&ifr->ifr_addr))->sin_addr)); thisname = newstr(thisbuf); *avp++ = thisname; } *avp = NULL; return (nicknames);}/* * MAPHOSTNAME -- turn a hostname into canonical form * * Parameters: * hbuf -- a buffer containing a hostname. * hbsize -- the size of hbuf. * * Returns: * none. * * Side Effects: * Looks up the host specified in hbuf. If it is not * the canonical name for that host, replace it with * the canonical name. If the name is unknown, or it * is already the canonical name, leave it unchanged. */maphostname(hbuf, hbsize) char *hbuf; int hbsize;{ register struct hostent *hp; extern struct hostent *gethostbyname(); EVENT *ev; /* * If first character is a bracket, then it is an address * lookup. Address is copied into a temporary buffer to * strip the brackets and to preserve hbuf if address is * unknown. */ if (*hbuf == '[') { extern struct hostent *gethostbyaddr(); u_long in_addr; char ptr[256]; char *bptr; (void) strcpy(ptr, hbuf); bptr = index(ptr,']'); *bptr = '\0'; in_addr = inet_addr(&ptr[1]); if (setjmp(NameTimeout) != 0) { hp = NULL; } else { ev = setevent(nametime, nametimeout, 0); hp = gethostbyaddr((char *) &in_addr, sizeof(struct in_addr), AF_INET); clrevent(ev); } } else { makelower(hbuf);#ifdef MXDOMAIN getcanonname(hbuf, hbsize); return;#else MXDOMAIN /* determine host name with timeout */ if (setjmp(NameTimeout) != 0) { hp = NULL; } else { ev = setevent(nametime, nametimeout, 0); hp = gethostbyname(hbuf); clrevent(ev); }#endif } if (hp != NULL) { int i = strlen(hp->h_name); if (i >= hbsize) hp->h_name[hbsize - 1] = '\0'; (void) strcpy(hbuf, hp->h_name); }}# else DAEMON/* code for systems without sophisticated networking *//* * MYHOSTNAME -- stub version for case of no daemon code. * * Can't convert to upper case here because might be a UUCP name. * * Mark, you can change this to be anything you want...... */char **myhostname(hostbuf, size) char hostbuf[]; int size;{ register FILE *f; hostbuf[0] = '\0'; f = fopen("/usr/include/whoami", "r"); if (f != NULL) { (void) fgets(hostbuf, size, f); fixcrlf(hostbuf, TRUE); (void) fclose(f); } return (NULL);}/* * MAPHOSTNAME -- turn a hostname into canonical form * * Parameters: * hbuf -- a buffer containing a hostname. * hbsize -- the size of hbuf. * * Returns: * none. * * Side Effects: * Looks up the host specified in hbuf. If it is not * the canonical name for that host, replace it with * the canonical name. If the name is unknown, or it * is already the canonical name, leave it unchanged. *//*ARGSUSED*/maphostname(hbuf, hbsize) char *hbuf; int hbsize;{ return;}#endif DAEMON
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -