You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeadmin/kcron/cttask.cpp

349 lines
10 KiB

/***************************************************************************
* CT Task Implementation *
* -------------------------------------------------------------------- *
* Copyright (C) 1999, Gary Meyer <gary@meyer.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. *
***************************************************************************/
// 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 "cttask.h"
#include "cti18n.h"
#include <time.h> // tm, strftime()
CTTask::CTTask(string tokStr, string _comment, bool _syscron) :
syscron(_syscron)
{
if (tokStr.substr(0,2) == "#\\")
{
tokStr = tokStr.substr(2,tokStr.length() - 2);
enabled = false;
}
else if (tokStr.substr(0,1) == "#")
{
tokStr = tokStr.substr(1,tokStr.length() - 1);
enabled = false;
}
else
enabled = true;
//older versions had something called silence. We should still be able to not choke on what we have been
//writing earlier. This has no use though.
if (tokStr.substr(0,1) == "-")
{
tokStr = tokStr.substr(1,tokStr.length() - 1);
}
if (tokStr.substr(0,1) == "@")
{
if (tokStr.substr(1,6) == "reboot")
{
// Dunno what to do with this...
tokStr = "0 0 1 1 *"+tokStr.substr(7,tokStr.length()-1);
}
else if (tokStr.substr(1,6) == "yearly")
{
tokStr = "0 0 1 1 *"+tokStr.substr(7,tokStr.length()-1);
}
else if (tokStr.substr(1,8) == "annually")
{
tokStr = "0 0 1 1 *"+tokStr.substr(9,tokStr.length()-1);
}
else if (tokStr.substr(1,7) == "monthly")
{
tokStr = "0 0 1 * *"+tokStr.substr(8,tokStr.length()-1);
}
else if (tokStr.substr(1,6) == "weekly")
{
tokStr = "0 0 * * 0"+tokStr.substr(7,tokStr.length()-1);
}
else if (tokStr.substr(1,5) == "daily")
{
tokStr = "0 0 * * *"+tokStr.substr(6,tokStr.length()-1);
}
else if (tokStr.substr(1,6) == "hourly")
{
tokStr = "0 * * * *"+tokStr.substr(7,tokStr.length()-1);
}
}
int spacepos(tokStr.find_first_of(" \t"));
minute.initialize(tokStr.substr(0,spacepos));
while(isspace(tokStr[spacepos+1])) spacepos++;
tokStr = tokStr.substr(spacepos+1,tokStr.length()-1);
spacepos = tokStr.find_first_of(" \t");
hour.initialize(tokStr.substr(0,spacepos));
while(isspace(tokStr[spacepos+1])) spacepos++;
tokStr = tokStr.substr(spacepos+1,tokStr.length()-1);
spacepos = tokStr.find_first_of(" \t");
dayOfMonth.initialize(tokStr.substr(0,spacepos));
while(isspace(tokStr[spacepos+1])) spacepos++;
tokStr = tokStr.substr(spacepos+1,tokStr.length()-1);
spacepos = tokStr.find_first_of(" \t");
month.initialize(tokStr.substr(0,spacepos));
while(isspace(tokStr[spacepos+1])) spacepos++;
tokStr = tokStr.substr(spacepos+1,tokStr.length()-1);
spacepos = tokStr.find_first_of(" \t");
dayOfWeek.initialize(tokStr.substr(0,spacepos));
if (syscron)
{
while(isspace(tokStr[spacepos+1])) spacepos++;
tokStr = tokStr.substr(spacepos+1,tokStr.length()-1);
spacepos = tokStr.find_first_of(" \t");
user = tokStr.substr(0,spacepos);
}
else
user = string("");
command = tokStr.substr(spacepos+1,tokStr.length()-1);
// remove leading whitespace
while (command.find_first_of(" \t") == 0)
command = command.substr(1,command.length()-1);
comment = _comment;
initialUser = user;
initialCommand = command;
initialComment = comment;
initialEnabled = enabled;
}
CTTask::CTTask(const CTTask &source) :
month(source.month),
dayOfMonth(source.dayOfMonth),
dayOfWeek(source.dayOfWeek),
hour(source.hour),
minute(source.minute),
user(source.user),
command(source.command),
comment(source.comment),
enabled(source.enabled),
initialUser(""),
initialCommand(""),
initialComment(""),
initialEnabled(true)
{
}
void CTTask::operator = (const CTTask& source)
{
month = source.month;
dayOfMonth = source.dayOfMonth;
dayOfWeek = source.dayOfWeek;
hour = source.hour;
minute = source.minute;
user = source.user;
command = source.command;
comment = source.comment;
enabled = source.enabled;
initialUser = "";
initialCommand = "";
initialComment = "";
initialEnabled = true;
return;
}
ostream& operator << (ostream& outputStream, const CTTask& task)
{
// if (task.comment != string(""))
outputStream << "# " << task.comment << "\n";
if (!task.enabled)
outputStream << "#\\";
outputStream << task.minute << " ";
outputStream << task.hour << " ";
outputStream << task.dayOfMonth << " ";
outputStream << task.month << " ";
outputStream << task.dayOfWeek << "\t";
if (task.user != string(""))
outputStream << task.user << "\t";
outputStream << task.command << "\n";
return outputStream;
}
void CTTask::apply()
{
month.apply();
dayOfMonth.apply();
dayOfWeek.apply();
hour.apply();
minute.apply();
initialUser = user;
initialCommand = command;
initialComment = comment;
initialEnabled = enabled;
}
void CTTask::cancel()
{
month.cancel();
dayOfMonth.cancel();
dayOfWeek.cancel();
hour.cancel();
minute.cancel();
user = initialUser;
command = initialCommand;
comment = initialComment;
enabled = initialEnabled;
}
bool CTTask::dirty() const
{
return (month.dirty() || dayOfMonth.dirty() || dayOfWeek.dirty() ||
hour.dirty() || minute.dirty() || (user != initialUser) ||
(command != initialCommand) || (comment != initialComment) ||
(enabled != initialEnabled) );
}
string CTTask::describe() const
{
// Of the whole program, this method is probably the trickiest.
//
// This method creates the natural language description, such as
// "At 1:00am, every Sun".
//
// First, I declare some strings for holding what can be internationalized.
// Note the tokens such as "MONTHS". Translators should reuse these
// tokens in their translations. See README.translators for more
// information.
//
// Second, I get the descriptions from the component parts such as
// days of the month.
//
// Third, I get hour/minute time combinations. Although a little bit
// awkward, I use the tm struct and strftime from <time.h>. This
// way this code is portable across all Unixes.
//
// Fourth, I know that "every day of the week" and "every day of the
// month" simply makes "every day".
//
// Fifth and finally I do tag substitution to create the natural language
// description.
string tmFormat((const char *)i18n("%H:%M").local8Bit());
string DOMFormat((const char *)i18n("Please translator, read the README.translators file in kcron's source code","DAYS_OF_MONTH of MONTHS").local8Bit());
string DOWFormat((const char *)i18n("Really, read that file","every DAYS_OF_WEEK").local8Bit());
string dateFormat((const char *)i18n("DOM_FORMAT as well as DOW_FORMAT").local8Bit());
string timeFormat((const char *)i18n("At TIME").local8Bit());
string format((const char *)i18n("TIME_FORMAT, DATE_FORMAT").local8Bit());
// Get natural language description of day of month,
// month name, and day of week.
string DOMDesc(dayOfMonth.describe());
string monthDesc(month.describe());
string DOWDesc(dayOfWeek.describe());
// Create time description.
int total(minute.count()*hour.count());
string timeDesc("");
int count(0);
for (int h = 0; h <= 23; h++)
if (hour.get(h))
for (int m = 0; m <= 59; m++)
if (minute.get(m))
{
tm time;
time.tm_sec = 0;
time.tm_min = m;
time.tm_hour = h;
time.tm_mday = 0;
time.tm_mon = 0;
time.tm_year = 0;
time.tm_wday = 0;
time.tm_yday = 0;
time.tm_isdst= 0;
char tmp[12];
strftime(tmp, 12, tmFormat.c_str(), &time);
string tmpStr = tmp;
// remove leading space
if (tmpStr.substr(0,1) == " ")
tmpStr = tmpStr.substr(1,tmpStr.length()-1);
timeDesc += tmpStr;
count++;
switch (total - count)
{
case 0: break;
case 1: if (total > 2)
timeDesc += (const char *)i18n(", and ").local8Bit();
else
timeDesc += (const char *)i18n(" and ").local8Bit();
break;
default: timeDesc += (const char*)i18n(", ").local8Bit();
}
}
// "* * *" means truly every day.
// Note: Languages may use different phrases to indicate
// every day of month versus every day of week.
if ((dayOfMonth.count() == 31) &&
(dayOfWeek.count() == 7))
dateFormat = (const char *)i18n("every day ").local8Bit();
else
{
// Day of month not specified, so use day of week.
if (dayOfMonth.count() == 31)
dateFormat = "DOW_FORMAT";
// Day of week not specified, so use day of month.
if (dayOfWeek.count() == 7)
dateFormat = "DOM_FORMAT";
}
// Replace tags to build natural language description.
int pos(0);
if ((pos = DOMFormat.find("DAYS_OF_MONTH")) > -1)
DOMFormat.replace(pos,13,DOMDesc);
if ((pos = DOMFormat.find("MONTHS")) > -1)
DOMFormat.replace(pos,6,monthDesc);
if ((pos = DOWFormat.find("DAYS_OF_WEEK")) > -1)
DOWFormat.replace(pos,12,DOWDesc);
if ((pos = dateFormat.find("DOM_FORMAT")) > -1)
dateFormat.replace(pos,10,DOMFormat);
if ((pos = dateFormat.find("DOW_FORMAT")) > -1)
dateFormat.replace(pos,10,DOWFormat);
if ((pos = timeFormat.find("TIME")) > -1)
timeFormat.replace(pos,4,timeDesc);
if ((pos = format.find("DATE_FORMAT")) > -1)
format.replace(pos,11,dateFormat);
if ((pos = format.find("TIME_FORMAT")) > -1)
format.replace(pos,11,timeFormat);
return format;
}
bool CTTask::system() const
{
return syscron;
}