Consistently include <config.h> in all C source files and never in header files.
[platform/upstream/dbus.git] / dbus / dbus-sysdeps-util-win.c
index b0e4eab..7b2472f 100644 (file)
@@ -22,7 +22,7 @@
  *
  */
 
-#undef open
+#include <config.h>
 
 #define STRSAFE_NO_DEPRECATE
 
 #include "dbus-string.h"
 #include "dbus-sysdeps.h"
 #include "dbus-sysdeps-win.h"
+#include "dbus-sockets-win.h"
 #include "dbus-memory.h"
 
 #include <io.h>
 #include <sys/stat.h>
 #include <aclapi.h>
+#include <winsock2.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <fcntl.h>
 #include <errno.h>
-
-#if defined __MINGW32__ || (defined _MSC_VER && _MSC_VER <= 1310)
-/* save string functions version
-   using DBusString needs to much time because of uncommon api 
-*/ 
-#define errno_t int
-
-errno_t strcat_s(char *dest, size_t size, char *src) 
-{
-  _dbus_assert(strlen(dest) + strlen(src) +1 <= size);
-  strcat(dest,src);
-  return 0;
-}
-
-errno_t strcpy_s(char *dest, size_t size, char *src)
-{
-  _dbus_assert(strlen(src) +1 <= size);
-  strcpy(dest,src);  
-  return 0;
-}
-#endif
+#include <winsock2.h>   // WSA error codes
 
 /**
  * Does the chdir, fork, setsid, etc. to become a daemon process.
@@ -90,30 +72,32 @@ _dbus_become_daemon (const DBusString *pidfile,
  * @param error return location for errors
  * @returns #FALSE on failure
  */
-dbus_bool_t
+static dbus_bool_t
 _dbus_write_pid_file (const DBusString *filename,
                       unsigned long     pid,
                       DBusError        *error)
 {
   const char *cfilename;
-  DBusFile file;
+  int fd;
   FILE *f;
 
   cfilename = _dbus_string_get_const_data (filename);
-
-  if (!_dbus_file_open(&file, cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644))
+  
+  fd = _open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
+  
+  if (fd < 0)
     {
       dbus_set_error (error, _dbus_error_from_errno (errno),
                       "Failed to open \"%s\": %s", cfilename,
-                      _dbus_strerror (errno));
+                      strerror (errno));
       return FALSE;
     }
 
-  if ((f = fdopen (file.FDATA, "w")) == NULL)
+  if ((f = fdopen (fd, "w")) == NULL)
     {
       dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "Failed to fdopen fd %d: %s", file.FDATA, _dbus_strerror (errno));
-      _dbus_file_close (&file, NULL);
+                      "Failed to fdopen fd %d: %s", fd, strerror (errno));
+      _close (fd);
       return FALSE;
     }
 
@@ -121,7 +105,7 @@ _dbus_write_pid_file (const DBusString *filename,
     {
       dbus_set_error (error, _dbus_error_from_errno (errno),
                       "Failed to write to \"%s\": %s", cfilename,
-                      _dbus_strerror (errno));
+                      strerror (errno));
 
       fclose (f);
       return FALSE;
@@ -131,7 +115,7 @@ _dbus_write_pid_file (const DBusString *filename,
     {
       dbus_set_error (error, _dbus_error_from_errno (errno),
                       "Failed to close \"%s\": %s", cfilename,
-                      _dbus_strerror (errno));
+                      strerror (errno));
       return FALSE;
     }
 
@@ -139,6 +123,84 @@ _dbus_write_pid_file (const DBusString *filename,
 }
 
 /**
+ * Writes the given pid_to_write to a pidfile (if non-NULL) and/or to a
+ * pipe (if non-NULL). Does nothing if pidfile and print_pid_pipe are both
+ * NULL.
+ *
+ * @param pidfile the file to write to or #NULL
+ * @param print_pid_pipe the pipe to write to or #NULL
+ * @param pid_to_write the pid to write out
+ * @param error error on failure
+ * @returns FALSE if error is set
+ */
+dbus_bool_t
+_dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,
+                                  DBusPipe         *print_pid_pipe,
+                                  dbus_pid_t        pid_to_write,
+                                  DBusError        *error)
+{
+  if (pidfile)
+    {
+      _dbus_verbose ("writing pid file %s\n", _dbus_string_get_const_data (pidfile));
+      if (!_dbus_write_pid_file (pidfile,
+                                 pid_to_write,
+                                 error))
+        {
+          _dbus_verbose ("pid file write failed\n");
+          _DBUS_ASSERT_ERROR_IS_SET(error);
+          return FALSE;
+        }
+    }
+  else
+    {
+      _dbus_verbose ("No pid file requested\n");
+    }
+
+  if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe))
+    {
+      DBusString pid;
+      int bytes;
+
+      _dbus_verbose ("writing our pid to pipe %d\n", print_pid_pipe->fd_or_handle);
+
+      if (!_dbus_string_init (&pid))
+        {
+          _DBUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      if (!_dbus_string_append_int (&pid, pid_to_write) ||
+          !_dbus_string_append (&pid, "\n"))
+        {
+          _dbus_string_free (&pid);
+          _DBUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      bytes = _dbus_string_get_length (&pid);
+      if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes)
+        {
+          /* _dbus_pipe_write sets error only on failure, not short write */
+          if (error != NULL && !dbus_error_is_set(error))
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "Printing message bus PID: did not write enough bytes\n");
+            }
+          _dbus_string_free (&pid);
+          return FALSE;
+        }
+
+      _dbus_string_free (&pid);
+    }
+  else
+    {
+      _dbus_verbose ("No pid pipe to write to\n");
+    }
+
+  return TRUE;
+}
+
+/**
  * Verify that after the fork we can successfully change to this user.
  *
  * @param user the username given in the daemon configuration
@@ -164,134 +226,46 @@ _dbus_change_to_daemon_user  (const char    *user,
   return TRUE;
 }
 
-/**
- * Changes the user and group the bus is running as.
- *
- * @param uid the new user ID
- * @param gid the new group ID
- * @param error return location for errors
- * @returns #FALSE on failure
- */
-dbus_bool_t
-_dbus_change_identity  (dbus_uid_t     uid,
-                        dbus_gid_t     gid,
-                        DBusError     *error)
+void
+_dbus_init_system_log (void)
 {
-  return TRUE;
+    // FIXME!
 }
 
-/** Checks if user is at the console
-*
-* @param username user to check
-* @param error return location for errors
-* @returns #TRUE is the user is at the consolei and there are no errors
-*/
-dbus_bool_t
-_dbus_user_at_console(const char *username,
-                      DBusError  *error)
+/**
+ * Log a message to the system log file (e.g. syslog on Unix).
+ *
+ * @param severity a severity value
+ * @param msg a printf-style format string
+ * @param args arguments for the format string
+ *
+ */
+void
+_dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...)
 {
-#ifdef DBUS_WINCE
-       return TRUE;
-#else
-  dbus_bool_t retval = FALSE;
-  wchar_t *wusername;
-  DWORD sid_length;
-  PSID user_sid, console_user_sid;
-  HWINSTA winsta;
-
-  wusername = _dbus_win_utf8_to_utf16 (username, error);
-  if (!wusername)
-    return FALSE;
-
-  // TODO remove
-  if (!_dbus_win_account_to_sid (wusername, &user_sid, error))
-    goto out0;
-
-  /* Now we have the SID for username. Get the SID of the
-   * user at the "console" (window station WinSta0)
-   */
-  if (!(winsta = OpenWindowStation ("WinSta0", FALSE, READ_CONTROL)))
-    {
-      _dbus_win_set_error_from_win_error (error, GetLastError ());
-      goto out2;
-    }
-
-  sid_length = 0;
-  GetUserObjectInformation (winsta, UOI_USER_SID,
-                            NULL, 0, &sid_length);
-  if (sid_length == 0)
-    {
-      /* Nobody is logged on */
-      goto out2;
-    }
-
-  if (sid_length < 0 || sid_length > 1000)
-    {
-      dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID length");
-      goto out3;
-    }
-
-  console_user_sid = dbus_malloc (sid_length);
-  if (!console_user_sid)
-    {
-      _DBUS_SET_OOM (error);
-      goto out3;
-    }
-
-  if (!GetUserObjectInformation (winsta, UOI_USER_SID,
-                                 console_user_sid, sid_length, &sid_length))
-    {
-      _dbus_win_set_error_from_win_error (error, GetLastError ());
-      goto out4;
-    }
+  va_list args;
 
-  if (!IsValidSid (console_user_sid))
-    {
-      dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
-      goto out4;
-    }
-
-  retval = EqualSid (user_sid, console_user_sid);
+  va_start (args, msg);
 
-out4:
-  dbus_free (console_user_sid);
-out3:
-  CloseWindowStation (winsta);
-out2:
-  dbus_free (user_sid);
-out0:
-  dbus_free (wusername);
+  _dbus_system_logv (severity, msg, args);
 
-  return retval;
-#endif //DBUS_WINCE
+  va_end (args);
 }
 
 /**
- * Removes a directory; Directory must be empty
- * 
- * @param filename directory filename
- * @param error initialized error object
- * @returns #TRUE on success
+ * Log a message to the system log file (e.g. syslog on Unix).
+ *
+ * @param severity a severity value
+ * @param msg a printf-style format string
+ * @param args arguments for the format string
+ *
+ * If the FATAL severity is given, this function will terminate the program
+ * with an error code.
  */
-dbus_bool_t
-_dbus_delete_directory (const DBusString *filename,
-                        DBusError        *error)
+void
+_dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args)
 {
-  const char *filename_c;
-
-  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-
-  filename_c = _dbus_string_get_const_data (filename);
-
-  if (rmdir (filename_c) != 0)
-    {
-      dbus_set_error (error, DBUS_ERROR_FAILED,
-                      "Failed to remove directory %s: %s\n",
-                      filename_c, _dbus_strerror (errno));
-      return FALSE;
-    }
-
-  return TRUE;
+    // FIXME!
 }
 
 /** Installs a signal handler
@@ -306,34 +280,6 @@ _dbus_set_signal_handler (int               sig,
   _dbus_verbose ("_dbus_set_signal_handler() has to be implemented\n");
 }
 
-/** Checks if a file exists
-*
-* @param file full path to the file
-* @returns #TRUE if file exists
-*/
-dbus_bool_t 
-_dbus_file_exists (const char *file)
-{
-  HANDLE h = CreateFile(
-          file, /* LPCTSTR lpFileName*/
-          0, /* DWORD dwDesiredAccess */
-          0, /* DWORD dwShareMode*/
-          NULL, /* LPSECURITY_ATTRIBUTES lpSecurityAttributes */
-          OPEN_EXISTING, /* DWORD dwCreationDisposition */
-          FILE_ATTRIBUTE_NORMAL, /* DWORD dwFlagsAndAttributes */
-          NULL /* HANDLE hTemplateFile */
-        );
-
-    /* file not found, use local copy of session.conf  */
-    if (h != INVALID_HANDLE_VALUE && GetLastError() != ERROR_PATH_NOT_FOUND)
-      {
-        CloseHandle(h);
-        return TRUE;
-      }
-    else
-        return FALSE;  
-}
-
 /**
  * stat() wrapper.
  *
@@ -352,17 +298,11 @@ _dbus_stat(const DBusString *filename,
        //TODO
 #else
   const char *filename_c;
-#if !defined(DBUS_WIN) && !defined(DBUS_WINCE)
-
-  struct stat sb;
-#else
-
   WIN32_FILE_ATTRIBUTE_DATA wfad;
   char *lastdot;
   DWORD rc;
   PSID owner_sid, group_sid;
   PSECURITY_DESCRIPTOR sd;
-#endif
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
@@ -512,7 +452,7 @@ DIR;
 * The DIR typedef is not compatible with Unix.
 **********************************************************************/
 
-DIR * _dbus_opendir(const char *dir)
+static DIR * _dbus_opendir(const char *dir)
 {
   DIR *dp;
   char *filespec;
@@ -545,7 +485,7 @@ DIR * _dbus_opendir(const char *dir)
   return dp;
 }
 
-struct dirent * _dbus_readdir(DIR *dp)
+static struct dirent * _dbus_readdir(DIR *dp)
   {
     if (!dp || dp->finished)
       return NULL;
@@ -570,7 +510,7 @@ struct dirent * _dbus_readdir(DIR *dp)
   }
 
 
-int _dbus_closedir(DIR *dp)
+static int _dbus_closedir(DIR *dp)
 {
   if (!dp)
     return 0;
@@ -801,6 +741,11 @@ _dbus_unix_user_is_process_owner (dbus_uid_t uid)
   return FALSE;
 }
 
+dbus_bool_t _dbus_windows_user_is_process_owner (const char *windows_sid)
+{
+  return TRUE;
+}
+
 /*=====================================================================
   unix emulation functions - should be removed sometime in the future
  =====================================================================*/
@@ -818,6 +763,8 @@ dbus_bool_t
 _dbus_unix_user_is_at_console (dbus_uid_t         uid,
                                DBusError         *error)
 {
+  dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
+                  "UNIX user IDs not supported on Windows\n");
   return FALSE;
 }
 
@@ -882,186 +829,6 @@ _dbus_unix_groups_from_uid (dbus_uid_t            uid,
  ************************************************************************/
 
 
-/**
- * Assigns an error name and message corresponding to a Win32 error
- * code to a DBusError. Does nothing if error is #NULL.
- *
- * @param error the error.
- * @param code the Win32 error code
- */
-void
-_dbus_win_set_error_from_win_error (DBusError *error,
-                                    int        code)
-{
-  char *msg;
-
-  /* As we want the English message, use the A API */
-  FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                  FORMAT_MESSAGE_IGNORE_INSERTS |
-                  FORMAT_MESSAGE_FROM_SYSTEM,
-                  NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US),
-                  (LPTSTR) &msg, 0, NULL);
-  if (msg)
-    {
-      char *msg_copy;
-
-      msg_copy = dbus_malloc (strlen (msg));
-      strcpy (msg_copy, msg);
-      LocalFree (msg);
-
-      dbus_set_error (error, "win32.error", "%s", msg_copy);
-    }
-  else
-    dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code);
-}
-
-void
-_dbus_win_warn_win_error (const char *message,
-                          int         code)
-{
-  DBusError error = DBUS_ERROR_INIT;
-
-  _dbus_win_set_error_from_win_error (&error, code);
-  _dbus_warn ("%s: %s\n", message, error.message);
-  dbus_error_free (&error);
-}
-
-/**
- * A wrapper around strerror() because some platforms
- * may be lame and not have strerror().
- *
- * @param error_number errno.
- * @returns error description.
- */
-const char*
-_dbus_strerror (int error_number)
-{
-#ifdef DBUS_WINCE
-  // TODO
-  return "unknown";
-#else
-  const char *msg;
-
-  switch (error_number)
-    {
-    case WSAEINTR:
-      return "Interrupted function call";
-    case WSAEACCES:
-      return "Permission denied";
-    case WSAEFAULT:
-      return "Bad address";
-    case WSAEINVAL:
-      return "Invalid argument";
-    case WSAEMFILE:
-      return "Too many open files";
-    case WSAEWOULDBLOCK:
-      return "Resource temporarily unavailable";
-    case WSAEINPROGRESS:
-      return "Operation now in progress";
-    case WSAEALREADY:
-      return "Operation already in progress";
-    case WSAENOTSOCK:
-      return "Socket operation on nonsocket";
-    case WSAEDESTADDRREQ:
-      return "Destination address required";
-    case WSAEMSGSIZE:
-      return "Message too long";
-    case WSAEPROTOTYPE:
-      return "Protocol wrong type for socket";
-    case WSAENOPROTOOPT:
-      return "Bad protocol option";
-    case WSAEPROTONOSUPPORT:
-      return "Protocol not supported";
-    case WSAESOCKTNOSUPPORT:
-      return "Socket type not supported";
-    case WSAEOPNOTSUPP:
-      return "Operation not supported";
-    case WSAEPFNOSUPPORT:
-      return "Protocol family not supported";
-    case WSAEAFNOSUPPORT:
-      return "Address family not supported by protocol family";
-    case WSAEADDRINUSE:
-      return "Address already in use";
-    case WSAEADDRNOTAVAIL:
-      return "Cannot assign requested address";
-    case WSAENETDOWN:
-      return "Network is down";
-    case WSAENETUNREACH:
-      return "Network is unreachable";
-    case WSAENETRESET:
-      return "Network dropped connection on reset";
-    case WSAECONNABORTED:
-      return "Software caused connection abort";
-    case WSAECONNRESET:
-      return "Connection reset by peer";
-    case WSAENOBUFS:
-      return "No buffer space available";
-    case WSAEISCONN:
-      return "Socket is already connected";
-    case WSAENOTCONN:
-      return "Socket is not connected";
-    case WSAESHUTDOWN:
-      return "Cannot send after socket shutdown";
-    case WSAETIMEDOUT:
-      return "Connection timed out";
-    case WSAECONNREFUSED:
-      return "Connection refused";
-    case WSAEHOSTDOWN:
-      return "Host is down";
-    case WSAEHOSTUNREACH:
-      return "No route to host";
-    case WSAEPROCLIM:
-      return "Too many processes";
-    case WSAEDISCON:
-      return "Graceful shutdown in progress";
-    case WSATYPE_NOT_FOUND:
-      return "Class type not found";
-    case WSAHOST_NOT_FOUND:
-      return "Host not found";
-    case WSATRY_AGAIN:
-      return "Nonauthoritative host not found";
-    case WSANO_RECOVERY:
-      return "This is a nonrecoverable error";
-    case WSANO_DATA:
-      return "Valid name, no data record of requested type";
-    case WSA_INVALID_HANDLE:
-      return "Specified event object handle is invalid";
-    case WSA_INVALID_PARAMETER:
-      return "One or more parameters are invalid";
-    case WSA_IO_INCOMPLETE:
-      return "Overlapped I/O event object not in signaled state";
-    case WSA_IO_PENDING:
-      return "Overlapped operations will complete later";
-    case WSA_NOT_ENOUGH_MEMORY:
-      return "Insufficient memory available";
-    case WSA_OPERATION_ABORTED:
-      return "Overlapped operation aborted";
-#ifdef WSAINVALIDPROCTABLE
-
-    case WSAINVALIDPROCTABLE:
-      return "Invalid procedure table from service provider";
-#endif
-#ifdef WSAINVALIDPROVIDER
-
-    case WSAINVALIDPROVIDER:
-      return "Invalid service provider version number";
-#endif
-#ifdef WSAPROVIDERFAILEDINIT
-
-    case WSAPROVIDERFAILEDINIT:
-      return "Unable to initialize a service provider";
-#endif
-
-    case WSASYSCALLFAILURE:
-      return "System call failure";
-    }
-  msg = strerror (error_number);
-  if (msg == NULL)
-    msg = "unknown";
-
-  return msg;
-#endif //DBUS_WINCE
-}
 
 
 
@@ -1711,3 +1478,27 @@ _dbus_lm_strerror(int error_number)
   return msg;
 #endif //DBUS_WINCE
 }
+
+/**
+ * Get a printable string describing the command used to execute
+ * the process with pid.  This string should only be used for
+ * informative purposes such as logging; it may not be trusted.
+ *
+ * The command is guaranteed to be printable ASCII and no longer
+ * than max_len.
+ *
+ * @param pid Process id
+ * @param str Append command to this string
+ * @param max_len Maximum length of returned command
+ * @param error return location for errors
+ * @returns #FALSE on error
+ */
+dbus_bool_t
+_dbus_command_for_pid (unsigned long  pid,
+                       DBusString    *str,
+                       int            max_len,
+                       DBusError     *error)
+{
+  // FIXME
+  return FALSE;
+}