1 /***************************************************************************
2 * CT Cron Implementation *
3 * -------------------------------------------------------------------- *
4 * Copyright (C) 1999, Gary Meyer <gary@meyer.net> *
5 * -------------------------------------------------------------------- *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 ***************************************************************************/
12 // Do not introduce any Qt or KDE dependencies into the "CT"-prefixed classes.
13 // I want to be able to reuse these classes with another GUI toolkit. -GM 11/99
19 #include "ctvariable.h"
20 #include <unistd.h> // getuid(), unlink()
21 #include <pwd.h> // pwd, getpwnam(), getpwuid()
29 #include <ktemporaryfile.h>
35 CTCron::CTCron(const QString
& crontabBinary
, bool _syscron
, string _login
) :
40 this->crontab
= crontabBinary
;
44 tmpFileName
= tmp
.fileName();
49 // root, so provide requested crontab
53 readCommand
= "cat /etc/crontab > " + KShell::quoteArg(tmpFileName
);
54 writeCommand
= "cat " + KShell::quoteArg(tmpFileName
) + " > /etc/crontab";
55 login
= (const char *)i18n("(System Crontab)").toLocal8Bit();
60 readCommand
= crontab
+ " -u " + _login
.c_str() + " -l > " + KShell::quoteArg(tmpFileName
);
61 writeCommand
= crontab
+ " -u " + _login
.c_str() + " " + KShell::quoteArg(tmpFileName
);
62 if (!initFromPasswd(getpwnam(_login
.c_str())))
64 error
= i18n("No password entry found for user '%1'", _login
.c_str());
69 // regular user, so provide user's own crontab
71 readCommand
= crontab
+ " -l > " + KShell::quoteArg(tmpFileName
);
72 writeCommand
= crontab
+ " " + KShell::quoteArg(tmpFileName
);
73 if (!initFromPasswd(getpwuid(uid
)))
75 error
= i18n("No password entry found for uid '%1'", uid
);
83 initialVariableCount
= 0;
88 // Don't set error if it can't be read, it means the user
89 // doesn't have a crontab.
90 if (system(QFile::encodeName(readCommand
)) == 0)
92 ifstream
cronfile(QFile::encodeName(tmpFileName
));
96 initialTaskCount
= task
.size();
97 initialVariableCount
= variable
.size();
100 CTCron::CTCron(const QString
& crontabBinary
, const struct passwd
*pwd
) :
105 crontab
= crontabBinary
;
109 tmpFileName
= tmp
.fileName();
111 QString readCommand
= crontab
+ " -u " + QString(pwd
->pw_name
) + " -l > " + KShell::quoteArg(tmpFileName
);
112 writeCommand
= crontab
+ " -u " + QString(pwd
->pw_name
) + " " + KShell::quoteArg(tmpFileName
);
116 initialTaskCount
= 0;
117 initialVariableCount
= 0;
122 // Don't set error if it can't be read, it means the user
123 // doesn't have a crontab.
124 if (system(QFile::encodeName(readCommand
)) == 0)
126 ifstream
cronfile(QFile::encodeName(tmpFileName
));
130 initialTaskCount
= task
.size();
131 initialVariableCount
= variable
.size();
134 bool CTCron::initFromPasswd(const struct passwd
*pwd
)
142 login
= pwd
->pw_name
;
143 name
= pwd
->pw_gecos
;
148 void CTCron::operator = (const CTCron
& source
)
150 assert(!source
.syscron
);
152 for (CTVariableIterator i
= const_cast<CTCron
&>(source
).variable
.begin();
153 i
!= source
.variable
.end(); ++i
)
155 CTVariable
* tmp
= new CTVariable(**i
);
156 variable
.push_back(tmp
);
159 for (CTTaskIterator i
= const_cast<CTCron
&>(source
).task
.begin();
160 i
!= source
.task
.end(); ++i
)
162 CTTask
* tmp
= new CTTask(**i
);
167 istream
& operator >> (istream
& inputStream
, CTCron
& cron
)
169 const int MAX
= 1024;
176 inputStream
.getline(buffer
, MAX
);
179 // search for comments "#" but not disabled tasks "#\"
180 if ((line
.find("#") == 0) && (line
.find("\\") != 1))
182 // If the first 10 characters don't contain a character, it's probably a disabled entry.
183 int first_text
= line
.find_first_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
189 // remove leading pound sign
190 line
= line
.substr(1,line
.length()-1);
191 // remove leading whitespace
192 while (line
.find_first_of(" \t") == 0)
193 line
= line
.substr(1,line
.length()-1);
201 // either a task or a variable
202 int firstWhiteSpace(line
.find_first_of(" \t"));
203 int firstEquals(line
.find("="));
205 // if there is an equals sign and either there is no
206 // whitespace or the first whitespace is after the equals
207 // sign, it must be a variable
208 if ((firstEquals
> 0) && ((firstWhiteSpace
== -1) ||
209 firstWhiteSpace
> firstEquals
))
212 CTVariable
*tmp
= new CTVariable(line
, comment
);
213 cron
.variable
.push_back(tmp
);
217 // must be a task, either enabled or disabled
219 if (firstWhiteSpace
> 0)
221 CTTask
*tmp
= new CTTask(line
, comment
, cron
.syscron
);
222 cron
.task
.push_back(tmp
);
231 ostream
& operator << (ostream
& outputStream
, const CTCron
& cron
)
235 for (CTVariableIterator i
= const_cast<CTCron
&>(cron
).variable
.begin();
236 i
!= cron
.variable
.end(); ++i
)
242 for (CTTaskIterator i
= const_cast<CTCron
&>(cron
).task
.begin();
243 i
!= cron
.task
.end(); ++i
)
251 outputStream
<< "# This file was written by KCron. Copyright (c) 1999, Gary Meyer\n";
252 outputStream
<< "# Although KCron supports most crontab formats, use care when editing.\n";
253 outputStream
<< "# Note: Lines beginning with \"#\\\" indicates a disabled task.\n";
261 for (CTTaskIterator i
= task
.begin(); i
!= task
.end(); ++i
)
263 for (CTVariableIterator i
= variable
.begin(); i
!= variable
.end(); ++i
)
269 // write to temp file
270 ofstream
cronfile(QFile::encodeName(tmpFileName
));
271 cronfile
<< *this << flush
;
273 // install temp file into crontab
274 if (system(QFile::encodeName(writeCommand
)) != 0)
276 error
= i18n("An error occurred while updating crontab.");
279 // remove the temp file
280 (void) unlink(QFile::encodeName(tmpFileName
));
286 for (CTTaskIterator i
= task
.begin(); i
!= task
.end(); ++i
)
289 for (CTVariableIterator i
= variable
.begin(); i
!= variable
.end(); ++i
)
292 initialTaskCount
= task
.size();
293 initialVariableCount
= variable
.size();
296 void CTCron::cancel()
298 for (CTTaskIterator i
= task
.begin(); i
!= task
.end(); ++i
)
301 for (CTVariableIterator i
= variable
.begin(); i
!= variable
.end(); ++i
)
309 if (initialTaskCount
!= task
.size()) isDirty
= true;
311 if (initialVariableCount
!= variable
.size()) isDirty
= true;
313 for (CTTaskIterator i
= task
.begin(); i
!= task
.end(); ++i
)
314 if ((*i
)->dirty()) isDirty
= true;
316 for (CTVariableIterator i
= variable
.begin(); i
!= variable
.end(); ++i
)
317 if ((*i
)->dirty()) isDirty
= true;
322 string
CTCron::path() const
326 for (CTVariableIterator var
= const_cast<CTCron
*>(this)->variable
.begin();
327 var
!= variable
.end(); var
++)
329 if ((*var
)->variable
== "PATH")
331 path
= (*var
)->value
;