示例#1
0
/*	Initializes the API used by the client for all the communication functions.
*	If the initialization is correct, a prompt is shown as part of the shell.
*/
int main (int argc, char const *argv[]) {

	signal(SIGINT, csignal);
	loadCommands();
	__connect();
	printf(MSG_CLIENT_CONNECTED);
	char input[INPUT_SIZE];
	int n;

	while (1) {

		printf(MSG_PROMPT);
		fflush(stdout);
		//	getLine(input);
		fgets(input, INPUT_SIZE - 16, stdin);
		int len = strlen(input);
		if (len > 0 && input[len - 1] == '\n')
			input[len - 1] = '\0';
		parse(input);
	}

	printf(ANSI_COLOR_RESET "Cliente termina\n");

	return 0;
}
static int
open_socket (void)
{
  int sock = __socket (PF_UNIX, SOCK_STREAM, 0);
  if (sock < 0)
    return -1;

  /* Make socket non-blocking.  */
  int fl = __fcntl (sock, F_GETFL);
  if (fl != -1)
    __fcntl (sock, F_SETFL, fl | O_NONBLOCK);

  struct sockaddr_un sun;
  sun.sun_family = AF_UNIX;
  strcpy (sun.sun_path, _PATH_NSCDSOCKET);
  if (__connect (sock, (struct sockaddr *) &sun, sizeof (sun)) < 0
      && errno != EINPROGRESS)
    goto out;

  struct pollfd fds[1];
  fds[0].fd = sock;
  fds[0].events = POLLOUT | POLLERR | POLLHUP;
  if (__poll (fds, 1, 5 * 1000) > 0)
    /* Success.  We do not check for success of the connect call here.
       If it failed, the following operations will fail.  */
    return sock;

 out:
  close_not_cancel_no_status (sock);

  return -1;
}
示例#3
0
/*
 * Create a socket that is locally bound to a non-reserve port. For
 * any failures, -1 is returned which will cause the RPC code to
 * create the socket.
 */
int
internal_function
__get_socket (struct sockaddr_in *saddr)
{
  int so = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (so < 0)
    return -1;

  struct sockaddr_in laddr;
  socklen_t namelen = sizeof (laddr);
  laddr.sin_family = AF_INET;
  laddr.sin_port = 0;
  laddr.sin_addr.s_addr = htonl (INADDR_ANY);

  int cc = __bind (so, (struct sockaddr *) &laddr, namelen);
  if (__glibc_unlikely (cc < 0))
    {
    fail:
      __close (so);
      return -1;
    }

  cc = __connect (so, (struct sockaddr *) saddr, namelen);
  if (__glibc_unlikely (cc < 0))
    goto fail;

  return so;
}
示例#4
0
static void
log_threaded_dest_driver_do_work(gpointer data)
{
  LogThrDestDriver *self = (LogThrDestDriver *)data;
  gint timeout_msec = 0;

  self->suspended = FALSE;
  log_threaded_dest_driver_stop_watches(self);

  if (!self->worker.connected)
    {
      __connect(self);
    }

  else if (log_queue_check_items(self->queue, &timeout_msec,
                                        log_threaded_dest_driver_message_became_available_in_the_queue,
                                        self, NULL))
    {
      log_threaded_dest_driver_do_insert(self);
      if (!self->suspended)
        log_threaded_dest_driver_start_watches(self);
    }
  else if (timeout_msec != 0)
    {
      log_queue_reset_parallel_push(self->queue);
      iv_validate_now();
      self->timer_throttle.expires = iv_now;
      timespec_add_msec(&self->timer_throttle.expires, timeout_msec);
      iv_timer_register(&self->timer_throttle);
    }
}
示例#5
0
static void
internal_function
openlog_internal(const char *ident, int logstat, int logfac)
{
	if (ident != NULL)
		LogTag = ident;
	LogStat = logstat;
	if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
		LogFacility = logfac;

	int retry = 0;
	while (retry < 2) {
		if (LogFile == -1) {
			SyslogAddr.sun_family = AF_UNIX;
			(void)strncpy(SyslogAddr.sun_path, _PATH_LOG,
				      sizeof(SyslogAddr.sun_path));
			if (LogStat & LOG_NDELAY) {
				if ((LogFile = __socket(AF_UNIX, LogType, 0))
				    == -1)
					return;
				(void)__fcntl(LogFile, F_SETFD, 1);
			}
		}
		if (LogFile != -1 && !connected)
		{
			int old_errno = errno;
			if (__connect(LogFile, &SyslogAddr, sizeof(SyslogAddr))
			    == -1)
			{
				int saved_errno = errno;
				int fd = LogFile;
				LogFile = -1;
				(void)__close(fd);
				__set_errno (old_errno);
				if (saved_errno == EPROTOTYPE)
				{
					/* retry with the other type: */
					LogType = (LogType == SOCK_DGRAM
						   ? SOCK_STREAM : SOCK_DGRAM);
					++retry;
					continue;
				}
			} else
				connected = 1;
		}
		break;
	}
}
示例#6
0
文件: client.c 项目: kpjjpk/so-tp1
int __get_product(product_name name, Product * productp){
	char toSend[sizeof(product_name_msg)];
	msg_type resp_type;
	char resp_body[sizeof(product_resp)];
	
	__connect();
	msg_serialize_product_name_msg(__get_id(), GET_PRODUCT, name, toSend);
	__send(toSend, sizeof(product_name_msg));
	__recv(&resp_type, sizeof(msg_type));

	if (resp_type == OK_RESP) {
		__recv(resp_body, sizeof(Product));
		msg_deserialize_product(resp_body, productp);
		__disconnect();
		return OK;
	}
	return __handle_not_ok_resp(resp_type);
}
示例#7
0
文件: client.c 项目: kpjjpk/so-tp1
int __write_product(product_name name, int quantity){
	char toSend[sizeof(product_msg)];
	msg_type resp_type;
	char resp_body[sizeof(error_resp)];
	int code;

	__connect();	
	msg_serialize_product_msg(__get_id(), WRITE_PRODUCT, product_new(name, quantity), toSend);
	__send(toSend, sizeof(product_msg));
	__recv(&resp_type, sizeof(msg_type));
	if (resp_type == OK_RESP) {
		__recv(resp_body, sizeof(int));
		msg_deserialize_code(resp_body, &code);
		__disconnect();
		return OK;
	}
	return __handle_not_ok_resp(resp_type);
}
示例#8
0
文件: dcc7.c 项目: clokep/libgadu
int connect(int socket, const struct sockaddr *address, socklen_t address_len)
#endif
{
	struct sockaddr_in sin;
#ifdef _WIN32
	int ret;
#endif

	if (connected && test_mode == TEST_MODE_SEND_NAT) {
		memcpy(&sin, address, address_len);
		sin.sin_addr.s_addr = INADDR_NONE;
		address = (struct sockaddr*) &sin;
	}

#ifdef _WIN32
	gg_win32_hook_set_enabled(&connect_hook, 0);
	ret = connect(socket, address, address_len);
	gg_win32_hook_set_enabled(&connect_hook, 1);

	return ret;
#else
	return __connect(socket, address, address_len);
#endif
}
示例#9
0
static void test_blocking_connection(void) {
    redisContext *c;
    redisReply *reply;
    int major, minor;

    test("Returns error when host cannot be resolved: ");
    c = redisConnect((char*)"idontexist.local", 6379);
    test_cond(c->err == REDIS_ERR_OTHER &&
        strcmp(c->errstr,"Can't resolve: idontexist.local") == 0);
    redisFree(c);

    test("Returns error when the port is not open: ");
    c = redisConnect((char*)"localhost", 56380);
    test_cond(c->err == REDIS_ERR_IO &&
        strcmp(c->errstr,"Connection refused") == 0);
    redisFree(c);

    __connect(&c);
    test("Is able to deliver commands: ");
    reply = redisCommand(c,"PING");
    test_cond(reply->type == REDIS_REPLY_STATUS &&
        strcasecmp(reply->str,"pong") == 0)
    freeReplyObject(reply);

    /* Switch to DB 9 for testing, now that we know we can chat. */
    reply = redisCommand(c,"SELECT 9");
    freeReplyObject(reply);

    /* Make sure the DB is emtpy */
    reply = redisCommand(c,"DBSIZE");
    if (reply->type != REDIS_REPLY_INTEGER || reply->integer != 0) {
        printf("Database #9 is not empty, test can not continue\n");
        exit(1);
    }
    freeReplyObject(reply);

    test("Is a able to send commands verbatim: ");
    reply = redisCommand(c,"SET foo bar");
    test_cond (reply->type == REDIS_REPLY_STATUS &&
        strcasecmp(reply->str,"ok") == 0)
    freeReplyObject(reply);

    test("%%s String interpolation works: ");
    reply = redisCommand(c,"SET %s %s","foo","hello world");
    freeReplyObject(reply);
    reply = redisCommand(c,"GET foo");
    test_cond(reply->type == REDIS_REPLY_STRING &&
        strcmp(reply->str,"hello world") == 0);
    freeReplyObject(reply);

    test("%%b String interpolation works: ");
    reply = redisCommand(c,"SET %b %b","foo",3,"hello\x00world",11);
    freeReplyObject(reply);
    reply = redisCommand(c,"GET foo");
    test_cond(reply->type == REDIS_REPLY_STRING &&
        memcmp(reply->str,"hello\x00world",11) == 0)

    test("Binary reply length is correct: ");
    test_cond(reply->len == 11)
    freeReplyObject(reply);

    test("Can parse nil replies: ");
    reply = redisCommand(c,"GET nokey");
    test_cond(reply->type == REDIS_REPLY_NIL)
    freeReplyObject(reply);

    /* test 7 */
    test("Can parse integer replies: ");
    reply = redisCommand(c,"INCR mycounter");
    test_cond(reply->type == REDIS_REPLY_INTEGER && reply->integer == 1)
    freeReplyObject(reply);

    test("Can parse multi bulk replies: ");
    freeReplyObject(redisCommand(c,"LPUSH mylist foo"));
    freeReplyObject(redisCommand(c,"LPUSH mylist bar"));
    reply = redisCommand(c,"LRANGE mylist 0 -1");
    test_cond(reply->type == REDIS_REPLY_ARRAY &&
              reply->elements == 2 &&
              !memcmp(reply->element[0]->str,"bar",3) &&
              !memcmp(reply->element[1]->str,"foo",3))
    freeReplyObject(reply);

    /* m/e with multi bulk reply *before* other reply.
     * specifically test ordering of reply items to parse. */
    test("Can handle nested multi bulk replies: ");
    freeReplyObject(redisCommand(c,"MULTI"));
    freeReplyObject(redisCommand(c,"LRANGE mylist 0 -1"));
    freeReplyObject(redisCommand(c,"PING"));
    reply = (redisCommand(c,"EXEC"));
    test_cond(reply->type == REDIS_REPLY_ARRAY &&
              reply->elements == 2 &&
              reply->element[0]->type == REDIS_REPLY_ARRAY &&
              reply->element[0]->elements == 2 &&
              !memcmp(reply->element[0]->element[0]->str,"bar",3) &&
              !memcmp(reply->element[0]->element[1]->str,"foo",3) &&
              reply->element[1]->type == REDIS_REPLY_STATUS &&
              strcasecmp(reply->element[1]->str,"pong") == 0);
    freeReplyObject(reply);

    {
        /* Find out Redis version to determine the path for the next test */
        const char *field = "redis_version:";
        char *p, *eptr;

        reply = redisCommand(c,"INFO");
        p = strstr(reply->str,field);
        major = strtol(p+strlen(field),&eptr,10);
        p = eptr+1; /* char next to the first "." */
        minor = strtol(p,&eptr,10);
        freeReplyObject(reply);
    }

    test("Returns I/O error when the connection is lost: ");
    reply = redisCommand(c,"QUIT");
    if (major >= 2 && minor > 0) {
        /* > 2.0 returns OK on QUIT and read() should be issued once more
         * to know the descriptor is at EOF. */
        test_cond(strcasecmp(reply->str,"OK") == 0 &&
            redisGetReply(c,(void**)&reply) == REDIS_ERR);
        freeReplyObject(reply);
    } else {
        test_cond(reply == NULL);
    }

    /* On 2.0, QUIT will cause the connection to be closed immediately and
     * the read(2) for the reply on QUIT will set the error to EOF.
     * On >2.0, QUIT will return with OK and another read(2) needed to be
     * issued to find out the socket was closed by the server. In both
     * conditions, the error will be set to EOF. */
    assert(c->err == REDIS_ERR_EOF &&
        strcmp(c->errstr,"Server closed the connection") == 0);
    redisFree(c);

    __connect(&c);
    test("Returns I/O error on socket timeout: ");
    struct timeval tv = { 0, 1000 };
    assert(redisSetTimeout(c,tv) == REDIS_OK);
    test_cond(redisGetReply(c,(void**)&reply) == REDIS_ERR &&
        c->err == REDIS_ERR_IO && errno == EAGAIN);
    redisFree(c);

    /* Context should be connected */
    __connect(&c);
}
示例#10
0
/*
 * Create a client handle for a tcp/ip connection.
 * If *sockp<0, *sockp is set to a newly created TCP socket and it is
 * connected to raddr.  If *sockp non-negative then
 * raddr is ignored.  The rpc/tcp package does buffering
 * similar to stdio, so the client must pick send and receive buffer sizes,];
 * 0 => use the default.
 * If raddr->sin_port is 0, then a binder on the remote machine is
 * consulted for the right port number.
 * NB: *sockp is copied into a private area.
 * NB: It is the clients responsibility to close *sockp.
 * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
 * something more useful.
 */
CLIENT *
clnttcp_create (struct sockaddr_in *raddr, u_long prog, u_long vers,
		int *sockp, u_int sendsz, u_int recvsz)
{
  CLIENT *h;
  struct ct_data *ct;
  struct rpc_msg call_msg;

  h = (CLIENT *) mem_alloc (sizeof (*h));
  ct = (struct ct_data *) mem_alloc (sizeof (*ct));
  if (h == NULL || ct == NULL)
    {
      struct rpc_createerr *ce = &get_rpc_createerr ();
      (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
      ce->cf_stat = RPC_SYSTEMERROR;
      ce->cf_error.re_errno = ENOMEM;
      goto fooy;
    }

  /*
   * If no port number given ask the pmap for one
   */
  if (raddr->sin_port == 0)
    {
      u_short port;
      if ((port = pmap_getport (raddr, prog, vers, IPPROTO_TCP)) == 0)
	{
	  mem_free ((caddr_t) ct, sizeof (struct ct_data));
	  mem_free ((caddr_t) h, sizeof (CLIENT));
	  return ((CLIENT *) NULL);
	}
      raddr->sin_port = htons (port);
    }

  /*
   * If no socket given, open one
   */
  if (*sockp < 0)
    {
      *sockp = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
      (void) bindresvport (*sockp, (struct sockaddr_in *) 0);
      if ((*sockp < 0)
	  || (__connect (*sockp, (struct sockaddr *) raddr,
			 sizeof (*raddr)) < 0))
	{
	  struct rpc_createerr *ce = &get_rpc_createerr ();
	  ce->cf_stat = RPC_SYSTEMERROR;
	  ce->cf_error.re_errno = errno;
	  if (*sockp >= 0)
	    (void) __close (*sockp);
	  goto fooy;
	}
      ct->ct_closeit = TRUE;
    }
  else
    {
      ct->ct_closeit = FALSE;
    }

  /*
   * Set up private data struct
   */
  ct->ct_sock = *sockp;
  ct->ct_wait.tv_usec = 0;
  ct->ct_waitset = FALSE;
  ct->ct_addr = *raddr;

  /*
   * Initialize call message
   */
  call_msg.rm_xid = _create_xid ();
  call_msg.rm_direction = CALL;
  call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  call_msg.rm_call.cb_prog = prog;
  call_msg.rm_call.cb_vers = vers;

  /*
   * pre-serialize the static part of the call msg and stash it away
   */
  xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE);
  if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg))
    {
      if (ct->ct_closeit)
	{
	  (void) __close (*sockp);
	}
      goto fooy;
    }
  ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
  XDR_DESTROY (&(ct->ct_xdrs));

  /*
   * Create a client handle which uses xdrrec for serialization
   * and authnone for authentication.
   */
  xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz,
		 (caddr_t) ct, readtcp, writetcp);
  h->cl_ops = (struct clnt_ops *) &tcp_ops;
  h->cl_private = (caddr_t) ct;
  h->cl_auth = authnone_create ();
  return h;

fooy:
  /*
   * Something goofed, free stuff and barf
   */
  mem_free ((caddr_t) ct, sizeof (struct ct_data));
  mem_free ((caddr_t) h, sizeof (CLIENT));
  return ((CLIENT *) NULL);
}
示例#11
0
int
rtime (struct sockaddr_in *addrp, struct rpc_timeval *timep,
       struct rpc_timeval *timeout)
{
  int s;
  struct pollfd fd;
  int milliseconds;
  int res;
  /* RFC 868 says the time is transmitted as a 32-bit value.  */
  uint32_t thetime;
  struct sockaddr_in from;
  int fromlen;
  int type;

  if (timeout == NULL)
    type = SOCK_STREAM;
  else
    type = SOCK_DGRAM;

  s = __socket (AF_INET, type, 0);
  if (s < 0)
    return (-1);

  addrp->sin_family = AF_INET;
  addrp->sin_port = htons (IPPORT_TIMESERVER);
  if (type == SOCK_DGRAM)
    {
      res = __sendto (s, (char *) &thetime, sizeof (thetime), 0,
		      (struct sockaddr *) addrp, sizeof (*addrp));
      if (res < 0)
	{
	  do_close (s);
	  return -1;
	}
      milliseconds = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
      fd.fd = s;
      fd.events = POLLIN;
      do
	res = __poll (&fd, 1, milliseconds);
      while (res < 0 && errno == EINTR);
      if (res <= 0)
	{
	  if (res == 0)
	    __set_errno (ETIMEDOUT);
	  do_close (s);
	  return (-1);
	}
      fromlen = sizeof (from);
      res = __recvfrom (s, (char *) &thetime, sizeof (thetime), 0,
			(struct sockaddr *) &from, &fromlen);
      do_close (s);
      if (res < 0)
	return -1;
    }
  else
    {
      if (__connect (s, (struct sockaddr *) addrp, sizeof (*addrp)) < 0)
	{
	  do_close (s);
	  return -1;
	}
      res = __read (s, (char *) &thetime, sizeof (thetime));
      do_close (s);
      if (res < 0)
	return (-1);
    }
  if (res != sizeof (thetime))
    {
      __set_errno (EIO);
      return -1;
    }
  thetime = ntohl (thetime);
  timep->tv_sec = thetime - TOFFSET;
  timep->tv_usec = 0;
  return 0;
}
示例#12
0
/*
 * Create a client handle for a tcp/ip connection.
 * If *sockp<0, *sockp is set to a newly created TCP socket and it is
 * connected to raddr.  If *sockp non-negative then
 * raddr is ignored.  The rpc/tcp package does buffering
 * similar to stdio, so the client must pick send and receive buffer sizes,];
 * 0 => use the default.
 * If raddr->sin_port is 0, then a binder on the remote machine is
 * consulted for the right port number.
 * NB: *sockp is copied into a private area.
 * NB: It is the clients responsibility to close *sockp.
 * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
 * something more useful.
 */
CLIENT *
clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers,
		 int *sockp, u_int sendsz, u_int recvsz)
{
  CLIENT *h;
  struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct));
  struct rpc_msg call_msg;
  int len;

  h = (CLIENT *) mem_alloc (sizeof (*h));
  if (h == NULL || ct == NULL)
    {
      struct rpc_createerr *ce = &get_rpc_createerr ();
      (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
      ce->cf_stat = RPC_SYSTEMERROR;
      ce->cf_error.re_errno = ENOMEM;
      goto fooy;
    }

  /*
   * If no socket given, open one
   */
  if (*sockp < 0)
    {
      *sockp = __socket (AF_UNIX, SOCK_STREAM, 0);
      len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
      if (*sockp < 0
	  || __connect (*sockp, (struct sockaddr *) raddr, len) < 0)
	{
	  struct rpc_createerr *ce = &get_rpc_createerr ();
	  ce->cf_stat = RPC_SYSTEMERROR;
	  ce->cf_error.re_errno = errno;
	  if (*sockp != -1)
	    __close (*sockp);
	  goto fooy;
	}
      ct->ct_closeit = TRUE;
    }
  else
    {
      ct->ct_closeit = FALSE;
    }

  /*
   * Set up private data struct
   */
  ct->ct_sock = *sockp;
  ct->ct_wait.tv_usec = 0;
  ct->ct_waitset = FALSE;
  ct->ct_addr = *raddr;

  /*
   * Initialize call message
   */
  call_msg.rm_xid = _create_xid ();
  call_msg.rm_direction = CALL;
  call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  call_msg.rm_call.cb_prog = prog;
  call_msg.rm_call.cb_vers = vers;

  /*
   * pre-serialize the static part of the call msg and stash it away
   */
  xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE);
  if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg))
    {
      if (ct->ct_closeit)
	__close (*sockp);
      goto fooy;
    }
  ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
  XDR_DESTROY (&(ct->ct_xdrs));

  /*
   * Create a client handle which uses xdrrec for serialization
   * and authnone for authentication.
   */
  xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz,
		 (caddr_t) ct, readunix, writeunix);
  h->cl_ops = (struct clnt_ops *) &unix_ops;
  h->cl_private = (caddr_t) ct;
  h->cl_auth = authnone_create ();
  return h;

fooy:
  /*
   * Something goofed, free stuff and barf
   */
  mem_free ((caddr_t) ct, sizeof (struct ct_data));
  mem_free ((caddr_t) h, sizeof (CLIENT));
  return (CLIENT *) NULL;
}
示例#13
0
static void
openlog_internal(const char *ident, int logstat, int logfac) {
    if (ident != NULL)
        LogTag = ident;
    LogStat = logstat;
    if (logfac != 0 && (logfac &~LOG_FACMASK) == 0)
        LogFacility = logfac;

    int retry = 0;
    while (retry < 2) {
        if (LogFile == -1) {
            SyslogAddr.sun_family = AF_UNIX;
            (void) strncpy(SyslogAddr.sun_path, _PATH_LOG,
                    sizeof (SyslogAddr.sun_path));
            if (LogStat & LOG_NDELAY) {
#ifdef SOCK_CLOEXEC
#ifndef __ASSUME_SOCK_CLOEXEC
                //if (__have_sock_cloexec >= 0) {
#endif /* __ASSUME_SOCK_CLOEXEC */
                    LogFile = socket(AF_UNIX,
                            LogType
                            | SOCK_CLOEXEC, 0);
#ifndef __ASSUME_SOCK_CLOEXEC
                  /*  if (__have_sock_cloexec == 0)
                        __have_sock_cloexec
                            = ((LogFile != -1
                            || errno != EINVAL)
                            ? 1 : -1);
                }*/
#endif /* __ASSUME_SOCK_CLOEXEC */
#endif /* SOCK_CLOEXEC */
#ifndef __ASSUME_SOCK_CLOEXEC
#ifdef SOCK_CLOEXEC
                //if (__have_sock_cloexec < 0)
#endif /* SOCK_CLOEXEC */
                    LogFile = socket(AF_UNIX, LogType, 0);
#endif /* __ASSUME_SOCK_CLOEXEC */
                if (LogFile == -1)
                    return;
#ifndef __ASSUME_SOCK_CLOEXEC
#ifdef SOCK_CLOEXEC
                //if (__have_sock_cloexec < 0)
#endif /* SOCK_CLOEXEC */
                    __fcntl(LogFile, F_SETFD, FD_CLOEXEC);
#endif /* __ASSUME_SOCK_CLOEXEC */
            }
        }
        if (LogFile != -1 && !connected) {
            int old_errno = errno;
            if (__connect(LogFile, &SyslogAddr, sizeof (SyslogAddr))
                    == -1) {
                int saved_errno = errno;
                int fd = LogFile;
                LogFile = -1;
                (void) __close(fd);
                __set_errno(old_errno);
                if (saved_errno == EPROTOTYPE) {
                    /* retry with the other type: */
                    LogType = (LogType == SOCK_DGRAM
                            ? SOCK_STREAM : SOCK_DGRAM);
                    ++retry;
                    continue;
                }
            } else
                connected = 1;
        }
        break;
    }
}
示例#14
0
int
res_send(struct SocketBase *	libPtr,
	 const char *		buf,
	 int			buflen,
	 char *			answer,
	 int 			anslen)
{
	register int n;
	int try, v_circuit, resplen, nscount;
	int gotsomewhere = 0, connected = 0;
	int connreset = 0;
	u_short id, len;
	char *cp;
	fd_set dsmask;
	struct timeval timeout;
	struct in_addr *ns;
	struct sockaddr_in host;
	HEADER *hp = (HEADER *) buf;
	HEADER *anhp = (HEADER *) answer;
	u_char terrno = ETIMEDOUT;
#define JUNK_SIZE 512
	char junk[JUNK_SIZE]; /* buffer for trash data */

#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send()\n"));
D(bug("[AROSTCP](res_send.c) res_send: using socket %d\n", res_sock));
#endif

#ifdef RES_DEBUG
		printf("res_send()\n");
		__p_query(buf, libPtr);
#endif /* RES_DEBUG */

	v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
	id = hp->id;
	/*
	 * Send request, RETRY times, or until successful
	 */
	for (try = 0; try < _res.retry; try++) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Attempt %d\n", try));
#endif
	  nscount = 0;
	  DRES(Printf("Retry #%ld\n",try);)
	  for (ns = _res.nsaddr_list; ns->s_addr; ns++) {
	    nscount++;
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Querying server #%ld address = %s\n", nscount,
			      __inet_ntoa(ns->s_addr, libPtr)));
#endif

#ifdef RES_DEBUG
			Printf("Querying server #%ld address = %s\n", nscount,
			      __Inet_NtoA(ns->s_addr, libPtr));
#endif /* RES_DEBUG */
	    host.sin_len = sizeof(host);
	    host.sin_family = AF_INET;
	    host.sin_port = htons(NAMESERVER_PORT);
	    host.sin_addr.s_addr = ns->s_addr;
	    aligned_bzero_const(&host.sin_zero, sizeof(host.sin_zero));
	usevc:
		if (v_circuit) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Using v_circuit\n"));
#endif
			int truncated = 0;

			/*
			 * Use virtual circuit;
			 * at most one attempt per server.
			 */
			try = _res.retry;
			if (res_sock < 0) {
				res_sock = __socket(AF_INET, SOCK_STREAM, 0, libPtr);
				if (res_sock < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed to create socket!!\n"));
					terrno = readErrnoValue(libPtr);
#endif
#ifdef RES_DEBUG
					    Perror("socket (vc)");
#endif /* RES_DEBUG */
					continue;
				}
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: created socket %d\n", res_sock));
#endif
				if (__connect(res_sock,
					    (struct sockaddr *)&host,
					    sizeof(struct sockaddr), libPtr) < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed to connect\n"));
#endif
				        terrno = readErrnoValue(libPtr);
#ifdef RES_DEBUG
					    Perror("connect (vc)");
#endif /* RES_DEBUG */
					(void) __CloseSocket(res_sock, libPtr);
					res_sock = -1;
					continue;
				}
			}
			/*
			 * Send length & message
			 */
			len = htons((u_short)buflen);
			if ((__send(res_sock, (char *)&len, sizeof(len), 0, libPtr)
			     != sizeof(len)) ||
			   ((__send(res_sock, (char *)buf, buflen, 0, libPtr)
			     != buflen))) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed sending query\n"));
#endif
				terrno = readErrnoValue(libPtr);
#ifdef RES_DEBUG
					Perror("write(vc)");
#endif /* RES_DEBUG */
				(void) __CloseSocket(res_sock, libPtr);
				res_sock = -1;
				continue;
			}
			/*
			 * Receive length & response
			 */
			cp = answer;
			len = sizeof(short);
			while (len != 0 &&
			    (n = __recv(res_sock,
				      (char *)cp, (int)len, 0, libPtr)) > 0) {
				cp += n;
				len -= n;
			}
			if (n <= 0) {
				terrno = readErrnoValue(libPtr);
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed recieving response\n"));
#endif
#ifdef RES_DEBUG
					Perror("read (vc)");
#endif /* RES_DEBUG */
				(void) __CloseSocket(res_sock, libPtr);
				res_sock = -1;
				/*
				 * A long running process might get its TCP
				 * connection reset if the remote server was
				 * restarted.  Requery the server instead of
				 * trying a new one.  When there is only one
				 * server, this means that a query might work
				 * instead of failing.  We only allow one reset
				 * per query to prevent looping.
				 */
				if (terrno == ECONNRESET && !connreset) {
					connreset = 1;
					ns--;
				}
				continue;
			}
			cp = answer;
			if ((resplen = ntohs(*(u_short *)cp)) > anslen) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Truncated response\n"));
#endif
#ifdef RES_DEBUG
				       Printf("response truncated\n");
#endif /* RES_DEBUG */
				len = anslen;
				truncated = 1;
			} else
				len = resplen;
			while (len != 0 &&
			   (n = __recv(res_sock,
				     (char *)cp, (int)len, 0, libPtr)) > 0) {
				cp += n;
				len -= n;
			}
			if (n <= 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Error recieving response\n"));
#endif
				terrno = readErrnoValue(libPtr);
#ifdef RES_DEBUG
					Perror("read (vc)");
#endif /* RES_DEBUG */
				(void) __CloseSocket(res_sock, libPtr);
				res_sock = -1;
				continue;
			}
			if (truncated) {
				/*
				 * Flush rest of answer
				 * so connection stays in synch.
				 */
				anhp->tc = 1;
				len = resplen - anslen;
				while (len != 0) {
					n = (len > JUNK_SIZE ? JUNK_SIZE : len);
					if ((n = __recv(res_sock,
						      junk, n, 0, libPtr)) > 0)
						len -= n;
					else
						break;
				}
			}
		} else {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Using datagrams\n"));
#endif
			/*
			 * Use datagrams.
			 */
			if (res_sock < 0) {
				res_sock = __socket(AF_INET, SOCK_DGRAM, 0, libPtr);
				if (res_sock < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed to create socket\n"));
#endif
					terrno = readErrnoValue(libPtr);
#ifdef RES_DEBUG
					    Perror("socket (dg)");
#endif /* RES_DEBUG */
					continue;
				}
			}
			/*
			 * I'm tired of answering this question, so:
			 * On a 4.3BSD+ machine (client and server,
			 * actually), sending to a nameserver datagram
			 * port with no nameserver will cause an
			 * ICMP port unreachable message to be returned.
			 * If our datagram socket is "connected" to the
			 * server, we get an ECONNREFUSED error on the next
			 * socket operation, and select returns if the
			 * error message is received.  We can thus detect
			 * the absence of a nameserver without timing out.
			 * If we have sent queries to at least two servers,
			 * however, we don't want to remain connected,
			 * as we wish to receive answers from the first
			 * server to respond.
			 */
#warning "TODO*: see comment here .."
			/* This piece of code still behaves slightly wrong in
			   case of ECONNREFUSED error. On next retry socket will
			   be in disconnected state and instead of getting
			   ECONNREFUSED again we'll timeout in WaitSelect() and
			   get ETIMEDOUT. However, this is not critical and is
			   queued for future - Pavel Fedin*/
			if (try == 0 && nscount == 1) {
				/*
				 * Don't use connect if we might
				 * still receive a response
				 * from another server.
				 */
				if (connected == 0) {
				  if (__connect(res_sock,
					      (struct sockaddr *)&host,
					      sizeof(struct sockaddr),
					      libPtr) < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Error connecting\n"));
#endif
#ifdef RES_DEBUG
							Perror("connect (dg)");
#endif /* RES_DEBUG */
						continue;
					}
					connected = 1;
				}
				if (__send(res_sock,
					 buf, buflen, 0, libPtr) != buflen) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Error sending\n"));
#endif
#ifdef RES_DEBUG
						Perror("send (dg)");
#endif /* RES_DEBUG */
					continue;
				}
			} else {
				/*
				 * Disconnect if we want to listen
				 * for responses from more than one server.
				 */
				if (connected) {
					(void) __connect(res_sock, &no_addr,
					    sizeof(no_addr), libPtr);
					connected = 0;
				}
				if (__sendto(res_sock, buf, buflen, 0,
				    (struct sockaddr *)&host,
				    sizeof(struct sockaddr), libPtr) != buflen) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: [__sendto] Error\n"));
#endif
#ifdef RES_DEBUG
						Perror("sendto (dg)");
#endif /* RES_DEBUG */
					continue;
				}
			}

			/*
			 * Wait for reply
			 */
			timeout.tv_sec = (_res.retrans << try);
			if (try > 0)
				timeout.tv_sec /= nscount;
			if (timeout.tv_sec <= 0)
				timeout.tv_sec = 1;
			timeout.tv_usec = 0;
wait:
			FD_ZERO(&dsmask);
			FD_SET(res_sock, &dsmask);
			n = __WaitSelect(res_sock+1, &dsmask, NULL,
				NULL, &timeout, NULL, libPtr);
			if (n < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: [__WaitSelect] Error\n"));
#endif
#ifdef RES_DEBUG
					Perror("select");
#endif /* RES_DEBUG */

            terrno = readErrnoValue(libPtr);
				if (terrno == EINTR) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: closing socket\n"));
#endif
					__CloseSocket(res_sock, libPtr);
					res_sock = -1;
					return (-1);
				}
				continue;
			}
			if (n == 0) {
				/*
				 * timeout
				 */
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Timeout!\n"));
#endif
#ifdef RES_DEBUG
					Printf("timeout\n");
#endif /* RES_DEBUG */
#if 1 || BSD >= 43
				gotsomewhere = 1;
#endif
				continue;
			}
			if ((resplen = __recv(res_sock,
					    answer, anslen, 0, libPtr)) <= 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Error recieving\n"));
#endif
#ifdef RES_DEBUG
					Perror("recv (dg)");
#endif /* RES_DEBUG */
				continue;
			}
			gotsomewhere = 1;
			if (id != anhp->id) {
				/*
				 * response from old query, ignore it
				 */
#ifdef RES_DEBUG
					Printf("old answer:\n");
					__p_query(answer, libPtr);
#endif /* RES_DEBUG */
				goto wait;
			}
			if (!(_res.options & RES_IGNTC) && anhp->tc) {
				/*
				 * get rest of answer;
				 * use TCP with same server.
				 */
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Response is truncated\n"));
#endif
#ifdef RES_DEBUG
					Printf("truncated answer\n");
#endif /* RES_DEBUG */
				(void)__CloseSocket(res_sock, libPtr);
				res_sock = -1;
				v_circuit = 1;
				goto usevc;
			}
		}

#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Recieved answer\n"));
#endif

#ifdef RES_DEBUG
			Printf("got answer:\n");
			__p_query(answer, libPtr);
#endif /* RES_DEBUG */
		/*
		 * If using virtual circuits, we assume that the first server
		 * is preferred * over the rest (i.e. it is on the local
		 * machine) and only keep that one open.
		 * If we have temporarily opened a virtual circuit,
		 * or if we haven't been asked to keep a socket open,
		 * close the socket.
		 */
		if ((v_circuit &&
		    ((_res.options & RES_USEVC) == 0 || ns->s_addr != 0)) ||
		    (_res.options & RES_STAYOPEN) == 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Closing socket\n"));
#endif
			(void) __CloseSocket(res_sock, libPtr);
			res_sock = -1;
		}
		return (resplen);
	   }