summaryrefslogtreecommitdiffstats
path: root/src/ctcron.cpp
diff options
context:
space:
mode:
authorMavridis Philippe <[email protected]>2021-01-13 19:26:24 +0200
committerMavridis Philippe <[email protected]>2021-01-13 19:26:24 +0200
commit8c20dc919f7d54eb48fb60f39ba5e1d466a70763 (patch)
tree44d89f278d5dd066603e5ab9c0b270bc8eb4ad51 /src/ctcron.cpp
downloadklamav-8c20dc919f7d54eb48fb60f39ba5e1d466a70763.tar.gz
klamav-8c20dc919f7d54eb48fb60f39ba5e1d466a70763.zip
Initial commit
Signed-off-by: Mavridis Philippe <[email protected]>
Diffstat (limited to 'src/ctcron.cpp')
-rw-r--r--src/ctcron.cpp332
1 files changed, 332 insertions, 0 deletions
diff --git a/src/ctcron.cpp b/src/ctcron.cpp
new file mode 100644
index 0000000..68a6483
--- /dev/null
+++ b/src/ctcron.cpp
@@ -0,0 +1,332 @@
+/***************************************************************************
+ * CT Cron Implementation *
+ * -------------------------------------------------------------------- *
+ * Copyright (C) 1999, Gary Meyer <[email protected]> *
+ * -------------------------------------------------------------------- *
+ * 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. *
+ ***************************************************************************/
+
+// Do not introduce any Qt or KDE dependencies into the "CT"-prefixed classes.
+// I want to be able to reuse these classes with another GUI toolkit. -GM 11/99
+
+#include "ctcron.h"
+
+#include "cttask.h"
+#include "ctvariable.h"
+#include <pwd.h> // pwd, getpwnam(), getpwuid()
+#include <assert.h>
+
+#include <qfile.h>
+
+#include <kprocess.h>
+#include <ktempfile.h>
+#include <stdlib.h> // system
+
+using namespace std;
+
+CTCron::CTCron(bool _syscron, string ) :
+ syscron(_syscron)
+{
+ int uid(getuid());
+
+ KTempFile tmp;
+ tmp.setAutoDelete(true);
+ tmp.close();
+ tmpFileName = tmp.name();
+
+ QString readCommand;
+
+/* if (uid == 0)
+ // root, so provide requested crontab
+ {
+ if (syscron)
+ {
+ readCommand = "cat /etc/crontab > " + KProcess::quote(tmpFileName);
+ writeCommand = "cat " + KProcess::quote(tmpFileName) + " > /etc/crontab";
+ login = (const char *)i18n("(System Crontab)").local8Bit();
+ name = "";
+ }
+ else
+ {
+ readCommand = QString("crontab -u ") + _login.c_str() + " -l > " + KProcess::quote(tmpFileName);
+ writeCommand = QString("crontab -u ") + _login.c_str() + " " + KProcess::quote(tmpFileName);
+ if (!initFromPasswd(getpwnam(_login.c_str())))
+ {
+ error = i18n("No password entry found for user '%1'").arg(_login.c_str());
+ }
+ }
+ }
+ else*/
+ // regular user, so provide user's own crontab
+ {
+ readCommand = "crontab -l > " + KProcess::quote(tmpFileName);
+ writeCommand = "crontab " + KProcess::quote(tmpFileName);
+ if (!initFromPasswd(getpwuid(uid)))
+ {
+ error = i18n("No password entry found for uid '%1'").arg(uid);
+ }
+ }
+
+ if (name.empty())
+ name = login;
+
+ initialTaskCount = 0;
+ initialVariableCount = 0;
+
+ if (isError())
+ return;
+
+ // Don't set error if it can't be read, it means the user
+ // doesn't have a crontab.
+ if (system(QFile::encodeName(readCommand)) == 0)
+ {
+ ifstream cronfile(QFile::encodeName(tmpFileName));
+ cronfile >> *this;
+ }
+
+ initialTaskCount = task.size();
+ initialVariableCount = variable.size();
+}
+
+CTCron::CTCron(const struct passwd *pwd) :
+ syscron(false)
+{
+ Q_ASSERT(pwd != 0L);
+
+ KTempFile tmp;
+ tmp.setAutoDelete(true);
+ tmp.close();
+ tmpFileName = tmp.name();
+
+ QString readCommand = QString("crontab -u ") + QString(pwd->pw_name) + " -l > " + KProcess::quote(tmpFileName);
+ writeCommand = QString("crontab -u ") + QString(pwd->pw_name) + " " + KProcess::quote(tmpFileName);
+
+ initFromPasswd(pwd);
+
+ initialTaskCount = 0;
+ initialVariableCount = 0;
+
+ if (isError())
+ return;
+
+ // Don't set error if it can't be read, it means the user
+ // doesn't have a crontab.
+ if (system(QFile::encodeName(readCommand)) == 0)
+ {
+ ifstream cronfile(QFile::encodeName(tmpFileName));
+ cronfile >> *this;
+ }
+
+ initialTaskCount = task.size();
+ initialVariableCount = variable.size();
+}
+
+bool CTCron::initFromPasswd(const struct passwd *pwd)
+{
+ if (pwd == 0)
+ {
+ return false;
+ }
+ else
+ {
+ login = pwd->pw_name;
+ name = pwd->pw_gecos;
+ return true;
+ }
+}
+
+void CTCron::operator = (const CTCron& source)
+{
+ assert(!source.syscron);
+
+ for (CTVariableIterator i = const_cast<CTCron&>(source).variable.begin();
+ i != source.variable.end(); ++i)
+ {
+ CTVariable* tmp = new CTVariable(**i);
+ variable.push_back(tmp);
+ }
+
+ for (CTTaskIterator i = const_cast<CTCron&>(source).task.begin();
+ i != source.task.end(); ++i)
+ {
+ CTTask* tmp = new CTTask(**i);
+ task.push_back(tmp);
+ }
+}
+
+istream& operator >> (istream& inputStream, CTCron& cron)
+{
+ const int MAX = 1024;
+ char buffer[MAX];
+ string line("");
+ string comment("");
+
+ while (inputStream)
+ {
+ inputStream.getline(buffer, MAX);
+ line = buffer;
+
+ // search for comments "#" but not disabled tasks "#\"
+ if ((line.find("#") == 0) && (line.find("\\") != 1))
+ {
+ // If the first 10 characters don't contain a character, it's probably a disabled entry.
+ int first_text = line.find_first_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ if (first_text < 0)
+ continue;
+
+ if (first_text < 10)
+ {
+ // remove leading pound sign
+ line = line.substr(1,line.length()-1);
+ // remove leading whitespace
+ while (line.find_first_of(" \t") == 0)
+ line = line.substr(1,line.length()-1);
+ comment = line;
+ continue;
+ }
+ }
+
+ // else
+ {
+ // either a task or a variable
+ int firstWhiteSpace(line.find_first_of(" \t"));
+ int firstEquals(line.find("="));
+
+ // if there is an equals sign and either there is no
+ // whitespace or the first whitespace is after the equals
+ // sign, it must be a variable
+ if ((firstEquals > 0) && ((firstWhiteSpace == -1) ||
+ firstWhiteSpace > firstEquals))
+ {
+ // create variable
+ CTVariable *tmp = new CTVariable(line, comment);
+ cron.variable.push_back(tmp);
+ comment = "";
+ }
+ else
+ // must be a task, either enabled or disabled
+ {
+ if (firstWhiteSpace > 0)
+ {
+ //kdDebug() << line << endl;
+ CTTask *tmp = new CTTask(line, comment, cron.syscron);
+ cron.task.push_back(tmp);
+ comment = "";
+ }
+ }
+ }
+ }
+ return inputStream;
+}
+
+ostream& operator << (ostream& outputStream, const CTCron& cron)
+{
+ int itemCount(0);
+
+ for (CTVariableIterator i = const_cast<CTCron&>(cron).variable.begin();
+ i != cron.variable.end(); ++i)
+ {
+ outputStream << **i;
+ itemCount++;
+ }
+
+ for (CTTaskIterator i = const_cast<CTCron&>(cron).task.begin();
+ i != cron.task.end(); ++i)
+ {
+ outputStream << **i;
+ itemCount++;
+ }
+
+ if (itemCount > 0)
+ {
+ outputStream << "# This file was written by KlamAV using code disembowelled from KCron.\n";
+ outputStream << "# KCron is (c) 1999, Gary Meyer; if your cron file looks screwed up \n";
+ outputStream << "# then that is probably (c) Robert Hogan and you should file a bug report.\n";
+ outputStream << "# Original notice from KCron reads:\n";
+ outputStream << "# Although KCron supports most crontab formats, use care when editing.\n";
+ outputStream << "# Note: Lines beginning with \"#\\\" indicates a disabled task.\n";
+ }
+
+ return outputStream;
+}
+
+CTCron::~CTCron()
+{
+ for (CTTaskIterator i = task.begin(); i != task.end(); ++i)
+ delete *i;
+ for (CTVariableIterator i = variable.begin(); i != variable.end(); ++i)
+ delete *i;
+}
+
+void CTCron::apply()
+{
+ // write to temp file
+ ofstream cronfile(QFile::encodeName(tmpFileName));
+ cronfile << *this << flush;
+
+ // install temp file into crontab
+ if (system(QFile::encodeName(writeCommand)) != 0)
+ {
+ error = i18n("An error occurred while updating crontab.");
+ }
+
+ // remove the temp file
+ (void) unlink(QFile::encodeName(tmpFileName));
+
+ if (isError())
+ return;
+
+ // mark as applied
+ for (CTTaskIterator i = task.begin(); i != task.end(); ++i)
+ (*i)->apply();
+
+ for (CTVariableIterator i = variable.begin(); i != variable.end(); ++i)
+ (*i)->apply();
+
+ initialTaskCount = task.size();
+ initialVariableCount = variable.size();
+}
+
+void CTCron::cancel()
+{
+ for (CTTaskIterator i = task.begin(); i != task.end(); ++i)
+ (*i)->cancel();
+
+ for (CTVariableIterator i = variable.begin(); i != variable.end(); ++i)
+ (*i)->cancel();
+}
+
+bool CTCron::dirty()
+{
+ bool isDirty(false);
+
+ if (initialTaskCount != task.size()) isDirty = true;
+
+ if (initialVariableCount != variable.size()) isDirty = true;
+
+ for (CTTaskIterator i = task.begin(); i != task.end(); ++i)
+ if ((*i)->dirty()) isDirty = true;
+
+ for (CTVariableIterator i = variable.begin(); i != variable.end(); ++i)
+ if ((*i)->dirty()) isDirty = true;
+
+ return isDirty;
+}
+
+string CTCron::path() const
+{
+ string path;
+
+ for (CTVariableIterator var = const_cast<CTCron*>(this)->variable.begin();
+ var != variable.end(); var++)
+ {
+ if ((*var)->variable == "PATH")
+ {
+ path = (*var)->value;
+ }
+ }
+ return path;
+}