summaryrefslogtreecommitdiff
path: root/ace/ACE.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ace/ACE.cpp')
-rw-r--r--ace/ACE.cpp738
1 files changed, 738 insertions, 0 deletions
diff --git a/ace/ACE.cpp b/ace/ACE.cpp
new file mode 100644
index 00000000000..3ce0ec93ccc
--- /dev/null
+++ b/ace/ACE.cpp
@@ -0,0 +1,738 @@
+// ACE.cpp
+// $Id$
+
+#define ACE_BUILD_DLL
+#include "ace/IPC_SAP.h"
+#include "ace/Time_Value.h"
+#include "ace/Handle_Set.h"
+#include "ace/ACE.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Reactor.h"
+
+int
+ACE::register_stdin_handler (ACE_Event_Handler *eh,
+ ACE_Reactor *reactor,
+ ACE_Thread_Manager *thr_mgr,
+ int flags)
+{
+#if defined (ACE_WIN32)
+ return thr_mgr->spawn (&ACE::read_adapter, eh, flags);
+#else
+ return reactor->register_handler (ACE_STDIN, eh, ACE_Event_Handler::READ_MASK);
+#endif /* ACE_WIN32 */
+}
+
+// Used to read from non-socket ACE_HANDLEs in our own thread to work
+// around Win32 limitations that don't allow us to select() on
+// non-sockets (such as ACE_STDIN). This is commonly used in
+// situations where the Reactor is used to demultiplex read events on
+// ACE_STDIN on UNIX. Note that <event_handler> must be a subclass of
+// <ACE_Event_Handler>. If the <get_handle> method of this event
+// handler returns <ACE_INVALID_HANDLE> we default to reading from
+// ACE_STDIN.
+
+void *
+ACE::read_adapter (void *t)
+{
+ ACE_Event_Handler *this_ptr = (ACE_Event_Handler *) t;
+ ACE_HANDLE handle = this_ptr->get_handle ();
+
+ if (handle == ACE_INVALID_HANDLE)
+ handle = ACE_STDIN;
+
+ while (this_ptr->handle_input (handle) != -1)
+ continue;
+
+ this_ptr->handle_close (handle, ACE_Event_Handler::READ_MASK);
+ return 0;
+}
+
+const char *
+ACE::execname (const char *old_name)
+{
+#if defined (ACE_HAS_WIN32)
+ if (ACE_OS::strstr (old_name, ".exe") == 0)
+ {
+ char *new_name;
+
+ ACE_NEW_RETURN (new_name, char[ACE_OS::strlen (old_name) +
+ ACE_OS::strlen (".exe") +
+ 1], -1);
+ char *end = new_name;
+ end = ACE::strecpy (new_name, old_name);
+ // Concatenate the .exe suffix onto the end of the executable.
+ ACE_OS::strcpy (end, ".exe");
+ return new_name;
+ }
+#endif /* ACE_HAS_WIN32 */
+ return old_name;
+}
+
+u_long
+ACE::hash_pjw (const char *str)
+{
+ u_long hash = 0;
+
+ for (const char *temp = str; *temp != 0; temp++)
+ {
+ hash = (hash << 4) + (*temp * 13);
+
+ u_long g = hash & 0xf0000000;
+
+ if (g)
+ {
+ hash ^= (g >> 24);
+ hash ^= g;
+ }
+ }
+
+ return hash;
+}
+
+char *
+ACE::strenvdup (const char *str)
+{
+ ACE_TRACE ("ACE::strenvdup");
+
+ char *temp;
+
+ if (str[0] == '$'
+ && (temp = ACE_OS::getenv (&str[1])) != 0)
+ return ACE_OS::strdup (temp);
+ else
+ return ACE_OS::strdup (str);
+}
+
+int
+ACE::ldfind (const char *filename,
+ char *pathname,
+ size_t maxlen)
+{
+ ACE_TRACE ("ACE::ldfind");
+ if (ACE_OS::strchr (filename, ACE_DIRECTORY_SEPARATOR_CHAR) != 0)
+ {
+ // Use absolute pathname.
+ ACE_OS::strncpy (pathname, filename, maxlen);
+ return 0;
+ }
+ else
+ {
+ // Using LD_LIBRARY_PATH
+ char *ld_path = ACE_OS::getenv (ACE_LD_SEARCH_PATH);
+
+ if (ld_path != 0 && (ld_path = ACE_OS::strdup (ld_path)) != 0)
+ {
+ // Look at each dynamic lib directory in the search path.
+ char *path_entry = ACE_OS::strtok (ld_path,
+ ACE_LD_SEARCH_PATH_SEPARATOR_STR);
+
+ int result = 0;
+
+ while (path_entry != 0)
+ {
+ if (ACE_OS::strlen (path_entry) + 1 + ACE_OS::strlen (filename) >= maxlen)
+ {
+ errno = ENOMEM;
+ result = -1;
+ break;
+ }
+ ACE_OS::sprintf (pathname, "%s%c%s",
+ path_entry,
+ ACE_DIRECTORY_SEPARATOR_CHAR,
+ filename);
+
+ if (ACE_OS::access (pathname, R_OK) == 0)
+ break;
+ path_entry = ACE_OS::strtok (0, ACE_LD_SEARCH_PATH_SEPARATOR_STR);
+ }
+
+ ACE_OS::free ((void *) ld_path);
+ return result;
+ }
+ }
+
+ errno = ENOENT;
+ return -1;
+}
+
+FILE *
+ACE::ldopen (const char *filename, const char *type)
+{
+ ACE_TRACE ("ACE::ldopen");
+ char buf[MAXPATHLEN];
+
+ if (ACE::ldfind (filename, buf, sizeof buf) == -1)
+ return 0;
+ else
+ return ACE_OS::fopen (buf, type);
+}
+
+const char *
+ACE::basename (const char *pathname, char delim)
+{
+ ACE_TRACE ("ACE::basename");
+ const char *temp = ::strrchr (pathname, delim);
+
+ if (temp == 0)
+ return pathname;
+ else
+ return temp + 1;
+}
+
+// Miscellaneous static methods used throughout ACE.
+
+ssize_t
+ACE::send_n (ACE_HANDLE handle, const void *buf, size_t len)
+{
+ ACE_TRACE ("ACE::send_n");
+ size_t bytes_written;
+ int n;
+
+ for (bytes_written = 0; bytes_written < len; bytes_written += n)
+ if ((n = ACE::send (handle, (const char *) buf + bytes_written,
+ len - bytes_written)) == -1)
+ return -1;
+
+ return bytes_written;
+}
+
+ssize_t
+ACE::send_n (ACE_HANDLE handle, const void *buf, size_t len, int flags)
+{
+ ACE_TRACE ("ACE::send_n");
+ size_t bytes_written;
+ int n;
+
+ for (bytes_written = 0; bytes_written < len; bytes_written += n)
+ if ((n = ACE_OS::send (handle, (const char *) buf + bytes_written,
+ len - bytes_written, flags)) == -1)
+ return -1;
+
+ return bytes_written;
+}
+
+ssize_t
+ACE::recv_n (ACE_HANDLE handle, void *buf, size_t len)
+{
+ ACE_TRACE ("ACE::recv_n");
+ size_t bytes_read;
+ int n;
+
+ for (bytes_read = 0; bytes_read < len; bytes_read += n)
+ if ((n = ACE::recv (handle, (char *) buf + bytes_read,
+ len - bytes_read)) == -1)
+ return -1;
+ else if (n == 0)
+ break;
+
+ return bytes_read;
+}
+
+ssize_t
+ACE::recv_n (ACE_HANDLE handle, void *buf, size_t len, int flags)
+{
+ ACE_TRACE ("ACE::recv_n");
+ size_t bytes_read;
+ int n;
+
+ for (bytes_read = 0; bytes_read < len; bytes_read += n)
+ if ((n = ACE_OS::recv (handle, (char *) buf + bytes_read,
+ len - bytes_read, flags)) == -1)
+ return -1;
+ else if (n == 0)
+ break;
+
+ return bytes_read;
+}
+
+ // Receive <len> bytes into <buf> from <handle> (uses the <read>
+ // system call on UNIX and the <ReadFile> call on Win32).
+ssize_t
+ACE::read_n (ACE_HANDLE handle,
+ void *buf,
+ size_t len)
+{
+ ACE_TRACE ("ACE::read_n");
+
+ size_t bytes_read;
+ int n;
+
+ for (bytes_read = 0; bytes_read < len; bytes_read += n)
+ if ((n = ACE_OS::read (handle, (char *) buf + bytes_read,
+ len - bytes_read)) == -1)
+ return -1;
+ else if (n == 0)
+ break;
+
+ return bytes_read;
+}
+
+// Receive <len> bytes into <buf> from <handle> (uses the <write>
+// system call on UNIX and the <WriteFile> call on Win32).
+
+ssize_t
+ACE::write_n (ACE_HANDLE handle,
+ const void *buf,
+ size_t len)
+{
+ ACE_TRACE ("ACE::write_n");
+
+ size_t bytes_written;
+ int n;
+
+ for (bytes_written = 0; bytes_written < len; bytes_written += n)
+ if ((n = ACE_OS::write (handle, (const char *) buf + bytes_written,
+ len - bytes_written)) == -1)
+ return -1;
+
+ return bytes_written;
+}
+
+// Format buffer into printable format. This is useful for debugging.
+// Portions taken from mdump by J.P. Knight (J.P.Knight@lut.ac.uk)
+// Modifications by Todd Montgomery.
+
+int
+ACE::format_hexdump (char *buffer, int size, char *obuf, int obuf_sz)
+{
+ ACE_TRACE ("ACE::format_hexdump");
+
+ u_char c;
+ char textver[16 + 1];
+
+ int maxlen = (obuf_sz / 68) * 16;
+
+ if (size > maxlen)
+ size = maxlen;
+
+ int i;
+
+ for (i = 0; i < (size >> 4); i++)
+ {
+ int j;
+
+ for (j = 0 ; j < 16; j++)
+ {
+ c = buffer[(i << 4) + j];
+ ::sprintf (obuf, "%02x ", c);
+ obuf += 3;
+ if (j == 7)
+ {
+ ::sprintf (obuf, " ");
+ obuf++;
+ }
+ textver[j] = (c < 0x20 || c > 0x7e) ? '.' : c;
+ }
+
+ textver[j] = 0;
+
+ ::sprintf (obuf, " %s\n", textver);
+
+ while (*obuf != '\0')
+ obuf++;
+ }
+
+ if (size % 16)
+ {
+ for (i = 0 ; i < size % 16; i++)
+ {
+ c = buffer[size - size % 16 + i];
+ ::sprintf (obuf,"%02x ",c);
+ obuf += 3;
+ if (i == 7)
+ {
+ ::sprintf (obuf, " ");
+ obuf++;
+ }
+ textver[i] = (c < 0x20 || c > 0x7e) ? '.' : c;
+ }
+
+ for (i = size % 16; i < 16; i++)
+ {
+ ::sprintf (obuf, " ");
+ obuf += 3;
+ textver[i] = ' ';
+ }
+
+ textver[i] = 0;
+ ::sprintf (obuf, " %s\n", textver);
+ }
+ return size;
+}
+
+// Returns the current timestamp in the form
+// "hour:minute:second:microsecond." The month, day, and year are
+// also stored in the beginning of the date_and_time array. Returns 0
+// if unsuccessful, else returns pointer to beginning of the "time"
+// portion of <day_and_time>.
+
+char *
+ACE::timestamp (char date_and_time[], int date_and_timelen)
+{
+ ACE_TRACE ("ACE::timestamp");
+
+ if (date_and_timelen < 35)
+ {
+ errno = EINVAL;
+ return 0;
+ }
+
+#if defined (WIN32)
+ // @@ Jesper, I think Win32 supports all the UNIX versions below.
+ // Therefore, we can probably remove this WIN32 ifdef altogether.
+ SYSTEMTIME local;
+ ::GetLocalTime (&local);
+
+ ACE_OS::sprintf (date_and_time, "%02d/%02d/%04d%02d.%02d.%02d.%06d",
+ (int) local.wMonth, // new, also the %02d in sprintf
+ (int) local.wDay, // new, also the %02d in sprintf
+ (int) local.wYear, // new, also the %02d in sprintf
+ (int) local.wHour,
+ (int) local.wMinute,
+ (int) local.wSecond,
+ (int) local.wMilliseconds * 1000);
+#else // UNIX
+ char timebuf[26]; // This magic number is based on the ctime(3c) man page.
+ ACE_Time_Value cur_time = ACE_OS::gettimeofday ();
+ time_t secs = cur_time.sec ();
+ ACE_OS::ctime_r (&secs, timebuf, sizeof timebuf);
+ ACE_OS::strncpy (date_and_time, timebuf, date_and_timelen);
+ ACE_OS::sprintf (&date_and_time[19], ".%06d", cur_time.usec ());
+#endif /* WIN32 */
+ date_and_time[26] = '\0';
+ return &date_and_time[11];
+}
+
+// This function rounds the request to a multiple of the page size.
+
+size_t
+ACE::round_to_pagesize (off_t len)
+{
+ ACE_TRACE ("ACE::round_to_pagesize");
+ return (len + (ACE_PAGE_SIZE - 1)) & ~(ACE_PAGE_SIZE - 1);
+}
+
+ACE_HANDLE
+ACE::handle_timed_complete (ACE_HANDLE h,
+ ACE_Time_Value *timeout)
+{
+ ACE_TRACE ("ACE::handle_timed_complete");
+ ACE_Handle_Set rd_handles;
+ ACE_Handle_Set wr_handles;
+
+ rd_handles.set_bit (h);
+ wr_handles.set_bit (h);
+
+ int n = ACE_OS::select (int (h) + 1,
+ rd_handles,
+ wr_handles,
+ 0, timeout);
+ // If we failed to connect within the time period allocated by the
+ // caller, then we fail (e.g., the remote host might have been too
+ // busy to accept our call).
+ if (n <= 0)
+ {
+ if (n == 0)
+ errno = ETIMEDOUT;
+ return ACE_INVALID_HANDLE;
+ }
+ // Check if the handle is ready for reading and the handle is *not*
+ // ready for writing, which may indicate a problem. But we need to
+ // make sure...
+#if defined (ACE_HAS_TLI)
+ else if (rd_handles.is_set (h) && !wr_handles.is_set (h))
+#else
+ else if (rd_handles.is_set (h))
+#endif /* ACE_HAS_TLI */
+ {
+ char dummy;
+ // The following recv() won't block provided that the
+ // ACE_NONBLOCK flag has not been turned off .
+
+ n = ACE::recv (h, &dummy, 1, MSG_PEEK);
+ if (n <= 0)
+ {
+ if (n == 0)
+ errno = ECONNREFUSED;
+ return ACE_INVALID_HANDLE;
+ }
+ }
+
+ // 1. The HANDLE is ready for writing or 2. recv() returned that
+ // there are data to be read, which indicates the connection was
+ // successfully established.
+ return h;
+}
+
+ACE_HANDLE
+ACE::handle_timed_open (ACE_Time_Value *timeout,
+ LPCTSTR name,
+ int flags,
+ int perms)
+{
+ ACE_TRACE ("ACE::handle_timed_open");
+
+ if (timeout != 0)
+ {
+ // Open the named pipe or file using non-blocking mode...
+ ACE_HANDLE handle = ACE_OS::open (name,
+ flags | ACE_NONBLOCK,
+ perms);
+ if (handle == ACE_INVALID_HANDLE
+ && (errno == EWOULDBLOCK
+ && (timeout->sec () > 0 || timeout->usec () > 0)))
+ // This expression checks if we were polling.
+ errno = ETIMEDOUT;
+
+ return handle;
+ }
+ else
+ return ACE_OS::open (name, flags, perms);
+}
+
+// Wait up to <timeout> amount of time to accept a connection.
+
+int
+ACE::handle_timed_accept (ACE_HANDLE listener,
+ ACE_Time_Value *timeout,
+ int restart)
+{
+ ACE_TRACE ("ACE::handle_timed_accept");
+ // Make sure we don't bomb out on erroneous values.
+ if (listener == ACE_INVALID_HANDLE)
+ return -1;
+
+ // Use the select() implementation rather than poll().
+ ACE_Handle_Set rd_handle;
+ rd_handle.set_bit (listener);
+
+ // We need a loop here if <restart> is enabled.
+
+ for (;;)
+ {
+ switch (ACE_OS::select (int (listener) + 1,
+ rd_handle, 0, 0,
+ timeout))
+ {
+ case -1:
+ if (errno == EINTR && restart)
+ continue;
+ else
+ return -1;
+ /* NOTREACHED */
+ case 0:
+ if (timeout != 0 && timeout->sec() == 0 && timeout->usec() == 0)
+ errno = EWOULDBLOCK;
+ else
+ errno = ETIMEDOUT;
+ return -1;
+ /* NOTREACHED */
+ case 1:
+ return 0;
+ /* NOTREACHED */
+ default:
+ errno = EINVAL;
+ return -1;
+ /* NOTREACHED */
+ }
+ }
+ /* NOTREACHED */
+ return 0;
+}
+
+// Bind socket to an unused port.
+
+int
+ACE::bind_port (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE::bind_port");
+ sockaddr_in sin;
+ const int MAX_SHORT = 65535;
+ static int upper_limit = MAX_SHORT;
+ int lower_limit = IPPORT_RESERVED;
+ int round_trip = upper_limit;
+
+ ACE_OS::memset ((void *) &sin, 0, sizeof sin);
+ sin.sin_family = AF_INET;
+#if defined (ACE_HAS_SIN_LEN)
+ sin.sin_family = sizeof sin;
+#endif /* ACE_HAS_SIN_LEN */
+ sin.sin_addr.s_addr = INADDR_ANY;
+
+ for (;;)
+ {
+ sin.sin_port = htons (upper_limit);
+
+ if (ACE_OS::bind (handle, (sockaddr *) &sin, sizeof sin) >= 0)
+ return 0;
+ else if (errno != EADDRINUSE)
+ return -1;
+ else
+ {
+ upper_limit--;
+
+ /* Wrap back around when we reach the bottom. */
+ if (upper_limit <= lower_limit)
+ upper_limit = MAX_SHORT;
+
+ /* See if we have already gone around once! */
+ if (upper_limit == round_trip)
+ {
+ errno = EAGAIN;
+ return -1;
+ }
+ }
+ }
+}
+
+// Make the current process a UNIX daemon. This is based on Stevens
+// code from APUE.
+
+int
+ACE::daemonize (void)
+{
+ ACE_TRACE ("ACE::daemonize");
+#if !defined (ACE_WIN32)
+ pid_t pid;
+
+ if ((pid = ACE_OS::fork ()) == -1)
+ return -1;
+ else if (pid != 0)
+ ACE_OS::exit (0); /* parent exits */
+
+ /* child continues */
+ ACE_OS::setsid (); /* become session leader */
+
+ ACE_OS::chdir ("/"); /* change working directory */
+
+ ACE_OS::umask (0); /* clear our file mode creation mask */
+ return 0;
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+int
+ACE::max_handles (void)
+{
+ ACE_TRACE ("ACE::set_handle_limit");
+#if defined (_SC_OPEN_MAX)
+ return ACE_OS::sysconf (_SC_OPEN_MAX);
+#elif defined (RLIMIT_NOFILE)
+ rlimit rl;
+ ACE_OS::getrlimit (RLIMIT_NOFILE, &rl);
+ rl.rlim_cur;
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+// Set the number of currently open handles in the process.
+//
+// If NEW_LIMIT == -1 set the limit to the maximum allowable.
+// Otherwise, set it to be the value of NEW_LIMIT.
+
+int
+ACE::set_handle_limit (int new_limit)
+{
+ ACE_TRACE ("ACE::set_handle_limit");
+#if defined (RLIMIT_NOFILE)
+ struct rlimit rl;
+
+ int max_handles = ACE::max_handles ();
+
+ if (new_limit < 0 || new_limit > max_handles)
+ rl.rlim_cur = max_handles;
+ else
+ rl.rlim_cur = new_limit;
+
+ return ACE_OS::setrlimit (RLIMIT_NOFILE, &rl);
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+// Flags are file status flags to turn on.
+
+int
+ACE::set_flags (ACE_HANDLE handle, int flags)
+{
+ ACE_TRACE ("ACE::set_fl");
+#if defined (ACE_WIN32)
+ switch (flags)
+ {
+ case ACE_NONBLOCK:
+ // nonblocking argument (1)
+ // blocking: (0)
+ {
+ u_long nonblock = 1;
+ return ACE_OS::ioctl (handle, FIONBIO, &nonblock);
+ }
+ default:
+ errno = ENOTSUP;
+ return -1;
+ }
+#else
+ int val;
+
+ if ((val = ACE_OS::fcntl (handle, F_GETFL, 0)) == -1)
+ return -1;
+
+ val |= flags; /* turn on flags */
+
+ if (ACE_OS::fcntl (handle, F_SETFL, val) == -1)
+ return -1;
+ else
+ return 0;
+#endif /* ACE_WIN32 */
+}
+
+// Flags are the file status flags to turn off.
+
+int
+ACE::clr_flags (ACE_HANDLE handle, int flags)
+{
+ ACE_TRACE ("ACE::clr_fl");
+
+#if defined (ACE_WIN32)
+ switch (flags)
+ {
+ case ACE_NONBLOCK:
+ // nonblocking argument (1)
+ // blocking: (0)
+ {
+ u_long nonblock = 0;
+ return ACE_OS::ioctl (handle, FIONBIO, &nonblock);
+ }
+ default:
+ errno = ENOTSUP;
+ return -1;
+ }
+#else
+ int val;
+
+ if ((val = ACE_OS::fcntl (handle, F_GETFL, 0)) == -1)
+ return -1;
+
+ val &= ~flags; /* turn flags off */
+
+ if (ACE_OS::fcntl (handle, F_SETFL, val) == -1)
+ return -1;
+ else
+ return 0;
+#endif /* ACE_WIN32 */
+}
+
+int
+ACE::map_errno (int error)
+{
+ switch (error)
+ {
+#if defined (ACE_WIN32)
+ case WSAEWOULDBLOCK:
+ return EAGAIN; // Same as UNIX errno EWOULDBLOCK.
+#endif /* ACE_WIN32 */
+ }
+
+ return error;
+}