/*
** Returns 1 or 0 depending on whether or not the host described by #host# can
** be verified to be name server within #timeOut# seconds.
*/
static int
IsANameServer(const struct host_desc *host,
              double timeOut) {

  struct host_cookie hostCookie;
  HostInfo hostInfo;
  char hostName[127 + 1];

  SAFESTRCPY(hostName, HostDImage(host));
  MakeHostCookie(host->host_name, host->port, &hostCookie);

  if(!ConnectToHost(&hostCookie, &hostCookie.sd)) {
    FAIL1("IsANameServer: unable to contact %s\n", hostName);
  }

  if(DoTestHost(hostCookie.sd, &hostInfo, timeOut) != HEALTHY) {
    DisconnectHost(&hostCookie);
    FAIL1("IsANameServer: unable to verify that %s is a name server\n",
          hostName);
  }

  DisconnectHost(&hostCookie);

  if(strcmp(hostName, hostInfo.nameServer) != 0) {
    FAIL1("IsANameServer: %s is not a name server\n", hostName);
  }

  return(1);

}
int
CreateLocalChild(pid_t *pid,
                 Socket *parentToChild,
                 Socket *childToParent) {

  int childWrite[2];
  int parentWrite[2];
  int myEnd;

  if(parentToChild != NULL) {
    if(pipe(parentWrite) == -1) {
      FAIL1("CreateLocalChild: couldn't get pipe, errno: %d\n", errno);
    }
  }
  if(childToParent != NULL) {
    if(pipe(childWrite) == -1) {
      if(parentToChild != NULL) {
        close(parentWrite[0]);
        close(parentWrite[1]);
      }
      FAIL1("CreateLocalChild: couldn't get pipe, errno: %d\n", errno);
    }
  }

  *pid = fork();

  if(*pid == -1) {
    if(parentToChild != NULL) {
      close(parentWrite[0]);
      close(parentWrite[1]);
    }
    if(childToParent != NULL) {
      close(childWrite[0]);
      close(childWrite[1]);
    }
    FAIL2("CreateLocalChild: couldn't fork, errno: %d (%s)\n",
          errno, strerror(errno));
  }

  /* Close descriptors that this process won't be using. */
  if(parentToChild != NULL) {
    myEnd = (*pid == 0) ? READ_END : WRITE_END;
    close(parentWrite[1 - myEnd]);
    FD_SET(parentWrite[myEnd], &connectedPipes);
    *parentToChild = parentWrite[myEnd];
  }

  if(childToParent != NULL) {
    myEnd = (*pid == 0) ? WRITE_END : READ_END;
    close(childWrite[1 - myEnd]);
    FD_SET(childWrite[myEnd], &connectedPipes);
    *childToParent = childWrite[myEnd];
  }

  return(1);

}
/*
** A "local" function of ProcessRequest().  Implements the MEMORY_CLEAN service
** by deleting all files in the memory directory that have not been accessed
** within the past #idle# seconds.  Returns 1 if successful, else 0.
*/
static int
DoClean(unsigned long idle) {

  struct dirent *entry;
  DIR *directory;
  time_t expiration;
  char filePath[255 + 1];
  struct stat fileStat;
  char *namePlace;

  directory = opendir(memoryDir);
  if(directory == NULL) {
    FAIL1("DoClean: unable to open directory %s\n", memoryDir);
  }

  expiration = (time_t)CurrentTime() - (time_t)idle;
  SAFESTRCPY(filePath, memoryDir);
  namePlace = filePath + strlen(filePath);

  while((entry = readdir(directory)) != NULL) {
    strcpy(namePlace, entry->d_name);
    if(stat(filePath, &fileStat) != 0) {
      WARN1("DoClean: unable to state file %s\n", filePath);
    }
    else if(fileStat.st_mtime < expiration) {
      LOG2("DoClean: deleting %s, last modified %d\n",
           filePath, fileStat.st_mtime);
      (void)unlink(filePath);
    }
  }

  (void)closedir(directory);
  return(1);

}
/*
** A "local" function of KeepState().  Enters #name# marked with #seqNo# into
** the state file (global) #journalPath#.  Used to keep a log of all writes
** performed by the memory.  Returns 1 if successful, else 0.
*/
static int
EnterInJournal(const char *name,
               double seqNo) {

  char journalRec[MAX_RECORD_SIZE];
  double now;

  memset(journalRec, 0, sizeof(journalRec));
  now = CurrentTime();

  if(sprintf(journalRec,"%10.0f %64s", seqNo, name) < 2) {
    FAIL1("EnterInJournal: write failed, errno %d\n", errno);
  }

  if(!WriteState(journalPath,
                 journalFileSize,
                 KEEP_A_LONG_TIME,
                 now,
                 journalRec,
                 strlen(journalRec))) {
    FAIL("EnterInJournal: write state failed\n");
  }

  return(1);

}
int
SendBytes(Socket sd,
          const void *bytes,
          size_t byteSize,
          double timeOut) {

  int isPipe;
  char *nextByte;
  int sent;
  int totalSent;

  if (debug > 0) {
      DDEBUG2("SendBytes: To %d with t/o %f\n", sd, timeOut);
  }

  isPipe = FD_ISSET(sd, &connectedPipes);
  nextByte = (char *)bytes;

  for(totalSent = 0; totalSent < byteSize; totalSent += sent) {
    sent = isPipe ? write(sd, nextByte, (size_t)(byteSize - totalSent)) :
                    send(sd, nextByte, byteSize - totalSent, 0);
    if(sent <= 0) {
      FAIL1("SendBytes: %d send failed\n", sd);
    }
    nextByte += sent;
  }

  return(1);

}
Ejemplo n.º 6
0
TReal32 CHuiFxEffectParser::ParseFloatAttributeL(CMDXMLNode* aNode, const TDesC& aName, TBool aMustExist)
    {
    TInt index = ((CMDXMLElement*)aNode)->FindIndex(aName);
    if( index == KErrNotFound )
        {
        if (aMustExist)
            {
            FAIL1(KErrGeneral, _L("Attribute not found: %S"), &aName); // leaves 
            return 0.0f; // never reached. For completeness
            }
        else
            {
            return 0.0f;
            }
        }

    TPtrC attributeValue;
    TPtrC attributeName;
    TReal32 value = 0.0f;
    User::LeaveIfError(((CMDXMLElement*)aNode)->AttributeDetails( index, attributeName, attributeValue ));

    value = ParseFloatVal(attributeValue);
    return value;
    }
Ejemplo n.º 7
0
Archivo: socket.c Proyecto: kvirund/mmc
int	sconnect(char *addr,int port,char *laddr,int doproc,PSHANDLER hf,void *ha) {
    int			idx,opt;
    struct sockaddr_in	rem,loc;

#define FAIL0(m) { clwarnx(m); return -1; }
#define	FAIL1(m) { sockerrmsg(m,0); return -1; }
#define	FAIL2(m) { sockerrmsg(m,0); goto free_sock; }
#define	FAIL3(m) { sockerrmsg(m,0); goto free_event; }
#define	FAILD(m) { sockerrmsg(m,1); return -1; }

#ifdef WIN32
    if (initsockets()<0)
	return -1;
#endif

    if (!hf)
	return -1;
    for (idx=0;idx<NSOCK;idx++)
	if (!sockets[idx].inuse)
	    break;
    if (idx==NSOCK) {
	clwarnx("too many open sockets");
	return -1;
    }
    sockets[idx].handler=hf;
    sockets[idx].data=ha;
    sockets[idx].ilen=sockets[idx].olen=0;
    sockets[idx].lp=1;
    sockets[idx].lpevent=-1;
    sockets[idx].state=sNORMAL;
    sockets[idx].attr=7;
    sockets[idx].mode=SM_NORM;
    sockets[idx].opmode=doproc ? SM_NORM : SM_HALF;
    sockets[idx].type=RT_SOCK;
    sockets[idx].zsp=NULL;
    sockets[idx].rawin=sockets[idx].rawout=sockets[idx].procin=0;
    window_flush(); /* flush output before a long blocking operation */
    memset(&rem,0,sizeof(rem));
    rem.sin_family=AF_INET;
    rem.sin_port=htons((short)port);
    if ((rem.sin_addr.s_addr=inet_addr(addr))==INADDR_NONE) {
	struct hostent	*hp=gethostbyname(addr);

	if (!hp)
	    FAILD("can't get remote address");
	memcpy(&rem.sin_addr,hp->h_addr,sizeof(rem.sin_addr));
    }
    memcpy(&sockets[idx].remote,&rem,sizeof(sockets[idx].remote));
    if (laddr) {
	int   slen;
	char  *cp,*buf;

	memset(&loc,0,sizeof(loc));
	loc.sin_family=AF_INET;
	slen=strlen(laddr);
	for (cp=laddr+slen;cp>laddr;--cp)
	  if (*cp==':')
	    break;
	if (*cp==':') {
	  buf=malloc(cp-laddr+1);
	  if (!buf)
	    FAIL0("out of memory");
	  memcpy(buf,laddr,cp-laddr);
	  buf[cp-laddr]='\0';
	  ++cp;
	  loc.sin_port=htons((short)atoi(cp));
	} else
	  buf=laddr;
	if ((loc.sin_addr.s_addr=inet_addr(buf))==INADDR_NONE) {
	    struct hostent  *hp=gethostbyname(buf);

	    if (!hp)
		FAILD("can't get local address");
	    memcpy(&loc.sin_addr,hp->h_addr,sizeof(loc.sin_addr));
	}
	if (buf!=laddr)
	  free(buf);
    }
    if ((sockets[idx].sock=socket(PF_INET,SOCK_STREAM,0))<0)
	FAIL1("can't create socket");
    if (laddr)
	if (bind(sockets[idx].sock,(struct sockaddr *)&loc,sizeof(loc))<0)
	    FAIL2("can't bind socket");
#ifdef WIN32
    if ((sockets[idx].event=CreateEvent(NULL,FALSE,FALSE,NULL))==NULL) {
	clwarn("can't create event");
	goto free_sock;
    }
    if (WSAEventSelect(sockets[idx].sock,sockets[idx].event,FD_READ|FD_CLOSE|FD_CONNECT))
	FAIL3("can't bind event to socket");
#endif
#ifndef WIN32
    {
      int flags=fcntl(sockets[idx].sock,F_GETFL,0);
      if (flags<0)
	FAIL3("can't get fd flags");
      if (fcntl(sockets[idx].sock,F_SETFL,flags|O_NONBLOCK)<0)
	FAIL3("can't set fd flags");
    }
#endif
    opt=KERN_SOCKBUFSIZE;
    setsockopt(sockets[idx].sock,SOL_SOCKET,SO_RCVBUF,(void*)&opt,sizeof(opt)); /* ignore result */
    if (connect(sockets[idx].sock,(struct sockaddr *)&rem,sizeof(rem))<0) {
#ifdef WIN32
      if (WSAGetLastError()!=WSAEWOULDBLOCK)
#else
      if (errno!=EINPROGRESS)
#endif
	FAIL3("can't connect to remote host");
      sockets[idx].mode=SM_CONN;
      sockets[idx].inuse=1;
    } else {
      sockets[idx].inuse=1;
      if (sockets[idx].handler)
	sockets[idx].handler(idx,SCONN,sockets[idx].data,NULL,0);
    }
    return idx;
free_event:
#ifdef WIN32
    CloseHandle(sockets[idx].event);
#endif
free_sock:
    closesocket(sockets[idx].sock);
    return -1;
#undef FAIL0
#undef FAIL1
#undef FAIL2
#undef FAIL3
}
/*
** A "local" function of ProcessRequest() .  Stores #data# in #directory# with
** the attributes indicated by #s#.  Fails if the record size and count in #s#
** yield more than #max_size# total bytes.  Returns 1 if successful, else 0.
*/
static int
KeepState(const struct loglocation* logLoc,
          const struct state *s,
          const char *data,
          size_t max_size) {

  const char *curr;
  int i;
  size_t recordSize;

  if(s->rec_count > fileSize) {
    FAIL("KeepState: rec count too big\n");
  }

  if(s->rec_size > MAX_RECORD_SIZE) {
    WARN("KeepState: state record too big.\n");
    recordSize = MAX_RECORD_SIZE;
  }
  else {
    recordSize = (size_t)s->rec_size;
  }

  if(s->rec_count * recordSize > max_size) {
    FAIL1("KeepState: too much data %d\n", s->rec_count * recordSize);
  }

#ifdef WITH_NETLOGGER
  if (logLoc->loc_type==MEMORY_LOG_NETLOGGER)
  {
          for(curr = data, i = 0; i < s->rec_count; curr += recordSize, i++) {
                  if(!WriteStateNL(logLoc->path,
                          s->id,
                          fileSize,
                          s->time_out,
                          s->seq_no,
                          curr,
                          recordSize) ||
                          !EnterInJournal(s->id, s->seq_no)) {
                          if(errno == EMFILE) {
                                  CheckConnections();
                          }
                          FAIL("KeepState: write failed\n");
                  }
          }
          return (1);
  }
#endif /* WITH_NETLOGGER */

  for(curr = data, i = 0; i < s->rec_count; curr += recordSize, i++) {
    if(!WriteState(FileOfState(logLoc->path, s->id),
                   fileSize,
                   s->time_out,
                   s->seq_no,
                   curr,
                   recordSize) ||
       !EnterInJournal(s->id, s->seq_no)) {
      if(errno == EMFILE) {
        CheckConnections();
      }
      FAIL("KeepState: write failed\n");
    }
  }

  return(1);

}
/*
** A "local" function of MatchFilter().  Returns 1 or 0 depending on whether or
** not #item# contains the first attribute specified by #filter#.  Updates
** #filter# to point to the next attribute.
*/
static int
MatchFilterAndUpdate(const char *item,
                     const char **filter) {

  char firstChar;
  const char *itemAttribute;
  char operator;
  int returnValue;
  char simpleName[127 + 1];
  char simplePattern[127 + 1];
  const char *value;
  const char *valueEnd;
  size_t valueLen;

  /* Allow leading and trailing spaces for legibility. */
  while(**filter == ' ')
    (*filter)++;
  firstChar = **filter;

  if(firstChar == '(') {
    /* Nested pattern. */
    (*filter)++;
    returnValue = MatchFilterAndUpdate(item, filter);
    if(**filter == ')')
      (*filter)++;
  }
  else if((firstChar == '!') || (firstChar == '|') || (firstChar == '&')) {
    /* Prefix operator: unary not, n-ary or, n-ary and */
    (*filter)++;
    if(firstChar == '!') {
      returnValue = !MatchFilterAndUpdate(item, filter);
    }
    else {
      returnValue = firstChar == '&';
      /* To advance filter correctly we must avoid short-circuit matches. */
      while((**filter != '\0') && (**filter != ')')) {
        if(MatchFilterAndUpdate(item, filter)) {
          if(firstChar == '|')
            returnValue = 1;
        }
        else if(firstChar == '&')
          returnValue = 0;
      }
    }
  }
  else {
    /* Grab the individual parts of the <attribute><op><pattern> pair. */
    if(!GETTOK(simpleName, *filter, "<=>~", filter))
      FAIL1("MatchFilterAndUpdate: parse error in %s\n", filter);
    strcat(simpleName, ":");
    operator = **filter;
    if(operator != '=') {
      (*filter)++; /* Skip < > or ~ */
      if(**filter != '=')
        FAIL1("MatchFilterAndUpdate: parse error in %s\n", filter);
    }
    (*filter)++; /* Skip '=' */
    if(!GETTOK(simplePattern, *filter, ") ", filter))
      FAIL1("MatchFilterAndUpdate: parse error in %s\n", filter);
    /* Now match against the value of each occurence of <attribute> in item. */
    for(itemAttribute = strstr(item, simpleName); itemAttribute != NULL;
        itemAttribute = strstr(itemAttribute + 1, simpleName)) {
      value = itemAttribute + strlen(simpleName);
      valueEnd = strchr(value, '\t');
      valueLen = (valueEnd == NULL) ? strlen(value) : (valueEnd - value);
      if((operator == '=') && strnmatch(value, simplePattern, valueLen))
        break;
      else if((operator == '<') &&
              (strncmp(value, simplePattern, valueLen) <= 0))
        break;
      else if((operator == '>') &&
              (strncmp(value, simplePattern, valueLen) >= 0))
        break;
      else if((operator == '~') && strnmatch(value, simplePattern, valueLen))
        /* We recognize ~= but treat it as simple = */
        break;
    }
    returnValue = itemAttribute != NULL;
  }

  while(**filter == ' ')
    (*filter)++;
  return returnValue;

}
int
IncomingRequest(double timeOut,
                Socket *sd) {

  Socket dead;
  Socket i;
  char lookahead;
  Socket newSock;
  double now;
  struct sockaddr_in peer_in;
  SOCKLEN_T peer_in_len = sizeof(peer_in);
  fd_set readFds;
  struct timeval tout;
  double wakeup;

  /*
  ** nextToService is used to make sure that every connection gets a chance to
  ** be serviced.  If we always started checking at 0, very active connections
  ** with small descriptor numbers could starve larger-descriptor connections.
  */
  static Socket nextToService = 0;

  *sd = NO_SOCKET;
  tout.tv_usec = 0;
  wakeup = CurrentTime() + timeOut;

  while((now = CurrentTime()) < wakeup) {

    /* Construct in readFds the union of connected ears, pipes, and sockets. */
    readFds = connectedSockets;
    for(i = 0; i < FD_SETSIZE; i++) {
      if(FD_ISSET(i, &connectedPipes)) {
        FD_SET(i, &readFds);
      }
    }
    for(i = 0; i < FD_SETSIZE; i++) {
      if(FD_ISSET(i, &connectedEars)) {
        FD_SET(i, &readFds);
      }
    }

    tout.tv_sec = (unsigned int)wakeup - (unsigned int)now;

    switch(select(FD_SETSIZE, &readFds, NULL, NULL, &tout)) {

    case -1:
      if(errno == EINTR) {
        continue;
      }
      else if(errno == EINVAL) {
        /* we blew it somehow -- this is mostly for osf... */
        /* can be because (from man page):
          [EINVAL] The time limit specified by the timeout parameter is invalid.

                   The nfds parameter is less than 0, or greater than or equal
                   to FD_SETSIZE.

                   One of the specified file descriptors refers to a STREAM or
                   multiplexer that is linked (directly or indirectly)
                   downstream from a multiplexer.
        */

        FAIL4("IncomingRequest: invalid select - nfds: %d, rfds: %d, to: %d.%d",
              FD_SETSIZE, readFds, tout.tv_sec, tout.tv_usec);
      }
      else {
        FAIL1("IncomingRequest: select error %d\n", errno);
      }
      break;

    case 0:
      /* timeout */
      break;

    default:

      i = nextToService;

      while(1) {

        if(FD_ISSET(i, &readFds)) {

          if(FD_ISSET(i, &connectedEars)) {
            /* Add the new connection to connectedSockets. */
            newSock = accept(i, (struct sockaddr *)&peer_in, &peer_in_len);
            if(newSock == -1) {
              SocketFailure(SIGPIPE);
            }
            else {
              ConditionSocket(newSock);
	      if (debug > 0) {
                  DDEBUG2("IncomingRequest: connected socket %d to %s\n",
                      newSock, PeerName(newSock));
	      }
              FD_SET(newSock, &connectedSockets);
            }
          }
          else if(FD_ISSET(i, &connectedPipes)) {
            *sd = i;
            nextToService = (i + 1) % FD_SETSIZE;
            return(1);
          }
          else {
            /* Existing socket connection. */
            if(recv(i, &lookahead, 1, MSG_PEEK) > 0) {
              *sd = i;
              nextToService = (i + 1) % FD_SETSIZE;
              return(1);
            }
            else {
              /*
              ** This is how we find out about connections closed by a peer.
              ** Drop it from our list of known connections.
              */
		if (debug > 0) {
                  DDEBUG1("IncomingRequest: Dropping closed connection %d\n", i);
		}
              dead = i;
              DROP_SOCKET(&dead);
            }
          }

        }

        i = (i + 1) % FD_SETSIZE;
        if(i == nextToService) {
          /* We've been through the entire set without finding a request. */
          break;
        }

      }
      break;

    }

  }

  return(0);

}