[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    Administrator mode in systemsettings
From:       Lubos Lunak <l.lunak () suse ! cz>
Date:       2008-04-10 16:03:39
Message-ID: 200804101803.39797.l.lunak () suse ! cz
[Download RAW message or body]

Hello,

 systemsettings, as far as I can say, has no support at all for actions 
requiring root rights, and the only way to handle those seems to be running 
it as root directly.

 How about the attached patch? It makes the date/time to work normally as 
user, and when doing changes, it runs a small helper using kdesu that 
actually does those changes. Well, not that small, but it only links kdecore. 
I more or less copied the code from save() to the helper and the new values 
are passed using arguments, and since there's nothing fancy done with them, 
it looks quite safe to my security-not-much-trained eye. The arguments only 
look a bit ugly in the kdesu dialog.

 The patch reduces the amount of code that's run as root, doesn't make root 
modules possibly look different, avoids the XEmbed fun and makes it work. 
Comments, flames, improvements?

-- 
Lubos Lunak
KDE developer
--------------------------------------------------------------
SUSE LINUX, s.r.o.   e-mail: l.lunak@suse.cz , l.lunak@kde.org
Lihovarska 1060/12   tel: +420 284 028 972
190 00 Prague 9      fax: +420 284 028 951
Czech Republic       http://www.suse.cz

["dateandtime.patch" (text/x-diff)]

--- dateandtime/clock.desktop.sav	2008-04-04 13:59:39.000000000 +0200
+++ dateandtime/clock.desktop	2008-04-10 17:51:14.000000000 +0200
@@ -6,8 +6,6 @@ X-KDE-ServiceTypes=KCModule
 X-DocPath=kcontrol/clock/index.html
 
 X-KDE-Library=kcm_clock
-X-KDE-RootOnly=true
-X-KDE-SubstituteUID=true
 X-KDE-ParentApp=kcontrol
 
 #FIXME should this be in system settings when we can get to it through the panel?
--- dateandtime/dtime.cpp.sav	2008-03-18 17:58:56.000000000 +0100
+++ dateandtime/dtime.cpp	2008-04-10 17:26:33.000000000 +0200
@@ -49,6 +49,8 @@
 
 #include "dtime.moc"
 
+#include "helper.h"
+
 HMSTimeWidget::HMSTimeWidget(QWidget *parent) :
 	KIntSpinBox(parent)
 {
@@ -202,15 +204,6 @@ Dtime::Dtime(QWidget * parent)
 
   load();
 
-  if (getuid() != 0)
-    {
-      cal->setEnabled(false);
-      hour->setEnabled(false);
-      minute->setEnabled(false);
-      second->setEnabled(false);
-      timeServerList->setEnabled(false);
-      setDateTimeAuto->setEnabled(false);
-    }
   kclock->setEnabled(false);
 }
 
@@ -263,7 +256,9 @@ void Dtime::configChanged(){
 
 void Dtime::load()
 {
-  KConfig _config( "kcmclockrc", KConfig::NoGlobals  );
+  // The config is actually written to the system config, but the user does not have \
any local config, +  // since there is nothing writing it.
+  KConfig _config( "kcmclockrc", KConfig::NoGlobals );
   KConfigGroup config(&_config, "NTP");
   timeServerList->addItems(config.readEntry("servers",
     i18n("Public Time Server (pool.ntp.org),\
@@ -284,11 +279,8 @@ oceania.pool.ntp.org")).split(',', QStri
   timeout();
 }
 
-void Dtime::save()
+void Dtime::save( QStringList& helperargs )
 {
-  KConfig _config("kcmclockrc", KConfig::NoGlobals);
-  KConfigGroup config(&_config, "NTP");
-
   // Save the order, but don't duplicate!
   QStringList list;
   if( timeServerList->count() != 0)
@@ -301,32 +293,17 @@ void Dtime::save()
     if( list.count() == 10)
       break;
   }
-  config.writeEntry("servers", list);
-  config.writeEntry("enabled", setDateTimeAuto->isChecked());
+  helperargs << "ntp" << QString::number( list.count()) << list
+      << ( setDateTimeAuto->isChecked() ? "enabled" : "disabled" );
 
   if(setDateTimeAuto->isChecked() && !ntpUtility.isEmpty()){
-    // NTP Time setting
-    QString timeServer = timeServerList->currentText();
-    if( timeServer.indexOf( QRegExp(".*\\(.*\\)$") ) != -1 ) {
-      timeServer.replace( QRegExp(".*\\("), "" );
-      timeServer.replace( QRegExp("\\).*"), "" );
-      // Would this be better?: s/^.*\(([^)]*)\).*$/\1/
-    }
-    KProcess proc;
-    proc << ntpUtility << timeServer;
-    if( proc.execute() != 0 ){
-      KMessageBox::error( this, i18n("Unable to contact time server: %1.", \
                timeServer) );
-      setDateTimeAuto->setChecked( false );
-    }
-    else {
-        // success
-        kDebug() << "Set date from time server " << timeServer.toLatin1() << " \
                success!";
-    }
+    // NTP Time setting - done in helper
+    timeServer = timeServerList->currentText();
+    kDebug() << "Setting date from time server " << timeServer;
   }
   else {
     // User time setting
-    KProcess c_proc;
-
+    QString BufS;
   // BSD systems reverse year compared to Susv3
 #if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__DragonFly__)  BufS.sprintf("%04d%02d%02d%02d%02d.%02d",
@@ -342,27 +319,24 @@ void Dtime::save()
 
     kDebug() << "Set date " << BufS;
 
-    c_proc << "date" << BufS;
-    int result = c_proc.execute();
-    if (result != 0
-#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
                defined(__DragonFly__)
-  	  && result != 2	// can only set local date, which is okay
-#endif
-      ) {
-      KMessageBox::error( this, i18n("Can not set date."));
-      return;
-    }
-
-    // try to set hardware clock. We do not care if it fails
-    KProcess hwc_proc;
-    hwc_proc << "hwclock" << "--systohc";
-    hwc_proc.execute();
+    helperargs << "date" << BufS;
   }
 
   // restart time
   internalTimer.start( 1000 );
 }
 
+void Dtime::processHelperErrors( int code )
+{
+  if( code & ERROR_DTIME_NTP ) {
+    KMessageBox::error( this, i18n("Unable to contact time server: %1.", timeServer) \
); +    setDateTimeAuto->setChecked( false );
+  }
+  if( code & ERROR_DTIME_DATE ) {
+    KMessageBox::error( this, i18n("Can not set date."));
+  }
+}
+
 void Dtime::timeout()
 {
   // get current time
--- dateandtime/dtime.h.sav	2007-05-28 13:45:54.000000000 +0200
+++ dateandtime/dtime.h	2008-04-10 16:07:34.000000000 +0200
@@ -53,7 +53,8 @@ class Dtime : public QWidget
  public:
   Dtime( QWidget *parent=0 );
 
-  void	save();
+  void	save( QStringList& helperargs );
+  void processHelperErrors( int code );
   void	load();
 
   QString quickHelp() const;
@@ -90,7 +91,7 @@ private:
   QDate		date;
   QTimer	internalTimer;
 
-  QString	BufS;
+  QString       timeServer;
   int		BufI;
   bool		refresh;
   bool		ontimeout;
--- dateandtime/main.cpp.sav	2008-01-09 13:19:10.000000000 +0100
+++ dateandtime/main.cpp	2008-04-10 17:32:16.000000000 +0200
@@ -33,11 +33,15 @@
 #include <kdialog.h>
 #include <kpluginfactory.h>
 #include <kpluginloader.h>
+#include <kprocess.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
 
 #include "main.moc"
 
 #include "tzone.h"
 #include "dtime.h"
+#include "helper.h"
 
 K_PLUGIN_FACTORY(KlockModuleFactory, registerPlugin<KclockModule>();)
 K_EXPORT_PLUGIN(KlockModuleFactory("kcmkclock"))
@@ -77,17 +81,30 @@ KclockModule::KclockModule(QWidget *pare
 
   layout->addStretch();
 
-  if(getuid() == 0)
-    setButtons(Help|Apply);
-  else
-    setButtons(Help);
+  setButtons(Help|Apply);
 }
 
 void KclockModule::save()
 {
-//  The order here is important
-  dtime->save();
-  tzone->save();
+  QStringList helperargs;
+  dtime->save( helperargs );
+  tzone->save( helperargs );
+  QString helper = KStandardDirs::findExe( "kcmdatetimehelper" );
+  int error = 0;
+  if( helper.isEmpty())
+    error = -1;
+  else {
+    KProcess proc;
+    proc << "kdesu" << "--" << helper;
+    proc << helperargs;
+    error = proc.execute();
+  }
+  if( error < 0 || error == ERROR_CALL )
+    KMessageBox::error( this, i18n( "Failed to set system date/time/timezone."), \
i18n( "Date/Time Error" )); +  else {
+    dtime->processHelperErrors( error );
+    tzone->processHelperErrors( error );
+  }
 #if 0
   // Tell the clock applet about the change so that it can update its timezone
   QDBusInterface clock("org.kde.kicker", "/Applets/Clock", \
"org.kde.kicker.ClockApplet"); @@ -100,4 +117,3 @@ void KclockModule::load()
   dtime->load();
   tzone->load();
 }
-
--- dateandtime/tzone.cpp.sav	2007-09-18 19:00:24.000000000 +0200
+++ dateandtime/tzone.cpp	2008-04-10 16:05:46.000000000 +0200
@@ -57,6 +57,8 @@
 #include <sys/stat.h>
 #endif
 
+#include "helper.h"
+
 Tzone::Tzone(QWidget * parent)
   : QGroupBox(parent)
 {
@@ -73,8 +75,6 @@ Tzone::Tzone(QWidget * parent)
     lay->addWidget(tzonelist);
 
     load();
-
-    tzonelist->setEnabled(getuid() == 0);
 }
 
 void Tzone::load()
@@ -99,123 +99,24 @@ void Tzone::currentZone()
 
 // FIXME: Does the logic in this routine actually work correctly? For example,
 // on non-Solaris systems which do not use /etc/timezone?
-void Tzone::save()
+void Tzone::save( QStringList& helperargs )
 {
     QStringList selectedZones(tzonelist->selection());
 
     if (selectedZones.count() > 0)
     {
-      // Find untranslated selected zone
       QString selectedzone(selectedZones[0]);
-
-#if defined(USE_SOLARIS)	// MARCO
-
-        KTemporaryFile tf;
-        tf.setPrefix("kde-tzone");
-        tf.open();
-        QTextStream ts(&tf);
-
-        QFile fTimezoneFile(INITFILE);
-        bool updatedFile = false;
-
-        if (fTimezoneFile.open(QIODevice::ReadOnly))
-        {
-            bool found = false;
-
-            QTextStream is(&fTimezoneFile);
-
-            for (QString line = is.readLine(); !line.isNull();
-                 line = is.readLine())
-            {
-                if (line.find("TZ=") == 0)
-                {
-                    ts << "TZ=" << selectedzone << endl;
-                    found = true;
-                }
-                else
-                {
-                    ts << line << endl;
-                }
-            }
-
-            if (!found)
-            {
-                ts << "TZ=" << selectedzone << endl;
-            }
-
-            updatedFile = true;
-            fTimezoneFile.close();
-        }
-
-        if (updatedFile)
-        {
-            ts.device()->reset();
-            fTimezoneFile.remove();
-
-            if (fTimezoneFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
-            {
-                QTextStream os(&fTimezoneFile);
-
-                for (QString line = ts->readLine(); !line.isNull();
-                     line = ts->readLine())
-                {
-                    os << line << endl;
-                }
-
-                fchmod(fTimezoneFile.handle(),
-                       S_IXUSR | S_IRUSR | S_IRGRP | S_IXGRP |
-                       S_IROTH | S_IXOTH);
-                fTimezoneFile.close();
-            }
-        }
-
-
-        QString val = selectedzone;
-#else
-        QString tz = "/usr/share/zoneinfo/" + selectedzone;
-
-        kDebug() << "Set time zone " << tz;
-
-        if( !KStandardDirs::findExe( "zic" ).isEmpty())
-        {
-            KProcess::execute("zic", QStringList() << "-l" << selectedzone);
-        }
-        else
-        {
-            QFile fTimezoneFile("/etc/timezone");
-
-            if (fTimezoneFile.open(QIODevice::WriteOnly | QIODevice::Truncate) )
-            {
-                QTextStream t(&fTimezoneFile);
-                t << selectedzone;
-                fTimezoneFile.close();
-            }
-
-            if (!QFile::remove("/etc/localtime"))
-            {
-                //After the KDE 3.2 release, need to add an error message
-            }
-            else
-                if (!KIO::NetAccess::file_copy(KUrl(tz),KUrl("/etc/localtime")))
-                        KMessageBox::error( 0, i18n("Error setting new timezone."),
-                                            i18n("Timezone Error"));
-        }
-
-        QString val = ':' + tz;
-#endif // !USE_SOLARIS
-
-        setenv("TZ", val.toAscii(), 1);
-        tzset();
-
+      helperargs << "tz" << selectedzone; // make the helper set the timezone
     } else {
-#if !defined(USE_SOLARIS) // Do not update the System!
-        unlink( "/etc/timezone" );
-        unlink( "/etc/localtime" );
-
-        setenv("TZ", "", 1);
-        tzset();
-#endif // !USE SOLARIS
+      helperargs << "tzreset"; // // make the helper reset the timezone
     }
 
     currentZone();
 }
+
+void Tzone::processHelperErrors( int code )
+{
+  if( code & ERROR_TZONE )
+    KMessageBox::error( this, i18n("Error setting new timezone."),
+        i18n("Timezone Error"));
+}
--- dateandtime/tzone.h.sav	2007-10-23 11:02:58.000000000 +0200
+++ dateandtime/tzone.h	2008-04-10 16:03:48.000000000 +0200
@@ -37,7 +37,8 @@ class Tzone : public QGroupBox
 public:
   Tzone( QWidget *parent=0 );
 
-  void	save();
+  void	save( QStringList& helperargs );
+  void processHelperErrors( int code );
   void  load();
 
 Q_SIGNALS:
--- dateandtime/CMakeLists.txt.sav	2008-03-18 17:58:56.000000000 +0100
+++ dateandtime/CMakeLists.txt	2008-04-10 17:55:01.000000000 +0200
@@ -13,6 +13,12 @@ target_link_libraries(kcm_clock  ${KDE4_
 
 install(TARGETS kcm_clock  DESTINATION ${PLUGIN_INSTALL_DIR} )
 
+########### next target ###############
+
+set(kcmdatetimehelper_SRCS helper.cpp)
+kde4_add_executable(kcmdatetimehelper ${kcmdatetimehelper_SRCS})
+target_link_libraries(kcmdatetimehelper  ${KDE4_KDECORE_LIBS} )
+install(TARGETS kcmdatetimehelper DESTINATION ${LIBEXEC_INSTALL_DIR})
 
 ########### install files ###############
 
--- dateandtime/helper.cpp.sav	2008-04-10 14:12:38.000000000 +0200
+++ dateandtime/helper.cpp	2008-04-10 17:32:04.000000000 +0200
@@ -0,0 +1,285 @@
+/*
+ *  tzone.cpp
+ *
+ *  Copyright (C) 1998 Luca Montecchiani <m.luca@usa.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 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.
+ *
+ */
+
+/*
+
+ A helper that's run using kdesu and does the system modifications.
+
+*/
+
+#include "helper.h"
+
+#include <config-workspace.h>
+
+#include <time.h>
+#include <unistd.h>
+
+#include <kconfig.h>
+#include <kconfiggroup.h>
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include <kprocess.h>
+#include <qfile.h>
+
+#if defined(USE_SOLARIS)
+#include <ktemporaryfile.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+static int Dtime_save_ntp( const QStringList& ntpServers, bool ntpEnabled )
+{
+  int ret = 0;
+  // write to the system config file
+  KConfig _config( KDE_CONFDIR "kcmclockrc", KConfig::SimpleConfig);
+  KConfigGroup config(&_config, "NTP");
+  config.writeEntry("servers", ntpServers );
+  config.writeEntry("enabled", ntpEnabled );
+
+  QString ntpUtility;
+  if(!KStandardDirs::findExe("ntpdate").isEmpty()) {
+    ntpUtility = "ntpdate";
+  } else if(!KStandardDirs::findExe("rdate").isEmpty()) {
+    ntpUtility = "rdate";
+  }
+
+  if(ntpEnabled && !ntpUtility.isEmpty()){
+    // NTP Time setting
+    QString timeServer = ntpServers.first();
+    if( timeServer.indexOf( QRegExp(".*\\(.*\\)$") ) != -1 ) {
+      timeServer.replace( QRegExp(".*\\("), "" );
+      timeServer.replace( QRegExp("\\).*"), "" );
+      // Would this be better?: s/^.*\(([^)]*)\).*$/\1/
+    }
+    KProcess proc;
+    proc << ntpUtility << timeServer;
+    if( proc.execute() != 0 ){
+      ret |= ERROR_DTIME_NTP;
+    }
+  } else {
+    ret |= ERROR_DTIME_NTP;
+  }
+  return ret;
+}
+
+static int Dtime_save_date( const QString& date )
+{
+    int ret = 0;
+    // User time setting
+    KProcess c_proc;
+    c_proc << "date" << date;
+    int result = c_proc.execute();
+    if (result != 0
+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__DragonFly__) +  	  && result != 2	// can only set local date, which is okay
+#endif
+      ) {
+      ret |= ERROR_DTIME_DATE;
+      return ret;
+    }
+
+    // try to set hardware clock. We do not care if it fails
+    KProcess hwc_proc;
+    hwc_proc << "hwclock" << "--systohc";
+    hwc_proc.execute();
+    return ret;
+}
+
+// on non-Solaris systems which do not use /etc/timezone?
+static int Tzone_save_set( const QString& selectedzone )
+{
+    int ret = 0;
+#if defined(USE_SOLARIS)	// MARCO
+
+        KTemporaryFile tf;
+        tf.setPrefix("kde-tzone");
+        tf.open();
+        QTextStream ts(&tf);
+
+        QFile fTimezoneFile(INITFILE);
+        bool updatedFile = false;
+
+        if (fTimezoneFile.open(QIODevice::ReadOnly))
+        {
+            bool found = false;
+
+            QTextStream is(&fTimezoneFile);
+
+            for (QString line = is.readLine(); !line.isNull();
+                 line = is.readLine())
+            {
+                if (line.find("TZ=") == 0)
+                {
+                    ts << "TZ=" << selectedzone << endl;
+                    found = true;
+                }
+                else
+                {
+                    ts << line << endl;
+                }
+            }
+
+            if (!found)
+            {
+                ts << "TZ=" << selectedzone << endl;
+            }
+
+            updatedFile = true;
+            fTimezoneFile.close();
+        }
+
+        if (updatedFile)
+        {
+            ts.device()->reset();
+            fTimezoneFile.remove();
+
+            if (fTimezoneFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
+            {
+                QTextStream os(&fTimezoneFile);
+
+                for (QString line = ts->readLine(); !line.isNull();
+                     line = ts->readLine())
+                {
+                    os << line << endl;
+                }
+
+                fchmod(fTimezoneFile.handle(),
+                       S_IXUSR | S_IRUSR | S_IRGRP | S_IXGRP |
+                       S_IROTH | S_IXOTH);
+                fTimezoneFile.close();
+            }
+        }
+
+
+        QString val = selectedzone;
+#else
+        QString tz = "/usr/share/zoneinfo/" + selectedzone;
+
+        kDebug() << "Set time zone " << tz;
+
+        if( !KStandardDirs::findExe( "zic" ).isEmpty())
+        {
+            KProcess::execute("zic", QStringList() << "-l" << selectedzone);
+        }
+        else
+        {
+            QFile fTimezoneFile("/etc/timezone");
+
+            if (fTimezoneFile.open(QIODevice::WriteOnly | QIODevice::Truncate) )
+            {
+                QTextStream t(&fTimezoneFile);
+                t << selectedzone;
+                fTimezoneFile.close();
+            }
+
+            if (!QFile::remove("/etc/localtime"))
+            {
+                ret |= ERROR_TZONE;
+            }
+            else
+                if (!QFile::copy(tz,"/etc/localtime"))
+                    ret |= ERROR_TZONE;
+        }
+
+        QString val = ':' + tz;
+#endif // !USE_SOLARIS
+
+        setenv("TZ", val.toAscii(), 1);
+        tzset();
+
+    return ret;
+}
+
+static int Tzone_save_reset()
+{
+#if !defined(USE_SOLARIS) // Do not update the System!
+        unlink( "/etc/timezone" );
+        unlink( "/etc/localtime" );
+
+        setenv("TZ", "", 1);
+        tzset();
+#endif // !USE SOLARIS
+    return 0;
+}
+
+
+int main( int argc, char* argv[] )
+{
+  if( getuid() != 0 ) {
+    fprintf( stderr, "Needs to be called as root.\n" );
+    return ERROR_CALL;
+  }
+  bool ntp = false;
+  QStringList ntpServerList;
+  bool ntpEnabled;
+  bool date = false;
+  QString datestr;
+  bool tz = false;
+  QString timezone;
+  bool tzreset = false;
+  QStringList args;
+  for( int pos = 1;
+       pos < argc;
+       ++pos )
+    args.append( argv[ pos ] ); // convert to QStringList first to protect against \
possible overflows +  while( !args.isEmpty()) {
+    QString arg = args.takeFirst();
+    if( arg == "ntp" && !args.isEmpty()) {
+      int ntpCount = args.takeFirst().toInt();
+      if( ntpCount >= 0 && ntpCount <= args.count()) {
+        for( int i = 0;
+             i < ntpCount;
+             ++i ) {
+          ntpServerList.append( args.takeFirst());
+        }
+      }
+      if( args.isEmpty()) {
+        fprintf( stderr, "Wrong arguments!\n" );
+        exit( ERROR_CALL );
+      }
+      ntpEnabled = args.takeFirst() == "enabled";
+      ntp = true;
+    } else if( arg == "date" && !args.isEmpty()) {
+      datestr = args.takeFirst();
+      date = true;
+    } else if( arg == "tz" && !args.isEmpty()) {
+      timezone = args.takeFirst();
+      tz = true;
+    } else if( arg == "tzreset" ) {
+      tzreset = true;
+    } else {
+      fprintf( stderr, "Wrong arguments!\n" );
+      exit( ERROR_CALL );
+    }
+  }
+  int ret = 0; // error code
+//  The order here is important
+  if( ntp )
+    ret |= Dtime_save_ntp( ntpServerList, ntpEnabled );
+  if( date )
+    ret |= Dtime_save_date( datestr );
+  if( tz )
+    ret |= Tzone_save_set( timezone );
+  if( tzreset )
+    ret |= Tzone_save_reset();
+  return ret;
+}
--- dateandtime/helper.h.sav	2008-04-10 16:04:32.000000000 +0200
+++ dateandtime/helper.h	2008-04-10 17:32:10.000000000 +0200
@@ -0,0 +1,40 @@
+/*
+ *  main.h
+ *
+ *  Copyright (C) 1998 Luca Montecchiani <m.luca@usa.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 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.
+ *
+ */
+#ifndef helper_included
+#define helper_included
+
+/*
+ commands:
+   ntp <count> <servers> <enabled/disabled>
+   date <date>
+   tz <timezone>
+   tzreset
+*/
+
+enum
+    {
+    ERROR_CALL       = 1 << 0,
+    ERROR_TZONE      = 1 << 1,
+    ERROR_DTIME_NTP  = 1 << 2,
+    ERROR_DTIME_DATE = 1 << 3
+    };
+
+#endif // main_included



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic