[PATCH] - HSA Windows
by Adam Stokes
- Handle compilation on windows since DNS SRV is
not implemented yet.
---
src/lib/CMakeLists.txt | 4 ++-
src/lib/dnssrv_private.h | 42 -------------------------------
src/lib/dnssrv_windows.c | 35 ++++++++++++++++++++++++++
src/tests/CMakeLists.txt | 2 +-
src/tests/mh_hsa.h | 59 --------------------------------------------
src/tests/mh_hsa_linux.h | 59 ++++++++++++++++++++++++++++++++++++++++++++
src/tests/mh_hsa_windows.h | 59 ++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 157 insertions(+), 103 deletions(-)
delete mode 100644 src/lib/dnssrv_private.h
create mode 100644 src/lib/dnssrv_windows.c
delete mode 100644 src/tests/mh_hsa.h
create mode 100644 src/tests/mh_hsa_linux.h
create mode 100644 src/tests/mh_hsa_windows.h
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index ab21bba..f03d6e0 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -31,12 +31,14 @@ if(WIN32)
target_link_libraries(${lib} wsock32)
install(TARGETS ${lib} DESTINATION sbin)
endforeach (lib ${LIBS})
+ add_library(mcommon_resolv SHARED dnssrv_${VARIANT}.c)
+ target_link_libraries(mcommon mcommon_resolv)
else(WIN32)
foreach (lib ${LIBS})
install(TARGETS ${lib} DESTINATION lib${LIB_SUFFIX})
endforeach (lib ${LIBS})
# libresolv
- add_library(mcommon_resolv SHARED dnssrv_linux.c)
+ add_library(mcommon_resolv SHARED dnssrv_${VARIANT}.c)
target_link_libraries(mcommon mcommon_resolv resolv)
endif(WIN32)
diff --git a/src/lib/dnssrv_private.h b/src/lib/dnssrv_private.h
deleted file mode 100644
index 0752311..0000000
--- a/src/lib/dnssrv_private.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* dnssrv.h - Copyright (c) 2011 Red Hat, Inc.
- * Written by Adam Stokes <astokes(a)fedoraproject.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#define MAX_NAME_LEN 1024
-
-struct srv_reply
-{
- int prio;
- int weight;
- int port;
- char name[];
-};
-
-struct srv_reply **srv_lookup(char *service,
- char *protocol,
- char *domain);
-
-void srv_free(struct srv_reply **srv);
-
-/*
- * Local Variables:
- * mode: c
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- * vim: et
- */
diff --git a/src/lib/dnssrv_windows.c b/src/lib/dnssrv_windows.c
new file mode 100644
index 0000000..32b00ee
--- /dev/null
+++ b/src/lib/dnssrv_windows.c
@@ -0,0 +1,35 @@
+/* dnssrv_windows.c - Copyright (c) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "matahari/dnssrv.h"
+
+/**
+ * Domain lookup providing a Matahari broker
+ *
+ * \param[in] srv record query i.e. "_matahari._tcp.matahariproject.org
+ * \param[in] set buffer to hold domain retrieved
+ * \param[in] set buffer length
+ *
+ * \return 0 or greater for successful match
+ */
+
+int
+mh_srv_lookup(const char *query, char *target, size_t len)
+{
+ return -1;
+}
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index f57b9f0..5f79618 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -5,7 +5,7 @@ if(CXXTEST_FOUND)
ENABLE_TESTING()
CXXTEST_ADD_TEST(mh_api_network_unittest network_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_network.h)
CXXTEST_ADD_TEST(mh_api_host_unittest host_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_host.h)
- CXXTEST_ADD_TEST(mh_hsa_unittest hsa_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_hsa.h)
+ CXXTEST_ADD_TEST(mh_hsa_unittest hsa_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_hsa_${VARIANT}.h)
add_library(mh_tester SHARED test_utilities.c)
target_link_libraries(mh_tester ${pcre_LIBRARIES} mcommon mnetwork mhost)
target_link_libraries(mh_api_network_unittest mh_tester)
diff --git a/src/tests/mh_hsa.h b/src/tests/mh_hsa.h
deleted file mode 100644
index 17034f0..0000000
--- a/src/tests/mh_hsa.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * mh_hs.h: dns srv high availability test
- *
- * Copyright (C) 2011 Red Hat Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Author: Adam Stokes <astokes(a)fedoraproject.org>
- */
-
-
-#ifndef __MH_HSA_UNITTEST_H
-#define __MH_HSA_UNITTEST_H
-
-#include <string.h>
-#include <stdlib.h>
-#include <cxxtest/TestSuite.h>
-
-extern "C" {
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#include "mh_test_utilities.h"
-#include "matahari/dnssrv.h"
-};
-
-using namespace std;
-
-class MhHsaSuite : public CxxTest::TestSuite
-{
- public:
- std::stringstream infomsg;
-
- void testSrvLookup(void)
- {
- char target[NS_MAXDNAME];
- const char *host = "_matahari._tcp.matahariproject.org";
- int ret = 0;
-
- ret = mh_srv_lookup(host, target, NS_MAXDNAME);
- TS_ASSERT(ret == 0);
- TS_ASSERT((mh_test_is_match("^qpid.*matahariproject\\.org$",
- target)) >= 0);
- }
-};
-
-#endif
diff --git a/src/tests/mh_hsa_linux.h b/src/tests/mh_hsa_linux.h
new file mode 100644
index 0000000..17034f0
--- /dev/null
+++ b/src/tests/mh_hsa_linux.h
@@ -0,0 +1,59 @@
+/*
+ * mh_hs.h: dns srv high availability test
+ *
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Adam Stokes <astokes(a)fedoraproject.org>
+ */
+
+
+#ifndef __MH_HSA_UNITTEST_H
+#define __MH_HSA_UNITTEST_H
+
+#include <string.h>
+#include <stdlib.h>
+#include <cxxtest/TestSuite.h>
+
+extern "C" {
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include "mh_test_utilities.h"
+#include "matahari/dnssrv.h"
+};
+
+using namespace std;
+
+class MhHsaSuite : public CxxTest::TestSuite
+{
+ public:
+ std::stringstream infomsg;
+
+ void testSrvLookup(void)
+ {
+ char target[NS_MAXDNAME];
+ const char *host = "_matahari._tcp.matahariproject.org";
+ int ret = 0;
+
+ ret = mh_srv_lookup(host, target, NS_MAXDNAME);
+ TS_ASSERT(ret == 0);
+ TS_ASSERT((mh_test_is_match("^qpid.*matahariproject\\.org$",
+ target)) >= 0);
+ }
+};
+
+#endif
diff --git a/src/tests/mh_hsa_windows.h b/src/tests/mh_hsa_windows.h
new file mode 100644
index 0000000..1cf1ea8
--- /dev/null
+++ b/src/tests/mh_hsa_windows.h
@@ -0,0 +1,59 @@
+/*
+ * mh_hs.h: dns srv high availability test
+ *
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Adam Stokes <astokes(a)fedoraproject.org>
+ */
+
+
+#ifndef __MH_HSA_UNITTEST_H
+#define __MH_HSA_UNITTEST_H
+
+#include <string.h>
+#include <stdlib.h>
+#include <cxxtest/TestSuite.h>
+
+extern "C" {
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include "mh_test_utilities.h"
+#include "matahari/dnssrv.h"
+};
+
+using namespace std;
+
+class MhHsaSuite : public CxxTest::TestSuite
+{
+ public:
+ std::stringstream infomsg;
+
+ void testSrvLookup(void)
+ {
+ char target[NI_MAXHOST];
+ const char *host = "_matahari._tcp.matahariproject.org";
+ int ret = 0;
+
+ ret = mh_srv_lookup(host, target, NI_MAXHOST);
+ TS_ASSERT(ret == 0);
+ TS_ASSERT((mh_test_is_match("^qpid.*matahariproject\\.org$",
+ target)) >= 0);
+ }
+};
+
+#endif
--
1.7.5.4
12 years, 10 months
Re: [Matahari] [PATCH] Add Power Management (PM) agent
by Jaroslav Skarvada
Updated patch according to comments from thread:
http://fedorahosted.org/pipermail/matahari/2011-June/001124.html
thanks & regards
Jaroslav
---
CMakeLists.txt | 3 +
matahari.spec | 45 +++++
src/CMakeLists.txt | 1 +
src/include/matahari/pm.h | 70 +++++++
src/lib/CMakeLists.txt | 6 +-
src/lib/pm.c | 45 +++++
src/lib/pm_linux.c | 335 +++++++++++++++++++++++++++++++++
src/lib/pm_private.h | 39 ++++
src/lib/pm_windows.c | 301 +++++++++++++++++++++++++++++
src/pm/CMakeLists.txt | 61 ++++++
src/pm/org.matahariproject.PM.conf | 18 ++
src/pm/org.matahariproject.PM.policy | 27 +++
src/pm/org.matahariproject.PM.service | 4 +
src/pm/pm-dbus.c | 144 ++++++++++++++
src/pm/pm-qmf.cpp | 112 +++++++++++
src/pm/schema.xml | 21 ++
src/schema.xml | 18 ++
src/windows/install.bat | 2 +-
18 files changed, 1250 insertions(+), 2 deletions(-)
create mode 100644 src/include/matahari/pm.h
create mode 100644 src/lib/pm.c
create mode 100644 src/lib/pm_linux.c
create mode 100644 src/lib/pm_private.h
create mode 100644 src/lib/pm_windows.c
create mode 100644 src/pm/CMakeLists.txt
create mode 100644 src/pm/org.matahariproject.PM.conf
create mode 100644 src/pm/org.matahariproject.PM.policy
create mode 100644 src/pm/org.matahariproject.PM.service
create mode 100644 src/pm/pm-dbus.c
create mode 100644 src/pm/pm-qmf.cpp
create mode 100644 src/pm/schema.xml
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e4daf05..a656085 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -79,15 +79,18 @@ if(WIN32)
set( CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS}
" Some comment\\n DetailPrint \\\"Stopping Matahari services\\\"\\n"
" Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe stop mh_hostd\\\"'\\n"
+ " Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe stop mh_pmd\\\"'\\n"
" Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe stop mh_netd\\\"'\\n"
" Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe stop mh_serviced\\\"'\\n"
" Give them time to stop\\n Sleep 10000\\n"
" Some comment\\n DetailPrint \\\"Removing Matahari services\\\"\\n"
" Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe delete mh_hostd\\\"'\\n"
+ " Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe delete mh_pmd\\\"'\\n"
" Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe delete mh_netd\\\"'\\n"
" Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe delete mh_serviced\\\"'\\n"
" Some comment\\n DetailPrint \\\"Removing Matahari service binaries\\\"\\n"
" Some comment\\n ExecWait 'del \\\"$INSTDIR\\\\mh_hostd.exe\\\"'\\n"
+ " Some comment\\n ExecWait 'del \\\"$INSTDIR\\\\mh_pmd.exe\\\"'\\n"
" Some comment\\n ExecWait 'del \\\"$INSTDIR\\\\mh_netd.exe\\\"'\\n"
" Some comment\\n ExecWait 'del \\\"$INSTDIR\\\\mh_serviced.exe\\\"'\\n"
)
diff --git a/matahari.spec b/matahari.spec
index a52b1d7..f0e8ffa 100644
--- a/matahari.spec
+++ b/matahari.spec
@@ -107,6 +107,17 @@ Requires: %{name}-agent-lib = %{version}-%{release}
%description host
QMF agent for viewing and controlling remote hosts
+%package pm
+License: GPLv2+
+Summary: QMF agent for PM
+Group: Applications/System
+Requires: %{name}-lib = %{version}-%{release}
+Requires: %{name}-agent-lib = %{version}-%{release}
+Requires: tuned
+
+%description pm
+QMF agent for viewing and controlling power management settings
+
%package network
License: GPLv2+
Summary: QMF agent for network devices
@@ -202,6 +213,22 @@ if [ "$1" -ge "1" ]; then
/sbin/service matahari-host condrestart >/dev/null 2>&1 || :
fi
+#== PM
+
+%post pm
+/sbin/service matahari-pm condrestart
+
+%preun pm
+if [ $1 = 0 ]; then
+ /sbin/service matahari-pm stop >/dev/null 2>&1 || :
+ chkconfig --del matahari-pm
+fi
+
+%postun pm
+if [ "$1" -ge "1" ]; then
+ /sbin/service matahari-pm condrestart >/dev/null 2>&1 || :
+fi
+
#== Network
%post network
@@ -297,6 +324,7 @@ test "x%{buildroot}" != "x" && rm -rf %{buildroot}
%defattr(644, root, root, 755)
%{_libdir}/libmcommon.so.*
%{_libdir}/libmhost.so.*
+%{_libdir}/libmpm.so.*
%{_libdir}/libmnetwork.so.*
%{_libdir}/libmservice.so.*
%{_libdir}/libmconfig.so.*
@@ -328,6 +356,19 @@ test "x%{buildroot}" != "x" && rm -rf %{buildroot}
%attr(755, root, root) %{_sbindir}/matahari-dbus-hostd
%endif
+%files pm
+%defattr(644, root, root, 755)
+%doc AUTHORS COPYING
+
+%if %{with qmf}
+%attr(755, root, root) %{_initddir}/matahari-pm
+%attr(755, root, root) %{_sbindir}/matahari-qmf-pmd
+%endif
+
+%if %{with dbus}
+%attr(755, root, root) %{_sbindir}/matahari-dbus-pmd
+%endif
+
%files service
%defattr(644, root, root, 755)
%doc AUTHORS COPYING
@@ -372,15 +413,19 @@ test "x%{buildroot}" != "x" && rm -rf %{buildroot}
%if %{with dbus}
%files dbus
%{_sysconfdir}/dbus-1/system.d/org.matahariproject.Host.conf
+%{_sysconfdir}/dbus-1/system.d/org.matahariproject.PM.conf
%{_sysconfdir}/dbus-1/system.d/org.matahariproject.Network.conf
%{_sysconfdir}/dbus-1/system.d/org.matahariproject.Services.conf
%{_datadir}/dbus-1/interfaces/org.matahariproject.Host.xml
+%{_datadir}/dbus-1/interfaces/org.matahariproject.PM.xml
%{_datadir}/dbus-1/interfaces/org.matahariproject.Network.xml
%{_datadir}/dbus-1/interfaces/org.matahariproject.Services.xml
%{_datadir}/dbus-1/system-services/org.matahariproject.Host.service
+%{_datadir}/dbus-1/system-services/org.matahariproject.PM.service
%{_datadir}/dbus-1/system-services/org.matahariproject.Network.service
%{_datadir}/dbus-1/system-services/org.matahariproject.Services.service
%{_datadir}/polkit-1/actions/org.matahariproject.Host.policy
+%{_datadir}/polkit-1/actions/org.matahariproject.PM.policy
%{_datadir}/polkit-1/actions/org.matahariproject.Network.policy
%{_datadir}/polkit-1/actions/org.matahariproject.Services.policy
%endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5dda02d..7013e1e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -132,6 +132,7 @@ endif(WITH-QMF)
### Subdirectories
add_subdirectory(lib)
add_subdirectory(host)
+add_subdirectory(pm)
add_subdirectory(network)
add_subdirectory(service)
add_subdirectory(config)
diff --git a/src/include/matahari/pm.h b/src/include/matahari/pm.h
new file mode 100644
index 0000000..4857a47
--- /dev/null
+++ b/src/include/matahari/pm.h
@@ -0,0 +1,70 @@
+/* ph.h - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <jskarvad(a)redhat.com>
+ * Based on code from Arjun Roy <arroy(a)redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * \file
+ * \brief PM API
+ * \ingroup coreapi
+ */
+
+#ifndef __MH_PM_H__
+#define __MH_PM_H__
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define TIMEOUT 10
+#define TA_PATH "/usr/bin/"
+#define TA_SETPROFILE "profile"
+#define TA_GETPROFILE "active"
+#define TA_LISTPROFILES "list"
+#define TA_OFF "off"
+#define TUNEDADM TA_PATH "tuned-adm"
+
+#define SYSTEM32 "system32"
+#define POWERCFG "powercfg"
+#define PC_SETPROFILE "-SETACTIVE"
+#define PC_GETPROFILE "-GETACTIVESCHEME"
+#define PC_LISTPROFILES "-LIST"
+
+#define STR_UNK "UNKNOWN"
+#define STR_ERR "ERROR"
+
+enum exec_exitcode {
+ EC_OK = 0,
+ EC_UNKNOWN_ERROR = 1,
+ EC_INVALID_PARAM = 2,
+ EC_UNIMPLEMENT_FEATURE = 3,
+ EC_INSUFFICIENT_PRIV = 4,
+ EC_NOT_INSTALLED = 5,
+
+ /* 150-199<>reserved for application use */
+ EC_SIGNAL = 194,
+ EC_NOT_SUPPORTED = 195,
+ EC_PENDING = 196,
+ EC_CANCELLED = 197,
+ EC_TIMEOUT = 198,
+ EC_OTHER_ERROR = 199, /* Keep the same codes as LSB */
+};
+
+extern gboolean mh_pm_set_profile(const char *profile);
+extern const char *mh_pm_get_profile(void);
+extern GList *mh_pm_list_profiles(void);
+
+#endif // __MH_PM_H__
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index ab21bba..7c9fc14 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -1,6 +1,6 @@
# Library
-set(LIBS mcommon mhost mnetwork mservice mconfig)
+set(LIBS mcommon mhost mnetwork mpm mservice mconfig)
include_directories(${pcre_INCLUDE_DIRS})
# See http://sourceware.org/autobook/autobook/autobook_91.html for
@@ -18,6 +18,10 @@ add_library (mnetwork SHARED network.c network_${VARIANT}.c)
set_target_properties(mnetwork PROPERTIES SOVERSION 1.0.0)
target_link_libraries(mnetwork ${pcre_LIBRARIES} mcommon ${SIGAR} ${glib_LIBRARIES})
+add_library (mpm SHARED pm.c pm_${VARIANT}.c)
+set_target_properties(mpm PROPERTIES SOVERSION 1.0.0)
+target_link_libraries(mpm ${pcre_LIBRARIES} mcommon ${SIGAR} ${glib_LIBRARIES})
+
add_library (mservice SHARED services.c services_${VARIANT}.c)
set_target_properties(mservice PROPERTIES SOVERSION 1.0.0)
target_link_libraries(mservice ${pcre_LIBRARIES} mcommon ${SIGAR} ${glib_LIBRARIES})
diff --git a/src/lib/pm.c b/src/lib/pm.c
new file mode 100644
index 0000000..a413c94
--- /dev/null
+++ b/src/lib/pm.c
@@ -0,0 +1,45 @@
+/* pm.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <andrew(a)beekhof.net>
+ * Based on code from Andrew Beekhof <andrew(a)beekhof.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef WIN32
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include "matahari/pm.h"
+#include "matahari/logging.h"
+#include "pm_private.h"
+
+MH_TRACE_INIT_DATA(mh_pm);
+
+gboolean mh_pm_set_profile(const char* profile)
+{
+ return pm_set_profile(profile);
+}
+
+const char *mh_pm_get_profile(void)
+{
+ return pm_get_profile();
+}
+
+GList *mh_pm_list_profiles(void)
+{
+ return pm_list_profiles();
+}
diff --git a/src/lib/pm_linux.c b/src/lib/pm_linux.c
new file mode 100644
index 0000000..db8821e
--- /dev/null
+++ b/src/lib/pm_linux.c
@@ -0,0 +1,335 @@
+/* pm_linux.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <jskarvad(a)redhat.com>
+ * Based on code from Andrew Beekhof <andrew(a)beekhof.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/wait.h>
+
+#include "matahari/logging.h"
+#include "matahari/pm.h"
+#include "host_private.h"
+#include "sigar.h"
+
+static gboolean read_output(int fd, char **data)
+{
+ int rc = 0, len = 0;
+ char buf[500];
+ static const size_t bufsize = sizeof(buf);
+
+ if (*data)
+ len = strlen(*data);
+
+ do {
+ rc = read(fd, buf, bufsize - 1);
+ if (rc > 0) {
+ buf[rc] = 0;
+ *data = realloc(*data, len + rc + 1);
+ snprintf(*data + len, bufsize, "%s", buf);
+ len += rc;
+
+ } else if (errno != EINTR)
+ return FALSE;
+ } while (rc == bufsize - 1 || rc < 0);
+
+ return TRUE;
+}
+
+static int exec_command(const char *command, int atimeout, char **stdoutbuf,
+ char **stderrbuf, char *const argv[])
+{
+ pid_t pid;
+ int fd, rc = 0;
+ int stdout_fd[2];
+ int stderr_fd[2];
+
+ if (! command)
+ return EC_OTHER_ERROR;
+
+ if (pipe(stdout_fd) < 0) {
+ mh_perror(LOG_ERR, "pipe() failed");
+ }
+ if (pipe(stderr_fd) < 0) {
+ mh_perror(LOG_ERR, "pipe() failed");
+ }
+ pid = fork();
+
+ switch (pid) {
+ case -1:
+ mh_perror(LOG_ERR, "fork() failed");
+ close(stdout_fd[0]);
+ close(stdout_fd[1]);
+ close(stderr_fd[0]);
+ close(stderr_fd[1]);
+ return EC_OTHER_ERROR;
+ /* Child. */
+ case 0:
+ setpgid(0, 0);
+ close(stdout_fd[0]);
+ close(stderr_fd[0]);
+ if (STDOUT_FILENO != stdout_fd[1]) {
+ if (dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
+ mh_perror(LOG_ERR, "dup2() failed (stdout)");
+ }
+ close(stdout_fd[1]);
+ }
+ if (STDERR_FILENO != stderr_fd[1]) {
+ if (dup2(stderr_fd[1], STDERR_FILENO) != STDERR_FILENO) {
+ mh_perror(LOG_ERR, "dup2() failed (stderr)");
+ }
+ close(stderr_fd[1]);
+ }
+
+ /* close all descriptors except stdin/out/err and channels to logd */
+ for (fd = getdtablesize() - 1; fd > STDERR_FILENO; fd--)
+ close(fd);
+
+ /* execute the command */
+ execvp(command, argv);
+
+ switch (errno) { /* see execvp */
+ case ENOENT: /* No such file or directory */
+ case EISDIR: /* Is a directory */
+ rc = EC_NOT_INSTALLED;
+ break;
+ case EACCES: /* permission denied (various errors) */
+ rc = EC_INSUFFICIENT_PRIV;
+ break;
+ default:
+ rc = EC_UNKNOWN_ERROR;
+ break;
+ }
+ exit(rc);
+ }
+ /* Only the parent reaches here */
+ close(stdout_fd[1]);
+ close(stderr_fd[1]);
+
+ int status = 0;
+ int timeout = atimeout;
+ mh_trace("Waiting for %d", pid);
+ while (timeout > 0 && waitpid(pid, &status, WNOHANG) <= 0) {
+ sleep(1);
+ timeout--;
+ }
+
+ if (timeout == 0) {
+ int killrc = sigar_proc_kill(pid, SIGKILL);
+
+ rc = EC_TIMEOUT;
+ mh_warn("%d - timed out after %dms", pid, atimeout);
+
+ if (killrc != SIGAR_OK && killrc != ESRCH) {
+ mh_err("kill(%d, KILL) failed: %d", pid, killrc);
+ }
+
+ } else if (WIFEXITED(status)) {
+ rc = WEXITSTATUS(status);
+ mh_err("Managed process %d exited with rc=%d", pid, rc);
+
+ } else if (WIFSIGNALED(status)) {
+ int signo = WTERMSIG(status);
+ rc = EC_SIGNAL;
+ mh_err("Managed process %d exited with signal=%d", pid, signo);
+ }
+#ifdef WCOREDUMP
+ if (WCOREDUMP(status)) {
+ rc = EC_OTHER_ERROR;
+ mh_err("Managed process %d dumped core", pid);
+ }
+#endif
+ mh_trace("Child done: %d", pid);
+
+ read_output(stdout_fd[0], stdoutbuf);
+ read_output(stderr_fd[0], stderrbuf);
+
+ close(stdout_fd[0]);
+ close(stdout_fd[0]);
+ return rc;
+}
+
+
+GList *pm_list_profiles(void)
+{
+ char *stdoutbuf = NULL;
+ char *stderrbuf = NULL;
+ char *c1, *c2;
+ char *args[3] = {0};
+ int cnt = 0;
+ GList *list = NULL;
+ gboolean rc;
+
+ args[0] = TUNEDADM;
+ args[1] = TA_LISTPROFILES;
+ args[2] = NULL;
+
+ rc = exec_command(args[0], TIMEOUT, &stdoutbuf, &stderrbuf, args) == EC_OK;
+
+ if (stdoutbuf) {
+ mh_trace(" > stdout: %s", stdoutbuf);
+ }
+ if (stderrbuf) {
+ mh_trace(" > stderr: %s", stderrbuf);
+ free(stderrbuf);
+ }
+
+ if (rc && stdoutbuf)
+ {
+ c1 = stdoutbuf;
+ do
+ {
+ if (*c1 == '-')
+ {
+ c2 = strchr(c1++, '\n');
+ if (c2 > c1)
+ {
+ *c2 = 0;
+ list = g_list_append(list, strdup(++c1));
+ *c2 = '\n';
+ cnt++;
+ }
+ }
+ c2 = strchr(c1, '\n');
+ if (c2)
+ c1 = ++c2;
+ }
+ while (c2 && c1 - stdoutbuf < strlen(stdoutbuf));
+
+ if (cnt)
+ list = g_list_append(list, strdup(TA_OFF));
+ }
+
+ free(stdoutbuf);
+
+ return list;
+}
+
+static gboolean check_profile(const char *profile)
+{
+ GList *list = NULL;
+ GList *llist;
+ gboolean rc = FALSE;
+
+ if (!(list = pm_list_profiles()))
+ return FALSE;
+
+ if (! g_list_length(list))
+ return FALSE;
+
+ for (llist = g_list_first(list); llist && !rc; llist = g_list_next(llist))
+ {
+ mh_trace("comparing '%s' with '%s'", (char *)llist->data, profile);
+ if (! strcmp(profile, (char *)llist->data))
+ rc = TRUE;
+ free(llist->data);
+ }
+ g_list_free(list);
+
+ return rc;
+}
+
+gboolean pm_set_profile(const char *profile)
+{
+ char *stdoutbuf = NULL;
+ char *stderrbuf = NULL;
+ char *args[4] = {0};
+ gboolean rc;
+
+ args[0] = TUNEDADM;
+ if (! profile)
+ return FALSE;
+
+ if (! strcmp(profile, TA_OFF)) {
+ args[1] = TA_OFF;
+ mh_trace("switching tuning off");
+ }
+ else
+ {
+ if (! check_profile(profile)) {
+ mh_err("invalid profile: %s", profile);
+ return FALSE;
+ }
+ args[1] = TA_SETPROFILE;
+ mh_trace("setting profile: %s", profile);
+ }
+
+ args[2] = strdup(profile);
+ args[3] = NULL;
+
+ rc = exec_command(args[0], TIMEOUT, &stdoutbuf, &stderrbuf, args) == EC_OK;
+ free(args[2]);
+
+ if (stdoutbuf) {
+ mh_trace(" > stdout: %s", stdoutbuf);
+ free(stdoutbuf);
+ }
+ if (stderrbuf) {
+ mh_trace(" > stderr: %s", stderrbuf);
+ free(stderrbuf);
+ }
+
+ return rc;
+}
+
+const char *pm_get_profile(void)
+{
+ char *stdoutbuf = NULL;
+ char *stderrbuf = NULL;
+ char *rbuf = NULL;
+ char *c1, *c2;
+ char *args[3] = {0};
+ gboolean rc;
+
+ args[0] = TUNEDADM;
+ args[1] = TA_GETPROFILE;
+ args[2] = NULL;
+
+ rc = exec_command(args[0], TIMEOUT, &stdoutbuf, &stderrbuf, args) == EC_OK;
+
+ if (stdoutbuf) {
+ mh_trace(" > stdout: %s", stdoutbuf);
+ }
+ if (stderrbuf) {
+ mh_trace(" > stderr: %s", stderrbuf);
+ free(stderrbuf);
+ }
+
+ if (rc)
+ {
+ if (stdoutbuf && strlen(stdoutbuf) && (c1 = strchr(stdoutbuf, ':')) &&
+ (++c1 - stdoutbuf < strlen(stdoutbuf)))
+ {
+ if ((c2 = strchr(stdoutbuf, '\n')))
+ *c2 = 0;
+ rbuf = strdup(c1);
+ }
+ else
+ rbuf = strdup(STR_UNK);
+ }
+ else
+ rbuf = strdup(STR_ERR);
+
+ free(stdoutbuf);
+
+ return rbuf;
+}
diff --git a/src/lib/pm_private.h b/src/lib/pm_private.h
new file mode 100644
index 0000000..019f605
--- /dev/null
+++ b/src/lib/pm_private.h
@@ -0,0 +1,39 @@
+/* pm_private.h - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <jskarvad(a)redhat.com>
+ * Based on code from Darryl L. Pierce <dpierce(a)redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * \file
+ * \brief Platform specific function prototypes.
+ *
+ * The functions in this header must be implemented by the platform
+ * specific pm data code.
+ * - pm_linux.c
+ * - pm_windows.c
+ */
+
+#ifndef __MH_PM_PRIVATE_H__
+#define __MH_PM_PRIVATE_H__
+
+#include <glib.h>
+
+extern gboolean pm_set_profile(const char *profile);
+extern const char *pm_get_profile(void);
+extern GList *pm_list_profiles(void);
+
+#endif /* __MH_PM_PRIVATE_H__ */
diff --git a/src/lib/pm_windows.c b/src/lib/pm_windows.c
new file mode 100644
index 0000000..7725f4c
--- /dev/null
+++ b/src/lib/pm_windows.c
@@ -0,0 +1,301 @@
+/* pm_windows.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <jskarvad(a)redhat.com>
+ * Based on code from Andrew Beekhof <andrew(a)beekhof.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* Some code adapted from http://msdn.microsoft.com/en-us/library/ms682499(v=vs.85).aspx */
+
+#include <winsock.h>
+#include <windows.h>
+#include <winbase.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include "matahari/logging.h"
+#include "matahari/pm.h"
+#include "host_private.h"
+
+#define BUFSIZE 4096
+
+#define malloc_usable_size(size) _msize(size)
+
+static void
+read_output(HANDLE h, char **output, int *len)
+{
+ /* Read output from the child process's pipe for STDOUT
+ * Stop when there is no more data.
+ */
+ DWORD bytes = 0;
+ char buf[BUFSIZE];
+
+ *len = 0;
+ while (ReadFile(h, buf, BUFSIZE - 1, &bytes, NULL) && bytes > 0 &&
+ (*output = realloc(*output, *len + (int) bytes + 1)))
+ {
+ buf[bytes] = 0;
+ mh_info("Read %d: %.*s", *len, (int) bytes, buf);
+ sprintf(*output + *len, "%s", buf);
+ *len += (int)bytes;
+ }
+
+ mh_info("Read %d bytes", len);
+}
+
+static
+int exec_command(char *apath, char *acommand, int atimeout,
+ char **stdoutbuf)
+{
+ DWORD status = 0;
+ int max = 0;
+ int len;
+ char *bcommand;
+ LPWSTR command;
+ STARTUPINFO siStartInfo;
+ SECURITY_ATTRIBUTES saAttr;
+ PROCESS_INFORMATION piProcInfo;
+ HANDLE child_pipe_rd = NULL;
+ HANDLE child_pipe_wr = NULL;
+
+ if (! acommand)
+ return EC_OTHER_ERROR;
+
+ /* Initialize all structures */
+ ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
+ ZeroMemory(&saAttr, sizeof(SECURITY_ATTRIBUTES));
+ ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
+
+ /* Set the bInheritHandle flag so pipe handles are inherited. */
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.bInheritHandle = TRUE;
+ saAttr.lpSecurityDescriptor = NULL;
+
+ /* Copyrightreate a pipe for the child process's stdout */
+ if (!CreatePipe(&child_pipe_rd, &child_pipe_wr, &saAttr, 0)) {
+ mh_err("Couldn't create child pipe");
+ return FALSE;
+ }
+
+ /* Ensure the read handle to the pipe for STDOUT is not inherited. */
+ if (!SetHandleInformation(child_pipe_rd, HANDLE_FLAG_INHERIT, 0)) {
+ mh_err("Couldn't set pipe handle information");
+ CloseHandle(child_pipe_rd);
+ CloseHandle(child_pipe_wr);
+ return FALSE;
+ }
+
+ if (apath)
+ {
+ bcommand = malloc((len = strlen(apath) + strlen(acommand) + 2));
+ len--;
+ if (! bcommand)
+ {
+ CloseHandle(child_pipe_rd);
+ CloseHandle(child_pipe_wr);
+ return EC_OTHER_ERROR;
+ }
+ bcommand[len] = 0;
+ strcpy(bcommand, apath);
+ strcat(bcommand, "\\");
+ strcat(bcommand, acommand);
+ }
+ else bcommand = strdup(acommand);
+
+ command = char2wide(bcommand);
+ free(bcommand);
+
+ siStartInfo.cb = sizeof(STARTUPINFO);
+ siStartInfo.hStdError = child_pipe_wr;
+ siStartInfo.hStdOutput = child_pipe_wr;
+ siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
+
+ if (!CreateProcess(NULL,
+ command, // command line
+ NULL, // process security attributes
+ NULL, // primary thread security attributes
+ TRUE, // handles are inherited
+ 0, // creation flags
+ NULL, // use parent's environment
+ NULL, // use parent's current directory
+ &siStartInfo, // STARTUPINFO pointer
+ &piProcInfo)) { // receives PROCESS_INFORMATION
+ mh_err("Could not create child process");
+ CloseHandle(child_pipe_rd);
+ CloseHandle(child_pipe_wr);
+ free(command);
+ return EC_OTHER_ERROR;
+ }
+
+ WaitForSingleObject(piProcInfo.hProcess, atimeout);
+
+ if (GetExitCodeProcess(piProcInfo.hProcess, &status) == 0) {
+ mh_err("Could not get exit code: %lu", GetLastError());
+ status = EC_PENDING;
+ }
+
+ if (status == EC_PENDING) {
+ status = EC_TIMEOUT;
+ TerminateProcess(piProcInfo.hProcess, 1);
+ mh_err("Operation timeout out after %dms", atimeout);
+
+ }
+ /* Nice to log it somewhere */
+ mh_debug("Result of '%ls' was %d", command, (int)status);
+
+ /* Close the write end of the pipe before reading from the
+ * read end of the pipe, to control child process execution.
+ * The pipe is assumed to have enough buffer space to hold the
+ * data the child process has already written to it.
+ */
+
+ if (!CloseHandle(child_pipe_wr))
+ mh_err("Couldn't close write end of child pipe");
+
+ read_output(child_pipe_rd, stdoutbuf, &max);
+
+ if (*stdoutbuf)
+ mh_debug("RAW: %s", *stdoutbuf);
+
+ CloseHandle(piProcInfo.hProcess);
+ CloseHandle(piProcInfo.hThread);
+ CloseHandle(child_pipe_rd);
+
+ free(command);
+
+ return (int) status;
+}
+
+static
+gboolean get_profiles(GList **names, GList **guids)
+{
+ gboolean rc = FALSE;
+ int len;
+ char *stdoutbuf = NULL;
+ char *c1, *c2;
+
+ if (exec_command(getenv("WINDIR"),
+ SYSTEM32 "\\" POWERCFG " " PC_LISTPROFILES, TIMEOUT * 1000,
+ &stdoutbuf) == EC_OK && stdoutbuf)
+ {
+ rc = TRUE;
+ len = strlen(stdoutbuf);
+ c1 = stdoutbuf;
+
+ while ((c1 = strstr(c1, "GUID: ")))
+ {
+ c1 += 6;
+ if (c1 - stdoutbuf < len && (c2 = strchr(c1, ' ')))
+ {
+ *c2++ = 0;
+ *guids = g_list_append(*guids, strdup(c1));
+ if ((c1 = strchr(c2, '(')) && ++c1 - stdoutbuf < len &&
+ (c2 = strchr(c1, ')')))
+ {
+ *c2 = 0;
+ *names = g_list_append(*names, strdup(c1));
+ *c2 = ')';
+ }
+ }
+ }
+ }
+
+ if (!*names || !*guids || g_list_length(*names) != g_list_length(*guids))
+ rc = FALSE;
+
+ free(stdoutbuf);
+
+ return rc;
+}
+
+#define PMSP_COMMAND SYSTEM32 "\\" POWERCFG " " PC_SETPROFILE " "
+gboolean pm_set_profile(const char *profile)
+{
+ gboolean rc = FALSE;
+ char *guid = NULL;
+ char *stdoutbuf = NULL;
+ char *cmd = NULL;
+ GList *names = NULL;
+ GList *guids = NULL;
+ GList *pnames, *pguids;
+
+ if (! get_profiles(&names, &guids))
+ return FALSE;
+
+ for (pnames = g_list_first(names), pguids = g_list_first(guids);
+ pnames && pguids;
+ pnames = g_list_next(pnames), pguids = g_list_next(pguids))
+ {
+ if (!strcmp((char *)pnames->data, profile))
+ guid = strdup((char *)pguids->data);
+ free(pnames->data);
+ free(pguids->data);
+ }
+ g_list_free(names);
+ g_list_free(guids);
+
+ if (guid && (cmd = malloc(strlen(PMSP_COMMAND) + strlen(guid) + 1)))
+ {
+ strcpy(cmd, PMSP_COMMAND);
+ strcat(cmd, guid);
+ rc = exec_command(getenv("WINDIR"), cmd, TIMEOUT * 1000,
+ &stdoutbuf) == EC_OK;
+ free(cmd);
+ free(stdoutbuf);
+ }
+
+ return rc;
+}
+#undef PMSP_COMMAND
+
+const char *pm_get_profile(void)
+{
+ char *rbuf = NULL;
+ char *stdoutbuf = NULL;
+ char *c1, *c2;
+
+ if (exec_command(getenv("WINDIR"), SYSTEM32 "\\" POWERCFG " " PC_GETPROFILE,
+ TIMEOUT * 1000, &stdoutbuf) == EC_OK && stdoutbuf &&
+ (c1 = strchr(stdoutbuf, '(')) && ++c1 - stdoutbuf < strlen(stdoutbuf) &&
+ (c2 = strchr(c1, ')')))
+ {
+ *c2 = 0;
+ rbuf = strdup(c1);
+ }
+ else rbuf = strdup(STR_ERR);
+
+ free(stdoutbuf);
+
+ return rbuf;
+}
+
+GList *pm_list_profiles(void)
+{
+ GList *list;
+ GList *names = NULL;
+ GList *guids = NULL;
+
+ get_profiles(&names, &guids);
+
+ for (list = g_list_first(guids); list; list = g_list_next(list))
+ free((char *)list->data);
+
+ g_list_free(guids);
+
+ return names;
+}
diff --git a/src/pm/CMakeLists.txt b/src/pm/CMakeLists.txt
new file mode 100644
index 0000000..512f3f4
--- /dev/null
+++ b/src/pm/CMakeLists.txt
@@ -0,0 +1,61 @@
+set(BASE "pm")
+set(BASE_LIB "m${BASE}")
+set(QMF_AGENT "matahari-qmf-${BASE}d")
+set(DBUS_AGENT "matahari-dbus-${BASE}d")
+
+# QMF daemon
+if(WITH-QMF)
+ set(SCHEMA_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/qmf/org/matahariproject/QmfPackage.cpp)
+ generate_qmf_schemas(${CMAKE_CURRENT_SOURCE_DIR}/schema.xml ${SCHEMA_SOURCES})
+ include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ add_executable(${QMF_AGENT} ${BASE}-qmf.cpp ${SCHEMA_SOURCES})
+ target_link_libraries(${QMF_AGENT} ${BASE_LIB} mcommon mcommon_qmf)
+
+ target_link_libraries(${QMF_AGENT} ${QPIDCOMMON_LIBRARY} ${QPIDCLIENT_LIBRARY} ${QPIDMESSAGING_LIBRARY} ${QMF2_LIBRARY})
+ if(QPIDTYPES_LIBRARY)
+ target_link_libraries(${QMF_AGENT} ${QPIDTYPES_LIBRARY})
+ endif(QPIDTYPES_LIBRARY)
+
+ if(WIN32)
+ target_link_libraries(${QMF_AGENT} wsock32)
+ endif(WIN32)
+
+ if(NOT WIN32)
+ configure_file(${CMAKE_SOURCE_DIR}/matahari.init.in ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE})
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE} DESTINATION ${initdir})
+ endif(NOT WIN32)
+
+ install(TARGETS ${QMF_AGENT} DESTINATION sbin)
+endif(WITH-QMF)
+
+
+# DBus daemon
+if(WITH-DBUS)
+ # Auto-generated stuff
+ generate_dbus_headers(${BASE} ${CMAKE_CURRENT_BINARY_DIR}/org.matahariproject.PM.xml)
+ # Create src/dbus directory and generate DBus XML definition files into it
+ generate_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/schema.xml)
+
+ # Must be included to find matahari-API-dbus-properties.h
+ include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ set(DBUS_AGENT_SOURCE
+ ${BASE}-dbus.c
+ ${BASE}-dbus-glue.h
+ ${BASE}-dbus-properties.h
+ )
+
+ add_executable(${DBUS_AGENT} ${DBUS_AGENT_SOURCE})
+
+ target_link_libraries(${DBUS_AGENT} ${BASE_LIB} mcommon_dbus ${dbus-glib_LIBRARIES})
+ include_directories(${dbus-glib_INCLUDE_DIRS})
+
+ # Install targets
+ # TODO: fix hardcoded paths, should go to libexec
+ install(TARGETS ${DBUS_AGENT} DESTINATION sbin)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.matahariproject.PM.xml DESTINATION share/dbus-1/interfaces)
+ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.matahariproject.PM.service DESTINATION share/dbus-1/system-services)
+ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.matahariproject.PM.conf DESTINATION /etc/dbus-1/system.d)
+ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.matahariproject.PM.policy DESTINATION share/polkit-1/actions)
+endif(WITH-DBUS)
diff --git a/src/pm/org.matahariproject.PM.conf b/src/pm/org.matahariproject.PM.conf
new file mode 100644
index 0000000..1afe8a8
--- /dev/null
+++ b/src/pm/org.matahariproject.PM.conf
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+ <!-- Only root can own the service -->
+ <policy user="root">
+ <allow own="org.matahariproject.PM"/>
+ </policy>
+
+ <!-- Allow anyone to invoke methods on the interfaces -->
+ <policy context="default">
+ <allow send_destination="org.matahariproject.PM"/>
+ </policy>
+
+</busconfig>
diff --git a/src/pm/org.matahariproject.PM.policy b/src/pm/org.matahariproject.PM.policy
new file mode 100644
index 0000000..eb2c617
--- /dev/null
+++ b/src/pm/org.matahariproject.PM.policy
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+<policyconfig>
+ <vendor>Matahari</vendor>
+ <vendor_url>https://fedorahosted.org/matahari/</vendor_url>
+ <action id="org.matahariproject.PM.set_profile">
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin</allow_active>
+ </defaults>
+ </action>
+ <action id="org.matahariproject.PM.get_profile">
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin</allow_active>
+ </defaults>
+ </action>
+ <action id="org.matahariproject.PM.list_profiles">
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin</allow_active>
+ </defaults>
+ </action>
+</policyconfig>
diff --git a/src/pm/org.matahariproject.PM.service b/src/pm/org.matahariproject.PM.service
new file mode 100644
index 0000000..f293a71
--- /dev/null
+++ b/src/pm/org.matahariproject.PM.service
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.matahariproject.PM
+Exec=/usr/sbin/matahari-dbus-pmd
+User=root
diff --git a/src/pm/pm-dbus.c b/src/pm/pm-dbus.c
new file mode 100644
index 0000000..bfc1c99
--- /dev/null
+++ b/src/pm/pm-dbus.c
@@ -0,0 +1,144 @@
+/*
+ * matahari-pm-dbus.c
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <jskarvad(a)redhat.com>
+ * Based on code from Roman Rakus <rrakus(a)redhat.com>,
+ * Radek Novacek <rnovacek(a)redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <string.h>
+
+#include "matahari/mh_dbus_common.h"
+#include "matahari/utilities.h"
+
+/* PM methods */
+#include "matahari/pm.h"
+
+/* Generated properties list */
+#include "pm-dbus-properties.h"
+
+/* DBus names */
+#define PM_BUS_NAME "org.matahariproject.PM"
+#define PM_OBJECT_PATH "/org/matahariproject/PM"
+#define PM_INTERFACE_NAME "org.matahariproject.PM"
+#define DBUS_PROPERTY_INTERAFACE_NAME "org.freedesktop.DBus.Properties"
+
+/* Dbus methods */
+gboolean
+PM_set_profile(Matahari* matahari, const char *profile, DBusGMethodInvocation *context)
+{
+ GError* error = NULL;
+ if (!check_authorization(PM_BUS_NAME ".set_profile", &error, context)) {
+ dbus_g_method_return_error(context, error);
+ return FALSE;
+ }
+ dbus_g_method_return(context, mh_pm_set_profile(profile));
+ return TRUE;
+}
+
+gboolean
+PM_get_profile(Matahari* matahari, DBusGMethodInvocation *context)
+{
+ char *profile;
+ GError* error = NULL;
+ if (!check_authorization(PM_BUS_NAME ".get_profile", &error, context)) {
+ dbus_g_method_return_error(context, error);
+ return FALSE;
+ }
+ profile = (char *)mh_pm_get_profile();
+ dbus_g_method_return(context, g_strdup(profile));
+ free(profile);
+ return TRUE;
+}
+
+gboolean
+PM_list_profiles(Matahari* matahari, DBusGMethodInvocation *context)
+{
+ GError* error = NULL;
+ GList *list;
+ GList *plist;
+ char **profiles;
+ int i = 0;
+
+ if (!check_authorization(PM_BUS_NAME ".list_profiles", &error, context)) {
+ dbus_g_method_return_error(context, error);
+ return FALSE;
+ }
+ list = mh_pm_list_profiles();
+ profiles = g_new(char *, g_list_length(list) + 1);
+ for (plist = g_list_first(list); plist; plist = g_list_next(plist)) {
+ profiles[i++] = g_strdup((char *)plist->data);
+ free(plist->data);
+ }
+ profiles[i] = NULL;
+ dbus_g_method_return(context, profiles);
+ g_strfreev(profiles);
+ g_list_free(list);
+ return TRUE;
+}
+
+/* Generated dbus stuff for pm
+ * MUST be after declaration of user defined functions.
+ */
+#include "pm-dbus-glue.h"
+
+void
+matahari_set_property(GObject *object, guint property_id, const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ default:
+ /* We don't have any other property... */
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+void
+matahari_get_property(GObject *object, guint property_id, GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_UUID:
+ g_value_set_string(value, mh_uuid());
+ break;
+ case PROP_HOSTNAME:
+ g_value_set_string(value, mh_hostname());
+ break;
+ default:
+ /* We don't have any other property... */
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+GType
+matahari_dict_type(int prop)
+{
+ g_printerr("Type of property %s is map of unknown types\n",
+ properties[prop].name);
+ return G_TYPE_VALUE;
+}
+
+int
+main(int argc, char** argv)
+{
+ g_type_init();
+ return run_dbus_server(PM_BUS_NAME, PM_OBJECT_PATH);
+}
diff --git a/src/pm/pm-qmf.cpp b/src/pm/pm-qmf.cpp
new file mode 100644
index 0000000..9577d93
--- /dev/null
+++ b/src/pm/pm-qmf.cpp
@@ -0,0 +1,112 @@
+/* matahari-pm.cpp - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <jskarvad(a)redhat.com>
+ * Based on code from Roman Rakus <rrakus(a)redhat.com>,
+ * Radek Novacek <rnovacek(a)redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef WIN32
+#include "config.h"
+#endif
+
+#include "matahari/mh_agent.h"
+#include <qmf/Data.h>
+#include "qmf/org/matahariproject/QmfPackage.h"
+
+extern "C" {
+#include <string.h>
+#include "matahari/pm.h"
+#include "matahari/logging.h"
+#include "matahari/utilities.h"
+}
+
+class PMAgent : public MatahariAgent
+{
+private:
+ qmf::org::matahariproject::PackageDefinition _package;
+public:
+ virtual int setup(qmf::AgentSession session);
+ virtual gboolean invoke(qmf::AgentSession session, qmf::AgentEvent event,
+ gpointer user_data);
+};
+
+int
+main(int argc, char **argv)
+{
+ PMAgent *agent = new PMAgent();
+ int rc = agent->init(argc, argv, "pm");
+ if (rc == 0) {
+ agent->run();
+ }
+
+ return rc;
+}
+
+gboolean
+PMAgent::invoke(qmf::AgentSession session, qmf::AgentEvent event,
+ gpointer user_data)
+{
+ if (event.getType() != qmf::AGENT_METHOD) {
+ session.methodSuccess(event);
+ return TRUE;
+ }
+
+ const std::string& methodName(event.getMethodName());
+
+ if (methodName == "set_profile") {
+ event.addReturnArgument("status",
+ mh_pm_set_profile(event.getArguments()["profile"].asString().c_str()));
+ } else if (methodName == "get_profile") {
+ _qtype::Variant profile;
+ char *pprofile = (char *)mh_pm_get_profile();
+ profile = pprofile;
+ free(pprofile);
+ event.addReturnArgument("profile", profile);
+ } else if (methodName == "list_profiles") {
+ GList *plist = NULL;
+ GList *profiles = mh_pm_list_profiles();
+ _qtype::Variant::List s_list;
+ for (plist = g_list_first(profiles); plist;
+ plist = g_list_next(plist))
+ {
+ s_list.push_back((char *)plist->data);
+ free(plist->data);
+ }
+ g_list_free(profiles);
+ event.addReturnArgument("profiles", s_list);
+ } else {
+ session.raiseException(event, MH_NOT_IMPLEMENTED);
+ goto bail;
+ }
+
+ session.methodSuccess(event);
+
+bail:
+ return TRUE;
+}
+
+int
+PMAgent::setup(qmf::AgentSession session)
+{
+ _package.configure(session);
+ _instance = qmf::Data(_package.data_PM);
+
+ _instance.setProperty("hostname", mh_hostname());
+ _instance.setProperty("uuid", mh_uuid());
+
+ session.addData(_instance);
+ return 0;
+}
diff --git a/src/pm/schema.xml b/src/pm/schema.xml
new file mode 100644
index 0000000..c2e580b
--- /dev/null
+++ b/src/pm/schema.xml
@@ -0,0 +1,21 @@
+<schema package="org.matahariproject">
+
+<!-- PM API -->
+ <class name="PM">
+ <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
+ <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y" />
+
+ <!-- APIs -->
+ <method name="set_profile" desc="Set PM profile">
+ <arg name="profile" dir="I" type="sstr" />
+ <arg name="status" dir="O" type="uint32" />
+ </method>
+ <method name="get_profile" desc="Get current PM profile">
+ <arg name="profile" dir="O" type="sstr" />
+ </method>
+ <method name="list_profiles" desc="List available PM profiles">
+ <arg name="profiles" dir="O" type="list" />
+ </method>
+ </class>
+
+</schema>
diff --git a/src/schema.xml b/src/schema.xml
index d39c82d..1645bf4 100644
--- a/src/schema.xml
+++ b/src/schema.xml
@@ -58,6 +58,24 @@
<event name="heartbeat" args="timestamp,sequence" />
+<!-- PM API -->
+ <class name="PM">
+ <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
+ <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y" />
+
+ <!-- APIs -->
+ <method name="set_profile" desc="Set PM profile">
+ <arg name="profile" dir="I" type="sstr" />
+ <arg name="status" dir="O" type="uint32" />
+ </method>
+ <method name="get_profile" desc="Get current PM profile">
+ <arg name="profile" dir="O" type="sstr" />
+ </method>
+ <method name="list_profiles" desc="List available PM profiles">
+ <arg name="profiles" dir="O" type="list" />
+ </method>
+ </class>
+
<!-- Network API -->
<class name="Network">
<property name="uuid" type="sstr" access="RO" desc="Host UUID" />
diff --git a/src/windows/install.bat b/src/windows/install.bat
index 5e6307e..5a47775 100644
--- a/src/windows/install.bat
+++ b/src/windows/install.bat
@@ -12,7 +12,7 @@ cd "%target%"
rem Now install the agents as services and start them
-set agents=hostd networkd serviced
+set agents=hostd pmd networkd serviced
for %%A in (%agents%) do sc delete mh_%%A
for %%A in (%agents%) do del mh_%%A.exe
for %%A in (%agents%) do copy srvany.exe mh_%%A.exe
--
1.7.4.4
12 years, 10 months
[PATCH] Add Power Management (PM) agent
by Jaroslav Skarvada
Add Power Management (PM) agent - this RFE was received from users.
It provides pm_set_profile, pm_get_profile, and pm_list_profiles
methods for setting, getting, and listing all available PM profiles.
For PM profiles handling it uses "tuned" on Linux and "powercfg" on
Windows. Functionality was tested on F15 and Windows Server 2008 R2.
In the future we could extend it to support power capping and
power consumption sensors reading (on supported HW platforms)
thanks & regards
Jaroslav Škarvada
SIGs/PowerManagement
---
CMakeLists.txt | 3 +
matahari.spec | 45 +++++
src/CMakeLists.txt | 1 +
src/include/matahari/pm.h | 70 +++++++
src/lib/CMakeLists.txt | 6 +-
src/lib/pm.c | 45 +++++
src/lib/pm_linux.c | 335 +++++++++++++++++++++++++++++++++
src/lib/pm_private.h | 39 ++++
src/lib/pm_windows.c | 301 +++++++++++++++++++++++++++++
src/pm/CMakeLists.txt | 61 ++++++
src/pm/org.matahariproject.PM.conf | 18 ++
src/pm/org.matahariproject.PM.policy | 27 +++
src/pm/org.matahariproject.PM.service | 4 +
src/pm/pm-dbus.c | 148 +++++++++++++++
src/pm/pm-qmf.cpp | 116 ++++++++++++
src/pm/schema.xml | 21 ++
src/schema.xml | 18 ++
src/windows/install.bat | 2 +-
18 files changed, 1258 insertions(+), 2 deletions(-)
create mode 100644 src/include/matahari/pm.h
create mode 100644 src/lib/pm.c
create mode 100644 src/lib/pm_linux.c
create mode 100644 src/lib/pm_private.h
create mode 100644 src/lib/pm_windows.c
create mode 100644 src/pm/CMakeLists.txt
create mode 100644 src/pm/org.matahariproject.PM.conf
create mode 100644 src/pm/org.matahariproject.PM.policy
create mode 100644 src/pm/org.matahariproject.PM.service
create mode 100644 src/pm/pm-dbus.c
create mode 100644 src/pm/pm-qmf.cpp
create mode 100644 src/pm/schema.xml
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e4daf05..a656085 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -79,15 +79,18 @@ if(WIN32)
set( CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS}
" Some comment\\n DetailPrint \\\"Stopping Matahari services\\\"\\n"
" Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe stop mh_hostd\\\"'\\n"
+ " Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe stop mh_pmd\\\"'\\n"
" Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe stop mh_netd\\\"'\\n"
" Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe stop mh_serviced\\\"'\\n"
" Give them time to stop\\n Sleep 10000\\n"
" Some comment\\n DetailPrint \\\"Removing Matahari services\\\"\\n"
" Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe delete mh_hostd\\\"'\\n"
+ " Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe delete mh_pmd\\\"'\\n"
" Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe delete mh_netd\\\"'\\n"
" Some comment\\n ExecWait '\\\"$SYSDIR\\\\sc.exe delete mh_serviced\\\"'\\n"
" Some comment\\n DetailPrint \\\"Removing Matahari service binaries\\\"\\n"
" Some comment\\n ExecWait 'del \\\"$INSTDIR\\\\mh_hostd.exe\\\"'\\n"
+ " Some comment\\n ExecWait 'del \\\"$INSTDIR\\\\mh_pmd.exe\\\"'\\n"
" Some comment\\n ExecWait 'del \\\"$INSTDIR\\\\mh_netd.exe\\\"'\\n"
" Some comment\\n ExecWait 'del \\\"$INSTDIR\\\\mh_serviced.exe\\\"'\\n"
)
diff --git a/matahari.spec b/matahari.spec
index a52b1d7..f0e8ffa 100644
--- a/matahari.spec
+++ b/matahari.spec
@@ -107,6 +107,17 @@ Requires: %{name}-agent-lib = %{version}-%{release}
%description host
QMF agent for viewing and controlling remote hosts
+%package pm
+License: GPLv2+
+Summary: QMF agent for PM
+Group: Applications/System
+Requires: %{name}-lib = %{version}-%{release}
+Requires: %{name}-agent-lib = %{version}-%{release}
+Requires: tuned
+
+%description pm
+QMF agent for viewing and controlling power management settings
+
%package network
License: GPLv2+
Summary: QMF agent for network devices
@@ -202,6 +213,22 @@ if [ "$1" -ge "1" ]; then
/sbin/service matahari-host condrestart >/dev/null 2>&1 || :
fi
+#== PM
+
+%post pm
+/sbin/service matahari-pm condrestart
+
+%preun pm
+if [ $1 = 0 ]; then
+ /sbin/service matahari-pm stop >/dev/null 2>&1 || :
+ chkconfig --del matahari-pm
+fi
+
+%postun pm
+if [ "$1" -ge "1" ]; then
+ /sbin/service matahari-pm condrestart >/dev/null 2>&1 || :
+fi
+
#== Network
%post network
@@ -297,6 +324,7 @@ test "x%{buildroot}" != "x" && rm -rf %{buildroot}
%defattr(644, root, root, 755)
%{_libdir}/libmcommon.so.*
%{_libdir}/libmhost.so.*
+%{_libdir}/libmpm.so.*
%{_libdir}/libmnetwork.so.*
%{_libdir}/libmservice.so.*
%{_libdir}/libmconfig.so.*
@@ -328,6 +356,19 @@ test "x%{buildroot}" != "x" && rm -rf %{buildroot}
%attr(755, root, root) %{_sbindir}/matahari-dbus-hostd
%endif
+%files pm
+%defattr(644, root, root, 755)
+%doc AUTHORS COPYING
+
+%if %{with qmf}
+%attr(755, root, root) %{_initddir}/matahari-pm
+%attr(755, root, root) %{_sbindir}/matahari-qmf-pmd
+%endif
+
+%if %{with dbus}
+%attr(755, root, root) %{_sbindir}/matahari-dbus-pmd
+%endif
+
%files service
%defattr(644, root, root, 755)
%doc AUTHORS COPYING
@@ -372,15 +413,19 @@ test "x%{buildroot}" != "x" && rm -rf %{buildroot}
%if %{with dbus}
%files dbus
%{_sysconfdir}/dbus-1/system.d/org.matahariproject.Host.conf
+%{_sysconfdir}/dbus-1/system.d/org.matahariproject.PM.conf
%{_sysconfdir}/dbus-1/system.d/org.matahariproject.Network.conf
%{_sysconfdir}/dbus-1/system.d/org.matahariproject.Services.conf
%{_datadir}/dbus-1/interfaces/org.matahariproject.Host.xml
+%{_datadir}/dbus-1/interfaces/org.matahariproject.PM.xml
%{_datadir}/dbus-1/interfaces/org.matahariproject.Network.xml
%{_datadir}/dbus-1/interfaces/org.matahariproject.Services.xml
%{_datadir}/dbus-1/system-services/org.matahariproject.Host.service
+%{_datadir}/dbus-1/system-services/org.matahariproject.PM.service
%{_datadir}/dbus-1/system-services/org.matahariproject.Network.service
%{_datadir}/dbus-1/system-services/org.matahariproject.Services.service
%{_datadir}/polkit-1/actions/org.matahariproject.Host.policy
+%{_datadir}/polkit-1/actions/org.matahariproject.PM.policy
%{_datadir}/polkit-1/actions/org.matahariproject.Network.policy
%{_datadir}/polkit-1/actions/org.matahariproject.Services.policy
%endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d3fd72f..e238ed1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -131,6 +131,7 @@ endif(WITH-QMF)
### Subdirectories
add_subdirectory(lib)
add_subdirectory(host)
+add_subdirectory(pm)
add_subdirectory(network)
add_subdirectory(service)
add_subdirectory(config)
diff --git a/src/include/matahari/pm.h b/src/include/matahari/pm.h
new file mode 100644
index 0000000..4857a47
--- /dev/null
+++ b/src/include/matahari/pm.h
@@ -0,0 +1,70 @@
+/* ph.h - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <jskarvad(a)redhat.com>
+ * Based on code from Arjun Roy <arroy(a)redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * \file
+ * \brief PM API
+ * \ingroup coreapi
+ */
+
+#ifndef __MH_PM_H__
+#define __MH_PM_H__
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define TIMEOUT 10
+#define TA_PATH "/usr/bin/"
+#define TA_SETPROFILE "profile"
+#define TA_GETPROFILE "active"
+#define TA_LISTPROFILES "list"
+#define TA_OFF "off"
+#define TUNEDADM TA_PATH "tuned-adm"
+
+#define SYSTEM32 "system32"
+#define POWERCFG "powercfg"
+#define PC_SETPROFILE "-SETACTIVE"
+#define PC_GETPROFILE "-GETACTIVESCHEME"
+#define PC_LISTPROFILES "-LIST"
+
+#define STR_UNK "UNKNOWN"
+#define STR_ERR "ERROR"
+
+enum exec_exitcode {
+ EC_OK = 0,
+ EC_UNKNOWN_ERROR = 1,
+ EC_INVALID_PARAM = 2,
+ EC_UNIMPLEMENT_FEATURE = 3,
+ EC_INSUFFICIENT_PRIV = 4,
+ EC_NOT_INSTALLED = 5,
+
+ /* 150-199<>reserved for application use */
+ EC_SIGNAL = 194,
+ EC_NOT_SUPPORTED = 195,
+ EC_PENDING = 196,
+ EC_CANCELLED = 197,
+ EC_TIMEOUT = 198,
+ EC_OTHER_ERROR = 199, /* Keep the same codes as LSB */
+};
+
+extern gboolean mh_pm_set_profile(const char *profile);
+extern const char *mh_pm_get_profile(void);
+extern GList *mh_pm_list_profiles(void);
+
+#endif // __MH_PM_H__
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index d33057b..fc48c74 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -1,6 +1,6 @@
# Library
-set(LIBS mcommon mhost mnetwork mservice mconfig)
+set(LIBS mcommon mhost mnetwork mpm mservice mconfig)
include_directories(${pcre_INCLUDE_DIRS})
# See http://sourceware.org/autobook/autobook/autobook_91.html for
@@ -18,6 +18,10 @@ add_library (mnetwork SHARED network.c network_${VARIANT}.c)
set_target_properties(mnetwork PROPERTIES SOVERSION 1.0.0)
target_link_libraries(mnetwork ${pcre_LIBRARIES} mcommon ${SIGAR} ${glib_LIBRARIES})
+add_library (mpm SHARED pm.c pm_${VARIANT}.c)
+set_target_properties(mpm PROPERTIES SOVERSION 1.0.0)
+target_link_libraries(mpm ${pcre_LIBRARIES} mcommon ${SIGAR} ${glib_LIBRARIES})
+
add_library (mservice SHARED services.c services_${VARIANT}.c)
set_target_properties(mservice PROPERTIES SOVERSION 1.0.0)
target_link_libraries(mservice ${pcre_LIBRARIES} mcommon ${SIGAR} ${glib_LIBRARIES})
diff --git a/src/lib/pm.c b/src/lib/pm.c
new file mode 100644
index 0000000..a413c94
--- /dev/null
+++ b/src/lib/pm.c
@@ -0,0 +1,45 @@
+/* pm.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <andrew(a)beekhof.net>
+ * Based on code from Andrew Beekhof <andrew(a)beekhof.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef WIN32
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include "matahari/pm.h"
+#include "matahari/logging.h"
+#include "pm_private.h"
+
+MH_TRACE_INIT_DATA(mh_pm);
+
+gboolean mh_pm_set_profile(const char* profile)
+{
+ return pm_set_profile(profile);
+}
+
+const char *mh_pm_get_profile(void)
+{
+ return pm_get_profile();
+}
+
+GList *mh_pm_list_profiles(void)
+{
+ return pm_list_profiles();
+}
diff --git a/src/lib/pm_linux.c b/src/lib/pm_linux.c
new file mode 100644
index 0000000..db8821e
--- /dev/null
+++ b/src/lib/pm_linux.c
@@ -0,0 +1,335 @@
+/* pm_linux.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <jskarvad(a)redhat.com>
+ * Based on code from Andrew Beekhof <andrew(a)beekhof.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/wait.h>
+
+#include "matahari/logging.h"
+#include "matahari/pm.h"
+#include "host_private.h"
+#include "sigar.h"
+
+static gboolean read_output(int fd, char **data)
+{
+ int rc = 0, len = 0;
+ char buf[500];
+ static const size_t bufsize = sizeof(buf);
+
+ if (*data)
+ len = strlen(*data);
+
+ do {
+ rc = read(fd, buf, bufsize - 1);
+ if (rc > 0) {
+ buf[rc] = 0;
+ *data = realloc(*data, len + rc + 1);
+ snprintf(*data + len, bufsize, "%s", buf);
+ len += rc;
+
+ } else if (errno != EINTR)
+ return FALSE;
+ } while (rc == bufsize - 1 || rc < 0);
+
+ return TRUE;
+}
+
+static int exec_command(const char *command, int atimeout, char **stdoutbuf,
+ char **stderrbuf, char *const argv[])
+{
+ pid_t pid;
+ int fd, rc = 0;
+ int stdout_fd[2];
+ int stderr_fd[2];
+
+ if (! command)
+ return EC_OTHER_ERROR;
+
+ if (pipe(stdout_fd) < 0) {
+ mh_perror(LOG_ERR, "pipe() failed");
+ }
+ if (pipe(stderr_fd) < 0) {
+ mh_perror(LOG_ERR, "pipe() failed");
+ }
+ pid = fork();
+
+ switch (pid) {
+ case -1:
+ mh_perror(LOG_ERR, "fork() failed");
+ close(stdout_fd[0]);
+ close(stdout_fd[1]);
+ close(stderr_fd[0]);
+ close(stderr_fd[1]);
+ return EC_OTHER_ERROR;
+ /* Child. */
+ case 0:
+ setpgid(0, 0);
+ close(stdout_fd[0]);
+ close(stderr_fd[0]);
+ if (STDOUT_FILENO != stdout_fd[1]) {
+ if (dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
+ mh_perror(LOG_ERR, "dup2() failed (stdout)");
+ }
+ close(stdout_fd[1]);
+ }
+ if (STDERR_FILENO != stderr_fd[1]) {
+ if (dup2(stderr_fd[1], STDERR_FILENO) != STDERR_FILENO) {
+ mh_perror(LOG_ERR, "dup2() failed (stderr)");
+ }
+ close(stderr_fd[1]);
+ }
+
+ /* close all descriptors except stdin/out/err and channels to logd */
+ for (fd = getdtablesize() - 1; fd > STDERR_FILENO; fd--)
+ close(fd);
+
+ /* execute the command */
+ execvp(command, argv);
+
+ switch (errno) { /* see execvp */
+ case ENOENT: /* No such file or directory */
+ case EISDIR: /* Is a directory */
+ rc = EC_NOT_INSTALLED;
+ break;
+ case EACCES: /* permission denied (various errors) */
+ rc = EC_INSUFFICIENT_PRIV;
+ break;
+ default:
+ rc = EC_UNKNOWN_ERROR;
+ break;
+ }
+ exit(rc);
+ }
+ /* Only the parent reaches here */
+ close(stdout_fd[1]);
+ close(stderr_fd[1]);
+
+ int status = 0;
+ int timeout = atimeout;
+ mh_trace("Waiting for %d", pid);
+ while (timeout > 0 && waitpid(pid, &status, WNOHANG) <= 0) {
+ sleep(1);
+ timeout--;
+ }
+
+ if (timeout == 0) {
+ int killrc = sigar_proc_kill(pid, SIGKILL);
+
+ rc = EC_TIMEOUT;
+ mh_warn("%d - timed out after %dms", pid, atimeout);
+
+ if (killrc != SIGAR_OK && killrc != ESRCH) {
+ mh_err("kill(%d, KILL) failed: %d", pid, killrc);
+ }
+
+ } else if (WIFEXITED(status)) {
+ rc = WEXITSTATUS(status);
+ mh_err("Managed process %d exited with rc=%d", pid, rc);
+
+ } else if (WIFSIGNALED(status)) {
+ int signo = WTERMSIG(status);
+ rc = EC_SIGNAL;
+ mh_err("Managed process %d exited with signal=%d", pid, signo);
+ }
+#ifdef WCOREDUMP
+ if (WCOREDUMP(status)) {
+ rc = EC_OTHER_ERROR;
+ mh_err("Managed process %d dumped core", pid);
+ }
+#endif
+ mh_trace("Child done: %d", pid);
+
+ read_output(stdout_fd[0], stdoutbuf);
+ read_output(stderr_fd[0], stderrbuf);
+
+ close(stdout_fd[0]);
+ close(stdout_fd[0]);
+ return rc;
+}
+
+
+GList *pm_list_profiles(void)
+{
+ char *stdoutbuf = NULL;
+ char *stderrbuf = NULL;
+ char *c1, *c2;
+ char *args[3] = {0};
+ int cnt = 0;
+ GList *list = NULL;
+ gboolean rc;
+
+ args[0] = TUNEDADM;
+ args[1] = TA_LISTPROFILES;
+ args[2] = NULL;
+
+ rc = exec_command(args[0], TIMEOUT, &stdoutbuf, &stderrbuf, args) == EC_OK;
+
+ if (stdoutbuf) {
+ mh_trace(" > stdout: %s", stdoutbuf);
+ }
+ if (stderrbuf) {
+ mh_trace(" > stderr: %s", stderrbuf);
+ free(stderrbuf);
+ }
+
+ if (rc && stdoutbuf)
+ {
+ c1 = stdoutbuf;
+ do
+ {
+ if (*c1 == '-')
+ {
+ c2 = strchr(c1++, '\n');
+ if (c2 > c1)
+ {
+ *c2 = 0;
+ list = g_list_append(list, strdup(++c1));
+ *c2 = '\n';
+ cnt++;
+ }
+ }
+ c2 = strchr(c1, '\n');
+ if (c2)
+ c1 = ++c2;
+ }
+ while (c2 && c1 - stdoutbuf < strlen(stdoutbuf));
+
+ if (cnt)
+ list = g_list_append(list, strdup(TA_OFF));
+ }
+
+ free(stdoutbuf);
+
+ return list;
+}
+
+static gboolean check_profile(const char *profile)
+{
+ GList *list = NULL;
+ GList *llist;
+ gboolean rc = FALSE;
+
+ if (!(list = pm_list_profiles()))
+ return FALSE;
+
+ if (! g_list_length(list))
+ return FALSE;
+
+ for (llist = g_list_first(list); llist && !rc; llist = g_list_next(llist))
+ {
+ mh_trace("comparing '%s' with '%s'", (char *)llist->data, profile);
+ if (! strcmp(profile, (char *)llist->data))
+ rc = TRUE;
+ free(llist->data);
+ }
+ g_list_free(list);
+
+ return rc;
+}
+
+gboolean pm_set_profile(const char *profile)
+{
+ char *stdoutbuf = NULL;
+ char *stderrbuf = NULL;
+ char *args[4] = {0};
+ gboolean rc;
+
+ args[0] = TUNEDADM;
+ if (! profile)
+ return FALSE;
+
+ if (! strcmp(profile, TA_OFF)) {
+ args[1] = TA_OFF;
+ mh_trace("switching tuning off");
+ }
+ else
+ {
+ if (! check_profile(profile)) {
+ mh_err("invalid profile: %s", profile);
+ return FALSE;
+ }
+ args[1] = TA_SETPROFILE;
+ mh_trace("setting profile: %s", profile);
+ }
+
+ args[2] = strdup(profile);
+ args[3] = NULL;
+
+ rc = exec_command(args[0], TIMEOUT, &stdoutbuf, &stderrbuf, args) == EC_OK;
+ free(args[2]);
+
+ if (stdoutbuf) {
+ mh_trace(" > stdout: %s", stdoutbuf);
+ free(stdoutbuf);
+ }
+ if (stderrbuf) {
+ mh_trace(" > stderr: %s", stderrbuf);
+ free(stderrbuf);
+ }
+
+ return rc;
+}
+
+const char *pm_get_profile(void)
+{
+ char *stdoutbuf = NULL;
+ char *stderrbuf = NULL;
+ char *rbuf = NULL;
+ char *c1, *c2;
+ char *args[3] = {0};
+ gboolean rc;
+
+ args[0] = TUNEDADM;
+ args[1] = TA_GETPROFILE;
+ args[2] = NULL;
+
+ rc = exec_command(args[0], TIMEOUT, &stdoutbuf, &stderrbuf, args) == EC_OK;
+
+ if (stdoutbuf) {
+ mh_trace(" > stdout: %s", stdoutbuf);
+ }
+ if (stderrbuf) {
+ mh_trace(" > stderr: %s", stderrbuf);
+ free(stderrbuf);
+ }
+
+ if (rc)
+ {
+ if (stdoutbuf && strlen(stdoutbuf) && (c1 = strchr(stdoutbuf, ':')) &&
+ (++c1 - stdoutbuf < strlen(stdoutbuf)))
+ {
+ if ((c2 = strchr(stdoutbuf, '\n')))
+ *c2 = 0;
+ rbuf = strdup(c1);
+ }
+ else
+ rbuf = strdup(STR_UNK);
+ }
+ else
+ rbuf = strdup(STR_ERR);
+
+ free(stdoutbuf);
+
+ return rbuf;
+}
diff --git a/src/lib/pm_private.h b/src/lib/pm_private.h
new file mode 100644
index 0000000..019f605
--- /dev/null
+++ b/src/lib/pm_private.h
@@ -0,0 +1,39 @@
+/* pm_private.h - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <jskarvad(a)redhat.com>
+ * Based on code from Darryl L. Pierce <dpierce(a)redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * \file
+ * \brief Platform specific function prototypes.
+ *
+ * The functions in this header must be implemented by the platform
+ * specific pm data code.
+ * - pm_linux.c
+ * - pm_windows.c
+ */
+
+#ifndef __MH_PM_PRIVATE_H__
+#define __MH_PM_PRIVATE_H__
+
+#include <glib.h>
+
+extern gboolean pm_set_profile(const char *profile);
+extern const char *pm_get_profile(void);
+extern GList *pm_list_profiles(void);
+
+#endif /* __MH_PM_PRIVATE_H__ */
diff --git a/src/lib/pm_windows.c b/src/lib/pm_windows.c
new file mode 100644
index 0000000..7725f4c
--- /dev/null
+++ b/src/lib/pm_windows.c
@@ -0,0 +1,301 @@
+/* pm_windows.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <jskarvad(a)redhat.com>
+ * Based on code from Andrew Beekhof <andrew(a)beekhof.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* Some code adapted from http://msdn.microsoft.com/en-us/library/ms682499(v=vs.85).aspx */
+
+#include <winsock.h>
+#include <windows.h>
+#include <winbase.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include "matahari/logging.h"
+#include "matahari/pm.h"
+#include "host_private.h"
+
+#define BUFSIZE 4096
+
+#define malloc_usable_size(size) _msize(size)
+
+static void
+read_output(HANDLE h, char **output, int *len)
+{
+ /* Read output from the child process's pipe for STDOUT
+ * Stop when there is no more data.
+ */
+ DWORD bytes = 0;
+ char buf[BUFSIZE];
+
+ *len = 0;
+ while (ReadFile(h, buf, BUFSIZE - 1, &bytes, NULL) && bytes > 0 &&
+ (*output = realloc(*output, *len + (int) bytes + 1)))
+ {
+ buf[bytes] = 0;
+ mh_info("Read %d: %.*s", *len, (int) bytes, buf);
+ sprintf(*output + *len, "%s", buf);
+ *len += (int)bytes;
+ }
+
+ mh_info("Read %d bytes", len);
+}
+
+static
+int exec_command(char *apath, char *acommand, int atimeout,
+ char **stdoutbuf)
+{
+ DWORD status = 0;
+ int max = 0;
+ int len;
+ char *bcommand;
+ LPWSTR command;
+ STARTUPINFO siStartInfo;
+ SECURITY_ATTRIBUTES saAttr;
+ PROCESS_INFORMATION piProcInfo;
+ HANDLE child_pipe_rd = NULL;
+ HANDLE child_pipe_wr = NULL;
+
+ if (! acommand)
+ return EC_OTHER_ERROR;
+
+ /* Initialize all structures */
+ ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
+ ZeroMemory(&saAttr, sizeof(SECURITY_ATTRIBUTES));
+ ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
+
+ /* Set the bInheritHandle flag so pipe handles are inherited. */
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.bInheritHandle = TRUE;
+ saAttr.lpSecurityDescriptor = NULL;
+
+ /* Copyrightreate a pipe for the child process's stdout */
+ if (!CreatePipe(&child_pipe_rd, &child_pipe_wr, &saAttr, 0)) {
+ mh_err("Couldn't create child pipe");
+ return FALSE;
+ }
+
+ /* Ensure the read handle to the pipe for STDOUT is not inherited. */
+ if (!SetHandleInformation(child_pipe_rd, HANDLE_FLAG_INHERIT, 0)) {
+ mh_err("Couldn't set pipe handle information");
+ CloseHandle(child_pipe_rd);
+ CloseHandle(child_pipe_wr);
+ return FALSE;
+ }
+
+ if (apath)
+ {
+ bcommand = malloc((len = strlen(apath) + strlen(acommand) + 2));
+ len--;
+ if (! bcommand)
+ {
+ CloseHandle(child_pipe_rd);
+ CloseHandle(child_pipe_wr);
+ return EC_OTHER_ERROR;
+ }
+ bcommand[len] = 0;
+ strcpy(bcommand, apath);
+ strcat(bcommand, "\\");
+ strcat(bcommand, acommand);
+ }
+ else bcommand = strdup(acommand);
+
+ command = char2wide(bcommand);
+ free(bcommand);
+
+ siStartInfo.cb = sizeof(STARTUPINFO);
+ siStartInfo.hStdError = child_pipe_wr;
+ siStartInfo.hStdOutput = child_pipe_wr;
+ siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
+
+ if (!CreateProcess(NULL,
+ command, // command line
+ NULL, // process security attributes
+ NULL, // primary thread security attributes
+ TRUE, // handles are inherited
+ 0, // creation flags
+ NULL, // use parent's environment
+ NULL, // use parent's current directory
+ &siStartInfo, // STARTUPINFO pointer
+ &piProcInfo)) { // receives PROCESS_INFORMATION
+ mh_err("Could not create child process");
+ CloseHandle(child_pipe_rd);
+ CloseHandle(child_pipe_wr);
+ free(command);
+ return EC_OTHER_ERROR;
+ }
+
+ WaitForSingleObject(piProcInfo.hProcess, atimeout);
+
+ if (GetExitCodeProcess(piProcInfo.hProcess, &status) == 0) {
+ mh_err("Could not get exit code: %lu", GetLastError());
+ status = EC_PENDING;
+ }
+
+ if (status == EC_PENDING) {
+ status = EC_TIMEOUT;
+ TerminateProcess(piProcInfo.hProcess, 1);
+ mh_err("Operation timeout out after %dms", atimeout);
+
+ }
+ /* Nice to log it somewhere */
+ mh_debug("Result of '%ls' was %d", command, (int)status);
+
+ /* Close the write end of the pipe before reading from the
+ * read end of the pipe, to control child process execution.
+ * The pipe is assumed to have enough buffer space to hold the
+ * data the child process has already written to it.
+ */
+
+ if (!CloseHandle(child_pipe_wr))
+ mh_err("Couldn't close write end of child pipe");
+
+ read_output(child_pipe_rd, stdoutbuf, &max);
+
+ if (*stdoutbuf)
+ mh_debug("RAW: %s", *stdoutbuf);
+
+ CloseHandle(piProcInfo.hProcess);
+ CloseHandle(piProcInfo.hThread);
+ CloseHandle(child_pipe_rd);
+
+ free(command);
+
+ return (int) status;
+}
+
+static
+gboolean get_profiles(GList **names, GList **guids)
+{
+ gboolean rc = FALSE;
+ int len;
+ char *stdoutbuf = NULL;
+ char *c1, *c2;
+
+ if (exec_command(getenv("WINDIR"),
+ SYSTEM32 "\\" POWERCFG " " PC_LISTPROFILES, TIMEOUT * 1000,
+ &stdoutbuf) == EC_OK && stdoutbuf)
+ {
+ rc = TRUE;
+ len = strlen(stdoutbuf);
+ c1 = stdoutbuf;
+
+ while ((c1 = strstr(c1, "GUID: ")))
+ {
+ c1 += 6;
+ if (c1 - stdoutbuf < len && (c2 = strchr(c1, ' ')))
+ {
+ *c2++ = 0;
+ *guids = g_list_append(*guids, strdup(c1));
+ if ((c1 = strchr(c2, '(')) && ++c1 - stdoutbuf < len &&
+ (c2 = strchr(c1, ')')))
+ {
+ *c2 = 0;
+ *names = g_list_append(*names, strdup(c1));
+ *c2 = ')';
+ }
+ }
+ }
+ }
+
+ if (!*names || !*guids || g_list_length(*names) != g_list_length(*guids))
+ rc = FALSE;
+
+ free(stdoutbuf);
+
+ return rc;
+}
+
+#define PMSP_COMMAND SYSTEM32 "\\" POWERCFG " " PC_SETPROFILE " "
+gboolean pm_set_profile(const char *profile)
+{
+ gboolean rc = FALSE;
+ char *guid = NULL;
+ char *stdoutbuf = NULL;
+ char *cmd = NULL;
+ GList *names = NULL;
+ GList *guids = NULL;
+ GList *pnames, *pguids;
+
+ if (! get_profiles(&names, &guids))
+ return FALSE;
+
+ for (pnames = g_list_first(names), pguids = g_list_first(guids);
+ pnames && pguids;
+ pnames = g_list_next(pnames), pguids = g_list_next(pguids))
+ {
+ if (!strcmp((char *)pnames->data, profile))
+ guid = strdup((char *)pguids->data);
+ free(pnames->data);
+ free(pguids->data);
+ }
+ g_list_free(names);
+ g_list_free(guids);
+
+ if (guid && (cmd = malloc(strlen(PMSP_COMMAND) + strlen(guid) + 1)))
+ {
+ strcpy(cmd, PMSP_COMMAND);
+ strcat(cmd, guid);
+ rc = exec_command(getenv("WINDIR"), cmd, TIMEOUT * 1000,
+ &stdoutbuf) == EC_OK;
+ free(cmd);
+ free(stdoutbuf);
+ }
+
+ return rc;
+}
+#undef PMSP_COMMAND
+
+const char *pm_get_profile(void)
+{
+ char *rbuf = NULL;
+ char *stdoutbuf = NULL;
+ char *c1, *c2;
+
+ if (exec_command(getenv("WINDIR"), SYSTEM32 "\\" POWERCFG " " PC_GETPROFILE,
+ TIMEOUT * 1000, &stdoutbuf) == EC_OK && stdoutbuf &&
+ (c1 = strchr(stdoutbuf, '(')) && ++c1 - stdoutbuf < strlen(stdoutbuf) &&
+ (c2 = strchr(c1, ')')))
+ {
+ *c2 = 0;
+ rbuf = strdup(c1);
+ }
+ else rbuf = strdup(STR_ERR);
+
+ free(stdoutbuf);
+
+ return rbuf;
+}
+
+GList *pm_list_profiles(void)
+{
+ GList *list;
+ GList *names = NULL;
+ GList *guids = NULL;
+
+ get_profiles(&names, &guids);
+
+ for (list = g_list_first(guids); list; list = g_list_next(list))
+ free((char *)list->data);
+
+ g_list_free(guids);
+
+ return names;
+}
diff --git a/src/pm/CMakeLists.txt b/src/pm/CMakeLists.txt
new file mode 100644
index 0000000..512f3f4
--- /dev/null
+++ b/src/pm/CMakeLists.txt
@@ -0,0 +1,61 @@
+set(BASE "pm")
+set(BASE_LIB "m${BASE}")
+set(QMF_AGENT "matahari-qmf-${BASE}d")
+set(DBUS_AGENT "matahari-dbus-${BASE}d")
+
+# QMF daemon
+if(WITH-QMF)
+ set(SCHEMA_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/qmf/org/matahariproject/QmfPackage.cpp)
+ generate_qmf_schemas(${CMAKE_CURRENT_SOURCE_DIR}/schema.xml ${SCHEMA_SOURCES})
+ include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ add_executable(${QMF_AGENT} ${BASE}-qmf.cpp ${SCHEMA_SOURCES})
+ target_link_libraries(${QMF_AGENT} ${BASE_LIB} mcommon mcommon_qmf)
+
+ target_link_libraries(${QMF_AGENT} ${QPIDCOMMON_LIBRARY} ${QPIDCLIENT_LIBRARY} ${QPIDMESSAGING_LIBRARY} ${QMF2_LIBRARY})
+ if(QPIDTYPES_LIBRARY)
+ target_link_libraries(${QMF_AGENT} ${QPIDTYPES_LIBRARY})
+ endif(QPIDTYPES_LIBRARY)
+
+ if(WIN32)
+ target_link_libraries(${QMF_AGENT} wsock32)
+ endif(WIN32)
+
+ if(NOT WIN32)
+ configure_file(${CMAKE_SOURCE_DIR}/matahari.init.in ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE})
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE} DESTINATION ${initdir})
+ endif(NOT WIN32)
+
+ install(TARGETS ${QMF_AGENT} DESTINATION sbin)
+endif(WITH-QMF)
+
+
+# DBus daemon
+if(WITH-DBUS)
+ # Auto-generated stuff
+ generate_dbus_headers(${BASE} ${CMAKE_CURRENT_BINARY_DIR}/org.matahariproject.PM.xml)
+ # Create src/dbus directory and generate DBus XML definition files into it
+ generate_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/schema.xml)
+
+ # Must be included to find matahari-API-dbus-properties.h
+ include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ set(DBUS_AGENT_SOURCE
+ ${BASE}-dbus.c
+ ${BASE}-dbus-glue.h
+ ${BASE}-dbus-properties.h
+ )
+
+ add_executable(${DBUS_AGENT} ${DBUS_AGENT_SOURCE})
+
+ target_link_libraries(${DBUS_AGENT} ${BASE_LIB} mcommon_dbus ${dbus-glib_LIBRARIES})
+ include_directories(${dbus-glib_INCLUDE_DIRS})
+
+ # Install targets
+ # TODO: fix hardcoded paths, should go to libexec
+ install(TARGETS ${DBUS_AGENT} DESTINATION sbin)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.matahariproject.PM.xml DESTINATION share/dbus-1/interfaces)
+ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.matahariproject.PM.service DESTINATION share/dbus-1/system-services)
+ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.matahariproject.PM.conf DESTINATION /etc/dbus-1/system.d)
+ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.matahariproject.PM.policy DESTINATION share/polkit-1/actions)
+endif(WITH-DBUS)
diff --git a/src/pm/org.matahariproject.PM.conf b/src/pm/org.matahariproject.PM.conf
new file mode 100644
index 0000000..1afe8a8
--- /dev/null
+++ b/src/pm/org.matahariproject.PM.conf
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+ <!-- Only root can own the service -->
+ <policy user="root">
+ <allow own="org.matahariproject.PM"/>
+ </policy>
+
+ <!-- Allow anyone to invoke methods on the interfaces -->
+ <policy context="default">
+ <allow send_destination="org.matahariproject.PM"/>
+ </policy>
+
+</busconfig>
diff --git a/src/pm/org.matahariproject.PM.policy b/src/pm/org.matahariproject.PM.policy
new file mode 100644
index 0000000..eb2c617
--- /dev/null
+++ b/src/pm/org.matahariproject.PM.policy
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+<policyconfig>
+ <vendor>Matahari</vendor>
+ <vendor_url>https://fedorahosted.org/matahari/</vendor_url>
+ <action id="org.matahariproject.PM.set_profile">
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin</allow_active>
+ </defaults>
+ </action>
+ <action id="org.matahariproject.PM.get_profile">
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin</allow_active>
+ </defaults>
+ </action>
+ <action id="org.matahariproject.PM.list_profiles">
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin</allow_active>
+ </defaults>
+ </action>
+</policyconfig>
diff --git a/src/pm/org.matahariproject.PM.service b/src/pm/org.matahariproject.PM.service
new file mode 100644
index 0000000..f293a71
--- /dev/null
+++ b/src/pm/org.matahariproject.PM.service
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.matahariproject.PM
+Exec=/usr/sbin/matahari-dbus-pmd
+User=root
diff --git a/src/pm/pm-dbus.c b/src/pm/pm-dbus.c
new file mode 100644
index 0000000..e7fbf10
--- /dev/null
+++ b/src/pm/pm-dbus.c
@@ -0,0 +1,148 @@
+/*
+ * matahari-pm-dbus.c
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <jskarvad(a)redhat.com>
+ * Based on code from Roman Rakus <rrakus(a)redhat.com>,
+ * Radek Novacek <rnovacek(a)redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <string.h>
+
+#include "matahari/mh_dbus_common.h"
+#include "matahari/utilities.h"
+
+/* PM methods */
+#include "matahari/pm.h"
+
+/* Generated properties list */
+#include "pm-dbus-properties.h"
+
+/* DBus names */
+#define PM_BUS_NAME "org.matahariproject.PM"
+#define PM_OBJECT_PATH "/org/matahariproject/PM"
+#define PM_INTERFACE_NAME "org.matahariproject.PM"
+#define DBUS_PROPERTY_INTERAFACE_NAME "org.freedesktop.DBus.Properties"
+
+/* Dbus methods */
+gboolean
+PM_set_profile(Matahari* matahari, const char *profile, DBusGMethodInvocation *context)
+{
+ GError* error = NULL;
+ if (!check_authorization(PM_BUS_NAME ".set_profile", &error, context)) {
+ dbus_g_method_return_error(context, error);
+ return FALSE;
+ }
+ dbus_g_method_return(context, mh_pm_set_profile(profile));
+ return TRUE;
+}
+
+gboolean
+PM_get_profile(Matahari* matahari, DBusGMethodInvocation *context)
+{
+ char *profile;
+ GError* error = NULL;
+ if (!check_authorization(PM_BUS_NAME ".get_profile", &error, context)) {
+ dbus_g_method_return_error(context, error);
+ return FALSE;
+ }
+ profile = (char *)mh_pm_get_profile();
+ dbus_g_method_return(context, g_strdup(profile));
+ free(profile);
+ return TRUE;
+}
+
+gboolean
+PM_list_profiles(Matahari* matahari, DBusGMethodInvocation *context)
+{
+ GError* error = NULL;
+ GList *list;
+ GList *plist;
+ char **profiles;
+ int i = 0;
+
+ if (!check_authorization(PM_BUS_NAME ".list_profiles", &error, context)) {
+ dbus_g_method_return_error(context, error);
+ return FALSE;
+ }
+ list = mh_pm_list_profiles();
+ profiles = g_new(char *, g_list_length(list) + 1);
+ for (plist = g_list_first(list); plist; plist = g_list_next(plist)) {
+ profiles[i++] = g_strdup((char *)plist->data);
+ free(plist->data);
+ }
+ profiles[i] = NULL;
+ dbus_g_method_return(context, profiles);
+ g_strfreev(profiles);
+ g_list_free(list);
+ return TRUE;
+}
+
+/* Generated dbus stuff for pm
+ * MUST be after declaration of user defined functions.
+ */
+#include "pm-dbus-glue.h"
+
+void
+matahari_set_property(GObject *object, guint property_id, const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ default:
+ /* We don't have any other property... */
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+void
+matahari_get_property(GObject *object, guint property_id, GValue *value,
+ GParamSpec *pspec)
+{
+ char *str;
+
+ switch (property_id) {
+ case PROP_UUID:
+ g_value_set_string(value, str = (char *)mh_uuid());
+ free(str);
+ break;
+ case PROP_HOSTNAME:
+ g_value_set_string(value, str = (char *)mh_hostname());
+ free(str);
+ break;
+ default:
+ /* We don't have any other property... */
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+GType
+matahari_dict_type(int prop)
+{
+ g_printerr("Type of property %s is map of unknown types\n",
+ properties[prop].name);
+ return G_TYPE_VALUE;
+}
+
+int
+main(int argc, char** argv)
+{
+ g_type_init();
+ return run_dbus_server(PM_BUS_NAME, PM_OBJECT_PATH);
+}
diff --git a/src/pm/pm-qmf.cpp b/src/pm/pm-qmf.cpp
new file mode 100644
index 0000000..e070d41
--- /dev/null
+++ b/src/pm/pm-qmf.cpp
@@ -0,0 +1,116 @@
+/* matahari-pm.cpp - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Jaroslav Škarvada <jskarvad(a)redhat.com>
+ * Based on code from Roman Rakus <rrakus(a)redhat.com>,
+ * Radek Novacek <rnovacek(a)redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef WIN32
+#include "config.h"
+#endif
+
+#include "matahari/mh_agent.h"
+#include <qmf/Data.h>
+#include "qmf/org/matahariproject/QmfPackage.h"
+
+extern "C" {
+#include <string.h>
+#include "matahari/pm.h"
+#include "matahari/logging.h"
+#include "matahari/utilities.h"
+}
+
+class PMAgent : public MatahariAgent
+{
+private:
+ qmf::org::matahariproject::PackageDefinition _package;
+public:
+ virtual int setup(qmf::AgentSession session);
+ virtual gboolean invoke(qmf::AgentSession session, qmf::AgentEvent event,
+ gpointer user_data);
+};
+
+int
+main(int argc, char **argv)
+{
+ PMAgent *agent = new PMAgent();
+ int rc = agent->init(argc, argv, "pm");
+ if (rc == 0) {
+ agent->run();
+ }
+
+ return rc;
+}
+
+gboolean
+PMAgent::invoke(qmf::AgentSession session, qmf::AgentEvent event,
+ gpointer user_data)
+{
+ if (event.getType() != qmf::AGENT_METHOD) {
+ session.methodSuccess(event);
+ return TRUE;
+ }
+
+ const std::string& methodName(event.getMethodName());
+
+ if (methodName == "set_profile") {
+ event.addReturnArgument("status",
+ mh_pm_set_profile(event.getArguments()["profile"].asString().c_str()));
+ } else if (methodName == "get_profile") {
+ _qtype::Variant profile;
+ char *pprofile = (char *)mh_pm_get_profile();
+ profile = pprofile;
+ free(pprofile);
+ event.addReturnArgument("profile", profile);
+ } else if (methodName == "list_profiles") {
+ GList *plist = NULL;
+ GList *profiles = mh_pm_list_profiles();
+ _qtype::Variant::List s_list;
+ for (plist = g_list_first(profiles); plist;
+ plist = g_list_next(plist))
+ {
+ s_list.push_back((char *)plist->data);
+ free(plist->data);
+ }
+ g_list_free(profiles);
+ event.addReturnArgument("profiles", s_list);
+ } else {
+ session.raiseException(event, MH_NOT_IMPLEMENTED);
+ goto bail;
+ }
+
+ session.methodSuccess(event);
+
+bail:
+ return TRUE;
+}
+
+int
+PMAgent::setup(qmf::AgentSession session)
+{
+ char *str;
+
+ _package.configure(session);
+ _instance = qmf::Data(_package.data_PM);
+
+ _instance.setProperty("hostname", str = (char *)mh_hostname());
+ free(str);
+ _instance.setProperty("uuid", str = (char *)mh_uuid());
+ free(str);
+
+ session.addData(_instance);
+ return 0;
+}
diff --git a/src/pm/schema.xml b/src/pm/schema.xml
new file mode 100644
index 0000000..c2e580b
--- /dev/null
+++ b/src/pm/schema.xml
@@ -0,0 +1,21 @@
+<schema package="org.matahariproject">
+
+<!-- PM API -->
+ <class name="PM">
+ <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
+ <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y" />
+
+ <!-- APIs -->
+ <method name="set_profile" desc="Set PM profile">
+ <arg name="profile" dir="I" type="sstr" />
+ <arg name="status" dir="O" type="uint32" />
+ </method>
+ <method name="get_profile" desc="Get current PM profile">
+ <arg name="profile" dir="O" type="sstr" />
+ </method>
+ <method name="list_profiles" desc="List available PM profiles">
+ <arg name="profiles" dir="O" type="list" />
+ </method>
+ </class>
+
+</schema>
diff --git a/src/schema.xml b/src/schema.xml
index d39c82d..1645bf4 100644
--- a/src/schema.xml
+++ b/src/schema.xml
@@ -58,6 +58,24 @@
<event name="heartbeat" args="timestamp,sequence" />
+<!-- PM API -->
+ <class name="PM">
+ <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
+ <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y" />
+
+ <!-- APIs -->
+ <method name="set_profile" desc="Set PM profile">
+ <arg name="profile" dir="I" type="sstr" />
+ <arg name="status" dir="O" type="uint32" />
+ </method>
+ <method name="get_profile" desc="Get current PM profile">
+ <arg name="profile" dir="O" type="sstr" />
+ </method>
+ <method name="list_profiles" desc="List available PM profiles">
+ <arg name="profiles" dir="O" type="list" />
+ </method>
+ </class>
+
<!-- Network API -->
<class name="Network">
<property name="uuid" type="sstr" access="RO" desc="Host UUID" />
diff --git a/src/windows/install.bat b/src/windows/install.bat
index 5e6307e..5a47775 100644
--- a/src/windows/install.bat
+++ b/src/windows/install.bat
@@ -12,7 +12,7 @@ cd "%target%"
rem Now install the agents as services and start them
-set agents=hostd networkd serviced
+set agents=hostd pmd networkd serviced
for %%A in (%agents%) do sc delete mh_%%A
for %%A in (%agents%) do del mh_%%A.exe
for %%A in (%agents%) do copy srvany.exe mh_%%A.exe
--
1.7.5.2
12 years, 10 months
[PATCH 1/2] - Inclusion of DNS SRV lookup
by Adam Stokes
- This patch is for utilizing the DNS SRV records
so that Matahari brokers may be prioritized, switched out,
re-arranged without disrupting connectivity.
Signed-off-by: Adam Stokes <astokes(a)fedoraproject.org>
---
src/include/config.h.in | 1 +
src/include/matahari/dnssrv.h | 32 ++++++++++++
src/lib/CMakeLists.txt | 3 +
src/lib/dnssrv_linux.c | 106 ++++++++++++-----------------------------
src/lib/dnssrv_private.h | 42 ----------------
5 files changed, 66 insertions(+), 118 deletions(-)
create mode 100644 src/include/matahari/dnssrv.h
delete mode 100644 src/lib/dnssrv_private.h
diff --git a/src/include/config.h.in b/src/include/config.h.in
index 9f2989c..710e1ce 100644
--- a/src/include/config.h.in
+++ b/src/include/config.h.in
@@ -1,3 +1,4 @@
#cmakedefine HAVE_STRING_H 1
#cmakedefine HAVE_SYS_IOCTL_H 1
#cmakedefine HAVE_ASPRINTF 1
+#cmakedefine HAVE_RESOLV_H 1
diff --git a/src/include/matahari/dnssrv.h b/src/include/matahari/dnssrv.h
new file mode 100644
index 0000000..3aa014f
--- /dev/null
+++ b/src/include/matahari/dnssrv.h
@@ -0,0 +1,32 @@
+/* dnssrv.h - Copyright (c) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * \file
+ * \brief Config API
+ * \ingroup coreapi
+ */
+
+#ifndef __MH_DNSSRV_H__
+#define __MH_DNSSRV_H__
+
+#define MAX_NAME_LEN 1024
+
+extern int srv_lookup(char *query, char *target);
+
+#endif /* __MH_DNSSRV_H__ */
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index d33057b..ab21bba 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -35,6 +35,9 @@ else(WIN32)
foreach (lib ${LIBS})
install(TARGETS ${lib} DESTINATION lib${LIB_SUFFIX})
endforeach (lib ${LIBS})
+ # libresolv
+ add_library(mcommon_resolv SHARED dnssrv_linux.c)
+ target_link_libraries(mcommon mcommon_resolv resolv)
endif(WIN32)
if(WITH-QMF)
diff --git a/src/lib/dnssrv_linux.c b/src/lib/dnssrv_linux.c
index c1e11d8..44c3c19 100644
--- a/src/lib/dnssrv_linux.c
+++ b/src/lib/dnssrv_linux.c
@@ -16,95 +16,49 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <string.h>
+#include <glib.h>
+#include <stdlib.h>
+
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
-#include <glib.h>
-#include "dnssrv_private.h"
+#include "matahari/dnssrv.h"
-struct srv_reply **srv_lookup(char *service,
- char *protocol,
- char *domain)
+int
+srv_lookup(char *query, char *target)
{
- struct srv_reply **replies = NULL;
-#ifdef HAVE_RESOLV_A
- struct srv_reply *reply = NULL;
- char name[MAX_NAME_LEN];
- unsigned char querybuf[MAX_NAME_LEN];
- const unsigned char *buf;
+ union {
+ HEADER hdr;
+ unsigned char buf[MAX_NAME_LEN];
+ } answer;
ns_msg nsh;
ns_rr rr;
- int, i, n, len, size;
-
- g_snprintf(name, sizeof(name), "_%s._%s.%s", service, protocol, domain);
- if((size = res_query(name, C_IN, T_SRV, querybuf, sizeof(querybuf))) < 0) {
- return NULL;
- }
-
- if(ns_initparse(querybuf, size, &nsh) != 0) {
- reutnr NULL;
- }
-
- n = 0;
- while(ns_parserr(&nsh, ns_s_an, n, &rr) == 0) {
- size = ns_rr_rdlen(rr);
- buf = ns_rr_rdata(rr);
-
- len = 0;
- for(i=6; i < size && buf[i]; i+= buf[i] + 1) {
- len += buf[i] + 1;
- }
+ char buf[MAX_NAME_LEN], *p;
+ int t, size;
- if(i > size) {
- break;
- }
+ size = res_query(query, C_IN, T_SRV, (unsigned char*)&answer, sizeof(answer));
- reply = g_malloc(sizeof(struct srv_reply) + len);
- memcpy(reply->name, buf+7, len);
-
- for(i=buf[6]; i < len && buf[7+i]; i += buf[7+i] + 1) {
- reply->name[i] = '.';
- }
-
- if(i > len) {
- g_free(reply);
- break;
- }
-
- reply->prio = (buf[0] << 8) | buf[1];
- reply->weight = (buf[2] << 8) | buf[3];
- reply->port = (buf[4] << 8) | buf[5];
- n++;
- replies = g_renew(struct srv_reply *, replies, n+1);
- replies[n-1] = reply;
- }
- if(replies) {
- replies[n] = NULL;
+ ns_initparse(answer.buf, size, &nsh);
+ if (ns_msg_count(nsh, ns_s_an) == 0) {
+ return -1;
}
-#endif
- return replies;
-}
-void srv_free(struct srv_reply **srv)
-{
- int i;
- if(srv == NULL) {
- return;
+ if (ns_parserr(&nsh, ns_s_an, 0, &rr) < 0) {
+ return -1;
}
- for(i = 0; srv[i]; i++) {
- g_free(srv[i]);
+ size = ns_rr_rdlen(rr);
+ memcpy(buf, ns_rr_rdata(rr), size);
+ p = buf;
+ p += 6;
+ while (*p > 0) {
+ t = *p;
+ *p = '.';
+ p += t+1;
}
- g_free(srv);
+ p = buf + 7;
+ strcpy(target, p);
+ return 0;
}
-
-/*
- * Local Variables:
- * mode: c
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- * vim: et
- */
-
diff --git a/src/lib/dnssrv_private.h b/src/lib/dnssrv_private.h
deleted file mode 100644
index 0752311..0000000
--- a/src/lib/dnssrv_private.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* dnssrv.h - Copyright (c) 2011 Red Hat, Inc.
- * Written by Adam Stokes <astokes(a)fedoraproject.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#define MAX_NAME_LEN 1024
-
-struct srv_reply
-{
- int prio;
- int weight;
- int port;
- char name[];
-};
-
-struct srv_reply **srv_lookup(char *service,
- char *protocol,
- char *domain);
-
-void srv_free(struct srv_reply **srv);
-
-/*
- * Local Variables:
- * mode: c
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- * vim: et
- */
--
1.7.5.2
12 years, 11 months
DBus type for incoming list arguments
by Antoine van Gelder
If I were to have a schema.xml entry that looked something like this:
<method name="export" desc="Export a file system">
<arg name="directory" dir="I" type="sstr" />
<arg name="client" dir="I" type="sstr" />
<arg name="options" dir="I" type="list" />
<arg name="rc" dir="O" type="uint32" />
</method>
...and a matching dbus method defined like so:
gboolean
Storage_export(Matahari *matahari,
const char *directory,
const char *client,
const char **options,
DBusGMethodInvocation *context)
...and then converted the list argument to a GList thusly:
const char **i;
GList *list = NULL;
for (i = options; i != NULL; i++) {
list = g_list_prepend(list, strdup(*i));
}
Can I rely on "options" being NULL terminated?
- antoine
12 years, 11 months
[PATCH] Create directories before starting broker
by Zane Bitter
The pid and data directories must exist and be writable by the user qpidd
before starting matahari-brokerd. Since these directories may be cleared on
reboot we shouldn't rely on them already existing, and we can't rely on the
broker to create them as qpidd does not have sufficient permissions. So
ensure they are created in the init script.
Signed-off-by: Zane Bitter <zbitter(a)redhat.com>
---
matahari-broker.init.in | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/matahari-broker.init.in b/matahari-broker.init.in
index de98002..340e5a2 100755
--- a/matahari-broker.init.in
+++ b/matahari-broker.init.in
@@ -51,8 +51,17 @@ fi
RETVAL=0
+create_directory() {
+ if [ ! -d $1 ]; then
+ mkdir -p $1
+ chown qpidd:qpidd $1
+ fi
+}
+
start() {
echo -n $"Starting Matahari broker daemon: "
+ create_directory @localstatedir@/run/matahari
+ create_directory @localstatedir@/lib/matahari
daemon --pidfile $pidfile --check $prog --user qpidd /usr/sbin/$prog --daemon --pid-dir @localstatedir@/run/matahari --data-dir @localstatedir@/lib/matahari $QPIDD_OPTIONS
RETVAL=$?
echo
12 years, 11 months