コード例 #1
0
ファイル: io.c プロジェクト: baruch/joes-sandbox
Port *privconnect(char *name,int port)
  {
  struct hostent *h=gethostbyname(name);
  struct sockaddr_in addr;
  int rsvd=IPPORT_RESERVED-1;
  int fd;
  if(!h) return 0;
  printf("Trying %s (%d.%d.%d.%d)...\n",h->h_name,
   ((unsigned char *)h->h_addr)[0],
   ((unsigned char *)h->h_addr)[1],
   ((unsigned char *)h->h_addr)[2],
   ((unsigned char *)h->h_addr)[3]);
  memset(&addr,0,sizeof(addr));
  addr.sin_family=h->h_addrtype;
  addr.sin_port=htons(port);
  memcpy(&addr.sin_addr.s_addr,h->h_addr,h->h_length);
  /* Privilidged version of socket().  Can this be done with bind() instead? */
  for(rsvd=IPPORT_RESERVED-1;rsvd && (fd=rresvport(&rsvd))!=-1;--rsvd);
  if(connect(fd,(struct sockaddr *)&addr,sizeof(addr)))
    {
    close(fd);
    return 0;
    }
  return new Port(fd);
  }
コード例 #2
0
ファイル: spamd-setup.c プロジェクト: SylvestreG/bitrig
int
configure_spamd(u_short dport, char *name, char *message,
    struct cidr *blacklists)
{
	int lport = IPPORT_RESERVED - 1, s;
	struct sockaddr_in sin;
	FILE* sdc;

	s = rresvport(&lport);
	if (s == -1)
		return (-1);
	memset(&sin, 0, sizeof sin);
	sin.sin_len = sizeof(sin);
	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	sin.sin_family = AF_INET;
	sin.sin_port = htons(dport);
	if (connect(s, (struct sockaddr *)&sin, sizeof sin) == -1)
		return (-1);
	sdc = fdopen(s, "w");
	if (sdc == NULL) {
		close(s);
		return (-1);
	}
	fprintf(sdc, "%s", name);
	do_message(sdc, message);
	while (blacklists->addr != 0) {
		fprintf(sdc, ";%s/%u", atop(blacklists->addr),
		    blacklists->bits);
		blacklists++;
	}
	fputc('\n', sdc);
	fclose(sdc);
	close(s);
	return (0);
}
コード例 #3
0
ファイル: mcserv.c プロジェクト: sfionov/mc-dev
static int
get_port_number (void)
{
    int port = 0;

#ifdef HAVE_RRESVPORT
    int start_port = IPPORT_RESERVED;

    port = rresvport (&start_port);
    if (port == -1) {
	if (geteuid () == 0) {
	    fprintf (stderr,
		     "Cannot bind the server on a reserved port\n");
	    DO_QUIT_NONVOID (-1);
	}
	port = 0;
    }
#endif
    if (port)
	return port;

    port = mcserver_port;

    return port;
}
コード例 #4
0
ファイル: testsuidroot.c プロジェクト: BlueBolt/BB_GridEngine
int main(int argc, char *argv[]) {
   int sock;
   int res_port = 1023;
   int quiet = 0;

   if(argc == 2 && strcmp(argv[1], "-q") == 0) {
      quiet = 1;
   }
   if(getuid() == SGE_SUPERUSER_UID) {
      if(!quiet) {
         fprintf(stderr, "%s: must be started with uid != 0\n", argv[0]);
      }
      return 1;
   }
   if(geteuid() != SGE_SUPERUSER_UID) {
      if(!quiet) {
         fprintf(stderr, "%s: effective uid should be 0\n", argv[0]);
      }
      return 2;
   }

   if((sock = rresvport(&res_port)) == -1) {
      if(!quiet) {
         fprintf(stderr, "%s: binding a privileged socket fails\n", argv[0]);
      }
      return 3;
   }

   shutdown(sock, 0);
   close(sock);

   return 0;
}
コード例 #5
0
/*
 * Test the bind() operation for a socket that is protected (< 1024).
 */
int main(int argc, char **argv)
{

	int fd;
	int aport;

	aport = IPPORT_RESERVED - 1;
	fd = rresvport(&aport);
	if(fd == -1) {
		perror("test_bind:rresvport");
		exit(1);
	}

	close(fd);
	exit(0);

}
コード例 #6
0
ファイル: rshd.c プロジェクト: 2asoft/freebsd
static void
doit (void)
{
    u_char buf[BUFSIZ];
    u_char *p;
    struct sockaddr_storage thisaddr_ss;
    struct sockaddr *thisaddr = (struct sockaddr *)&thisaddr_ss;
    struct sockaddr_storage thataddr_ss;
    struct sockaddr *thataddr = (struct sockaddr *)&thataddr_ss;
    struct sockaddr_storage erraddr_ss;
    struct sockaddr *erraddr = (struct sockaddr *)&erraddr_ss;
    socklen_t thisaddr_len, thataddr_len;
    int port;
    int errsock = -1;
    char *client_user = NULL, *server_user = NULL, *cmd = NULL;
    struct passwd *pwd;
    int s = STDIN_FILENO;
    char **env;
    int ret;
    char that_host[NI_MAXHOST];

    thisaddr_len = sizeof(thisaddr_ss);
    if (getsockname (s, thisaddr, &thisaddr_len) < 0)
	syslog_and_die("getsockname: %s", strerror(errno));
    thataddr_len = sizeof(thataddr_ss);
    if (getpeername (s, thataddr, &thataddr_len) < 0)
	syslog_and_die ("getpeername: %s", strerror(errno));

    /* check for V4MAPPED addresses? */

    if (do_kerberos == 0 && !is_reserved(socket_get_port(thataddr)))
	fatal(s, NULL, "Permission denied.");

    p = buf;
    port = 0;
    for(;;) {
	if (net_read (s, p, 1) != 1)
	    syslog_and_die ("reading port number: %s", strerror(errno));
	if (*p == '\0')
	    break;
	else if (isdigit(*p))
	    port = port * 10 + *p - '0';
	else
	    syslog_and_die ("non-digit in port number: %c", *p);
    }

    if (do_kerberos  == 0 && !is_reserved(htons(port)))
	fatal(s, NULL, "Permission denied.");

    if (port) {
	int priv_port = IPPORT_RESERVED - 1;

	/*
	 * There's no reason to require a ``privileged'' port number
	 * here, but for some reason the brain dead rsh clients
	 * do... :-(
	 */

	erraddr->sa_family = thataddr->sa_family;
	socket_set_address_and_port (erraddr,
				     socket_get_address (thataddr),
				     htons(port));

	/*
	 * we only do reserved port for IPv4
	 */

	if (erraddr->sa_family == AF_INET)
	    errsock = rresvport (&priv_port);
	else
	    errsock = socket (erraddr->sa_family, SOCK_STREAM, 0);
	if (errsock < 0)
	    syslog_and_die ("socket: %s", strerror(errno));
	if (connect (errsock,
		     erraddr,
		     socket_sockaddr_size (erraddr)) < 0) {
	    syslog (LOG_WARNING, "connect: %s", strerror(errno));
	    close (errsock);
	}
    }

    if(do_kerberos) {
	if (net_read (s, buf, 4) != 4)
	    syslog_and_die ("reading auth info: %s", strerror(errno));

#ifdef KRB5
	    if((do_kerberos & DO_KRB5) &&
	       recv_krb5_auth (s, buf, thisaddr, thataddr,
			       &client_user,
			       &server_user,
			       &cmd) == 0)
		auth_method = AUTH_KRB5;
	    else
#endif /* KRB5 */
		syslog_and_die ("unrecognized auth protocol: %x %x %x %x",
				buf[0], buf[1], buf[2], buf[3]);
    } else {
	if(recv_bsd_auth (s, buf,
			  (struct sockaddr_in *)thisaddr,
			  (struct sockaddr_in *)thataddr,
			  &client_user,
			  &server_user,
			  &cmd) == 0) {
	    auth_method = AUTH_BROKEN;
	    if(do_vacuous) {
		printf("Remote host requires Kerberos authentication\n");
		exit(0);
	    }
	} else
	    syslog_and_die("recv_bsd_auth failed");
    }

    if (client_user == NULL || server_user == NULL || cmd == NULL)
	syslog_and_die("mising client/server/cmd");

    pwd = getpwnam (server_user);
    if (pwd == NULL)
	fatal (s, NULL, "Login incorrect.");

    if (*pwd->pw_shell == '\0')
	pwd->pw_shell = _PATH_BSHELL;

    if (pwd->pw_uid != 0 && access (_PATH_NOLOGIN, F_OK) == 0)
	fatal (s, NULL, "Login disabled.");


    ret = getnameinfo_verified (thataddr, thataddr_len,
				that_host, sizeof(that_host),
				NULL, 0, 0);
    if (ret)
	fatal (s, NULL, "getnameinfo: %s", gai_strerror(ret));

    if (login_access(pwd, that_host) == 0) {
	syslog(LOG_NOTICE, "Kerberos rsh denied to %s from %s",
	       server_user, that_host);
	fatal(s, NULL, "Permission denied.");
    }

#ifdef HAVE_GETSPNAM
    {
	struct spwd *sp;
	long    today;

	sp = getspnam(server_user);
	if (sp != NULL) {
	    today = time(0)/(24L * 60 * 60);
	    if (sp->sp_expire > 0)
		if (today > sp->sp_expire)
		    fatal(s, NULL, "Account has expired.");
	}
    }
#endif


#ifdef HAVE_SETLOGIN
    if (setlogin(pwd->pw_name) < 0)
	syslog(LOG_ERR, "setlogin() failed: %s", strerror(errno));
#endif

#ifdef HAVE_SETPCRED
    if (setpcred (pwd->pw_name, NULL) == -1)
	syslog(LOG_ERR, "setpcred() failure: %s", strerror(errno));
#endif /* HAVE_SETPCRED */

    /* Apply limits if not root */
    if(pwd->pw_uid != 0) {
	 const char *file = _PATH_LIMITS_CONF;
	 read_limits_conf(file, pwd);
    }

    if (initgroups (pwd->pw_name, pwd->pw_gid) < 0)
	fatal (s, "initgroups", "Login incorrect.");

    if (setgid(pwd->pw_gid) < 0)
	fatal (s, "setgid", "Login incorrect.");

    if (setuid (pwd->pw_uid) < 0)
	fatal (s, "setuid", "Login incorrect.");

    if (chdir (pwd->pw_dir) < 0)
	fatal (s, "chdir", "Remote directory.");

    if (errsock >= 0) {
	if (dup2 (errsock, STDERR_FILENO) < 0)
	    fatal (s, "dup2", "Cannot dup stderr.");
	close (errsock);
    } else {
	if (dup2 (STDOUT_FILENO, STDERR_FILENO) < 0)
	    fatal (s, "dup2", "Cannot dup stderr.");
    }

#ifdef KRB5
    {
	int fd;

	if (!do_unique_tkfile)
	    snprintf(tkfile,sizeof(tkfile),"FILE:/tmp/krb5cc_%lu",
		     (unsigned long)pwd->pw_uid);
	else if (*tkfile=='\0') {
	    snprintf(tkfile,sizeof(tkfile),"FILE:/tmp/krb5cc_XXXXXX");
	    fd = mkstemp(tkfile+5);
	    close(fd);
	    unlink(tkfile+5);
	}

	if (kerberos_status)
	    krb5_start_session();
    }
#endif

    setup_environment (&env, pwd);

    if (do_encrypt) {
	setup_copier (errsock >= 0);
    } else {
	if (net_write (s, "", 1) != 1)
	    fatal (s, "net_write", "write failed");
    }

#if defined(KRB5)
    if(k_hasafs()) {
	char cell[64];

	if(do_newpag)
	    k_setpag();

	/* XXX */
       if (kerberos_status) {
	   krb5_ccache ccache;
	   krb5_error_code status;

	   status = krb5_cc_resolve (context, tkfile, &ccache);
	   if (!status) {
	       if (k_afs_cell_of_file (pwd->pw_dir, cell, sizeof(cell)) == 0)
		   krb5_afslog_uid_home(context, ccache, cell, NULL,
					pwd->pw_uid, pwd->pw_dir);
	       krb5_afslog_uid_home(context, ccache, NULL, NULL,
				    pwd->pw_uid, pwd->pw_dir);
	       krb5_cc_close (context, ccache);
	   }
       }
    }
#endif /* KRB5 */
    execle (pwd->pw_shell, pwd->pw_shell, "-c", cmd, NULL, env);
    err(1, "exec %s", pwd->pw_shell);
}
コード例 #7
0
ファイル: net_client.c プロジェクト: borlesanket/pbspro-1
int
client_to_svr_extend(pbs_net_t hostaddr, unsigned int port, int authport_flags, char *localaddr)
{
	struct sockaddr_in	remote;
	int	sock;
	int	local_port;
	int	errn;
	int	rc;
#ifdef WIN32
	int	ret;
	int	non_block = 1;
	struct	linger      li;
	struct	sockaddr_in from;
	struct	timeval     tv;
	fd_set	            writeset;
#else
	struct pollfd	fds[1];
	pbs_socklen_t	len = sizeof(rc);
	int		oflag;
#endif


	/*	If local privilege port requested, bind to one	*/
	/*	Must be root privileged to do this		*/
	local_port = authport_flags & B_RESERVED;

	if (local_port) {
#ifdef	IP_PORTRANGE_LOW
		int			lport = IPPORT_RESERVED - 1;

		sock = rresvport(&lport);
		if (sock < 0) {
			if (errno == EAGAIN)
				return PBS_NET_RC_RETRY;
			else
				return PBS_NET_RC_FATAL;
		}
#else	/* IP_PORTRANGE_LOW */
		struct sockaddr_in	local;
		unsigned short		tryport;
		static unsigned short	start_port = 0;

		sock = socket(AF_INET, SOCK_STREAM, 0);
		if (sock < 0) {
			return PBS_NET_RC_FATAL;
		}

		if (start_port == 0) {	/* arbitrary start point */
			start_port = (getpid() %(IPPORT_RESERVED/2)) +
				IPPORT_RESERVED/2;
		}
		else if (--start_port < IPPORT_RESERVED/2)
			start_port = IPPORT_RESERVED - 1;
		tryport = start_port;

		memset(&local, 0, sizeof(local));
		local.sin_family = AF_INET;
		if (localaddr != NULL) {
			local.sin_addr.s_addr = inet_addr(localaddr);
			if (local.sin_addr.s_addr == INADDR_NONE) {
				perror("inet_addr failed");
				return (PBS_NET_RC_FATAL);
			}
		} else if (pbs_conf.pbs_public_host_name) {
			pbs_net_t public_addr;
			public_addr = get_hostaddr(pbs_conf.pbs_public_host_name);
			if (public_addr == (pbs_net_t)0) {
				return (PBS_NET_RC_FATAL);
			}
			local.sin_addr.s_addr = htonl(public_addr);
		}
		for (;;) {

			local.sin_port = htons(tryport);
			if (bind(sock, (struct sockaddr *)&local,
				sizeof(local)) == 0)
				break;

#ifdef WIN32
			errno = WSAGetLastError();
			if (errno != EADDRINUSE && errno != EADDRNOTAVAIL && errno != WSAEACCES) {
				closesocket(sock);
#else
			if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
				close(sock);
#endif
				return PBS_NET_RC_FATAL;
			}
			else if (--tryport < (IPPORT_RESERVED/2)) {
				tryport = IPPORT_RESERVED - 1;
			}
			if (tryport == start_port) {
#ifdef WIN32
				closesocket(sock);
#else
				close(sock);
#endif
				return PBS_NET_RC_RETRY;
			}
		}
		/*
		 ** Ensure last tryport becomes start port on next call.
		 */
		start_port = tryport;
#endif	/* IP_PORTRANGE_LOW */
	}
	else {
		sock = socket(AF_INET, SOCK_STREAM, 0);
		if (sock < 0) {
			return PBS_NET_RC_FATAL;
		}
	}

	remote.sin_addr.s_addr = htonl(hostaddr);

	remote.sin_port = htons((unsigned short)port);
	remote.sin_family = AF_INET;
#ifdef WIN32
	li.l_onoff = 1;
	li.l_linger = 5;

	setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&li, sizeof(li));

	if (ioctlsocket(sock, FIONBIO, &non_block) == SOCKET_ERROR) {
		errno = WSAGetLastError();
		closesocket(sock);
		return (PBS_NET_RC_FATAL);
	}
#else
	oflag = fcntl(sock, F_GETFL);
	if (fcntl(sock, F_SETFL, (oflag | O_NONBLOCK)) == -1) {
		close(sock);
		return (PBS_NET_RC_FATAL);
	}
#endif

	if (connect(sock, (struct sockaddr *)&remote, sizeof(remote)) < 0) {

#ifdef WIN32
		errno = WSAGetLastError();
#endif
		/*
		 * Bacause of  threading, pbs_errno is actually a macro
		 * pointing to a variable within a tread context.  On certain
		 * platforms, the threading library resulted in errno being
		 * cleared after pbs_errno was set set from it, so save
		 * errno into a local variable first, then test it.
		 */
		errn = errno;
		pbs_errno = errn;
		switch (errn) {
#ifdef WIN32
			case WSAEINTR:
#else
			case EINTR:
#endif
			case EADDRINUSE:
			case ETIMEDOUT:
			case ECONNREFUSED:
#ifdef WIN32
				closesocket(sock);
#else
				close(sock);
#endif
				return (PBS_NET_RC_RETRY);

#ifdef WIN32
			case WSAEWOULDBLOCK:
				FD_ZERO(&writeset);
				FD_SET((unsigned int)sock, &writeset);
				tv.tv_sec = conn_timeout;	/* connect timeout */
				tv.tv_usec = 0;
				ret = select(1, NULL, &writeset, NULL, &tv);
				if (ret == SOCKET_ERROR) {
					errno = WSAGetLastError(); 
					errn = errno;
					pbs_errno = errn;
					closesocket(sock);
					return PBS_NET_RC_FATAL;
				} else if (ret == 0) {
					closesocket(sock);
					return PBS_NET_RC_RETRY;
				}
				break;
#else	/* UNIX */
			case EWOULDBLOCK:
			case EINPROGRESS:
				while (1) {
					fds[0].fd = sock;
					fds[0].events  = POLLOUT;
					fds[0].revents = 0;

					rc = poll(fds, (nfds_t)1, conn_timeout * 1000);
					if (rc == -1) {
						errn = errno;
						if ((errn != EAGAIN) && (errn != EINTR))
							break;
					} else
						break;	/* no error */
				}

				if (rc == 1) {
					/* socket may be connected and ready to write */
					rc = 0;
					if ((getsockopt(sock, SOL_SOCKET, SO_ERROR, &rc, &len) == -1) || (rc != 0)) {
						close(sock);
						return PBS_NET_RC_FATAL;
					}
					break;

				} else if (rc == 0) {
					/* socket not ready - not connected in time */
					close(sock);
					return PBS_NET_RC_RETRY;
				} else {
					/* socket not ready - error */
					close(sock);
					return PBS_NET_RC_FATAL;
				}
#endif	/* end UNIX */

			default:
#ifdef WIN32
				closesocket(sock);
#else
				close(sock);
#endif
				return (PBS_NET_RC_FATAL);
		}
	}

	/* reset socket to blocking */
#ifdef WIN32
	non_block = 0;
	if (ioctlsocket(sock, FIONBIO, &non_block) == SOCKET_ERROR) {
		errno = WSAGetLastError();
		closesocket(sock);
		return PBS_NET_RC_FATAL;
	}
#else	/* UNIX */
	if (fcntl(sock, F_SETFL, oflag) == -1) {
		close(sock);
		return (PBS_NET_RC_FATAL);
	}
#endif

	if (engage_authentication(sock,
		remote.sin_addr, port, authport_flags) != -1)
		return sock;

	/*authentication unsuccessful*/

#ifdef WIN32
	closesocket(sock);
#else
	close(sock);
#endif
	return (PBS_NET_RC_FATAL);
}
コード例 #8
0
ファイル: rcmd.c プロジェクト: JamesLinus/uClibc-or1k
int rcmd(char **ahost, u_short rport, const char *locuser, const char *remuser,
         const char *cmd, int *fd2p)
{
#ifdef __UCLIBC_HAS_REENTRANT_RPC__
    int herr;
    struct hostent hostbuf;
    size_t hstbuflen;
    char *tmphstbuf;
#endif
    struct hostent *hp;
    struct sockaddr_in sin, from;
    struct pollfd pfd[2];
    int32_t oldmask;
    pid_t pid;
    int s, lport, timo;
    char c;

    pid = getpid();

#ifdef __UCLIBC_HAS_REENTRANT_RPC__
    hstbuflen = 1024;
    tmphstbuf = stack_heap_alloc(hstbuflen);

    while (gethostbyname_r (*ahost, &hostbuf, tmphstbuf,
                            hstbuflen, &hp, &herr) != 0 || hp == NULL)
    {
        if (herr != NETDB_INTERNAL || errno != ERANGE)
        {
            __set_h_errno (herr);
            stack_heap_free(tmphstbuf);
            herror(*ahost);
            return -1;
        }
        else
        {
            /* Enlarge the buffer.  */
            hstbuflen *= 2;
            stack_heap_free(tmphstbuf);
            tmphstbuf = stack_heap_alloc(hstbuflen);
        }
    }
    stack_heap_free(tmphstbuf);
#else /* call the non-reentrant version */
    if ((hp = gethostbyname(*ahost)) == NULL) {
        return -1;
    }
#endif
    pfd[0].events = POLLIN;
    pfd[1].events = POLLIN;

    *ahost = hp->h_name;
    oldmask = sigblock(sigmask(SIGURG)); /* __sigblock */
    for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
        s = rresvport(&lport);
        if (s < 0) {
            if (errno == EAGAIN)
                (void)fprintf(stderr,
                              "rcmd: socket: All ports in use\n");
            else
                (void)fprintf(stderr, "rcmd: socket: %m\n");
            sigsetmask(oldmask); /* sigsetmask */
            return -1;
        }
        fcntl(s, F_SETOWN, pid);
        sin.sin_family = hp->h_addrtype;
        memmove(&sin.sin_addr, hp->h_addr_list[0],
                MIN (sizeof (sin.sin_addr), hp->h_length));
        sin.sin_port = rport;
        if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) /* __connect */
            break;
        (void)close(s);
        if (errno == EADDRINUSE) {
            lport--;
            continue;
        }
        if (errno == ECONNREFUSED && timo <= 16) {
            (void)sleep(timo); /* __sleep */
            timo *= 2;
            continue;
        }
        if (hp->h_addr_list[1] != NULL) {
            int oerrno = errno;

            (void)fprintf(stderr, "connect to address %s: ",
                          inet_ntoa(sin.sin_addr));
            __set_errno (oerrno);
            perror(0);
            hp->h_addr_list++;
            memmove(&sin.sin_addr, hp->h_addr_list[0],
                    MIN (sizeof (sin.sin_addr), hp->h_length));
            (void)fprintf(stderr, "Trying %s...\n",
                          inet_ntoa(sin.sin_addr));
            continue;
        }
        (void)fprintf(stderr, "%s: %m\n", hp->h_name);
        sigsetmask(oldmask); /* __sigsetmask */
        return -1;
    }
    lport--;
    if (fd2p == 0) {
        write(s, "", 1);
        lport = 0;
    } else {
        char num[8];
        int s2 = rresvport(&lport), s3;
        socklen_t len = sizeof(from);

        if (s2 < 0)
            goto bad;
        listen(s2, 1);
        (void)snprintf(num, sizeof(num), "%d", lport); /* __snprintf */
        if (write(s, num, strlen(num)+1) != strlen(num)+1) {
            (void)fprintf(stderr,
                          "rcmd: write (setting up stderr): %m\n");
            (void)close(s2);
            goto bad;
        }
        pfd[0].fd = s;
        pfd[1].fd = s2;
        __set_errno (0);
        if (poll (pfd, 2, -1) < 1 || (pfd[1].revents & POLLIN) == 0) {
            if (errno != 0)
                (void)fprintf(stderr, "rcmd: poll (setting up stderr): %m\n");
            else
                (void)fprintf(stderr, "poll: protocol failure in circuit setup\n");
            (void)close(s2);
            goto bad;
        }
        s3 = accept(s2, (struct sockaddr *)&from, &len);
        (void)close(s2);
        if (s3 < 0) {
            (void)fprintf(stderr,
                          "rcmd: accept: %m\n");
            lport = 0;
            goto bad;
        }
        *fd2p = s3;
        from.sin_port = ntohs((u_short)from.sin_port);
        if (from.sin_family != AF_INET ||
                from.sin_port >= IPPORT_RESERVED ||
                from.sin_port < IPPORT_RESERVED / 2) {
            (void)fprintf(stderr,
                          "socket: protocol failure in circuit setup\n");
            goto bad2;
        }
    }
    (void)write(s, locuser, strlen(locuser)+1);
    (void)write(s, remuser, strlen(remuser)+1);
    (void)write(s, cmd, strlen(cmd)+1);
    if (read(s, &c, 1) != 1) {
        (void)fprintf(stderr,
                      "rcmd: %s: %m\n", *ahost);
        goto bad2;
    }
    if (c != 0) {
        while (read(s, &c, 1) == 1) {
            (void)write(STDERR_FILENO, &c, 1);
            if (c == '\n')
                break;
        }
        goto bad2;
    }
    sigsetmask(oldmask);
    return s;
bad2:
    if (lport)
        (void)close(*fd2p);
bad:
    (void)close(s);
    sigsetmask(oldmask);
    return -1;
}
コード例 #9
0
ファイル: printer.c プロジェクト: mit-athena/larvnetd
static void printer_host_callback(void *arg, int status, int timeouts,
				  struct hostent *host)
{
  struct printer_poll_args *pargs = (struct printer_poll_args *) arg;
  struct printer *printer = pargs->printer;
  int s = -1, lport = IPPORT_RESERVED - 1, flags;
  unsigned short port;
  struct servent *servent;
  struct sockaddr_in sin;

  if (status == ARES_EDESTRUCTION)
    {
      syslog(LOG_DEBUG, "printer_host_callback: printer %s hostname query "
	     "halted for channel destruction", printer->name);
      free(pargs);
      return;
    }

  if (status != ARES_SUCCESS)
    {
      syslog(LOG_ERR, "printer_host_callback: printer %s can't resolve print "
	     "server name: %s", printer->name, ares_strerror(status));
      goto failure;
    }

  s = rresvport(&lport);
  if (s < 0)
    {
      syslog(LOG_ERR, "printer_host_callback: printer %s can't get reserved "
	     "port", printer->name);
      goto failure;
    }

  /* Set s non-blocking so we can do a non-blocking connect. */
  flags = fcntl(s, F_GETFL);
  fcntl(s, F_SETFL, flags | O_NONBLOCK);

  servent = getservbyname("printer", "tcp");
  port = (servent) ? servent->s_port : htons(PRINTER_FALLBACK_PORT);

  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  memcpy(&sin.sin_addr, host->h_addr, sizeof(sin.sin_addr));
  sin.sin_port = port;
  if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1
      && errno != EINPROGRESS)
    {
      syslog(LOG_ERR, "printer_host_callback: printer %s can't connect to "
	     "print server %s: %m", printer->name, host->h_name);
      goto failure;
    }

  /* Set up the request we want to send; the main loop will call
   * printer_handle_output() when the socket selects true for
   * writing.
   */
  printer->s = s;
  printer->to_send = 1;
  sprintf(printer->buf, "\3%.*s\n", (int)(sizeof(printer->buf) - 3),
	  printer->name);
  printer->buflen = strlen(printer->buf);
  printer->jobs_counted = 0;
  printer->up_so_far = 1;

  syslog(LOG_DEBUG, "printer_host_callback: printer %s queued %d-byte query",
	 printer->name, printer->buflen);

  free(pargs);
  return;

failure:
  if (s >= 0)
    close(s);
  printer->timer = timer_set_rel(60, printer_poll, pargs);
  return;
}
コード例 #10
0
ファイル: rsh.c プロジェクト: sumikawa/fang
void
rsh_dual_relay(int s_src, int s_dst)
{
	fd_set readfds;
	int len, s_wld, error;
	struct sockaddr_storage ctladdr6;
	struct sockaddr_storage ctladdr;
	int port6 = 0, lport, lport6;
	char *p;
	struct timeval tv;
	struct sockaddr *sa;

	half = NO;
	s_rcv = s_src;
	s_snd = s_dst;
	syslog(LOG_INFO, "starting rsh connection");

	for (p = rshbuf; *p; p++)
		port6 = port6 * 10 + *p - '0';

	len = sizeof(ctladdr6);
	getpeername(s_src, (struct sockaddr *)&ctladdr6, &len);
	if (((struct sockaddr *)&ctladdr6)->sa_family == AF_INET6)
		((struct sockaddr_in6 *)&ctladdr6)->sin6_port = htons(port6);
	else
		((struct sockaddr_in *)&ctladdr6)->sin_port = htons(port6);

	s_wld = rresvport(&lport);
	if (s_wld == -1) goto bad;
	error = listen(s_wld, 1);
	if (error == -1) goto bad;
	snprintf(rshbuf, sizeof(rshbuf), "%d", lport);
	write(s_dst, rshbuf, strlen(rshbuf)+1);

	len = sizeof(ctladdr);
	s_ctl = accept(s_wld, (struct sockaddr *)&ctladdr, &len);
	if (s_ctl == -1) goto bad;
	close(s_wld);
	
	sa = (struct sockaddr *)&ctladdr6;
	s_ctl6 = rresvport_af(&lport6, sa->sa_family);
	if (s_ctl6 == -1) goto bad;
	error = connect(s_ctl6, sa, sa->sa_len);
	if (error == -1) goto bad;
	
	syslog(LOG_INFO, "starting rsh control connection");

	for (;;) {
		int maxfd = 0;

		FD_ZERO(&readfds);
		if (half == NO)
			FD_SET(s_src, &readfds);
		FD_SET(s_dst, &readfds);
		if (s_dst > maxfd)
			maxfd = s_dst;
		FD_SET(s_ctl, &readfds);
		if (s_ctl > maxfd)
			maxfd = s_ctl;
		FD_SET(s_ctl6, &readfds);
		if (s_ctl6 > maxfd)
			maxfd = s_ctl6;

		tv.tv_sec = FAITH_TIMEOUT;
		tv.tv_usec = 0;

		error = select(maxfd + 1, &readfds, NULL, NULL, &tv);
		if (error == -1)
			exit_failure("select 4 sockets: %s", strerror(errno));
		else if (error == 0)
			exit_failure("connection timeout");

		if (half == NO && FD_ISSET(s_src, &readfds)) {
			s_rcv = s_src;
			s_snd = s_dst;
			relay(s_src, s_dst);
		}
		if (FD_ISSET(s_dst, &readfds)) {
			s_rcv = s_dst;
			s_snd = s_src;
			relay(s_src, s_dst);
		}
		if (FD_ISSET(s_ctl, &readfds)) {
			s_rcv = s_ctl;
			s_snd = s_ctl6;
			relay(s_src, s_dst);
		}
		if (FD_ISSET(s_ctl6, &readfds)) {
			s_rcv = s_ctl6;
			s_snd = s_ctl;
			relay(s_src, s_dst);
		}
	}
	/* NOTREACHED */

 bad:
	exit_failure("%s", strerror(errno));
}
コード例 #11
0
ファイル: rcmd.c プロジェクト: AustenConrad/plan-9
int
rcmd(char **dst, int port, char *luser, char *ruser, char *cmd, int *fd2p)
{
	char c;
	int i, fd, lfd, fd2, port2;
	struct hostent *h;
	Rock *r;
	struct sockaddr_in in;
	char buf[128];
	void	(*x)(int);

	h = gethostbyname(*dst);
	if(h == 0)
		return -1;
	*dst = h->h_name;

	/* connect using a reserved tcp port */
	fd = socket(PF_INET, SOCK_STREAM, 0);
	if(fd < 0)
		return -1;
	r = _sock_findrock(fd, 0);
	if(r == 0){
		errno = ENOTSOCK;
		return -1;
	}
	r->reserved = 1;
	in.sin_family = AF_INET;
	in.sin_port = htons(port);
	memmove(&in.sin_addr, h->h_addr_list[0], sizeof(in.sin_addr));
	if(connect(fd, &in, sizeof(in)) < 0){
		close(fd);
		return -1;
	}

	/* error stream */
	if(fd2p){
		/* create an error stream and wait for a call in */
		for(i = 0; i < 10; i++){
			lfd = rresvport(&port2);
			if(lfd < 0)
				continue;
			if(listen(lfd, 1) == 0)
				break;
			close(lfd);
		}
		if(i >= 10){
			fprintf(stderr, pbotch);
			return -1;
		}

		snprintf(buf, sizeof buf, "%d", port2);
		if(write(fd, buf, strlen(buf)+1) < 0){
			close(fd);
			close(lfd);
			fprintf(stderr, lbotch);
			return -1;
		}
	} else {
		if(write(fd, "", 1) < 0){
			fprintf(stderr, pbotch);
			return -1;
		}
	}

	/* pass id's and command */
	if(write(fd, luser, strlen(luser)+1) < 0
	|| write(fd, ruser, strlen(ruser)+1) < 0
	|| write(fd, cmd, strlen(cmd)+1) < 0){
		if(fd2p)
			close(fd2);
		fprintf(stderr, pbotch);
		return -1;
	}

	if(fd2p){
		x = signal(SIGALRM, ding);
		alarm(15);
		fd2 = accept(lfd, &in, &i);
		alarm(0);
		close(lfd);
		signal(SIGALRM, x);

		if(fd2 < 0){
			close(fd);
			close(lfd);
			fprintf(stderr, lbotch);
			return -1;
		}
		*fd2p = fd2;
	}

	/* get reply */
	if(read(fd, &c, 1) != 1){
		if(fd2p)
			close(fd2);
		fprintf(stderr, pbotch);
		return -1;
	}
	if(c == 0)
		return fd;
	i = 0;
	while(c){
		buf[i++] = c;
		if(read(fd, &c, 1) != 1)
			break;
		if(i >= sizeof(buf)-1)
			break;
	}
	buf[i] = 0;
	fprintf(stderr, "rcmd: %s\n", buf);
	close(fd);
	return -1;
}
コード例 #12
0
fsal_status_t
fsal_proxy_create_rpc_clnt(proxyfsal_op_context_t * ctx)
{
  int sock;
  struct sockaddr_in addr_rpc;
  struct timeval timeout = TIMEOUTRPC;
  int rc;
  int priv_port = 0 ; 
  fsal_status_t fsal_status;
  char addr[INET_ADDRSTRLEN];

  memset(&addr_rpc, 0, sizeof(addr_rpc));
  addr_rpc.sin_port = ctx->srv_port;
  addr_rpc.sin_family = AF_INET;
  addr_rpc.sin_addr.s_addr = ctx->srv_addr;

  if(!strcmp(ctx->srv_proto, "udp"))
    {
      struct timeval tv = { 25, 0};

      if((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
        ReturnCode(ERR_FSAL_FAULT, errno);

      ctx->rpc_client = clntudp_bufcreate(&addr_rpc,
                                          ctx->srv_prognum,
                                          FSAL_PROXY_NFS_V4,
                                          tv,
                                          &sock,
                                          ctx->srv_sendsize,
                                          ctx->srv_recvsize);

      if(ctx->rpc_client == NULL)
        {

          LogCrit(COMPONENT_FSAL,
                  "Cannot contact server addr=%s port=%u prognum=%u using NFSv4 protocol",
                  inet_ntop(AF_INET, &ctx->srv_addr, addr, sizeof(addr)),
                  ntohs(ctx->srv_port), ctx->srv_prognum);

          ReturnCode(ERR_FSAL_INVAL, 0);
        }
    }
  else if(!strcmp(ctx->srv_proto, "tcp"))
    {
      if( ctx->use_privileged_client_port  == TRUE )
        {
	  if( (sock = rresvport( &priv_port ) )< 0 )
           {
             LogCrit(COMPONENT_FSAL, "Cannot create a tcp socket on a privileged port");
             ReturnCode(ERR_FSAL_FAULT, 0);
           }
        }
      else
        {
          if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
            {
              LogCrit(COMPONENT_FSAL, "Cannot create a tcp socket - %d", errno);
              ReturnCode(ERR_FSAL_FAULT, 0);
            }
        }

      if(connect(sock, (struct sockaddr *)&addr_rpc, sizeof(addr_rpc)) < 0)
        {
          LogCrit(COMPONENT_FSAL,
                  "Cannot connect to server addr=%s port=%u",
                  inet_ntop(AF_INET, &ctx->srv_addr, addr, sizeof(addr)),
                  ntohs(ctx->srv_port));

          ReturnCode(ERR_FSAL_FAULT, 0);
        }

      ctx->rpc_client = clnttcp_create(&addr_rpc,
                                       ctx->srv_prognum,
                                       FSAL_PROXY_NFS_V4,
                                       &sock,
                                       ctx->srv_sendsize,
                                       ctx->srv_recvsize);
      if(ctx->rpc_client == NULL)
        {
          LogCrit(COMPONENT_FSAL,
                  "Cannot contact server addr=%s port=%u prognum=%u using NFSv4 protocol",
                  inet_ntop(AF_INET, &ctx->srv_addr, addr, sizeof(addr)),
                  ntohs(ctx->srv_port), ctx->srv_prognum);

          ReturnCode(ERR_FSAL_INVAL, 0);
        }
    }
  else
    {
      ReturnCode(ERR_FSAL_INVAL, 0);
    }

  ctx->socket = sock;

#ifdef _USE_GSSRPC
  if(global_fsal_proxy_specific_info.active_krb5 == TRUE)
    {
      fsal_status = fsal_internal_set_auth_gss(ctx);
      if(FSAL_IS_ERROR(fsal_status))
        ReturnCode(fsal_status.major, fsal_status.minor);
    }
  else
#endif                          /* _USE_GSSRPC */

  if((ctx->rpc_auth = authunix_create_default()) == NULL)
    ReturnCode(ERR_FSAL_INVAL, 0);

  /* test if the newly created context can 'ping' the server via PROC_NULL */
  rc = clnt_call(ctx->rpc_client, ctx->rpc_auth, NFSPROC4_NULL,
                 (xdrproc_t) xdr_void, (caddr_t) NULL,
                 (xdrproc_t) xdr_void, (caddr_t) NULL, timeout);
  if(rc  != RPC_SUCCESS)
    ReturnCode(ERR_FSAL_INVAL, rc);

  fsal_status = FSAL_proxy_setclientid(ctx);
  if(FSAL_IS_ERROR(fsal_status))
    ReturnCode(ERR_FSAL_FAULT, 0);

  ReturnCode(ERR_FSAL_NO_ERROR, 0);
}
コード例 #13
0
ファイル: tclXunixSock.c プロジェクト: flightaware/tclx
/*-----------------------------------------------------------------------------
 * TclX_ServerCreateCmd --
 *     Implements the TCL server_create command:
 *
 *        server_create ?options?
 *
 *  Creates a socket, binds the address and port on the local machine 
 * (optionally specified by the caller), and starts the port listening 
 * for connections by calling listen (2).
 *
 *  Options may be "-myip ip_address", "-myport port_number",
 * "-myport reserved", and "-backlog backlog".
 *
 * Results:
 *   If successful, a Tcl fileid is returned.
 *
 *-----------------------------------------------------------------------------
 */
static int
TclX_ServerCreateCmd (ClientData clientData,
                      Tcl_Interp *interp,
                      int argc,
                      const char **argv)
{
    int socketFD = -1, nextArg;
    struct sockaddr_in  local;
    int myPort, value;
    int backlog = 5;
    int getReserved = FALSE;
    Tcl_Channel channel = NULL;

    /*
     * Parse arguments.
     */
    bzero ((VOID *) &local, sizeof (local));
    local.sin_family = AF_INET;
    local.sin_addr.s_addr = INADDR_ANY;
    nextArg = 1;

    while ((nextArg < argc) && (argv [nextArg][0] == '-')) {
        if (STREQU ("-myip", argv [nextArg])) {
            if (nextArg >= argc - 1)
                goto missingArg;
            nextArg++;
            if (TclXOSInetAtoN (interp, argv [nextArg],
                                &local.sin_addr) == TCL_ERROR)
                return TCL_ERROR;
        } else if (STREQU ("-myport", argv [nextArg])) {
            if (nextArg >= argc - 1)
                goto missingArg;
            nextArg++;
            if (STREQU (argv [nextArg], "reserved")) {
                getReserved = TRUE;
            } else {
                if (Tcl_GetInt (interp, argv [nextArg], &myPort) != TCL_OK)
                    return TCL_ERROR;
                local.sin_port = htons (myPort);
            }
        } else if (STREQU ("-backlog", argv [nextArg])) {
            if (nextArg >= argc - 1)
                goto missingArg;
            nextArg++;
            if (Tcl_GetInt (interp, argv [nextArg], &backlog) != TCL_OK)
                return TCL_ERROR;
        } else if (STREQU ("-reuseaddr", argv [nextArg])) {
            /* Ignore for compatibility */
        } else {
            TclX_AppendObjResult (interp, "expected ",
                                  "\"-myip\", \"-myport\", or \"-backlog\", ",
                                  "got \"", argv [nextArg], "\"",
                                  (char *) NULL);
            return TCL_ERROR;
        }
        nextArg++;
    }

    if (nextArg != argc) {
        TclX_AppendObjResult (interp, tclXWrongArgs, argv[0],
                              " ?options?", (char *) NULL);
        return TCL_ERROR;
    }

    /*
     * Allocate a reserved port if requested.
     */
    if (getReserved) {
        int port;
        if (rresvport (&port) < 0)
            goto unixError;
        local.sin_port = port;
    }

    /*
     * Open a socket and bind an address and port to it.
     */
    socketFD = socket (local.sin_family, SOCK_STREAM, 0);
    if (socketFD < 0)
        goto unixError;

    value = 1;
    if (setsockopt (socketFD, SOL_SOCKET, SO_REUSEADDR,
                    (void*) &value, sizeof (value)) < 0) {
        goto unixError;
    }
    if (bind (socketFD, (struct sockaddr *) &local, sizeof (local)) < 0) {
        goto unixError;
    }

    if (listen (socketFD, backlog) < 0)
        goto unixError;

    channel = Tcl_MakeTcpClientChannel ((ClientData) socketFD);
    Tcl_RegisterChannel (interp, channel);

    TclX_AppendObjResult (interp, Tcl_GetChannelName (channel), (char *) NULL);
    return TCL_OK;

    /*
     * Exit points for errors.
     */
  missingArg:
    TclX_AppendObjResult (interp, "missing argument for ", argv [nextArg],
                          (char *) NULL);
    return TCL_ERROR;

  unixError:
    TclX_AppendObjResult (interp, Tcl_PosixError (interp), (char *) NULL);
    CloseForError (interp, channel, socketFD);
    return TCL_ERROR;
}
コード例 #14
0
ファイル: pt_tcp.c プロジェクト: alexandermerritt/dragonfly
/*
 * Key will be tcp/host/port[/"priv"]
 * Create a TCP socket connected to the
 * requested host and port.
 * Some trailing suffix values have special meanings.
 * An unrecognized suffix is an error.
 */
int
portal_tcp(struct portal_cred *pcr, char *key, char **v, int kso __unused,
    int *fdp)
{
	char host[MAXHOSTNAMELEN];
	char port[MAXHOSTNAMELEN];
	char *p = key + (v[1] ? strlen(v[1]) : 0);
	char *q;
	struct hostent *hp;
	struct servent *sp;
	struct in_addr **ipp;
	struct in_addr *ip[2];
	struct in_addr ina;
	u_short s_port;
	int priv = 0;
	struct sockaddr_in sain;

	q = strchr(p, '/');
	if (q == NULL || (size_t)(q - p) >= sizeof(host))
		return (EINVAL);
	*q = '\0';
	strcpy(host, p);
	p = q + 1;

	q = strchr(p, '/');
	if (q)
		*q = '\0';
	if (strlen(p) >= sizeof(port))
		return (EINVAL);
	strcpy(port, p);
	if (q) {
		p = q + 1;
		if (strcmp(p, "priv") == 0) {
			if (pcr->pcr_uid == 0)
				priv = 1;
			else
				return (EPERM);
		} else {
			return (EINVAL);
		}
	}

	hp = gethostbyname(host);
	if (hp != NULL) {
		ipp = (struct in_addr **) hp->h_addr_list;
	} else {
		ina.s_addr = inet_addr(host);
		if (ina.s_addr == INADDR_NONE)
			return (EINVAL);
		ip[0] = &ina;
		ip[1] = NULL;
		ipp = ip;
	}
#ifdef DEBUG
	printf ("inet address for %s is %s\n", host, inet_ntoa(*ipp[0]));
#endif

	sp = getservbyname(port, "tcp");
	if (sp != NULL) {
		s_port = (u_short)sp->s_port;
	} else {
		s_port = strtoul(port, &p, 0);
		if (s_port == 0 || *p != '\0')
			return (EINVAL);
		s_port = htons(s_port);
	}
#ifdef DEBUG
	printf ("port number for %s is %d\n", port, (int)ntohs(s_port));
#endif

	memset(&sain, 0, sizeof(sain));
	sain.sin_len = sizeof(sain);
	sain.sin_family = AF_INET;
	sain.sin_port = s_port;

	while (ipp[0]) {
		int so;

		if (priv)
			so = rresvport(NULL);
		else
			so = socket(AF_INET, SOCK_STREAM, 0);
		if (so < 0) {
			syslog(LOG_ERR, "socket: %m");
			return (errno);
		}

		sain.sin_addr = *ipp[0];
		if (connect(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) {
			*fdp = so;
			return (0);
		}
		close(so);

		ipp++;
	}

	return (errno);
}
コード例 #15
0
ファイル: lpd.c プロジェクト: sebjameswml/wmlcups
static int				/* O - Zero on success, non-zero on failure */
lpd_queue(const char *hostname,		/* I - Host to connect to */
          int        port,		/* I - Port to connect on */
          const char *printer,		/* I - Printer/queue name */
	  const char *filename,		/* I - File to print */
          const char *user,		/* I - Requesting user */
	  const char *title,		/* I - Job title */
	  int        copies,		/* I - Number of copies */
	  int        banner,		/* I - Print LPD banner? */
          int        format,		/* I - Format specifier */
          int        order,		/* I - Order of data/control files */
	  int        reserve,		/* I - Reserve ports? */
	  int        manual_copies,	/* I - Do copies by hand... */
	  int        timeout)		/* I - Timeout... */
{
  FILE			*fp;		/* Job file */
  char			localhost[255];	/* Local host name */
  int			error;		/* Error number */
  struct stat		filestats;	/* File statistics */
  int			lport;		/* LPD connection local port */
  int			fd;		/* LPD socket */
  char			control[10240],	/* LPD control 'file' */
			*cptr;		/* Pointer into control file string */
  char			status;		/* Status byte from command */
  struct sockaddr_in	addr;		/* Socket address */
  struct hostent	*hostaddr;	/* Host address */
  int			copy;		/* Copies written */
  size_t		nbytes,		/* Number of bytes written */
			tbytes;		/* Total bytes written */
  char			buffer[8192];	/* Output buffer */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction	action;		/* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */


 /*
  * Setup an alarm handler for timeouts...
  */

#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
  sigset(SIGALRM, lpd_timeout);
#elif defined(HAVE_SIGACTION)
  memset(&action, 0, sizeof(action));

  sigemptyset(&action.sa_mask);
  action.sa_handler = lpd_timeout;
  sigaction(SIGALRM, &action, NULL);
#else
  signal(SIGALRM, lpd_timeout);
#endif /* HAVE_SIGSET */

 /*
  * Loop forever trying to print the file...
  */

  for (;;) /* FOREVER */
  {
   /*
    * First try to reserve a port for this connection...
    */

    if ((hostaddr = httpGetHostByName(hostname)) == NULL)
    {
      fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s\n",
              hostname, hstrerror(h_errno));
      return (1);
    }

    fprintf(stderr, "INFO: Attempting to connect to host %s for printer %s\n",
            hostname, printer);

    memset(&addr, 0, sizeof(addr));
    memcpy(&(addr.sin_addr), hostaddr->h_addr, hostaddr->h_length);
    addr.sin_family = hostaddr->h_addrtype;
    addr.sin_port   = htons(port);

    for (lport = reserve == RESERVE_RFC1179 ? 732 : 1024;;)
    {
     /*
      * Choose the next priviledged port...
      */

      lport --;

      if (lport < 721 && reserve == RESERVE_RFC1179)
	lport = 731;
      else if (lport < 1)
	lport = 1023;

#ifdef HAVE_GETEUID
      if (geteuid() || !reserve)
#else
      if (getuid() || !reserve)
#endif /* HAVE_GETEUID */
      {
       /*
	* Just create a regular socket...
	*/

	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
          perror("ERROR: Unable to create socket");
          return (1);
	}

        lport = 0;
      }
      else
      {
       /*
	* We're running as root and want to comply with RFC 1179.  Reserve a
	* priviledged lport between 721 and 731...
	*/

	if ((fd = rresvport(&lport)) < 0)
	{
	  perror("ERROR: Unable to reserve port");
	  sleep(1);

	  continue;
	}
      }

      if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
      {
	error = errno;
	close(fd);
	fd = -1;

	if (error == ECONNREFUSED || error == EHOSTDOWN ||
            error == EHOSTUNREACH)
	{
	  fprintf(stderr, "WARNING: Network host \'%s\' is busy, down, or unreachable; will retry in 30 seconds...\n",
                  hostname);
	  sleep(30);
	}
	else if (error == EADDRINUSE)
	{
	 /*
	  * Try on another port...
	  */

	  sleep(1);
	}
	else
	{
	  perror("ERROR: Unable to connect to printer; will retry in 30 seconds...");
          sleep(30);
	}
      }
      else
	break;
    }

    fprintf(stderr, "INFO: Connected to %s...\n", hostname);
    fprintf(stderr, "DEBUG: Connected on ports %d (local %d)...\n", port,
            lport);

   /*
    * Next, open the print file and figure out its size...
    */

    if (stat(filename, &filestats))
    {
      perror("ERROR: unable to stat print file");
      return (1);
    }

    filestats.st_size *= manual_copies;

    if ((fp = fopen(filename, "rb")) == NULL)
    {
      perror("ERROR: unable to open print file for reading");
      return (1);
    }

   /*
    * Send a job header to the printer, specifying no banner page and
    * literal output...
    */

    if (lpd_command(fd, timeout, "\002%s\n",
                    printer))		/* Receive print job(s) */
      return (1);

    gethostname(localhost, sizeof(localhost));
    localhost[31] = '\0'; /* RFC 1179, Section 7.2 - host name < 32 chars */

    snprintf(control, sizeof(control), "H%s\nP%s\nJ%s\n", localhost, user,
             title);
    cptr = control + strlen(control);

    if (banner)
    {
      snprintf(cptr, sizeof(control) - (cptr - control), "C%s\nL%s\n",
               localhost, user);
      cptr   += strlen(cptr);
    }

    while (copies > 0)
    {
      snprintf(cptr, sizeof(control) - (cptr - control), "%cdfA%03d%.15s\n", format,
               getpid() % 1000, localhost);
      cptr   += strlen(cptr);
      copies --;
    }

    snprintf(cptr, sizeof(control) - (cptr - control),
             "UdfA%03d%.15s\nN%s\n",
             getpid() % 1000, localhost, title);

    fprintf(stderr, "DEBUG: Control file is:\n%s", control);

    if (order == ORDER_CONTROL_DATA)
    {
      if (lpd_command(fd, timeout, "\002%d cfA%03.3d%.15s\n", strlen(control),
                      getpid() % 1000, localhost))
        return (1);

      fprintf(stderr, "INFO: Sending control file (%lu bytes)\n",
              (unsigned long)strlen(control));

      if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
      {
	status = errno;
	perror("ERROR: Unable to write control file");
      }
      else
      {
        alarm(timeout);

        if (read(fd, &status, 1) < 1)
	{
	  fprintf(stderr, "WARNING: Remote host did not respond with control "
	                  "status byte after %d seconds!\n", timeout);
	  status = errno;
	}

        alarm(0);
      }

      if (status != 0)
	fprintf(stderr, "ERROR: Remote host did not accept control file (%d)\n",
        	status);
      else
	fputs("INFO: Control file sent successfully\n", stderr);
    }
    else
      status = 0;

    if (status == 0)
    {
     /*
      * Send the print file...
      */

      if (lpd_command(fd, timeout, "\003%u dfA%03.3d%.15s\n",
                      (unsigned)filestats.st_size, getpid() % 1000,
		      localhost))
        return (1);

      fprintf(stderr, "INFO: Sending data file (%u bytes)\n",
              (unsigned)filestats.st_size);

      tbytes = 0;
      for (copy = 0; copy < manual_copies; copy ++)
      {
	rewind(fp);

	while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
	{
	  fprintf(stderr, "INFO: Spooling LPR job, %u%% complete...\n",
        	  (unsigned)(100.0f * tbytes / filestats.st_size));

	  if (lpd_write(fd, buffer, nbytes) < nbytes)
	  {
            perror("ERROR: Unable to send print file to printer");
            break;
	  }
	  else
            tbytes += nbytes;
	}
      }

      if (tbytes < filestats.st_size)
	status = errno;
      else if (lpd_write(fd, "", 1) < 1)
      {
        perror("ERROR: Unable to send trailing nul to printer");
	status = errno;
      }
      else
      {
       /*
        * Read the status byte from the printer; if we can't read the byte
	* back now, we should set status to "errno", however at this point
	* we know the printer got the whole file and we don't necessarily
	* want to requeue it over and over...
	*/

	alarm(timeout);

        if (recv(fd, &status, 1, 0) < 1)
	{
	  fprintf(stderr, "WARNING: Remote host did not respond with data "
	                  "status byte after %d seconds!\n", timeout);
	  status = 0;
        }

	alarm(0);
      }

      if (status != 0)
	fprintf(stderr, "ERROR: Remote host did not accept data file (%d)\n",
        	status);
      else
	fputs("INFO: Data file sent successfully\n", stderr);
    }

    if (status == 0 && order == ORDER_DATA_CONTROL)
    {
      if (lpd_command(fd, timeout, "\002%d cfA%03.3d%.15s\n", strlen(control),
                      getpid() % 1000, localhost))
        return (1);

      fprintf(stderr, "INFO: Sending control file (%lu bytes)\n",
              (unsigned long)strlen(control));

      if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
      {
	status = errno;
	perror("ERROR: Unable to write control file");
      }
      else
      {
        alarm(timeout);

        if (read(fd, &status, 1) < 1)
	{
	  fprintf(stderr, "WARNING: Remote host did not respond with control "
	                  "status byte after %d seconds!\n", timeout);
	  status = errno;
	}

	alarm(0);
      }

      if (status != 0)
	fprintf(stderr, "ERROR: Remote host did not accept control file (%d)\n",
        	status);
      else
	fputs("INFO: Control file sent successfully\n", stderr);
    }

   /*
    * Close the socket connection and input file...
    */

    close(fd);
    fclose(fp);

    if (status == 0)
      return (0);

   /*
    * Waiting for a retry...
    */

    sleep(30);
  }
}
コード例 #16
0
ファイル: dial.c プロジェクト: AustenConrad/plan-9
int
dial(char *dest, char *local, char *dir, int *cfdp) {
	int sockconn, lport;
	struct hostent *hp;		/* Pointer to host info */
	struct sockaddr_in sin;		/* Socket address, Internet style */
	struct servent *sp = 0;
	char *tdest, *netname, *hostname, *servname;
	int sock_type;
#ifndef plan9
#define	USED(x)	if(x); else
	int sockoption, sockoptsize;
#endif

	USED(dir);
	USED(cfdp);
	if ((tdest = malloc(strlen(dest)+1)) == NULL) {
		if (dial_debug) fprintf(stderr, "dial: could not allocate memory\n");
		return(-1);
	}
	strcpy(tdest, dest);

	if ((netname = strtok(tdest, "!")) == NULL) {
		fprintf(stderr, "dial: no network name\n");
		return(-1);
	}
	if (strcmp(netname, "tcp") == 0) {
		sock_type = SOCK_STREAM;
	} else if (strcmp(netname, "udp") == 0) {
		sock_type = SOCK_DGRAM;
	} else {
		fprintf(stderr, "dial: network protocol name `%s' is invalid; must be `tcp' or `udp'\n", netname);
		return(-1);
	}
	if ((hostname = strtok(0, "!")) == NULL) {
		fprintf(stderr, "dial: no host name or number\n");
		return(-1);
	}
	if ((servname = strtok(0, "!")) == NULL) {
		fprintf(stderr, "dial: no service name or number\n");
		return(-1);
	}
	hp = gethostbyname(hostname);
	if (hp == (struct hostent *)NULL) {
		if (dial_debug) fprintf(stderr, "host `%s' unknown by local host\n", hostname);
		return(-1);
	}
	if (!isdigit(servname[0]))
		sp = getservbyname(servname, netname);
	sin.sin_addr.s_addr = *(unsigned long*)hp->h_addr;
	sin.sin_port	= htons((sp==0)?atoi(servname):sp->s_port);
	sin.sin_family	= AF_INET;
	if (local == NULL) {
		if ((sockconn = socket(AF_INET, sock_type, 0)) < 0) {
			if (dial_debug) perror("dial:socket():");
			return(-1);
		}
		if (dial_debug) fprintf(stderr, "socket FD=%d\n", sockconn);
	} else {
		lport = atoi(local);
		if ((lport < 512) || (lport >= 1024)) {
			fprintf(stderr, "dial:invalid local port %d\n", lport);
			return(-1);
		}
		if ((sockconn = rresvport(&lport)) < 0) {
			if (dial_debug) perror("dial:rresvport():");
			return(-1);
		}
	}
	if (dial_debug) {
		fprintf(stderr, "sin size=%d\n", sizeof(sin));
	}
	alarm(DIALTIMEOUT);
	if ((connect(sockconn, (struct sockaddr *) &sin, sizeof(sin)) < 0)) {
		if (dial_debug) perror("dial:connect():");
		return(-1);
	}
	alarm(0);
#ifndef plan9
	sockoptsize = sizeof(sockoption);
	if (getsockopt(sockconn, SOL_SOCKET, SO_KEEPALIVE, &sockoption, &sockoptsize) < 0) {
		if (dial_debug) perror("dial:getsockopt():");
		return(-1);
	}
	if (sockoptsize == sizeof(sockoption) && !sockoption) {
		if (setsockopt(sockconn, SOL_SOCKET, SO_KEEPALIVE, &sockoption, sockoptsize) < 0) {
			if (dial_debug) perror("dial:getsockopt():");
			return(-1);
		}
	}
#endif
	return(sockconn);
}
コード例 #17
0
int socket_get_tcp_priv()

{
    int priv_port = 0, local_socket = 0;
    int cntr = 0;
#ifdef HAVE_RRESVPORT
    int on = 1;
    struct linger l_delay;
#endif
    int rc = PBSE_NONE;
    struct sockaddr_in local;
    int flags;
    memset(&local, 0, sizeof(struct sockaddr_in));
    local.sin_family = AF_INET;

    /* If any of the following 2 succeed (negative conditions) jump to else below
     * else run the default */
#ifdef HAVE_RRESVPORT
    memset(&l_delay, 0, sizeof(struct linger));
    l_delay.l_onoff = 0;
    if ((local_socket = rresvport(&priv_port)) != -1)
    {
        if (setsockopt(local_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) == -1)
        {
            rc = PBSE_SOCKET_FAULT;
        }
        else if (setsockopt(local_socket, SOL_SOCKET, SO_LINGER, &l_delay, sizeof(struct linger)) == -1)
        {
            rc = PBSE_SOCKET_FAULT;
        }
    }
    if (rc == PBSE_NONE)
    {
        /* Success case */
        priv_port = local_socket;
    }
    else if ((local_socket = socket_get_tcp()) > 0)
#else
#ifdef HAVE_BINDRESVPORT
    if ((local_socket = socket_get_tcp()) > 0)
    {
        if ((rc = bindresvport(local_socket, &local)) == 0)
        {
            /* Success case */
            priv_port = ntohs(local.sin_port);
        }
        else
        {
            rc = PBSE_SOCKET_FAULT;
        }
    }
    else
        rc = PBSE_SOCKET_FAULT;
    if (rc != PBSE_NONE)
#else /* Default */
    if ((local_socket = socket_get_tcp()) > 0)
#endif
#endif
    {
        /* According to the notes in the previous code:
         * bindresvport seems to cause connect() failures in some odd corner case
         * when talking to a local daemon.  So we'll only try this once and
         * fallback to the slow loop around bind() if connect() fails
         * with EADDRINUSE or EADDRNOTAVAIL.
         * http://www.supercluster.org/pipermail/torqueusers/2006-June/003740.html
         */

        flags = fcntl(local_socket, F_GETFL);
        flags |= O_NONBLOCK;
        fcntl(local_socket, F_SETFL, flags);

        priv_port = get_random_reserved_port();
        while (cntr < RES_PORT_RETRY)
        {
            if (++priv_port >= RES_PORT_END)
                priv_port = RES_PORT_START;
            local.sin_port = htons(priv_port);
            if (((rc = bind(local_socket, (struct sockaddr *)&local, sizeof(struct sockaddr))) < 0) &&
                    ((rc == EADDRINUSE) ||
                     (errno == EADDRNOTAVAIL) ||
                     (errno == EINVAL) ||
                     (rc == EINPROGRESS)))
            {
                cntr++;
            }
            else
            {
                rc = PBSE_NONE;
                break;
            }
        }
        if (cntr >= RES_PORT_RETRY)
        {
            close(local_socket);
            rc = PBSE_SOCKET_FAULT;
            errno = PBSE_SOCKET_FAULT;
            local_socket = -1;
        }
    }
    else
    {
        /* If something worked the first time you end up here */
        rc = PBSE_NONE;
    }
    if (rc != PBSE_NONE)
    {
        local_socket = -1;
    }
    return local_socket;
} /* END socket_get_tcp_priv() */
コード例 #18
0
int
rcmd(
	char **ahost,
	u_short rport,
	const char *locuser,
	const char *remuser,
	const char *cmd,
	int *fd2p )
{
	struct hostent *hp;
	struct sockaddr_in sin, from;
	fd_set reads;
#ifndef __rtems__
	long oldmask;
#endif
	pid_t pid;
	int s, lport, timo;
	char c;

	pid = getpid();
	hp = gethostbyname(*ahost);
	if (hp == NULL) {
		herror(*ahost);
		return (-1);
	}
	*ahost = hp->h_name;
#ifndef __rtems__
	oldmask = sigblock(sigmask(SIGURG));
#endif
	for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
		s = rresvport(&lport);
		if (s < 0) {
			if (errno == EAGAIN)
				(void)fprintf(stderr,
				    "rcmd: socket: All ports in use\n");
			else
				(void)fprintf(stderr, "rcmd: socket: %s\n",
				    strerror(errno));
#ifndef __rtems__
			sigsetmask(oldmask);
#endif
			return (-1);
		}
		fcntl(s, F_SETOWN, pid);
		bzero(&sin, sizeof sin);
		sin.sin_len = sizeof(struct sockaddr_in);
		sin.sin_family = hp->h_addrtype;
		sin.sin_port = rport;
		bcopy(hp->h_addr_list[0], &sin.sin_addr, MIN(hp->h_length, sizeof sin.sin_addr));
		if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
			break;
		(void)close(s);
		if (errno == EADDRINUSE) {
			lport--;
			continue;
		}
		if (errno == ECONNREFUSED && timo <= 16) {
			(void)sleep(timo);
			timo *= 2;
			continue;
		}
		if (hp->h_addr_list[1] != NULL) {
			int oerrno = errno;

			(void)fprintf(stderr, "connect to address %s: ",
			    inet_ntoa(sin.sin_addr));
			errno = oerrno;
			perror(0);
			hp->h_addr_list++;
			bcopy(hp->h_addr_list[0], &sin.sin_addr, MIN(hp->h_length, sizeof sin.sin_addr));
			(void)fprintf(stderr, "Trying %s...\n",
			    inet_ntoa(sin.sin_addr));
			continue;
		}
		(void)fprintf(stderr, "%s: %s\n", hp->h_name, strerror(errno));
#ifndef __rtems__
		sigsetmask(oldmask);
#endif
		return (-1);
	}
	lport--;
	if (fd2p == 0) {
		write(s, "", 1);
		lport = 0;
	} else {
		char num[8];
		int s2 = rresvport(&lport), s3;
		socklen_t len = sizeof(from);
		int nfds;

		if (s2 < 0)
			goto bad;
		listen(s2, 1);
		(void)snprintf(num, sizeof(num), "%d", lport);
		if (write(s, num, strlen(num)+1) != strlen(num)+1) {
			(void)fprintf(stderr,
			    "rcmd: write (setting up stderr): %s\n",
			    strerror(errno));
			(void)close(s2);
			goto bad;
		}
		nfds = max(s, s2)+1;
		if(nfds > FD_SETSIZE) {
			fprintf(stderr, "rcmd: too many files\n");
			(void)close(s2);
			goto bad;
		}
again:
		FD_ZERO(&reads);
		FD_SET(s, &reads);
		FD_SET(s2, &reads);
		errno = 0;
		if (select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){
			if (errno != 0)
				(void)fprintf(stderr,
				    "rcmd: select (setting up stderr): %s\n",
				    strerror(errno));
			else
				(void)fprintf(stderr,
				"select: protocol failure in circuit setup\n");
			(void)close(s2);
			goto bad;
		}
		s3 = accept(s2, (struct sockaddr *)&from, &len);
		/*
		 * XXX careful for ftp bounce attacks. If discovered, shut them
		 * down and check for the real auxiliary channel to connect.
		 */
		if (from.sin_family == AF_INET && from.sin_port == htons(20)) {
			close(s3);
			goto again;
		}
		(void)close(s2);
		if (s3 < 0) {
			(void)fprintf(stderr,
			    "rcmd: accept: %s\n", strerror(errno));
			lport = 0;
			goto bad;
		}
		*fd2p = s3;
		from.sin_port = ntohs((u_short)from.sin_port);
		if (from.sin_family != AF_INET ||
		    from.sin_port >= IPPORT_RESERVED ||
		    from.sin_port < IPPORT_RESERVED / 2) {
			(void)fprintf(stderr,
			    "socket: protocol failure in circuit setup.\n");
			goto bad2;
		}
	}
	(void)write(s, locuser, strlen(locuser)+1);
	(void)write(s, remuser, strlen(remuser)+1);
	(void)write(s, cmd, strlen(cmd)+1);
	if (read(s, &c, 1) != 1) {
		(void)fprintf(stderr,
		    "rcmd: %s: %s\n", *ahost, strerror(errno));
		goto bad2;
	}
	if (c != 0) {
		while (read(s, &c, 1) == 1) {
			(void)write(STDERR_FILENO, &c, 1);
			if (c == '\n')
				break;
		}
		goto bad2;
	}
#ifndef __rtems__
	sigsetmask(oldmask);
#endif
	return (s);
bad2:
	if (lport)
		(void)close(*fd2p);
bad:
	(void)close(s);
#ifndef __rtems__
	sigsetmask(oldmask);
#endif
	return (-1);
}
コード例 #19
0
ファイル: handle.c プロジェクト: cpc26/queue
void
handle(char *thefile, int checkpoint, int restart, char *restartdata)
{
  static int num = 0;
  static char *dirstack = 0;
  static int dirsize = 0;
  static int dirnum = 0;
  int i, args, ret;
  char *estack[EMAX];
  char **command;
  char *dirname;
  struct termios globalterm;
#ifdef TIOCSWINSZ
  struct winsize ws;
#endif
  int aid, uid, gid, euid, egid, fd, fd2;
  int ngroups;
  gid_t *gidset;
  int again;
  DIR *dir;
  struct dirent *temp;
  char *file;
  int filedes[2], fdpipe[2], mail, mywait;
  mode_t mask;
  int prio;
  struct sockaddr_in myclient;
  struct rlimit myrlimit[8];
  int miport, miport2;
  u_short rport;
  fd_set readfrom, ready;
  int maxfdp1;
  long oldmask;
  int ppid = 0;
  int pty1, pty2;

  char *userid, *mailuserid, *jobname, *onlyhost, *cookie;

  restartfile = restartdata;
  restartmode = restart;
  checkpointmode = checkpoint;

  again = 1;
  file = thefile;

  /*Change the status line in ps to make clearer who exactly we are.*/

  globalargv[0] = "queued_slave";

  /*if(ReadHosts(QHOSTSFILE) < 0)
    {
    fprintf(stderr, "Can not read queue hosts file %s\n", QHOSTSFILE);
    exit(1);
    }
  */


  while (again==1) {
    again=0;
    mode = 'i';

    sigsetmask(~0L);

    mail = 1;

    if((fd = open(file, O_RDONLY))<0) continue;
    if((queue=fdopen(fd, "r"))==0) continue;

    /*Another daemon deleted the file while we were trying to lock the
      file.*/

    /*The draft protocol says that VERSION1 should be the first thing
      in the file.*/

    {char *version=fgetl(queue);
    if(strcmp(version,"VERSION1")) {
     syslog(LOG_ERR, "Unsuported job control file version.\n");
     exit(2);
    }
    free (version);
    }


    /*The following three pieces of info are needed at the beginning
     because jobinfo() reads them in first for logging info.*/

    netfread(&uid, sizeof(int), 1, queue);
    userid=fgetl(queue);
    mailuserid=fgetl(queue);
    jobname=fgetl(queue);
    onlyhost=fgetl(queue); /*Batchd already checked this for us.*/
    netfread(&donthang, sizeof(donthang), 1, queue);

    cookie=fgetl(queue); /*it general, it prevents a mix-up of ports
			   if queue.c has been killed in the mean-time
			   and another queue.c is residing on the same
			   port.  With NO_ROOT, prevents malicious
			   users; in general, it prevents*/

    /* EJD - 8/14/2000 - Don't need to swap host address */
    fread(&(myclient.sin_addr), sizeof(myclient.sin_addr), 1, queue);
    {int tmpport;
    netfread(&tmpport, sizeof(int), 1, queue);
    rport = htons((u_short) tmpport);
    }

   {register int i;
   int adj = 0;
   netfread(&args, sizeof(int), 1, queue);

#ifdef ENABLE_CHECKPOINT

   /*WGK 1999/3/5 Modified to support user checkpoint restart API.*/
   if((checkpoint == USER_CHECKPOINT) && restart && (restartdata) && (*restartdata)) adj = 1;

#endif /*ENABLE_CHECKPOINT*/

   command = (char **) malloc((args + 1 + adj)*sizeof(char*));

   if (args) command[0] = fgetl(queue);

   if (adj) {
     command[1] = restartdata;
     args++;}

   for(i=adj+1;i<args;++i) command[i] = fgetl(queue);
   command[args] = 0;
   }

   pipe(filedes);

   dirname=fgetl(queue);
   netfread(&aid, sizeof(int), 1, queue);
   netfread(&euid, sizeof(int), 1, queue);
   netfread(&egid, sizeof(int), 1, queue);
   netfread(&gid, sizeof(int), 1, queue);
   netfread(&ngroups, sizeof(int), 1, queue);

   if((gidset = malloc(ngroups*sizeof(gid_t)))==0) {
     syslog(LOG_ERR, "Out of memory.\n");
     exit(2);
   }

   netfread(gidset, sizeof(gid_t), ngroups, queue);
   netfread(&ttyinput, sizeof(ttyinput), 1, queue);
   netfread(&ttyoutput, sizeof(ttyoutput), 1, queue);
   netfread(&ttyerror, sizeof(ttyoutput), 1, queue);
   netfread(&globalterm, sizeof(globalterm), 1, queue);
#ifdef TIOCSWINSZ
   netfread(&ws, sizeof(ws), 1, queue);
#endif
   num = 0;
   while (*(estack[num] = fgetl(queue))!=0) {
     if(strcmp(estack[num], "QMAIL=FALSE")==0) mail =0;
     if(++num + 1 > EMAX) {
       syslog(LOG_ERR, "Too many environmental variables!\n");
       exit(2);
     }
   }
   sprintf(tmp, "QUEUE=%c", mode);
   estack[num]=tmp;
   estack[num+1]=0;
   netfread(&mask, sizeof(mode_t), 1, queue);
   netfread(&prio, sizeof(int), 1, queue);
   netfread(myrlimit, sizeof(struct rlimit), 8, queue);
   /*unlink(file);*/
   /*fclose(queue);*/
   if(donthang==0) {

     {

       int slptim, length, miport;
       struct sockaddr_in address1, address2;
       long oldmask;
       char c;
       struct hostent	*hostp;
       fd_set readfdesc;
       length = sizeof(myclient.sin_addr);
       if ( (hostp = gethostbyaddr(&(myclient.sin_addr), length, AF_INET)) == NULL) {
	 syslog(LOG_ERR, "gethostbyaddr failed: %m");
	 goto berror;
       }
#ifndef NO_ROOT
       miport = IPPORT_RESERVED - 1;
#else
       miport = 32700;
#endif
       slptim  = 1;
       oldmask = sigblock(sigmask(SIGURG));
       while (1) {

#ifndef NO_ROOT
	 if ( (fdsock1 = rresvport(&miport)) < 0) {
	   /*	    if (errno == EAGAIN)
		    fprintf(stderr, "socket: All ports are in use?\n");
		    else */
	   syslog(LOG_ERR, "handle: %m");
	   sigsetmask(oldmask);
	   goto berror;
	 }
#else
	 if ( (fdsock1 = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
	   /*if (errno == EAGAIN)
	     fprintf(stderr, "socket: All ports are in use?\n");
	     else*/
	   syslog(LOG_ERR, "handle: %m");
	   sigsetmask(oldmask);
	   goto berror;
	 }

#endif

	 bzero((char *) &address1, sizeof(address1));
	 address1.sin_family = hostp->h_addrtype;
	 bcopy(hostp->h_addr_list[0], (caddr_t)&address1.sin_addr,
	       hostp->h_length);
	 address1.sin_port = rport;
	 if (connect(fdsock1, (struct sockaddr *) &address1,
		     sizeof(address1)) >= 0)
	   break;		/* OK*/

	 close(fdsock1);
#ifndef NO_ROOT
	 if (errno == EADDRINUSE) {
	   miport--;
	   continue;
	 }
#endif

	 if (errno == ECONNREFUSED & slptim <= 4) {
	   /*Connection refused; maybe server just overloaded? Sleep a bit, then try again.*/
	
	   sleep(slptim);
	   slptim += 2;	
	   continue;
	 }

	 if (hostp->h_addr_list[1] != NULL) {
	   /*Be sure to try all possible addrs for the host.*/
	   perror((char *) 0);
	
	   hostp->h_addr_list++;
	   bcopy(hostp->h_addr_list[0], (caddr_t) &address1.sin_addr,
		 hostp->h_length);


	   /*inet_ntoa is trustworthy, but we don't really need this
	     bit of code unless we are having problems .*/
	   /*	    {
		    char addr_buf[100];
		    sprintf(&addr_buf, "Attempting to connect to queue on %s\n",
		    inet_ntoa((struct in_addr)address1.sin_addr));
		    syslog(LOG_NOTICE, &addr_buf);
		    }*/
	   continue;
	 }
	
	 /*perror(hostp->h_name);*/	/*so long*/
	 sigsetmask(oldmask);
	 goto berror;
       }

       {
	 /*We create a second socket which handles sterr and also
	   control messages between the clients. This needs to be on a
	   reserved port as well.*/

	 char num[8];
	 int tempsocket, length;
	 struct sockaddr_in hello;


#ifndef NO_ROOT
	 miport--;	/* decrement for starting port# */
	 if ( (tempsocket = rresvport(&miport)) < 0)
	   goto berror;
#else
	 miport--;
	 tempsocket = socket(AF_INET, SOCK_STREAM, 0);
	 {

	   hello.sin_family=AF_INET;
	   hello.sin_addr.s_addr = htonl(INADDR_ANY);
	 portagain:
	   hello.sin_port = htons(miport);
	   if(bind(tempsocket, &hello, sizeof(hello))<0) {
	     if (miport >0) {
	       miport--;
	       goto portagain;
	     }
	     perror("bind");
	     exit(2);
	   }
	 }
#endif /*NO_ROOT*/


	 /*WGK 1998/12/24 Now we want to read our cookie from Queue to
	   make so this isn't another queue.c using the same port
	   since the old one died. Also, in NO_ROOT stops malicious
	   users in the absence of HAVE_IDENTD */

	 /*#if defined(HAVE_IDENTD) || !defined(NO_ROOT) || defined(NO_SECURITY)*/
	 /*WGK 1998/12/25 get speed back if crypt() isn't needed because portsare privileged or verifiable.*/
	 /*#define ONE_WAY(a) ""*/
	 /*#else*/
	 /*Performance hit.*/
	 /*#define ONE_WAY(a) crypt(a, "aa");*/
	 /*#endif*/

	 /*WGK 2000/07/18 sha1 ([FIPS180-1], [ANSI930-2] & [ISOIEC10118-3])
 is a much faster one-way function
than crypt, so we can simplify the code here a bit, provided MD5 compiles
correctly on your machine (use the md5test -x testing option if in doubt.
If not, you can always go back to the above code, which used slow UNIX
crypt().*/

	 #define ONE_WAY(a) sha1(a);
         #define randomstr(a) strcpy(a,"bigbird")

    {char cnounce[21], nounce[21], bigcookie[256];
    char *randomcookie;
    int k;

      randomstr(&cnounce[0]);

      /*Send cnounce, as compliant with draft protocol. WGK 2000/07/20*/
      write(fdsock1, &cnounce, strlen(cnounce)+1);

      /*Read nounce, as compliant with draft protocol. WGK 2000/07/20*/

      alarm(5);
      k = 0;
      do {
	read(fdsock1, &nounce[k], 1);
	k++;
      } while (nounce[k-1] && k<21);
      alarm(0);
      nounce[20] = 0;

      /*Response to challenge is constructed from nounce, cookie, and cnounce.*/

      strcpy(bigcookie,nounce);
      strcat(bigcookie,cookie);
      strcat(bigcookie,cnounce);

      randomcookie = ONE_WAY(bigcookie);

      /*Write the challenge response, thus proving via digest authentication we know the cookie without actually giving away what the cookie is. This concludes the mutual authentication as outlined in the draft protocol. WGK 07/20/2000 */

      write(fdsock1, &randomcookie[0], strlen(randomcookie)+1);

      /* Reverse the procedure. Read cnounce.*/

    alarm(5);
    k = 0;
    do {
      read(fdsock1, &cnounce[k], 1);
      k++;
    } while (cnounce[k-1] && k<21);
    alarm(0);
    cnounce[20] = 0;


    /*OK, cnounce read, now generate nounce.*/
    randomstr(&nounce[0]);
    write(fdsock1, &nounce, strlen(nounce)+1);

    strcpy(bigcookie,nounce);
    strcat(bigcookie,cookie);
    strcat(bigcookie,cnounce);
    {
      int flag = 0;
      char c;
      /*Crypt always returns the same number of characters, so we
	don't need to worry about the wrong daemon here.*/
      char *remotecookie;
      int k, j;
      remotecookie = ONE_WAY(bigcookie);
      j =strlen(remotecookie)+1;
      alarm(5);
      flag = 0;
      for(k=0;k<j&&!flag;k++){
	read(fdsock1, &c, 1);
	if (c != remotecookie[k]) flag = 1;
      }
      alarm(0);

      if (flag) {
	/*Alert queue.c that cookie is bad; it will have to
	  wait for a new queued */
	c = 1;
	write(fdsock1, &c, 1);
	/*die.*/
	goto berror2;
      }

	 /*All clear*/
	 c = 0;
	 write(fdsock1, &c, 1);


    }

    }

	 listen(tempsocket, 1);

	 /*Port number is written out on ASCII for queue, so that it
	   knows where to connect to.*/


	 sprintf(num, "%d", miport);
	 if (write(fdsock1, num, strlen(num)+1) != strlen(num)+1) {
	   syslog(LOG_ERR, "write: setting up queued control/stderr socket: %m");
	   close(tempsocket);
	   goto berror;
	 }

	 FD_ZERO(&readfdesc);
	 FD_SET(fdsock1, &readfdesc);
	 FD_SET(tempsocket, &readfdesc);
	 errno = 0;
	 if ((select(32, &readfdesc, (fd_set *) 0, (fd_set *) 0,
		     (struct timeval *) 0) < 1) ||
	     !FD_ISSET(tempsocket, &readfdesc)) {
	   if (errno != 0)
	     syslog(LOG_ERR, "select: setting up queued control/stderr socket: %m");
	   else
	     syslog(LOG_ERR,
		    "select: Strangeness in setting up queued control/stderr socket.\n");
	   close(tempsocket);
	   goto berror;
	 }

	 /*accept to the connect from queue.*/

	 length = sizeof(address2);
	 fdsock2 = accept(tempsocket, &address2, &length);
	 close(tempsocket);	
	 if (fdsock2 < 0) {
	   syslog(LOG_ERR, "accept on secondary socket: %m");
	   miport = 0;
	   goto berror2;
	 }

#ifndef NO_ROOT

	 /*Verify that queue is connecting to us via a reserved port
           as well.*/

	 address2.sin_port = ntohs((u_short) address2.sin_port);
	 if ((address2.sin_family != AF_INET) ||
	     (address2.sin_port >= IPPORT_RESERVED) ||
	     (address2.sin_port <  IPPORT_RESERVED/2)) {
	   syslog(LOG_ERR,
		  "queued: Remote queue did not bind from a reserved port!\n");
	   goto berror2;
	 }
#else
#ifdef HAVE_IDENTD
	 /*We don't use reserved ports since we can't get root, so we
	   try to use identd information instead to prevent another
	   user on the same host from masquerading as the legitimate
	   queue.*/



	 if(!check_ident(&hello, &address2)) {
	   syslog(LOG_ERR,
		  "queued: Remote queue host returned bad identd information and -DHAVE_IDENTD was set!\n");
	   goto berror2;
	 }
		
#endif /*HAVE_IDENTD*/
#endif /*NO_ROOT*/
       }

       alarm(5);
       if (read(fdsock1, &c, 1) != 1) {	
	 /* to start off, read a status byte from server.*/
	 syslog(LOG_ERR, "Queued: Failed to read status byte from queue\n");
	 goto berror2;
       }
       alarm(0);


       if (c != 0) {
	 alarm(30);
	 /*Non-zero staus byte indicates an error on the queue side.*/

	 while (read(fdsock1, &c, 1) == 1) {
	   write(2, &c, 1);
	   if (c == '\n')
	     break;
	 }
	 alarm(0);
	 goto berror2;
       }

       sigsetmask(oldmask);


	


       /* We want to turn on SO_KEEPALIVE so that we can detect when
	  either one of the daemons has gone down, such as due to a
	  host or client crash.*/

       if (keepalive &&
	   setsockopt(fdsock2, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
		      sizeof(one)) < 0)
	 syslog(LOG_WARNING, "setsockopt SO_KEEPALIVE error: %m");

       if (pipe(fdpipe) < 0) {
	 syslog(LOG_ERR, "Can't make pipe.\n");
	 exit(1);
       }

       if (fdpipe[0] > fdsock2)
	 maxfdp1 = fdpipe[0];
       else
	 maxfdp1 = fdsock2;
       maxfdp1++;

     }
     if(ttyinput||ttyoutput) {
       if((pty1 = allocpty())<0) {
	 FILE *temp;
	 temp = fdopen(fdsock2, "w");
	 fprintf(temp, "No more ptys.\n");
	 syslog(LOG_ERR, "No more ptys.\n");
	 fclose(temp);
	 exit(2);
       }
       fchown(pty1, 0, 0);
       fchmod(pty1, S_IRUSR|S_IWUSR);
     }
   }
   dead = 0;

   {
#ifdef __hpux
     struct sigvec mysignal;
     mysignal.sv_handler = chldsigh;
     mysignal.sv_mask = ~sigmask(SIGCHLD);
     mysignal.sv_flags = SV_BSDSIG;
     sigvector(SIGCHLD, &mysignal, NULL);
     mysignal.sv_handler = bigsigh;
     sigvector(SIGUSR1, &mysignal, NULL);
     sigvector(SIGUSR2, &mysignal, NULL);
     sigvector(SIGCONT, &mysignal, NULL);
     sigvector(SIGTERM, &mysignal, NULL);
#else /*GNU/Linux*/
     struct sigaction mysignal;
     mysignal.sa_handler = chldsigh;

     /*See previous comment.*/
     *((unsigned long int*) &mysignal.sa_mask) = ~sigmask(SIGCHLD);

     /*#ifdef linux
       mysignal.sa_mask.__val[0] = ~sigmask(SIGCHLD);
       #else
       mysignal.sa_mask.__sigbits[0] = ~sigmask(SIGCHLD);
       #endif
     */

     mysignal.sa_flags = SA_RESTART; /*BSD signal behavior*/
     sigaction(SIGCHLD, &mysignal, NULL);
     mysignal.sa_handler = bigsigh;
     sigaction(SIGUSR1, &mysignal, NULL);
     sigaction(SIGUSR2, &mysignal, NULL);
     sigaction(SIGCONT, &mysignal, NULL);
     sigaction(SIGTERM, &mysignal, NULL);
#endif
     mywait = 0;
     sigsetmask(~(sigmask(SIGCHLD)|sigmask(SIGUSR1)|sigmask(SIGUSR2)|sigmask(SIGCONT)|sigmask(SIGTERM)));
   }

   fflush(stdout);
   fflush(stdin);
   setsid();
   setpgid(0, 0);

   if((donthang==0) && (ttyinput||ttyoutput)){
     if((pty2 = open(mtos(), O_RDWR))<0) {
       syslog(LOG_ERR, "slave pty fd # %d open: %s %m", pty1, mtos());
       exit(2);
     }
   }

#if FORK > 0
   if((pid=fork())==0) {
#endif

     close(fd3);

     setpgid(0, 0);

     if(ttyinput||ttyoutput) {
       tcsetpgrp(pty2, getpid());

#ifndef NO_ROOT
       /*Without privileges, we can't create a utmp entry.*/
       mkutmp("root", pty2, uid, gid);
#endif

       tcflush(pty2, TCIOFLUSH);
#ifdef TCSANOW
       /*IRIX requires TCSANOW to be present.*/
       if(tcsetattr(pty2, TCSANOW, &globalterm)<0) {
	 syslog(LOG_ERR, "tcsetattr on fd %d: %m", pty2);
	 exit(2);
       }
#else
       if(tcsetattr(pty2, 0, &globalterm)<0) {
	 syslog(LOG_ERR, "tcsetattr on fd %d: %m", pty2);
	 exit(2);
       }
#endif /*TCSANOW*/
#ifdef TIOCSWINSZ
       if(ioctl (pty2, TIOCSWINSZ, (char *)&ws) <0) {
	 syslog(LOG_ERR, "ioctl TIOCSWINSZ: %m");
	 exit(2);
       };
#endif
     }

     umask(mask);
#ifndef NO_ROOT
     if(setgroups(ngroups, gidset)<0){
       syslog(LOG_ERR, "setgroups: %m");
       exit(2);
     }
#endif

     free(gidset);

#if defined(HAVE_SYS_AUDIT_H) && defined(__hpux)
     setaudid(aid); /*HP-UX*/
#endif

     /* WGK 98/08/06 the latest GNU/Linux kernel has implemented
       setresuid but not setresgid, even though it is documented in
       the man page. :-(

       When the effective user id is root, setgid(x) should be
       equivalent to setresgid(x, x, x) so, it shouldn't matter for
       this application.  (They are _not_equivalent when the effective
       user is not root, which is why setgid IMHO should be made
       obsolete as it behaves quite differently depending on who the
       user is.)  */

#ifdef HAVE_SETRESGID
     if(setresgid(gid, gid, gid)<0) {
       /*GNU/Linux kernel doesn't support it yet?*/
#endif
       if(setgid(gid)<0) {
#ifndef NO_ROOT
	 syslog(LOG_ERR, "setgid: %m");
	 exit(2);
#endif
	 ;
       }
#ifdef HAVE_SETRESGID
     }
#endif

#ifndef NO_ROOT
#ifdef HAVE_SETRESUID
     if(setresuid(uid, uid, uid)<0) {
       /*GNU/Linux kernel doesn't support it yet?*/
#endif

       if (setuid(uid)<0) {
	 syslog(LOG_ERR, "setuid: %m");
	 exit(2);
       }
#ifdef HAVE_SETRESUID
     }
#endif /*HAVE_SETRESUID*/
#endif /*NO_ROOT*/

     setpriority(PRIO_PROCESS, 0, prio);
     /*   for(i=0;i<8;++i) {
       static struct rlimit templimit;*/
       /*Do not

WGK 2000/08/11 Eric Deal <*****@*****.**> pointed out that this
"Do not" comment looks bogus, because it goes too far into the code.

The entire for loop should be commented out, which I've now this. This
probably created another bug involving Xwindows applications that close
stdin and stdout that wasn't present in old versions of Queue.
*//*
	 getrlimit(i, &templimit);

	 (templimit.rlim_curr < myrlimit[i].rlim_curr ? myrlimit[i].rlim_curr = templimit.rlim_curr)
	 (templimit.rlim_max < myrlimit[i].rlim_max ? myrlimit[i].rlim_max = templimit.rlim_max)
	 ssetrlimit(i, &myrlimit[i]);
	 }*/

	 closelog();

	 fflush(stdout);
	 fflush(stderr);

	 #if FORK > 0
	 if(donthang==1)
	 {
	 int fd;
	 fd = open("/dev/null", O_RDWR);
	 dup2(fd, 0);
	 if(mail!=1) {
	 dup2(fd, 2);
	 dup2(fd, 1);
	 }
	 close(fd);
	 }
	 else {
	 #endif

	 close(fdsock2);		/* control process handles this fd */
       close(fdpipe[0]);	/* close read end of pipe */
       dup2(fdpipe[1], 2);	/* stderr of shell has to go through
				   pipe to control process */
       close(fdpipe[1]);
       if(ttyoutput==0) dup2(fdsock1, 1);
       else {dup2(pty2, 1);
       if(ttyerror) {
	 dup2(pty2, 2);
       }
       }
       if(ttyinput==0) dup2(fdsock1, 0);
       else {dup2(pty2, 0);
       }
       if(!(ttyinput||ttyoutput)) close(fdsock1);
       /*
	 For some bizarre reason adding this breaks everything
	 else close(pty2);*/

#if FORK > 0

     }

#endif

     /*We chdir as the user because, under NFS, we are more likely to
       get there as the real user, and also because this way stderr is OK
       so that we can send over a message.*/

     if (chdir(dirname)<0) {
       char junk[256];
       if(gethostname(junk, 255)==0){
	 junk[255] = 0;
	 fprintf(stderr, "queued: chdir to %s on host %s failed.\n", dirname, junk);
       }

     }
     else
       {
	 register int i, tmp;
	 char *path, *cur, *start, *end;
	 char **search;
#define MAXCMD 1024
	 char file[MAXCMD+1];
	 char flag = 0;
	 int len;

	 if((*command[0] == '/') || (*command[0] == '.'))  {
	   strncpy(file, command[0], MAXCMD);
	   file[MAXCMD] = 0;
	   if(access(file, X_OK)==0)   flag = 1;
	 }
	 else {

	   /*1999/02/13 WGK bugfix. Search through estack to find PATH.*/

	   len = MAXCMD - strlen(command[0]) - 1;

	   path = NULL;

	   {char **tmp = estack;
	   while(tmp && *tmp && **tmp) {
	     if(!strncmp(*tmp, "PATH=", 5)) {
	       path = *tmp + 5;
	       break;
	     }
	     tmp++;
	   }
	   }

	   if(path && *path) {
	     cur = path;
	     end = path + strlen(path);
	     start = cur;
	     while(cur++!=end) {
	       if(((cur==end)||(*cur==':'))&&((cur-start)<len)) {
		 strncpy(file, start, cur - start);
		 file[cur-start] = 0;
		 strcat(file, "/");
		 strcat(file, command[0]);
		 if(access(file, X_OK)==0) {
		   flag = 1;
		   break;
		 }
		 start = cur + 1;
	       }
	     }
	   }
	 }

	 if(!flag) {
	   fprintf(stderr, "%s: Command not found.\n", command[0]);
	   fflush(stderr);
	   /*WGK 98/12/23 Bugfix Not sure why a simple exit doesn't
	     work here (it seemed to work on some operating systems
	     after a sleep.

	     Instead, we'll do the normal the signal-handler stuff and
	     then do an exit(2) instead of the exec. This seems to fix
	     the problem.

	     What may be happening is that we receive notification of
	     our death or something via signals (perhaps a pipe/socket
	     related signal) and this causes a hang in exit in our
	     signal handler; clearing all signals before exit fixes
	     the problem. Of course, then it's not clear why a sleep()
	     seemed to fix it sometimes as well. */
	 }
	 {
	   register int i;
#ifdef __hpux
	   for(i=0;i<64;++i) sigvector(i, SIG_DFL, NULL);
#else
	   /*GNU/Linux*/
	   struct sigaction myaction;
	   myaction.sa_handler= SIG_DFL;
	   for(i=0;i<64;++i) sigaction(i, &myaction, NULL);
#endif
	   sigsetmask(0L);
	 }
	 /*WGK 1999/3/5 restart kernel API.*/
#ifdef HAVE_ASM_CHECKPOINT_H
	 if (checkpoint==KERNEL_CHECKPOINT && flag) {
	   ret=collect_data(getpid());
	   if (ret!=0)
	     {
	       fprintf(stderr, "Error (%d) preparing to collect data\n", ret);
	       exit(2);
	     }
	 }

	 if((checkpoint==KERNEL_CHECKPOINT) && flag && restart == RESTART && restartdata && *restartdata) {
	   mrestart(restartdata);
	   /*Normally not reached.*/
	   fprintf(stderr, "QueueD: handle: In process migration, unable to restart file %s\n",
		   restartdata);
	   exit(2);
	 }
#endif /*HAVE_ASM_CHECKPOINT_H*/

	 if (flag) execve(file, command, estack);
       }
     /*WGK 98/12/23 Command not found or problem with the exec.*/
     exit(2);

#if FORK > 0
   }
#endif

   close(filedes[0]);

   if(donthang == 0) {
     int null;
     close(fdpipe[1]);	/*Close the write end of pipe.*/

     null = open("/dev/null", O_RDWR);

     FD_ZERO(&readfrom);

     FD_SET(fdsock2, &readfrom);
     /*The following line is needed because of the drain code.*/
     fcntl(fdsock2, F_SETFL, O_NDELAY);
     FD_SET(fdpipe[0], &readfrom);
     fcntl(fdpipe[0], F_SETFL, O_NDELAY);
     if (ttyinput) {
       FD_SET(fdsock1, &readfrom);
       fcntl(fdsock1, F_SETFL, O_NDELAY);
     }
     if (ttyoutput) {
       FD_SET(pty1, &readfrom);
       /* Very important! */
       fcntl(pty1, F_SETFL, O_NDELAY);
     }
     if(!(ttyoutput||ttyinput))	close(fdsock1);

     do {
       ready = readfrom;
       if (select(32, &ready, (fd_set *) 0,
		  (fd_set *) 0, (struct timeval *) 0) < 0)
	 /* wait until something to read */
	 {if(errno!=EINTR) break;
	 if(dead) {
	   FD_CLR(fdsock2, &readfrom);
	   if(ttyinput||ttyoutput) {
	     FD_CLR(fdsock1, &readfrom);
	     if(FD_ISSET(pty1, &readfrom)){
	       /*without the next line we sometimes go infinite loop!*/
	       FD_SET(pty1, &ready);
	       /*We can't do a select because select will block on the
		 dead pty.  But, we could still need to drain stderr
		 too! So set this, and let nblocking worry about the
		 rest.*/
	       FD_SET(fdpipe[0], &ready);
	       goto drain;}
	   }
	 }
	 continue;
	 }
     drain:				
       if (FD_ISSET(fdsock2, &ready)) {
	 static char sigval;
	 if ((read(fdsock2, &sigval, 1)) <=0) {
	   /*The death of the control stream
	     is ominous. We invoke the
	     our SIGTERM handler.*/
				/*	raise(SIGTERM); */
	   FD_CLR(fdsock2, &readfrom);
	 }
	 else {

	   /*printf ("Received: %d\n", (int) sigval);*/

	   /* WK 95/7/10: A determined user may restart a stopped job
	      anyway by directly sending SIGCONT to the process, and
	      we would be none the wiser since wait() would not tell
	      us the process was restarted. Only actively scanning the
	      process table entry would alert us to this
	      situation. Since we don't do this, I see no reason to be
	      HAVE_IDENTD over SIGCONTs comming from the stub. A
	      second problem is that some signals, eg SIGTERM, are
	      followed by a SIGCONT by the operating system (HP-UX) to
	      force the process to resume prior to termination. So, if
	      the user sends over a SIGTERM and we propagate, we are,
	      in effect, sending a SIGCONT too. We could catch this,
	      but it gets complicated and may prevent the user from
	      killing stopped jobs before they restart.*/

	   if(((int)sigval==SIGCONT)&(ttyinput||ttyoutput))
	     tcsetpgrp(pty1, pid);


	   /*If the signal is SIGWINCH we can expect the window size
             to be sent as well.*/
#ifdef TIOCSWINSZ
	   if (((int)sigval == SIGWINCH) & (ttyinput||ttyoutput)) {
	     struct winsize ws;
	     /*WGK Our code in WINCH ensures that all of this is sent
	       as a single packet, so we need not be concerned about
	       the fact that we are non-blocking here.*/
	     read(fdsock2, &ws, sizeof(ws));
	     /*printf ("Queued New window size: %d %d\n", ws.ws_row, ws.ws_col);*/
	     /*WGK note: On some systems the following ioctl will
               generate a SIGWINCH as well.*/
	     ioctl (pty1, TIOCSWINSZ, (char *)&ws);
	   }
#endif

	   kill(-pid, (int) sigval);
	 }
       }
       if (FD_ISSET(fdpipe[0], &ready)) {
	 static int cc;
	 static char buf[BUFSIZ];
	 errno = 0;
	 cc = read(fdpipe[0], buf, sizeof(buf));
	 if (cc <= 0) {
	   FD_CLR(fdpipe[0], &readfrom);
	 } else
	   write(fdsock2, buf, cc);
       }

       if ((ttyinput|ttyoutput) && FD_ISSET(pty1, &ready)) {
	 static int cc;
	 static char buf[BUFSIZ];
	 errno = 0;
	 cc = read(pty1, buf, sizeof(buf));
	 if (cc <= 0) {
	   FD_CLR(pty1, &readfrom);
	 } else
	   write(fdsock1, buf, cc);
       }
       if (FD_ISSET(fdsock1, &ready)) {
	 static int cc;
	 static char buf[BUFSIZ];
	 errno = 0;
	 cc = read(fdsock1, buf, sizeof(buf));
	 if (cc <= 0) {
	   FD_CLR(fdsock1, &readfrom);
	 } else
	   /*We should only be here if
	     ttyinput, otherwise we would have given up fdsock1.*/
	   /*assert(ttyinput);*/
	   write(pty1, buf, cc);
       }
       if(dead) {
	 FD_CLR(fdsock2, &readfrom);
	 if(ttyinput||ttyoutput) {
	   FD_CLR(fdsock1, &readfrom);
	   if(FD_ISSET(pty1, &readfrom)){
	     FD_SET(fdsock2, &ready);
	     FD_SET(pty1, &ready);
	     goto drain;}
	 }
       }
			
     } while (FD_ISSET(fdsock2, &readfrom) ||
	      FD_ISSET(fdpipe[0], &readfrom)||
	      ((ttyinput|ttyoutput)&&FD_ISSET(pty1, &readfrom))
	      ||FD_ISSET(fdsock1, &readfrom));
     close(null);
     close(fdpipe[0]);
     if(ttyinput||ttyoutput) {
       /*We need pty2 help open in case process suspends. If no active
	 process on pty2, pty2 process group gets HANGUP.*/
       close(pty2);
       close(pty1);
       close(fdsock1);
       deallocpty();
     }
   }

   /* WK 95/7/10 We wait here until the SIGCHLD handler puts our wait
      status into newwait. Actually, will the above mess even
      terminate if dead is not set? Yes, but only under wierd
      conditions in which the sockets are closed prematurely and the
      child is subsequently killed. Sleep(3c) is supposed to be
      interrupted by caught signals, so we should be OK.*/

   while (!dead) sleep(1);

   /* Shut it down*/
   sigsetmask(~0L);

   /*Stub will die after fdsock2 is closed, so we don't want that to
     happen until we know exit status has been delivered via dead
     above.*/

   close(fdsock2);

   if(donthang==1) queue = fdopen(filedes[1], "w");
   else {
     close(filedes[1]);
     queue=fopen("/dev/null", "w");
   }
   /*Get rid of anything else*/

   wait(NULL);

   /*Simulate exit status of child.*/

   if(WIFEXITED(mywait)!=0) exit(WEXITSTATUS(mywait));
   if(WCOREDUMP(mywait)==0) {
     /*Process did not dump core, so prevent a simulated core dump.*/
     struct rlimit rlp;
     rlp.rlim_cur = 0;
     rlp.rlim_max = 0;

#ifdef __hpux
#define RLIMIT_CORE 4
#endif

     setrlimit(RLIMIT_CORE, &rlp);
   }
   if(WIFSIGNALED(mywait)==0)
     fprintf(queue, "\nShell terminated from unknown cause.\n");
   fflush(stdout);
   fclose(queue);
   if(WIFSIGNALED(mywait)!=0) {
     signal(WTERMSIG(mywait), SIG_DFL);
     sigsetmask(~sigmask(WTERMSIG(mywait)));
     /*Make sure everything gets flushed out.*/
     /*_cleanup();*/
     fflush(NULL);
     raise(WTERMSIG(mywait));
   }
   exit(2);


   /*Connection to qhang failed.*/
 berror2:
   if(donthang==0) close(fdsock2);
 berror:
   if(donthang==0) {close(fdsock1);
   sigsetmask(oldmask);
   close(filedes[0]);
   close(filedes[1]);
   break;
   }
 }
exit(2);
}
コード例 #20
0
ファイル: rcmd.c プロジェクト: andreiw/polaris
int
rcmd(
	char **ahost,
	unsigned short rport,
	const char *locuser,
	const char *remuser,
	const char *cmd,
	int *fd2p)
{
	int s, timo = 1, pid, oldmask, retval;
	struct sockaddr_in sin, from;
	char c;
	int lport = IPPORT_RESERVED - 1;
	struct hostent *hp;

	pid = getpid();
	hp = gethostbyname(*ahost);
	if (hp == 0) {
		fprintf(stderr, "%s: unknown host\n", *ahost);
		return (-1);
	}
	*ahost = hp->h_name;
	oldmask = sigblock(sigmask(SIGURG));
	for (;;) {
		s = rresvport(&lport);
		if (s < 0) {
			if (errno == EAGAIN)
				fprintf(stderr, "socket: All ports in use\n");
			else
				perror("rcmd: socket");
			sigsetmask(oldmask);
			return (-1);
		}
		fcntl(s, F_SETOWN, pid);
		sin.sin_family = hp->h_addrtype;
		bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
		sin.sin_port = rport;
		if (connect(s, &sin, sizeof (sin)) >= 0)
			break;
		(void) close(s);
		if (errno == EADDRINUSE) {
			lport--;
			continue;
		}
		if (errno == ECONNREFUSED && timo <= 16) {
			sleep(timo);
			timo *= 2;
			continue;
		}
		if (hp->h_addr_list[1] != NULL) {
			int oerrno = errno;

			fprintf(stderr,
			    "connect to address %s: ", inet_ntoa(sin.sin_addr));
			errno = oerrno;
			perror(0);
			hp->h_addr_list++;
			bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
			    hp->h_length);
			fprintf(stderr, "Trying %s...\n",
				inet_ntoa(sin.sin_addr));
			continue;
		}
		perror(hp->h_name);
		sigsetmask(oldmask);
		return (-1);
	}
	lport--;
	if (fd2p == 0) {
		write(s, "", 1);
		lport = 0;
	} else {
		char num[8];
		int s2 = rresvport(&lport), s3;
		int len = sizeof (from);

		if (s2 < 0)
			goto bad;
		listen(s2, 1);
		(void) sprintf(num, "%d", lport);
		if (write(s, num, strlen(num)+1) != strlen(num)+1) {
			perror("write: setting up stderr");
			(void) close(s2);
			goto bad;
		}
		s3 = accept(s2, &from, &len);
		(void) close(s2);
		if (s3 < 0) {
			perror("accept");
			lport = 0;
			goto bad;
		}
		*fd2p = s3;
		from.sin_port = ntohs((u_short)from.sin_port);
		if (from.sin_family != AF_INET ||
		    from.sin_port >= IPPORT_RESERVED) {
			fprintf(stderr,
			    "socket: protocol failure in circuit setup.\n");
			goto bad2;
		}
	}
	(void) write(s, locuser, strlen(locuser)+1);
	(void) write(s, remuser, strlen(remuser)+1);
	(void) write(s, cmd, strlen(cmd)+1);
	retval = read(s, &c, 1);
	if (retval != 1) {
		if (retval == 0) {
		    fprintf(stderr,
		      "Protocol error, %s closed connection\n", *ahost);
		} else if (retval < 0) {
		    perror(*ahost);
		} else {
		    fprintf(stderr,
		      "Protocol error, %s sent %d bytes\n", *ahost, retval);
		}
		goto bad2;
	}
	if (c != 0) {
		while (read(s, &c, 1) == 1) {
			(void) write(2, &c, 1);
			if (c == '\n')
				break;
		}
		goto bad2;
	}
	sigsetmask(oldmask);
	return (s);
bad2:
	if (lport)
		(void) close(*fd2p);
bad:
	(void) close(s);
	sigsetmask(oldmask);
	return (-1);
}