7fa6ab9
diff -up smartmontools-5.39/configure.in.lowcap smartmontools-5.39/configure.in
7fa6ab9
--- smartmontools-5.39/configure.in.lowcap	2009-11-19 10:54:53.000000000 +0100
7fa6ab9
+++ smartmontools-5.39/configure.in	2009-11-19 11:20:54.645701384 +0100
7fa6ab9
@@ -219,6 +219,40 @@ if test "$with_selinux" = "yes"; then
1a8b53a
 	AC_DEFINE(WITH_SELINUX, [1], [Define to 1 if SELinux support is enabled])
1a8b53a
 fi
1a8b53a
 
6b05469
+  AC_ARG_WITH(libcap-ng,
6b05469
+    [  --with-libcap-ng=[auto/yes/no]  Add Libcap-ng support [default=auto]],,
6b05469
+    with_libcap_ng=auto)
6b05469
+
6b05469
+# Check for Libcap-ng API
6b05469
+#
6b05469
+# libcap-ng detection
6b05469
+
6b05469
+if test x$with_libcap_ng = xno ; then
6b05469
+    have_libcap_ng=no;
6b05469
+else
6b05469
+    # Start by checking for header file
6b05469
+    AC_CHECK_HEADER(cap-ng.h, capng_headers=yes, capng_headers=no)
6b05469
+
6b05469
+    # See if we have libcap-ng library
6b05469
+    AC_CHECK_LIB(cap-ng, capng_clear, CAPNG_LDADD=-lcap-ng,)
6b05469
+
6b05469
+    # Check results are usable
6b05469
+    if test x$with_libcap_ng = xyes -a x$CAPNG_LDADD = x ; then
6b05469
+       AC_MSG_ERROR(libcap-ng support was requested and the library was not found)
6b05469
+    fi
6b05469
+    if test x$CAPNG_LDADD != x -a $capng_headers = no ; then
6b05469
+       AC_MSG_ERROR(libcap-ng libraries found but headers are missing)
6b05469
+    fi
6b05469
+fi
6b05469
+AC_SUBST(CAPNG_LDADD)
6b05469
+AC_MSG_CHECKING(whether to use libcap-ng)
6b05469
+if test x$CAPNG_LDADD != x ; then
6b05469
+    AC_DEFINE(HAVE_LIBCAP_NG,1,[libcap-ng support])
6b05469
+    AC_MSG_RESULT(yes)
6b05469
+else
6b05469
+    AC_MSG_RESULT(no)
6b05469
+fi
1a8b53a
+
1a8b53a
 if test "$prefix" = "NONE"; then
1a8b53a
     dnl no prefix and no mandir, so use ${prefix}/share/man as default
1a8b53a
     if test "$mandir" = '${prefix}/man'; then
7fa6ab9
diff -up smartmontools-5.39/Makefile.am.lowcap smartmontools-5.39/Makefile.am
7fa6ab9
--- smartmontools-5.39/Makefile.am.lowcap	2009-11-19 10:54:53.000000000 +0100
7fa6ab9
+++ smartmontools-5.39/Makefile.am	2009-11-19 11:20:54.646634706 +0100
7fa6ab9
@@ -45,7 +45,7 @@ smartd_SOURCES =  smartd.cpp      \
1a8b53a
                   utility.cpp     \
1a8b53a
                   utility.h
1a8b53a
 
1a8b53a
-smartd_LDADD = @os_deps@ @os_libs@
1a8b53a
+smartd_LDADD = @os_deps@ @os_libs@ @CAPNG_LDADD@
1a8b53a
 smartd_DEPENDENCIES = @os_deps@
1a8b53a
 
1a8b53a
 EXTRA_smartd_SOURCES = os_darwin.cpp    \
7fa6ab9
diff -up smartmontools-5.39/smartd.8.in.lowcap smartmontools-5.39/smartd.8.in
7fa6ab9
--- smartmontools-5.39/smartd.8.in.lowcap	2009-11-19 10:54:53.000000000 +0100
7fa6ab9
+++ smartmontools-5.39/smartd.8.in	2009-11-19 11:20:54.651596342 +0100
7fa6ab9
@@ -175,6 +175,12 @@ input. This is useful for commands like:
61520ec
 to perform quick and simple checks without a configuration file.
2ba6d85
 
2ba6d85
 .TP
5565886
+.B \-C, \-\-capabilities
2ba6d85
+Use possix \fBcapabilities(7)\fP (EXPERIMENTAL).
2ba6d85
+
2ba6d85
+Warning: Mail notification does not work when used.
2ba6d85
+
2ba6d85
+.TP
61520ec
 .B \-d, \-\-debug
61520ec
 Runs \fBsmartd\fP in "debug" mode. In this mode, it displays status
61520ec
 information to STDOUT rather than logging it to SYSLOG and does not
7fa6ab9
diff -up smartmontools-5.39/smartd.cpp.lowcap smartmontools-5.39/smartd.cpp
7fa6ab9
--- smartmontools-5.39/smartd.cpp.lowcap	2009-11-19 10:54:53.000000000 +0100
7fa6ab9
+++ smartmontools-5.39/smartd.cpp	2009-11-19 11:36:07.123632685 +0100
7fa6ab9
@@ -77,6 +77,10 @@ extern "C" int __stdcall FreeConsole(voi
1a8b53a
 #include <io.h> // setmode()
1a8b53a
 #endif // __CYGWIN__
1a8b53a
 
1a8b53a
+#ifdef HAVE_LIBCAP_NG
1a8b53a
+#include <cap-ng.h>
1a8b53a
+#endif //LIBCAP_NG
1a8b53a
+
1a8b53a
 // locally included files
1a8b53a
 #include "int64.h"
1a8b53a
 #include "atacmds.h"
7fa6ab9
@@ -190,6 +194,11 @@ static int facility=LOG_DAEMON;
2ba6d85
 static bool do_fork=true;
2ba6d85
 #endif
2ba6d85
 
2ba6d85
+#ifdef HAVE_LIBCAP_NG
2ba6d85
+// enable possix capabilities
2ba6d85
+static bool enable_capabilities=false;
2ba6d85
+#endif
2ba6d85
+
2ba6d85
 // used for control of printing, passing arguments to atacmds.c
2ba6d85
 smartmonctrl *con=NULL;
2ba6d85
 
7fa6ab9
@@ -875,8 +884,7 @@ static void MailWarning(const dev_config
7fa6ab9
   const char *unknown="[Unknown]";
7fa6ab9
 
7fa6ab9
   // See if user wants us to send mail
7fa6ab9
-  if (cfg.emailaddress.empty() && cfg.emailcmdline.empty())
7fa6ab9
-    return;
7fa6ab9
+ 
7fa6ab9
 
7fa6ab9
   std::string address = cfg.emailaddress;
7fa6ab9
   const char * executable = cfg.emailcmdline.c_str();
7fa6ab9
@@ -917,6 +925,15 @@ static void MailWarning(const dev_config
2ba6d85
     if  (epoch<(mail->lastsent+days))
2ba6d85
       return;
2ba6d85
   }
2ba6d85
+  
2ba6d85
+#ifdef HAVE_LIBCAP_NG
2ba6d85
+  if (enable_capabilities) {
2ba6d85
+    PrintOut(LOG_ERR,"Sending a mail was supressed. "
2ba6d85
+		     "Mails can't be send when capabilites are enabled\n");
2ba6d85
+    return;
2ba6d85
+  }
2ba6d85
+
2ba6d85
+#endif
2ba6d85
 
2ba6d85
   // record the time of this mail message, and the first mail message
2ba6d85
   if (!mail->logged)
7fa6ab9
@@ -1464,6 +1481,11 @@ void Usage (void){
7fa6ab9
   PrintOut(LOG_INFO,"\n");
7fa6ab9
   PrintOut(LOG_INFO,"  -c NAME|-, --configfile=NAME|-\n");
7fa6ab9
   PrintOut(LOG_INFO,"        Read configuration file NAME or stdin [default is %s]\n\n", configfile);
2ba6d85
+#ifdef HAVE_LIBCAP_NG
7fa6ab9
+  PrintOut(LOG_INFO,"  -C, --capabilities\n");
2ba6d85
+  PrintOut(LOG_INFO,"        Use possix capabilities (EXPERIMENTAL).\n"
5ec8254
+		    "        Warning: Mail notification does not work when used.\n\n");
2ba6d85
+#endif
7fa6ab9
   PrintOut(LOG_INFO,"  -d, --debug\n");
7fa6ab9
   PrintOut(LOG_INFO,"        Start smartd in debug mode\n\n");
7fa6ab9
   PrintOut(LOG_INFO,"  -D, --showdirectives\n");
7fa6ab9
@@ -3701,7 +3723,7 @@ void ParseOpts(int argc, char **argv){
9cd7b15
   char *tailptr;
9cd7b15
   long lchecktime;
9cd7b15
   // Please update GetValidArgList() if you edit shortopts
7fa6ab9
-  const char *shortopts = "c:l:q:dDni:p:r:s:A:B:Vh?";
7fa6ab9
+  const char *shortopts = "c:l:q:dDni:p:r:s:A:B:VCh?";
9cd7b15
   char *arg;
9cd7b15
   // Please update GetValidArgList() if you edit longopts
7fa6ab9
   struct option longopts[] = {
7fa6ab9
@@ -3727,6 +3749,9 @@ void ParseOpts(int argc, char **argv){
2ba6d85
     { "copyright",      no_argument,       0, 'V' },
2ba6d85
     { "help",           no_argument,       0, 'h' },
2ba6d85
     { "usage",          no_argument,       0, 'h' },
9cd7b15
+#ifdef HAVE_LIBCAP_NG
7fa6ab9
+    { "capabilities",   no_argument,       0, 'C' },
9cd7b15
+#endif
2ba6d85
     { 0,                0,                 0, 0   }
2ba6d85
   };
7fa6ab9
 
7fa6ab9
@@ -3885,6 +3910,12 @@ void ParseOpts(int argc, char **argv){
7fa6ab9
       PrintOut(LOG_INFO, "%s", format_version_info("smartd", true /*full*/).c_str());
2ba6d85
       EXIT(0);
2ba6d85
       break;
2ba6d85
+#ifdef HAVE_LIBCAP_NG
2ba6d85
+    case 'C':
2ba6d85
+      //enable possix capabilities
2ba6d85
+      enable_capabilities=1;
2ba6d85
+      break;
2ba6d85
+#endif
2ba6d85
     case 'h':
2ba6d85
       // help: print summary of command-line options
2ba6d85
       debugmode=1;
7fa6ab9
@@ -4224,6 +4255,16 @@ int main_worker(int argc, char **argv)
7fa6ab9
 
7fa6ab9
   bool write_states_always = true;
7fa6ab9
 
1a8b53a
+#ifdef HAVE_LIBCAP_NG
1a8b53a
+  // Drop capabilities
2ba6d85
+  if (enable_capabilities) {
2ba6d85
+    capng_clear(CAPNG_SELECT_BOTH);
2ba6d85
+    capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
2ba6d85
+                CAP_SYS_ADMIN, CAP_MKNOD, CAP_SYS_RAWIO, -1);
2ba6d85
+    capng_apply(CAPNG_SELECT_BOTH);
2ba6d85
+  }
1a8b53a
+#endif
7fa6ab9
+
1a8b53a
   // the main loop of the code
7fa6ab9
   for (;;) {
7fa6ab9
 
7fa6ab9
@@ -4318,7 +4359,18 @@ int main_worker(int argc, char **argv)
7fa6ab9
         PrintTestSchedule(configs, states, devices);
2ba6d85
         EXIT(0);
2ba6d85
       }
2ba6d85
-      
5ec8254
+
2ba6d85
+#ifdef HAVE_LIBCAP_NG
5ec8254
+      if (enable_capabilities) {
7fa6ab9
+        for (unsigned i = 0; i < configs.size(); i++) {
7fa6ab9
+	  if (configs.at(i).emailaddress.empty()) {
7fa6ab9
+            PrintOut(LOG_WARNING,"Mail can't be enabled together with --capabilities. All mail will be suppressed.\n");
5ec8254
+            break;
5ec8254
+          }
5ec8254
+        }
2ba6d85
+      }
2ba6d85
+#endif
5ec8254
+
2ba6d85
       // reset signal
2ba6d85
       caughtsigHUP=0;
7fa6ab9