⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httcp.c

📁 用于linux和其他unix下面的
💻 C
📖 第 1 页 / 共 4 页
字号:
    data->h.h_addrtype = phost->h_addrtype;    data->h.h_length = phost->h_length;    p_next_charptr = (char **)(rehostent + curlen);    p_next_char = rehostent + curlen;    if (phost->h_addr_list)	p_next_char += (num_addrs+1) * sizeof(phost->h_addr_list[0]);    if (phost->h_aliases)	p_next_char += (num_aliases+1) * sizeof(phost->h_aliases[0]);    if (phost->h_addr_list) {	data->h.h_addr_list = p_next_charptr;	for (pcnt=phost->h_addr_list, i_addr = 0;	     i_addr < num_addrs;	     pcnt++, i_addr++) {	    memcpy(p_next_char, *pcnt, sizeof(phost->h_addr_list[0]));	    *p_next_charptr++ = p_next_char;	    p_next_char += sizeof(phost->h_addr_list[0]);	}	*p_next_charptr++ = NULL;    } else {	data->h.h_addr_list = NULL;    }    if (phost->h_name) {	data->h.h_name = p_next_char;	if (name_len) {	    strcpy(p_next_char, phost->h_name);	    p_next_char += name_len + 1;	} else {	    *p_next_char++ = '\0';	}    } else {	data->h.h_name = NULL;    }    if (phost->h_aliases) {	data->h.h_aliases = p_next_charptr;	for (pcnt=phost->h_aliases, i_alias = 0;	     (*pcnt && i_alias < num_addrs);	     pcnt++, i_alias++) {	    mem_this_alias = strlen(*pcnt) + 1;	    required_this_alias = sizeof(phost->h_aliases[0]) +		mem_this_alias;	    if (available >= required_this_alias) {		i_alias++;		available -= required_this_alias;		strcpy(p_next_char, *pcnt);		*p_next_charptr++ = p_next_char;		p_next_char += mem_this_alias;	    }	    p_next_char += sizeof(phost->h_aliases[0]);	}	*p_next_charptr++ = NULL;    } else {	data->h.h_aliases = NULL;    }    curlen = p_next_char - (char *)rehostent;    return curlen;}#endif /* NSL_FORK */#ifndef HAVE_H_ERRNO#undef  h_errno#define h_errno my_errnostatic int my_errno;#else /* we do HAVE_H_ERRNO: */#ifndef h_errno		/* there may be a macro as well as the extern data */extern int h_errno;#endif#endif/*	Resolve an internet hostname, like gethostbyname**	------------------------------------------------****  On entry,**	str	points to the given host name, not numeric address,**		without colon or port number.****  On exit,**	returns a pointer to a struct hostent in static storage,**	or NULL in case of error or user interruption.****  The interface is intended to be exactly the same as for (Unix)**  gethostbyname(), except for the following:****  If NSL_FORK is not used, the result of gethostbyname is returned**  directly.  Otherwise:**  All lists, addresses, and strings referred to by pointers in the**  returned struct are located, together with the returned struct**  itself, in a buffer of size REHOSTENT_SIZE.  If not everything fits,**  some info is omitted, but the function is careful to still return**  a valid structure, without truncating strings; it tries to return,**  in order of decreasing priority, the first address (h_addr), the**  official name (h_name), the additional addresses, then alias names.****  If NULL is returned, the reason is made available in the global**  variable lynx_nsl_status, with one of the following values:**	HT_INTERRUPTED		Interrupted by user**	HT_NOT_ACCEPTABLE	Hostname detected as invalid**				(also sets h_errno)**	HT_H_ERRNO_VALID	An error occurred, and h_errno holds**				an appropriate value**	HT_ERROR		Resolver error, reason not known**	HT_INTERNAL		Internal error*/PUBLIC struct hostent * LYGetHostByName ARGS1(	char *,	str){#ifndef _WINDOWS_NSL    char *host = str;#endif#ifdef NSL_FORK    /* for transfer of result between from child to parent: */    static AlignedHOSTENT aligned_full_rehostent;    /*     * We could define rehosten directly as a     * static char rehostent[REHOSTENT_SIZE],     * but the indirect approach via the above struct     * should automatically take care of alignment requirements.     * Note that, in addition,     *  - this must be static, as we shall return a pointer to it     *    which must remain valid, and     *  - we have to use the same rehostent in the child process as     *    in the parent (its address in the parent's address space     *    must be the same as in the child's, otherwise the internal     *    pointers built by the child's call to fill_rehostent would     *    be invalid when seen by the parent). - kw     */    char *rehostent = (char *)&aligned_full_rehostent;    /* for transfer of status from child to parent: */    struct _statuses {	size_t rehostentlen;	int h_length;	int child_errno;  /* sometimes useful to pass this on */	int child_h_errno;	BOOL h_errno_valid;    } statuses;    size_t rehostentlen = 0;#endif /* NSL_FORK */    struct hostent *result_phost = NULL;    if (!str) {	CTRACE((tfp, "LYGetHostByName: Can't parse `NULL'.\n"));	lynx_nsl_status = HT_INTERNAL;	return NULL;    }    CTRACE((tfp, "LYGetHostByName: parsing `%s'.\n", str));	/*  Could disable this if all our callers already check - kw */    if (HTCheckForInterrupt()) {	CTRACE((tfp, "LYGetHostByName: INTERRUPTED for '%s'.\n", str));	lynx_nsl_status = HT_INTERRUPTED;	return NULL;    }#ifdef _WINDOWS_NSL    strncpy(host, str, sizeof(host));#endif /*  _WINDOWS_NSL */    if (!valid_hostname(host)) {	lynx_nsl_status = HT_NOT_ACCEPTABLE;#ifdef NO_RECOVERY#ifdef _WINDOWS	WSASetLastError(NO_RECOVERY);#else	h_errno = NO_RECOVERY;#endif#endif	return NULL;    }#ifdef MVS	/* Outstanding problem with crash in MVS gethostbyname */    CTRACE((tfp, "LYGetHostByName: Calling gethostbyname(%s)\n", host));#endif /* MVS */    CTRACE_FLUSH(tfp);  /* so child messages will not mess up parent log */    lynx_nsl_status = HT_INTERNAL;	/* should be set to something else below */#ifdef NSL_FORK    statuses.h_errno_valid = NO;	/*	**  Start block for fork-based gethostbyname() with	**  checks for interrupts. - Tom Zerucha (tz@execpc.com) & FM	*/    {	int got_rehostent = 0;#if HAVE_SIGACTION	sigset_t old_sigset;	sigset_t new_sigset;#endif	/*	**	Pipe, child pid, status buffers, start time, select()	**	control variables.	*/	pid_t fpid, waitret;	int pfd[2], selret, readret;#ifdef HAVE_TYPE_UNIONWAIT	union wait waitstat;#else	int waitstat = 0;#endif	time_t start_time = time((time_t *)0);	fd_set readfds;	struct timeval one_second;	long dns_patience = 30; /* how many seconds will we wait for DNS? */	int child_exited = 0;	    /*	    **  Reap any children that have terminated since last time	    **  through.  This might include children that we killed,	    **  then waited with WNOHANG before they were actually ready	    **  to be reaped.  (Should be max of 1 in this state, but	    **  the loop is safe if waitpid() is implemented correctly:	    **  returns 0 when children exist but none have exited; -1	    **  with errno == ECHILD when no children.)  -BL	    */	do {	    waitret = waitpid(-1, 0, WNOHANG);	} while (waitret > 0 || (waitret == -1 && errno == EINTR));	waitret = 0;	pipe(pfd);#if HAVE_SIGACTION	/*	 *  Attempt to prevent a rare situation where the child	 *  could execute the Lynx signal handlers because it gets	 *  killed before it even has a chance to reset its handlers,	 *  resulting in bogus 'Exiting via interrupt' message and	 *  screen corruption or worse.	 *  Should that continue to be reported, for systems without	 *  sigprocmask(), we need to find a different solutions for	 *  those. - kw 19990430	 */	sigemptyset(&new_sigset);	sigaddset(&new_sigset, SIGTERM);	sigaddset(&new_sigset, SIGINT);#ifndef NOSIGHUP	sigaddset(&new_sigset, SIGHUP);#endif /* NOSIGHUP */#ifdef SIGTSTP	sigaddset(&new_sigset, SIGTSTP);#endif /* SIGTSTP */#ifdef SIGWINCH	sigaddset(&new_sigset, SIGWINCH);#endif /* SIGWINCH */	sigprocmask(SIG_BLOCK, &new_sigset, &old_sigset);#endif /* HAVE_SIGACTION */	if ((fpid = fork()) == 0 ) {	    struct hostent  *phost;	/* Pointer to host - See netdb.h */	    /*	    **  Child - for the long call.	    **	    **  Make sure parent can kill us at will.  -BL	    */	    (void) signal(SIGTERM, quench);	    /*	    **  Also make sure the child does not run one of the	    **  signal handlers that may have been installed by	    **  Lynx if one of those signals occurs.  For example	    **  we don't want the child to remove temp files on	    **  ^C, let the parent deal with that. - kw	    */	    (void) signal(SIGINT, quench);#ifndef NOSIGHUP	    (void) signal(SIGHUP, quench);#endif /* NOSIGHUP */#ifdef SIGTSTP	    if (no_suspend)		(void) signal(SIGTSTP, SIG_IGN);	    else		(void) signal(SIGTSTP, SIG_DFL);#endif /* SIGTSTP */#ifdef SIGWINCH	    (void) signal(SIGWINCH, SIG_IGN);#endif /* SIGWINCH */#ifndef __linux__#ifndef DOSPATH	    signal(SIGBUS, SIG_DFL);#endif /* DOSPATH */#endif /* !__linux__ */	    signal(SIGSEGV, SIG_DFL);	    signal(SIGILL, SIG_DFL);#if HAVE_SIGACTION	    /* Restore signal mask to whatever it was before the fork. -kw */	    sigprocmask(SIG_SETMASK, &old_sigset, NULL);#endif /* HAVE_SIGACTION */	    /*	    **  Child won't use read side.  -BL	    */	    close(pfd[0]);#ifdef HAVE_H_ERRNO	    /* to detect cases when it doesn't get set although it should */	    h_errno = -2;#endif	    set_errno(0);	    phost = gethostbyname(host);	    statuses.child_errno = errno;	    statuses.child_h_errno = h_errno;#ifdef HAVE_H_ERRNO	    statuses.h_errno_valid = YES;#endif#ifdef MVS	    CTRACE((tfp, "LYGetHostByName: gethostbyname() returned %d\n", phost));#endif /* MVS */#ifdef DEBUG_HOSTENT_CHILD	    dump_hostent("CHILD gethostbyname", phost);#endif	    if (OK_HOST(phost)) {		rehostentlen = fill_rehostent(rehostent, REHOSTENT_SIZE, phost);#ifdef DEBUG_HOSTENT_CHILD		dump_hostent("CHILD fill_rehostent", (struct hostent *)rehostent);#endif	    }	    if (rehostentlen <= sizeof(struct hostent) ||		!OK_HOST((struct hostent *)rehostent)) {		rehostentlen = 0;		statuses.h_length = 0;	    } else {		statuses.h_length = ((struct hostent *)rehostent)->h_length;#ifdef HAVE_H_ERRNO		if (h_errno == -2) /* success, but h_errno unchanged? */		    statuses.h_errno_valid = NO;#endif	    }	    /*	    **  Send variables indicating status of lookup to parent.	    **  That includes rehostentlen, which the parent will use	    **  as the size for the second read (if > 0).	    */	    if (!statuses.child_errno)	    statuses.child_errno = errno;	    statuses.rehostentlen = rehostentlen;	    write(pfd[1], &statuses, sizeof(statuses));	    if (rehostentlen) {		/*		**  Return our resulting rehostent through pipe...		*/		write(pfd[1], rehostent, rehostentlen);		_exit(0);	    } else {		/*		**  ... or return error as exit code.		*/		_exit(1);	    }	}#if HAVE_SIGACTION	/*	**  (parent) Restore signal mask to whatever it was	**  before the fork. - kw	*/	sigprocmask(SIG_SETMASK, &old_sigset, NULL);#endif /* HAVE_SIGACTION */	/*	**	(parent) Wait until lookup finishes, or interrupt,	**	or cycled too many times (just in case) -BL	*/	close(pfd[1]);      /* parent won't use write side -BL */	if (fpid < 0) {     /* fork failed */		close(pfd[0]);		goto failed;	}	while (child_exited || (long)(time((time_t *)0) - start_time) < dns_patience) {	    FD_ZERO(&readfds);	    /*	    **  This allows us to abort immediately, not after 1-second	    **  timeout, when user hits abort key.  Can't do this when	    **  using SLANG (or at least I don't know how), so SLANG	    **  users must live with up-to-1s timeout.  -BL	    **	    **  Whoops -- we need to make sure stdin is actually	    **  selectable!  /dev/null isn't, on some systems, which	    **  makes some useful Lynx invocations fail.  -BL	    */	    {		int kbd_fd = LYConsoleInputFD(TRUE);		if (kbd_fd != INVSOC) {		    FD_SET(kbd_fd, &readfds);		}	    }	    one_second.tv_sec = 1;	    one_second.tv_usec = 0;	    FD_SET(pfd[0], &readfds);		/*		**  Return when data received, interrupted, or failed.		**  If nothing is waiting, we sleep for 1 second in		**  select(), to be nice to the system.  -BL		*/#ifdef SOCKS	    if (socks_flag)		selret = Rselect(pfd[0] + 1, (void *)&readfds, NULL, NULL, &one_second);	    else#endif /* SOCKS */		selret = select(pfd[0] + 1, (void *)&readfds, NULL, NULL, &one_second);	    if ((selret > 0) && FD_ISSET(pfd[0], &readfds)) {		/*		**	First get status, including length of address.  -BL, kw		*/		readret = read(pfd[0], &statuses, sizeof(statuses));		if (readret == sizeof(statuses)) {		    h_errno = statuses.child_h_errno;		    set_errno(statuses.child_errno);#ifdef HAVE_H_ERRNO		    if (statuses.h_errno_valid) {			lynx_nsl_status = HT_H_ERRNO_VALID;			/*			 *  If something went wrong in the child process			 *  other than normal lookup errors, and it appears			 *  that we have enough info to know what went wrong,			 *  generate diagnostic output.			 *  ENOMEM observed on linux in processes constrained			 *  with ulimit.  It would be too unkind to abort			 *  the session, access to local files or through a			 *  proxy may still work. - kw			 */			if (#ifdef NETDB_INTERNAL		/* linux glibc: defined in netdb.h */			    (errno && h_errno == NETDB_INTERNAL) ||#endif			    (errno == ENOMEM &&			     statuses.rehostentlen == 0 &&			     /* should probably be NETDB_INTERNAL if child				memory exhausted, but we may find that				h_errno remains unchanged. - kw */			     h_errno == -2)) {#ifndef MULTINET			    HTInetStatus("CHILD gethostbyname");#endif			    HTAlert(LYStrerror(statuses.child_errno));			    if (errno == ENOMEM) {				/*				 *  Not much point in continuing, right?				 *  Fake a 'z', should shorten pointless				 *  guessing cycle. - kw				 */				LYFakeZap(YES);			    }			}		    }#endif /* HAVE_H_ERRNO */		    if (statuses.rehostentlen > sizeof(struct hostent)) {			/*			**  Then get the full reorganized hostent.  -BL, kw			*/			readret = read(pfd[0], rehostent, statuses.rehostentlen);#ifdef DEBUG_HOSTENT			dump_hostent("Read from pipe", (struct hostent *)rehostent);#endif			if (readret == (int) statuses.rehostentlen) {			    got_rehostent = 1;			    result_phost = (struct hostent *)rehostent;			    lynx_nsl_status = HT_OK;			} else if (!statuses.h_errno_valid) {			    lynx_nsl_status = HT_INTERNAL;			}		    }		} else {		    lynx_nsl_status = HT_ERROR;		}		/*		**  Make sure child is cleaned up.  -BL		*/		if (!child_exited)		    waitret = waitpid(fpid, &waitstat, WNOHANG);		if (!WIFEXITED(waitstat) && !WIFSIGNALED(waitstat)) {		    kill(fpid, SIGTERM);		    waitret = waitpid(fpid, &waitstat, WNOHANG);		}		break;	    }	    /*	    **  Clean up if child exited before & no data received.  -BL	    */	    if (child_exited) {		waitret = waitpid(fpid, &waitstat, WNOHANG);		break;	    }	    /*	    **  If child exited, loop once more looking for data.  -BL	    */	    if ((waitret = waitpid(fpid, &waitstat, WNOHANG)) > 0) {		/*		**	Data will be arriving right now, so make sure we		**	don't short-circuit out for too many loops, and		**	skip the interrupt check.  -BL		*/		child_exited = 1;		continue;	    }	    /*	    **  Abort if interrupt key pressed.	    */	    if (HTCheckForInterrupt()) {		CTRACE((tfp, "LYGetHostByName: INTERRUPTED gethostbyname.\n"));		kill(fpid, SIGTERM);		waitpid(fpid, NULL, WNOHANG);		close(pfd[0]);		lynx_nsl_status = HT_INTERRUPTED;		return NULL;	    }	}	close(pfd[0]);	if (waitret <= 0) {	    kill(fpid, SIGTERM);	    waitret = waitpid(fpid, &waitstat, WNOHANG);	}	if (waitret > 0) {	    if (WIFEXITED(waitstat)) {		CTRACE((tfp, "LYGetHostByName: NSL_FORK child %d exited, status 0x%x.\n",

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -