/** * Read file, returning contents in buf * * @return file size on success, -1 on error */ static int readFile(const char *filename, char **buf) { int fd, res; struct stat statBuf; logVerb("%s('%s')\n", __func__, filename); if ((fd = open(filename, O_RDONLY, S_IRUSR | S_IWUSR)) < 0) { if (errno == ENOENT) logWarn("File '%s' not found\n", filename); return fd; } if ((res = stat(filename, &statBuf)) < 0) { logSysError("%s.stat\n", __func__); return res; } *buf = malloc(statBuf.st_size + 1); if (read(fd, *buf, statBuf.st_size) < 0) dieSysError("read()\n"); close(fd); return statBuf.st_size; }
int main() { assert(daemon_flag == false); log(INFO, "Info log message."); log(SCRIPT, "Script log message."); log(NOTICE, "Notice log message."); log(WARNING, "Warning log message."); log(SCRIPT_ERROR, "Script Error log message."); log(CRITICAL, "Critical log message."); log_formatted(INFO, "Info message with no \\n"); log_formatted(INFO, "Info message with a \\n\n"); log_formatted(INFO, "Info message with a \\n \n and text on another line"); log_formatted(INFO, "Info message with two \\n\n on two lines\n"); errno = 0; logSysError(INFO); logSysError(SCRIPT); logSysError(NOTICE); logSysError(WARNING); logSysError(SCRIPT_ERROR); logSysError(CRITICAL); errno = -1; logSysError(INFO); logSysError(SCRIPT); logSysError(NOTICE); logSysError(WARNING); logSysError(SCRIPT_ERROR); logSysError(CRITICAL); errno = EINVAL; logSysError(INFO); logSysError(SCRIPT); logSysError(NOTICE); logSysError(WARNING); logSysError(SCRIPT_ERROR); logSysError(CRITICAL); assert(testEventLog("/dev/null")); logEvent(START, "Test start event log message"); logEvent(STOP, "Test stop event log message"); logEvent(CONNECT, "Test connect event log message"); logEvent(DISCONNECT, "Test disconnect event log message"); logEvent(LOGIN, "Test login event log message"); logEvent(LOGOUT, "Test logout event log message"); logEvent(TAKE_CHAR, "Test take character event log message"); logEvent(DROP_CHAR, "Test drop character event log message"); logEvent(EXPORT_ENT, "Test export entity event log message"); logEvent(IMPORT_ENT, "Test import entity event log message"); logEvent(POSSESS_CHAR, "Test possess character event log message"); return 0; }
/// \brief Main program loop called repeatedly. /// /// Call the server idle function to do its processing. If the server is /// is currently busy, poll all the sockets as quickly as possible. /// If the server is idle, use select() to sleep on the sockets for /// a short period of time. If any sockets get broken or disconnected, /// they are noted and closed down at the end of the process. void CommServer::poll(bool busy) { // This is the main code loop. // Classic select code for checking incoming data on sockets. // It would be useful to let idle know if we are currently dealing with // traffic // bool busy = idle(); #ifdef HAVE_EPOLL_CREATE static const int max_events = 16; static struct epoll_event events[max_events]; int rval = ::epoll_wait(m_epollFd, events, max_events, (busy ? 0 : 100)); if (rval < 0) { if (errno != EINTR) { log(CYLOG_ERROR, String::compose("epoll_wait: %1", strerror(errno))); } return; } m_congested = (rval != 0) || (m_congested && busy); if (rval == max_events) { // If we see this alot, we should increase the maximum log(NOTICE, "epoll_wait returned the maximum number of events."); } for (int i = 0; i < rval; ++i) { struct epoll_event & event = events[i]; CommSocket * cs = static_cast<CommSocket *>(event.data.ptr); if (event.events & EPOLLERR) { // FIXME This is triggered by an outgoing connect fail, and by // process/src/bint. What to do? // log(WARNING, "Socket error returned by epoll_wait()"); } if (event.events & EPOLLIN) { if (cs->eof()) { removeSocket(cs); } else { if (cs->read() != 0) { // Remove it? // FIXME It could be bad to do this, as dispatch() // has not been called. removeSocket(cs); } else { cs->dispatch(); } } } else if (event.events & EPOLLHUP) { removeSocket(cs); } } #else // HAVE_EPOLL_CREATE fd_set sock_fds; SOCKET_TYPE highest = 0; struct timeval tv; tv.tv_sec = 0; tv.tv_usec = (busy ? 0 : 100000); FD_ZERO(&sock_fds); bool pendingConnections = false; CommSocketSet::const_iterator Iend = m_sockets.end(); for (CommSocketSet::const_iterator I = m_sockets.begin(); I != Iend; ++I) { if (!(*I)->isOpen()) { pendingConnections = true; continue; } SOCKET_TYPE socket_fd = (*I)->getFd(); FD_SET(socket_fd, &sock_fds); if (socket_fd > highest) { highest = socket_fd; } } highest++; int rval = ::select(highest, &sock_fds, NULL, NULL, &tv); if (rval < 0) { if (errno != EINTR) { log(CYLOG_ERROR, "Error caused by select() in main loop"); logSysError(CYLOG_ERROR); } return; } if (rval == 0 && !pendingConnections) { return; } // We assume Iend is still valid. m_sockets must not have been modified // between Iend's initialisation and here. CommSocketSet obsoleteConnections; for (CommSocketSet::const_iterator I = m_sockets.begin(); I != Iend; ++I) { CommSocket * socket = *I; if (!socket->isOpen()) { obsoleteConnections.insert(socket); continue; } if (FD_ISSET(socket->getFd(), &sock_fds)) { if (!socket->eof()) { if (socket->read() != 0) { debug(std::cout << "Removing socket due to failure" << std::endl << std::flush;); obsoleteConnections.insert(socket); } socket->dispatch(); } else {