/* ** 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); }
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; }
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); }