ssh-cron-1.01.00/CLASSES 0000644 0001750 0001750 00000000277 12605015302 013411 0 ustar frank frank ipcfunction
cronentry
options ipcfunction
crondata options cronentry
cron options
scanner
parser scanner options
daemon parser options cron
ssh-cron-1.01.00/Copyright-notice 0000644 0001750 0001750 00000002530 12605015302 015535 0 ustar frank frank -----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Ssh-cron implements a cron-like daemon that is able to use ssh-connections
using ssh keys that are protected by passphrases.
Copyright (C) 2012-2014 Frank B. Brokken (f.b.brokken@rug.nl)
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 3 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, see .
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQEVAwUBU+ESSH2yqL7q5NiqAQjaKAf/Ysdc6tSEAOUZz/rKWawJIlIhWmZI5U28
EIHg7A93edB5OV9emtIwXJ/j7YpAkLJKM5m8zX/RenOmmYuvDNIwhy4j8QTnxcEC
Gm4w/OvFWgzHxbewRTSCeqjR3OML8NrJyzM6hSHtMrG00ifusp/2ldgEuwKTbZvX
weqUFCKFkqQrf/CnkkG+phZmZl5/ubUClcCR1lJF+rmPMcHtbGyiFqbjNWH/o+VY
+ry261sGzcgGxA2x3BKAGv0YuHCb0vco8OymBnuKk27OyAUn8hrgGQ0KlEl3hOqN
ydhuEqUZibu7Dm3ufLzzWTrecb+niFc1bQqXRxpDtt6nWNXVaoDByA==
=kAf+
-----END PGP SIGNATURE-----
ssh-cron-1.01.00/INSTALL 0000644 0001750 0001750 00000007517 12605015302 013426 0 ustar frank frank To install ssh-cron by hand instead of using a binary distribution perform
the following steps:
0. ssh-cron and its construction depends, in addition to the normally
standard available system software on specific software and versions
which is documented in the file `required'.
(If you compile the bobcat library yourself, note that ssh-cron does
not use the SSL, Milter and Xpointer classes; they may --as far as
ssh-cron is concerned-- be left out of the library by running
'./build light')
1. It is expected you use icmake for the package construction. For this a
top-level script (build) and support scripts in the ./icmake/
directory are available. By default, the 'build' script echoes the
commands it executes to the standard output stream. By specifying the
option -q (e.g., ./build -q ...) this is prevented, significantly
reducing the output generated by 'build'.
2. Inspect the values of the variables in the file INSTALL.im Modify these
when necessary.
3. Run
./build program [strip]
to compile ssh-cron. The argument `strip' is optional and strips
symbolic information from the final executable.
4. If you installed Yodl then you can create the documentation:
./build man
builds the man-page.
5. Before installing the components of ssh-cron, consider defining the
environment variable SSHCRON, defining its value as the (preferably
absolute) filename of a file on which installed files and directories
are logged.
Defining the SSHCRON environment variable as ~/.ssh-cron usually
works well.
6. Run (probably as root)
./build install 'what' 'base'
to install. Here, 'what' specifies what you want to install.
Specify:
x, to install all components,
or specify a combination of:
b (binary program),
d (standard documentation),
m (man-page)
E.g., use
./build install b 'base'
if you only want to be able to run ssh-cron, and want it to be
installed below 'base'.
./build install's last argument 'base' is optional: the base directory
below which the requested files are installed. This base directory is
prepended to the paths #defined in the INSTALL.im file. If 'base' is
not specified, then INSTALL.im's #defined paths are used as-is.
When requesting non-existing elements (e.g., ./build install x was
requested, but the man-page hasn't been created) then these
non-existing elements are silently ignored by the installation
process.
If the environment variable SSHCRON was defined when issuing the
`./build install ...' command then a log of all installed files is
written to the file indicated by the SSHCRON environment variable
(see also the next item).
Defining the SSHCRON environment variable as ~/.ssh-cron usually
works well.
7. Uninstalling previously installed components of ssh-cron is easy if
the environment variable SSHCRON was defined before issuing the
`./build install ...' command. In that case, run the command
./build uninstall logfile
where 'logfile' is the file that was written by ./build install.
Modified files and non-empty directories are not removed, but the
logfile itself is removed following the de-installation.
8. Following the installation nothing in the directory tree which contains
this file (i.e., INSTALL) is required for the proper functioning of
ssh-cron, so consider removing it. If you only want to remove
left-over files from the build-process, just run
./build distclean
ssh-cron-1.01.00/INSTALL.im 0000644 0001750 0001750 00000002532 12605015302 014022 0 ustar frank frank // The name of the project:
#define PROJECT "ssh-cron"
// When defined, these overrule COMPILER and COMPILER_OPTIONS
// COMPILER and COMPILER_OPTIONS are now obsolete
// Instead of CXX and CXXFLAGS, CC and CFLAGS can be used.
// Their #define values are overruled by identically named environment
// variables.
// the compiler to use.
#define CXX "g++"
// the compiler options to use.
#define CXXFLAGS "--std=c++14 -pthread -Wall -O2 -fdiagnostics-color=never"
// flags passed to the linker
#define LDFLAGS ""
#define CPOPTS
// COMPONENTS TO INSTALL
// =====================
// For an operational non-Debian installation, you probably must be
// `root'.
// If necessary, adapt DOC, HDR, LIB and MAN (below) to your situation.
// The provided locations are used by Debian Linux.
// With 'build install' you can dynamically specify a location to prepend
// to the locations configured here, and select which components you want
// to install
// ONLY USE ABSOLUTE DIRECTORY NAMES:
// the final program
#define BINARY "/usr/bin/"${PROJECT}
// the directory where the standard documentation is stored
#define DOC "/usr/share/doc/"${PROJECT}
// the directory whre the manual page is stored
#define MAN "/usr/share/man/man1"
ssh-cron-1.01.00/README 0000644 0001750 0001750 00000002723 12605015302 013247 0 ustar frank frank Welcome to SSH-CRON.
Ssh-cron is now in its beta stage.
I wrote ssh-cron after a discussion with Jean-Paul van Oosten about the
dangers of using ssh keys without passphrases. But when using ssh keys with
passphrases your cron jobs performing tasks at remote computers, suddenly
can't be used anymore, since cron cannot provide the passphrases.
It's also not possible to simply start ssh-agent and then crontab as a child
process, as crontab loses access to ssh-agent's passphrases.
Ssh-cron was subsequently designed to allow jobs requiring access to
ssh-keys to be run regularly. In other words, ssh-cron combines crontab
facilities with the use of ssh keys protected by passphrases.
More information about ssh-cron and how to use its options and crontab-like
specification file is found in ssh-cron's man-page.
To compile ssh-cron from scratch you need a fairly recent Gnu g++ compiler
(e.g. version 4.9.1 or more recent) and you need the Bobcat library (available
at SourceForge and also as, e.g. Debian package). Compilation involves
compiling all .cc files in this and all subdirectories, and then linking these
components together. However, program construction is simplified if you also
install icmake (also available at Sourceforge and as Debian package). If you
have icmake available, check the defines in INSTALL.im for appropriateness for
your system. Adapt them if necessary and simply run './build program' from
this directory.
Frank B. Brokken
(f.b.brokken@rug.nl)
ssh-cron-1.01.00/README.protocol 0000644 0001750 0001750 00000004313 12605015302 015104 0 ustar frank frank When using the daemon, the following protocol is used to communicate with the
daemon:
The ipc file contains the process ID of the daemon and the ID of its
shared memory. The daemon started a service thread, calling the SharedCondition
wait() function and waiting for things to happen.
To request an action from the child, a process puts a request value (enum
value) in the shared memory's assigned location, and notifies the daemon. This
may be all that's needed, or the daemon has to respond.
The organization of the shared memory is as follows:
SharedCondition | request-field | free-area...
The following requests and actions are defined:
Request: Action:
TERMINATE the daemon terminates, no further action
LIST the requesting process starts a transmission loop,
the child writes info about the current cron-actions until
changing the request field into DONE
LOAD the daemon starts a transmission loop and the requesting
process writes info about the new set of cron-actions until
changing the request field into DONE
DONE communication loop completed
A communication loop looks like this:
---------------------------------------------------------------------
Initiating process Handling process
---------------------------------------------------------------------
loop:
lock
loop:
wait
lock
write request
write free area, if
neeeded
notify
release
maybe end the loop
(at, e.g., TERMINATE)
lock
wait_for(seconds(2))
process request
maybe end the loop
(at, e.g., TERMINATE)
notify
release
error if timeout
back to loop
back to loop
---------------------------------------------------------------------
ssh-cron-1.01.00/VERSION 0000644 0001750 0001750 00000000155 12633531202 013437 0 ustar frank frank #define AUTHOR "Frank B. Brokken (f.b.brokken@rug.nl)";
#define VERSION "1.01.00"
#define YEARS "2014-2015"
ssh-cron-1.01.00/VERSION.h 0000644 0001750 0001750 00000000104 12605015302 013654 0 ustar frank frank #include "VERSION"
SUBST(_CurVers_)(VERSION)
SUBST(_CurYrs_)(YEARS)
ssh-cron-1.01.00/build 0000755 0001750 0001750 00000007046 12633530165 013431 0 ustar frank frank #!/usr/bin/icmake -qt/tmp/guncat
#define LOGENV "SSHCRON"
#include "icmconf"
string
g_logPath = getenv(LOGENV)[1],
g_cwd = chdir(""); // initial working directory, ends in /
int g_echo = ON;
#include "icmake/cuteoln"
#include "icmake/backtick"
#include "icmake/setopt"
#include "icmake/run"
#include "icmake/md"
#include "icmake/precompileheaders"
#include "icmake/pathfile"
#include "icmake/findall"
#include "icmake/loginstall"
#include "icmake/logzip"
#include "icmake/logfile"
#include "icmake/uninstall"
#include "icmake/special"
#include "icmake/clean"
#include "icmake/manpage"
#include "icmake/install"
#include "icmake/github"
void main(int argc, list argv)
{
string option;
string strip;
int idx;
for (idx = listlen(argv); idx--; )
{
if (argv[idx] == "-q")
{
g_echo = OFF;
argv -= (list)"-q";
}
else if (argv[idx] == "-P")
{
g_gch = 0;
argv -= (list)"-P";
}
}
echo(g_echo);
option = argv[1];
if (option == "clean")
clean(0);
if (option == "distclean")
clean(1);
if (option != "")
special();
if (option == "install")
install(argv[2], argv[3]);
if (option == "uninstall")
uninstall(argv[2]);
if (option == "github")
github();
if (option == "man")
manpage();
if (option == "library")
{
precompileHeaders();
system("icmbuild library");
exit(0);
}
if (argv[2] == "strip")
strip = "strip";
if (option == "program")
{
precompileHeaders();
system("icmbuild program " + strip);
exit(0);
}
if (option == "oxref")
{
precompileHeaders();
system("icmbuild program " + strip);
run("oxref -fxs tmp/lib" LIBRARY ".a > " PROJECT ".xref");
exit(0);
}
printf("Usage: build [-q -P] what\n"
"Where\n"
" [-q]: run quietly, do not show executed commands\n"
" [-P]: do not use precompiled headers\n"
"`what' is one of:\n"
" clean - clean up remnants of previous "
"compilations\n"
" distclean - clean + fully remove tmp/\n"
" library - build " PROJECT "'s library\n"
" man - build the man-page (requires Yodl)\n"
" program [strip] - build " PROJECT " (optionally strip the\n"
" executable)\n"
" oxref [strip] - same a `program', also builds xref file\n"
" using oxref\n"
" install selection [base] - to install the software in the \n"
" locations defined in the INSTALL.im file,\n"
" optionally below base\n"
" selection can be\n"
" x, to install all components,\n"
" or a combination of:\n"
" b (binary program),\n"
" d (documentation),\n"
" m (man-page)\n"
" uninstall logfile - remove files and empty directories listed\n"
" in the file 'logfile'\n"
" github - prepare github's gh-pages update\n"
" (internal use only)\n"
"\n"
);
exit(1);
}
ssh-cron-1.01.00/changelog 0000644 0001750 0001750 00000006572 12633533300 014253 0 ustar frank frank ssh-cron (1.01.00)
* The user is interactively given an opportunity to remove an existing
(left-over) ipc file when (re)starting ssh-cron.
* Added option --forced (or: -f) to force the removal of an already existing
ipc-file during daemon startup.
* Build scripts adapted to icmake 8.00.04.
-- Frank B. Brokken Mon, 14 Dec 2015 13:15:41 +0100
ssh-cron (1.00.01)
* Kevin Brodsky observed that the installation scripts used 'chdir' rather
than 'cd'. Fixed in this release.
* Kevin Brodsky also observed that the combined size of all precompiled
headers might exceed some disks capacities. The option -P was added to the
./build script to prevent the use of precompiled headers.
-- Frank B. Brokken Mon, 05 Oct 2015 21:15:45 +0200
ssh-cron (1.00.00)
* Update to version 1.00.00 after being operational for one year without
issues.
* Added 'INSTALL' and 'required'
* Standardized the (de)installation procedures
-- Frank B. Brokken Sat, 03 Oct 2015 10:10:18 +0200
ssh-cron (0.92.00)
* cron/call checked the need to activate a program by either looking for a
matching month daynr, OR by looking for a matching day-of-week number. This
is wrong: a spec. like * * * * 4 should only run on Wednesdays. The check
now requires all time specifications to match the current time.
-- Frank B. Brokken Thu, 18 Sep 2014 08:33:24 +0200
ssh-cron (0.91.03)
* Michael Tautschnig reported a FTBFS error, probably due to a missing
-lpthread flag. Now added.
-- Frank B. Brokken Tue, 26 Aug 2014 09:11:41 +0200
ssh-cron (0.91.02)
* No idea what required this subminor version, but according to Debian's
changelog we're at 0.91.02....
-- Frank B. Brokken Tue, 26 Aug 2014 09:11:41 +0200
ssh-cron (0.91.01)
* Changed 'pass phrase' into 'passphrase' following Tony Mancill's advice
-- Frank B. Brokken Sat, 14 Jun 2014 22:31:08 +0200
ssh-cron (0.91.00)
* A passphrase is required when starting the ssh-cron daemon or when
modifiying the daemon's scheduled commands.
-- Frank B. Brokken Mon, 09 Jun 2014 13:45:06 +0200
ssh-cron (0.90.00)
* Commands using an ssh-key requiring a passphrase have been successfully
executed when scheduled. When running ssh-cron as a daemon scheduling
continued after the user starting the daemon had logged out.
* Be advised: to run (or compile) ssh-cron, bobcat >= 3.23.00 is required.
* SSH-cron's development status is now BETA.
-- Frank B. Brokken Sat, 07 Jun 2014 16:39:32 +0200
ssh-cron (0.80.00)
* SSH-cron's development status is now ALPHA: daemon,--no-daemon, --list,
--reload, and --terminate have been shown to work as planned.
* Be advised that compiling and running ssh-cron requires at least Bobcat
3.23.00, which is currently only available from Bobcat's git repo:
commit 9eb8bc8029a4472d12a92a350b302ae2f71f496e
Date: Wed Jun 4 21:21:05 2014 +0200
-- Frank B. Brokken Wed, 04 Jun 2014 21:35:39 +0200
ssh-cron (0.10.00)
* Proof of concept operational
-- Frank B. Brokken Mon, 12 May 2014 10:43:33 +0200
ssh-cron (0.00.00)
* Start of Project.
-- Frank B. Brokken Thu, 07 May 2014 20:44:12 +0200
ssh-cron-1.01.00/cron/ 0000755 0001750 0001750 00000000000 12633537420 013337 5 ustar frank frank ssh-cron-1.01.00/cron/reload.cc 0000644 0001750 0001750 00000000743 12605015302 015105 0 ustar frank frank #include "cron.ih"
bool Cron::reload(istream &sharedIn)
{
string passPhrase;
getline(sharedIn, passPhrase);
if (hmac(passPhrase) != d_passPhrase)
return false;
string path;
getline(sharedIn, path);
idmsg() << "reloading from " << path << endl;
d_cronData = CronData();
d_cronData.messages(false);
ifstream in;
Exception::open(in, path);
Parser parser(in, d_cronData);
parser.parse();
return true;
}
ssh-cron-1.01.00/cron/requesthandler.cc 0000644 0001750 0001750 00000000140 12605015302 016654 0 ustar frank frank #include "cron.ih"
void Cron::requestHandler(Cron *cronPtr)
{
cronPtr->handleRequests();
}
ssh-cron-1.01.00/cron/parentprocess.cc 0000644 0001750 0001750 00000001617 12605015302 016530 0 ustar frank frank #include "cron.ih"
// stop() handles the termination of the child process
// daemon/terminate ends the process via --terminate
void Cron::parentProcess()
{
// Set up the parent's sides of the pipes
OFdStream toChild(d_childInput.writeOnly());
d_toChild = &toChild;
thread requestThread;
if (d_options.daemon())
{
requestThread = thread(requestHandler, this);
requestThread.detach(); // ends when main() ends
}
defineRunFunction();
d_options.msg() << "scheduler: executing /usr/bin/ssh-add" << endl;
sendCommand("/usr/bin/ssh-add");
cronLoop();
if (int status = waitForChild())
scheduler() << "ssh-agent (pid = " << pid() << ") returned " <<
status << endl;
else
idmsg() << "normal end of ssh-agent (pid = " << pid() << ')' << endl;
}
ssh-cron-1.01.00/cron/hmac2str.cc.stdby 0000644 0001750 0001750 00000000367 12605015302 016510 0 ustar frank frank #include "cron.ih"
string Cron::hmac2str(string const &passPhrase)
{
ostringstream out;
out << setfill('0');
for (unsigned char ch: passPhrase)
out << setw(2) << (ch >> 4) << setw(2) << (ch & 0xff);
return out.str();
}
ssh-cron-1.01.00/cron/list.cc 0000644 0001750 0001750 00000001015 12605015302 014603 0 ustar frank frank #include "cron.ih"
void Cron::list(size_t *index, streamsize offset, SharedStream &out)
{
out.seekp(offset);
out.truncate(offset); // clear any previous contents
if (*index == 0) // write an initial \n separator
out.put('\n');
for (; *index != d_cronData.size(); ++*index)
{
streamsize lastOK = out.tellp();
if (not (out << d_cronData[*index] << endl))
{
out.truncate(lastOK);
return;
}
}
out << endl;
}
ssh-cron-1.01.00/cron/handlerequests.cc 0000644 0001750 0001750 00000003450 12605015302 016664 0 ustar frank frank #include "cron.ih"
void Cron::handleRequests()
{
ifstream ipcFile;
Exception::open(ipcFile, Options::instance().ipcFile());
int shmemId;
ipcFile >> shmemId;
SharedStream sharedStream(shmemId);
SharedCondition cond(sharedStream.attachSharedCondition());
cond.lock();
size_t index; // index for CronData elements
while (true)
{
idmsg() << "waiting for requests" << endl;
cond.wait();
Function request = readRequest(sharedStream);
if (request > TERMINATE)
{
scheduler() << "received invalid function request " << request <<
endl;
continue;
}
(request == MORE ? idmsg() : scheduler()) << "received request " <<
nameOf(request) << endl;
streamsize writeOffset = sharedStream.tellg();
switch (request)
{
case LIST:
{
index = 0;
idmsg() << "answering MORE" << endl;
writeRequest(sharedStream, MORE);
list(&index, writeOffset, sharedStream);
}
break;
case MORE:
if (index != d_cronData.size())
list(&index, writeOffset, sharedStream);
else
{
idmsg() << "answering DONE" << endl;
writeRequest(sharedStream, DONE);
}
break;
case RELOAD:
if (not reload(sharedStream))
continue;
break;
default:
break;
}
idmsg() << "notifying the requestor" << endl;
cond.notify();
}
}
ssh-cron-1.01.00/cron/cron.ih 0000644 0001750 0001750 00000001336 12605015302 014612 0 ustar frank frank #include "cron.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "../parser/parser.h"
#include "../crondata/crondata.h"
#include "../cronentry/cronentry.h"
#include "../options/options.h"
using namespace std;
using namespace FBB;
inline bool Cron::specified(size_t value, set const &request)
{
return request.find(value) != request.end();
}
ssh-cron-1.01.00/cron/call.cc 0000644 0001750 0001750 00000000622 12605015302 014546 0 ustar frank frank #include "cron.ih"
bool Cron::call(DateTime const &now, CronEntry const &entry)
{
return
specified(now.minutes(), entry.minutes())
&&
specified(now.hours(), entry.hours())
&&
specified(now.month() + 1, entry.monthOfYear())
&&
specified(now.monthDayNr(), entry.dayOfMonth())
&&
specified(now.weekday(), entry.dayOfWeek());
}
ssh-cron-1.01.00/cron/cronloop.cc 0000644 0001750 0001750 00000001151 12605015302 015464 0 ustar frank frank #include "cron.ih"
void Cron::cronLoop() // called from parentprocess
try
{
idmsg() << "starting cronloop" << endl;
while (d_run)
{
size_t seconds = time(0) % 60;
if (seconds != 0)
{
idmsg() << "sleeping for " << (60 - seconds) << " seconds" <<
endl;
sleep(60 - seconds); // ends at a sigint signal
}
runCronJobs();
if (time(0) % 60 == 0)
sleep(1); // ends at a sighup signal
}
}
catch(EndOfRun)
{}
ssh-cron-1.01.00/cron/definerunfunction.cc 0000644 0001750 0001750 00000000603 12605015302 017357 0 ustar frank frank #include "cron.ih"
void Cron::defineRunFunction()
{
std::string const &mailer = d_options.mailer();
if (mailer.empty())
*d_toChild << R"(
_run_()
{
eval $* 2>&1 > /dev/null
}
)";
else
*d_toChild << R"(
_run_()
{
out=`eval $* 2>&1`
[ "$out" == "" ] || echo "$out" |
)" << mailer << R"(
}
)";
idmsg() << "defined _run_()" << endl;
}
ssh-cron-1.01.00/cron/sendcommand.cc 0000644 0001750 0001750 00000000141 12605015302 016117 0 ustar frank frank #include "cron.ih"
void Cron::sendCommand(string line)
{
*d_toChild << line << endl;
}
ssh-cron-1.01.00/cron/idmsg.cc 0000644 0001750 0001750 00000000127 12605015302 014736 0 ustar frank frank #include "cron.ih"
ostream &Cron::idmsg() const
{
return imsg << "scheduler: ";
}
ssh-cron-1.01.00/cron/childredirections.cc 0000644 0001750 0001750 00000000405 12605015302 017330 0 ustar frank frank #include "cron.ih"
void Cron::childRedirections()
{
d_childInput.readFrom(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
open("/dev/null", O_WRONLY); // reopen cout
open("/dev/null", O_WRONLY); // reopen cerr
}
ssh-cron-1.01.00/cron/readrequest.cc 0000644 0001750 0001750 00000000555 12605015302 016164 0 ustar frank frank #include "cron.ih"
Cron::Function Cron::readRequest(istream &in)
{
in.clear(); // previously executed `read' commands
// may have raised in's failbit.
in.seekg(SharedCondition::size());
Function value;
in.read(reinterpret_cast(&value), sizeof(Function));
return value;
}
ssh-cron-1.01.00/cron/runparentprocess.cc 0000644 0001750 0001750 00000000113 12605015302 017243 0 ustar frank frank #include "cron.ih"
void Cron::runParentProcess()
{
parentProcess();
}
ssh-cron-1.01.00/cron/data.cc 0000644 0001750 0001750 00000000114 12605015302 014540 0 ustar frank frank #include "cron.ih"
string Cron::s_agent = "/usr/bin/ssh-agent /bin/bash";
ssh-cron-1.01.00/cron/writerequest.cc 0000644 0001750 0001750 00000000346 12605015302 016401 0 ustar frank frank #include "cron.ih"
void Cron::writeRequest(ostream &out, Function value)
{
out.seekp(SharedCondition::size()); // the shared cond. is at offset 0
out.write(reinterpret_cast(&value), sizeof(Function));
}
ssh-cron-1.01.00/cron/childprocess.cc 0000644 0001750 0001750 00000000443 12605015302 016316 0 ustar frank frank #include "cron.ih"
void Cron::childProcess()
{
Process process(Process::DIRECT, s_agent);
// ssh-add works OK, but requires package ssh-askpass to be installed
process.start();
// this point is never reached
fmsg << "could not execute `" << s_agent << '\'' << endl;
}
ssh-cron-1.01.00/cron/hmac.cc 0000644 0001750 0001750 00000000355 12605015302 014546 0 ustar frank frank #include "cron.ih"
string Cron::hmac(string const &passPhrase)
{
HMacBuf hmacbuf(passPhrase, "sha256");
ostream out(&hmacbuf);
out << passPhrase;
hmacbuf.close();
string hash = hmacbuf.hash();
return hash;
}
ssh-cron-1.01.00/cron/scheduler.cc 0000644 0001750 0001750 00000000146 12605015302 015612 0 ustar frank frank #include "cron.ih"
ostream &Cron::scheduler() const
{
return d_options.msg() << "scheduler: ";
}
ssh-cron-1.01.00/cron/runcronjobs.cc 0000644 0001750 0001750 00000000547 12605015302 016205 0 ustar frank frank #include "cron.ih"
void Cron::runCronJobs() // called from cronloop
{
DateTime now(DateTime::LOCALTIME);
for (CronEntry const &entry: d_cronData.cronEntries())
{
if (call(now, entry))
{
if (not d_run)
throw EndOfRun(); // caught by cronloop
execute(entry);
}
}
}
ssh-cron-1.01.00/cron/cron.h 0000644 0001750 0001750 00000004021 12605015302 014433 0 ustar frank frank #ifndef INCLUDED_CRON_
#define INCLUDED_CRON_
#include
#include
#include
#include
#include "../ipcfunction/ipcfunction.h"
namespace FBB
{
class DateTime;
class SharedStream;
}
class CronEntry;
class CronData;
class Options;
class Cron: public IPCFunction, public FBB::Fork
{
enum EndOfRun
{};
Options &d_options;
CronData &d_cronData;
FBB::Pipe d_childInput; // child reads this
std::ostream *d_toChild = 0;
std::string d_passPhrase;
volatile bool d_run = true; // set to false by stop
static std::string s_agent;
public:
Cron(CronData &cronData);
void runParentProcess();
void stop(size_t signal);
void setPassPhrase(std::string const &passPhrase);
static Function readRequest(std::istream &in);
static void writeRequest(std::ostream &out, Function value);
static std::string hmac2str(std::string const &passPhrase);
private:
void childRedirections() override;
void childProcess() override;
void parentProcess() override;
std::ostream &idmsg() const; // imsg << "scheduler: "
std::ostream &scheduler() const; // d_options.msg() << "scheduler: "
void defineRunFunction();
void sendCommand(std::string line);
void cronLoop();
void runCronJobs();
bool call(FBB::DateTime const &now, CronEntry const &entry);
void execute(CronEntry const &entry);
void handleRequests(); // separate thread
void list(size_t *index, std::streamsize offset,
FBB::SharedStream &sharedStream);
bool reload(std::istream &in);
static bool specified(size_t value, std::set const &request);
static void requestHandler(Cron *cron);
static std::string hmac(std::string const &passPhrase);
};
inline void Cron::setPassPhrase(std::string const &passPhrase)
{
d_passPhrase = hmac(passPhrase);
}
#endif
ssh-cron-1.01.00/cron/execute.cc 0000644 0001750 0001750 00000000606 12605015302 015277 0 ustar frank frank #include "cron.ih"
void Cron::execute(CronEntry const &entry)
{
string command("(");
for (size_t idx = 0, end = entry.nSettings(); idx != end; ++idx)
command += d_cronData.environment()[idx] + ';';
command += "_run_ " + entry.command() + ")&";
scheduler() << entry.command() << endl;
idmsg() << "executed as " << command << endl;
sendCommand(command);
}
ssh-cron-1.01.00/cron/frame 0000644 0001750 0001750 00000000037 12605015302 014341 0 ustar frank frank #include "cron.ih"
Cron::
{
}
ssh-cron-1.01.00/cron/stop.cc 0000644 0001750 0001750 00000000144 12605015302 014617 0 ustar frank frank #include "cron.ih"
void Cron::stop(size_t signal)
{
d_run = false;
kill(pid(), SIGTERM);
}
ssh-cron-1.01.00/cron/cron1.cc 0000644 0001750 0001750 00000000165 12605015302 014657 0 ustar frank frank #include "cron.ih"
Cron::Cron(CronData &cronData)
:
d_options(Options::instance()),
d_cronData(cronData)
{}
ssh-cron-1.01.00/crondata/ 0000755 0001750 0001750 00000000000 12633537420 014171 5 ustar frank frank ssh-cron-1.01.00/crondata/addname.cc 0000644 0001750 0001750 00000000166 12605015302 016061 0 ustar frank frank #include "crondata.ih"
void CronData::addName(std::string const &name)
{
d_names.push_back(String::lc(name));
}
ssh-cron-1.01.00/crondata/setmonthofyear.cc 0000644 0001750 0001750 00000000264 12605015302 017536 0 ustar frank frank #include "crondata.ih"
void CronData::setMonthOfYear()
{
d_next.setMonthOfYear(assign(s_month));
d_entryName = "day of week";
d_entryBegin = 0;
d_entryEnd = 7;
}
ssh-cron-1.01.00/crondata/sethours.cc 0000644 0001750 0001750 00000000243 12605015302 016340 0 ustar frank frank #include "crondata.ih"
void CronData::setHours()
{
d_next.setHours(assign());
d_entryName = "day of month";
d_entryBegin = 1;
d_entryEnd = 32;
}
ssh-cron-1.01.00/crondata/insert.cc 0000644 0001750 0001750 00000000356 12605015302 015775 0 ustar frank frank #include "crondata.ih"
ostream &CronData::insert(ostream &out) const
{
for (auto &spec: d_environment)
out << spec << '\n';
for (auto &entry: d_cronEntries)
entry.insert(out) << '\n';
return out << flush;
}
ssh-cron-1.01.00/crondata/addcroncommand.cc 0000644 0001750 0001750 00000000547 12605015302 017444 0 ustar frank frank #include "crondata.ih"
void CronData::addCronCommand()
{
d_next.setEnvironment(d_lastSize, d_environment.size(), &d_environment);
d_lastSize = d_environment.size();
d_cronEntries.push_back(d_next);
if (d_info)
imsg << Options::instance().basename() << ": cron " <<
d_cronEntries.size() << '\n' << d_next << endl;
}
ssh-cron-1.01.00/crondata/process.cc 0000644 0001750 0001750 00000000315 12605015302 016142 0 ustar frank frank #include "crondata.ih"
void CronData::process()
{
if (emsg.count() == 0)
addCronCommand();
d_entryName = "minutes";
d_entryEnd = 60;
d_next = CronEntry();
emsg.setCount(0);
}
ssh-cron-1.01.00/crondata/setenvvar.cc 0000644 0001750 0001750 00000000617 12605015302 016506 0 ustar frank frank #include "crondata.ih"
void CronData::setEnvVar(string const &var, string const &value)
{
if (not value.empty())
{
d_environment.push_back(var + '=' + String::trim(value));
if (d_info)
imsg << Options::instance().basename() << ": envvar " <<
d_environment.size() << " `" << d_environment.back() <<
'\'' << endl;
}
}
ssh-cron-1.01.00/crondata/setdayofmonth.cc 0000644 0001750 0001750 00000000230 12605015302 017344 0 ustar frank frank #include "crondata.ih"
void CronData::setDayOfMonth()
{
d_next.setDayOfMonth(assign());
d_entryName = "month of year";
d_entryEnd = 13;
}
ssh-cron-1.01.00/crondata/crondata.h 0000644 0001750 0001750 00000005225 12605015302 016126 0 ustar frank frank #ifndef INCLUDED_CRONDATA_
#define INCLUDED_CRONDATA_
#include
#include
#include
#include "../cronentry/cronentry.h"
class CronData
{
friend
std::ostream &operator<<(std::ostream &out, CronData const &cronData);
std::vector d_environment;
std::vector d_cronEntries;
size_t d_lastSize = 0;
CronEntry d_next;
std::string d_entryName;
size_t d_entryBegin = 0;
size_t d_entryEnd = 60;
std::set d_wip;
std::vector d_names; // names used for time specifications
// at a cron-job line
size_t d_lineNr;
bool d_all = false;
bool d_info = true;
static size_t s_values[60];
static char const *const s_month[12];
static char const *const s_day[7];
public:
CronData();
void addNr(size_t nr);
void addRange(size_t first, size_t last, size_t step);
void setAll(size_t step);
void addName(std::string const &str);
void setCommand(std::string const &command);
void process();
void reset(size_t lineNr = 0); // 0 means: do not update lineNr
void messages(bool on = true);
void setMinutes();
void setHours();
void setDayOfMonth();
void setMonthOfYear();
void setDayOfWeek();
void setEnvVar(std::string const &var, std::string const &value);
size_t lineNr() const;
size_t size() const;
std::vector const &cronEntries() const;
CronEntry const &operator[](size_t index) const;
std::vector const &environment() const;
private:
std::set assign();
std::set assign(char const *const *names,
bool allowEnd = false);
void invalidRange(size_t first, size_t last) const;
void outOfRange(size_t nr);
void addCronCommand();
std::ostream &insert(std::ostream &out) const;
};
inline size_t CronData::lineNr() const
{
return d_lineNr;
}
inline void CronData::messages(bool onOff)
{
d_info = onOff;
}
inline CronEntry const &CronData::operator[](size_t index) const
{
return d_cronEntries[index];
}
inline std::vector const &CronData::cronEntries() const
{
return d_cronEntries;
}
inline size_t CronData::size() const
{
return d_cronEntries.size();
}
inline std::vector const &CronData::environment() const
{
return d_environment;
}
inline std::ostream &operator<<(std::ostream &out, CronData const &cronData)
{
return cronData.insert(out);
}
#endif
ssh-cron-1.01.00/crondata/crondata.ih 0000644 0001750 0001750 00000000255 12605015302 016275 0 ustar frank frank #include "crondata.h"
#include
#include
#include
#include "../options/options.h"
using namespace std;
using namespace FBB;
ssh-cron-1.01.00/crondata/addnr.cc 0000644 0001750 0001750 00000000347 12605015302 015561 0 ustar frank frank #include "crondata.ih"
void CronData::addNr(size_t nr)
{
if (d_entryBegin <= nr && nr <= d_entryEnd) // <=, so allowEnd is
d_wip.insert(nr); // handled
else
outOfRange(nr);
}
ssh-cron-1.01.00/crondata/data.cc 0000644 0001750 0001750 00000001160 12605015302 015374 0 ustar frank frank #include "crondata.ih"
size_t CronData::s_values[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
};
char const *const CronData::s_month[] =
{
"jan",
"feb",
"mar",
"apr",
"may",
"jun",
"jul",
"aug",
"sep",
"oct",
"nov",
"dec"
};
char const *const CronData::s_day[] =
{
"sun",
"mon",
"tue",
"wed",
"thu",
"fri",
"sat"
};
ssh-cron-1.01.00/crondata/setcommand.cc 0000644 0001750 0001750 00000000162 12605015302 016616 0 ustar frank frank #include "crondata.ih"
void CronData::setCommand(std::string const &command)
{
d_next.setCommand(command);
}
ssh-cron-1.01.00/crondata/invalidrange.cc 0000644 0001750 0001750 00000000341 12605015302 017126 0 ustar frank frank #include "crondata.ih"
void CronData::invalidRange(size_t first, size_t last) const
{
emsg << "Line " << d_lineNr << " (" << d_entryName <<
"): invalid range " << first << '-' << last << endl;
}
ssh-cron-1.01.00/crondata/addrange.cc 0000644 0001750 0001750 00000001046 12605015302 016233 0 ustar frank frank #include "crondata.ih"
void CronData::addRange(size_t first, size_t last, size_t step)
{
if (first < d_entryBegin or d_entryEnd <= last)
invalidRange(first, last);
if (step == 0)
emsg << "Line " << d_lineNr << ": step size must be >= 1" << endl;
if (first > last)
{
emsg << "Line " << d_lineNr << ": invalid range " <<
first << '-' << last << endl;
}
if (emsg.count() != 0)
return;
for ( ; first <= last; first += step)
d_wip.insert(first);
}
ssh-cron-1.01.00/crondata/setminutes.cc 0000644 0001750 0001750 00000000213 12605015302 016661 0 ustar frank frank #include "crondata.ih"
void CronData::setMinutes()
{
d_next.setMinutes(assign());
d_entryName = "hours";
d_entryEnd = 24;
}
ssh-cron-1.01.00/crondata/frame 0000644 0001750 0001750 00000000047 12605015302 015174 0 ustar frank frank #include "crondata.ih"
CronData::
{
}
ssh-cron-1.01.00/crondata/outofrange.cc 0000644 0001750 0001750 00000000304 12605015302 016633 0 ustar frank frank #include "crondata.ih"
void CronData::outOfRange(size_t nr)
{
emsg << "Line " << d_lineNr << " (" << d_entryName << "): " << nr <<
" out of range" << endl;
d_wip.clear();
}
ssh-cron-1.01.00/crondata/reset.cc 0000644 0001750 0001750 00000000336 12605015302 015611 0 ustar frank frank #include "crondata.ih"
void CronData::reset(size_t lineNr)
{
d_lineNr = lineNr;
d_entryBegin = 0;
d_entryEnd = 60;
d_entryName = "minutes";
d_names.clear();
d_all = false;
d_wip.clear();
}
ssh-cron-1.01.00/crondata/setall.cc 0000644 0001750 0001750 00000000251 12605015302 015747 0 ustar frank frank #include "crondata.ih"
void CronData::setAll(size_t step)
{
if (step == 1)
d_all = true;
else
addRange(d_entryBegin, d_entryEnd - 1, step);
}
ssh-cron-1.01.00/crondata/crondata1.cc 0000644 0001750 0001750 00000000173 12605015302 016342 0 ustar frank frank #include "crondata.ih"
CronData::CronData()
:
d_entryName("minutes"),
d_info(not Options::instance().reload())
{}
ssh-cron-1.01.00/crondata/assign2.cc 0000644 0001750 0001750 00000001235 12605015302 016034 0 ustar frank frank #include "crondata.ih"
set CronData::assign(char const *const *names, bool allowEnd)
{
size_t size = d_entryEnd - d_entryBegin;
for (string const &name: d_names)
{
char const *const *ptr = find(names, names + size, name);
if (ptr != names + size)
d_wip.insert(d_entryBegin + ptr - names);
else
emsg << "Line " << d_lineNr << " (" << d_entryName << "): `" <<
name << "' not supported" << endl;
}
d_names.clear();
if (allowEnd && d_wip.find(d_entryEnd) != d_wip.end())
{
d_wip.erase(d_entryEnd);
d_wip.insert(0);
}
return assign();
}
ssh-cron-1.01.00/crondata/setdayofweek.cc 0000644 0001750 0001750 00000000150 12605015302 017153 0 ustar frank frank #include "crondata.ih"
void CronData::setDayOfWeek()
{
d_next.setDayOfWeek(assign(s_day, true));
}
ssh-cron-1.01.00/crondata/assign.cc 0000644 0001750 0001750 00000001046 12605015302 015752 0 ustar frank frank #include "crondata.ih"
set CronData::assign()
{
set dest;
if (d_wip.size())
{
size_t last = *d_wip.rbegin();
if (last >= d_entryEnd)
{
outOfRange(last);
return dest;
}
}
if (emsg.count() == 0)
{
if (!d_all)
dest = d_wip;
else
{
dest.insert(s_values, s_values + d_entryEnd);
dest.insert(dest.end(), CronEntry::STAR);
}
}
d_wip.clear();
d_all = false;
return dest;
}
ssh-cron-1.01.00/cronentry/ 0000755 0001750 0001750 00000000000 12633537420 014421 5 ustar frank frank ssh-cron-1.01.00/cronentry/setenvironment.cc 0000644 0001750 0001750 00000000346 12605015302 020000 0 ustar frank frank #include "cronentry.ih"
void CronEntry::setEnvironment(size_t begin, size_t end,
std::vector const *environment)
{
d_begin = begin;
d_end = end;
d_environment = environment;
}
ssh-cron-1.01.00/cronentry/operatorinsert.cc 0000644 0001750 0001750 00000001122 12605015302 017771 0 ustar frank frank #include "cronentry.ih"
ostream &operator<<(ostream &out, CronEntry const &entry)
{
auto begin = entry.d_environment->begin() + entry.d_begin;
auto end = entry.d_environment->begin() + entry.d_end;
bool envVars = begin != end;
if (envVars && entry.d_begin > 0) // separate previous command list by
out.put('\n'); // empty line
for ( ; begin != end; ++begin)
out << "Envvar: " << *begin << '\n';
if (envVars) // separate env. vars from command(s)
out.put('\n');
entry.insert(out);
return out;
}
ssh-cron-1.01.00/cronentry/insert.cc 0000644 0001750 0001750 00000000533 12605015302 016222 0 ustar frank frank #include "cronentry.ih"
ostream &CronEntry::insert(ostream &out) const
{
showSet(out, d_minutes);
out << " ";
showSet(out, d_hours);
out << " ";
showSet(out, d_dayOfMonth);
out << " ";
showSet(out, d_monthOfYear);
out << " ";
showSet(out, d_dayOfWeek);
return out << " " << d_command;
}
ssh-cron-1.01.00/cronentry/showset.cc 0000644 0001750 0001750 00000000503 12605015302 016407 0 ustar frank frank #include "cronentry.ih"
void CronEntry::showSet(ostream &out, set const &nrSet)
{
if (nrSet.find(STAR) != nrSet.end())
{
out << '*';
return;
}
auto begin = nrSet.begin();
out << *begin++;
for (auto end = nrSet.end(); begin != end; ++begin)
out << ',' << *begin;
}
ssh-cron-1.01.00/cronentry/cronentry.h 0000644 0001750 0001750 00000005322 12605015302 016604 0 ustar frank frank #ifndef INCLUDED_CRONENTRY_
#define INCLUDED_CRONENTRY_
#include
#include
#include
#include
class CronEntry
{
friend std::ostream &operator<<(std::ostream &out, CronEntry const &entry);
size_t d_begin = 0;
size_t d_end = 0;
std::vector const *d_environment;
std::set d_minutes;
std::set d_hours;
std::set d_dayOfMonth;
std::set d_monthOfYear;
std::set d_dayOfWeek;
std::string d_command;
public:
enum
{
STAR = 100 // * used to specify time
};
void setEnvironment(size_t begin, size_t end,
std::vector const *environment);
void setCommand(std::string const &src);
void setMinutes(std::set &&src);
void setHours(std::set &&src);
void setDayOfMonth(std::set &&src);
void setMonthOfYear(std::set &&src);
void setDayOfWeek(std::set &&src);
size_t nSettings() const;
std::string const &command() const;
std::set const &minutes() const;
std::set const &hours() const;
std::set const &dayOfMonth() const;
std::set const &monthOfYear() const;
std::set const &dayOfWeek() const;
std::ostream &insert(std::ostream &out) const;
private:
static void showSet(std::ostream &out, std::set const &nrSet);
};
inline void CronEntry::setCommand(std::string const &src)
{
d_command = src;
}
inline void CronEntry::setMinutes(std::set &&src)
{
d_minutes = std::move(src);
}
inline void CronEntry::setHours(std::set &&src)
{
d_hours = std::move(src);
}
inline void CronEntry::setDayOfMonth(std::set &&src)
{
d_dayOfMonth = std::move(src);
}
inline void CronEntry::setMonthOfYear(std::set &&src)
{
d_monthOfYear = std::move(src);
}
inline void CronEntry::setDayOfWeek(std::set &&src)
{
d_dayOfWeek = std::move(src);
}
inline size_t CronEntry::nSettings() const
{
return d_end;
}
inline std::string const &CronEntry::command() const
{
return d_command;
}
inline std::set const &CronEntry::minutes() const
{
return d_minutes;
}
inline std::set const &CronEntry::hours() const
{
return d_hours;
}
inline std::set const &CronEntry::dayOfMonth() const
{
return d_dayOfMonth;
}
inline std::set const &CronEntry::monthOfYear() const
{
return d_monthOfYear;
}
inline std::set const &CronEntry::dayOfWeek() const
{
return d_dayOfWeek;
}
#endif
ssh-cron-1.01.00/cronentry/frame 0000644 0001750 0001750 00000000051 12605015302 015417 0 ustar frank frank #include "cronentry.ih"
CronEntry::
{
}
ssh-cron-1.01.00/cronentry/cronentry.ih 0000644 0001750 0001750 00000000102 12605015302 016744 0 ustar frank frank #include "cronentry.h"
#include
using namespace std;
ssh-cron-1.01.00/crontab 0000644 0001750 0001750 00000000324 12605015302 013735 0 ustar frank frank # this file is used in the POC demo, and is for my use only.
# it requires the ssh-key to log into suffix.rc.rug.nl
* * * * * /bin/date >> /tmp/out
* * * * * /usr/bin/ssh suffix.rc.rug.nl ls www >> /tmp/out
ssh-cron-1.01.00/daemon/ 0000755 0001750 0001750 00000000000 12633537420 013641 5 ustar frank frank ssh-cron-1.01.00/daemon/daemon.ih 0000644 0001750 0001750 00000001077 12605015302 015420 0 ustar frank frank #include "daemon.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "../options/options.h"
#include "../parser/parser.h"
using namespace std;
using namespace FBB;
struct Daemon::IPCInfo
{
size_t shmemID;
size_t pid;
};
ssh-cron-1.01.00/daemon/reload.cc 0000644 0001750 0001750 00000002420 12605015302 015401 0 ustar frank frank #include "daemon.ih"
void Daemon::reload()
{
basename() << "--reload" << endl;
// send the name of the cron-file to the daemon
unique_ptr path(realpath(ArgConfig::instance()[0], 0));
// verify the availability of the IPC file
IPCInfo info = getIPCInfo();
SharedStream sharedStream(info.shmemID);
SharedCondition cond(sharedStream.attachSharedCondition(0));
cond.lock();
for (size_t attempt = 0; attempt != 3; ++attempt)
{
Cron::writeRequest(sharedStream, RELOAD);
// the offset is just beyond the request
// retrieve the passphrase
string passPhrase = askPassPhrase();
sharedStream << passPhrase << '\n' << path.get() << endl;
sharedStream.truncate(sharedStream.tellp());
idmsg() << "notifying the daemon: RELOAD " << path.get() << endl;
cond.notify();
cv_status status = cond.wait_for(chrono::seconds(5));
cond.unlock();
if (status != cv_status::timeout)
{
// show the scheduled jobs to be reloaded
cout << '\n' <<
d_cronData << endl;
return;
}
cout << "Invalid passphrase.\n" << endl;
}
cout << "Giving up after three attempts." << endl;
}
ssh-cron-1.01.00/daemon/parentprocess.cc 0000644 0001750 0001750 00000000573 12605015302 017032 0 ustar frank frank #include "daemon.ih"
void Daemon::parentProcess()
{
ofstream ipcFile; // open the daemon's ipc-file:
Exception::open(ipcFile, Options::instance().ipcFile());
// see also cron/handlerequests and daemon/terminate
ipcFile << d_shmem.id() << '\n' <<
pid() << endl;
cout << '\n' <<
d_cronData << endl;
}
ssh-cron-1.01.00/daemon/list.cc 0000644 0001750 0001750 00000001044 12605015302 015107 0 ustar frank frank #include "daemon.ih"
bool Daemon::list(istream &in)
{
in.clear();
Function function = Cron::readRequest(in);
if (function > TERMINATE)
{
basename() << "received corrupted function request, value = " <<
function << endl;
return false;
}
idmsg() << "received " << nameOf(function) << endl;
if (function == DONE)
return false;
string line;
while (getline(in, line))
cout << line << '\n';
return true;
}
ssh-cron-1.01.00/daemon/daemon1.cc 0000644 0001750 0001750 00000000775 12605015302 015472 0 ustar frank frank #include "daemon.ih"
Daemon::Daemon()
:
d_options(Options::instance()),
d_cron(d_cronData)
{
if (not d_options.cronfile()) // no file command-line argument
return;
ifstream in;
Exception::open(in, ArgConfig::instance()[0]);
Parser parser(in, d_cronData); // parse the input file
parser.parse(); // filling d_cronData
if (d_cronData.size() == 0) // warn if no commands
wmsg << "no cron-commands to execute." << endl;
}
ssh-cron-1.01.00/daemon/ipc.cc 0000644 0001750 0001750 00000000471 12605015302 014712 0 ustar frank frank #include "daemon.ih"
void Daemon::ipc()
{
switch (d_options.ipcFunction())
{
case TERMINATE:
terminate();
break;
case LIST:
listRequest();
break;
case RELOAD:
reload();
break;
default:
break;
}
}
ssh-cron-1.01.00/daemon/askpassphrase.cc 0000644 0001750 0001750 00000000440 12605015302 017003 0 ustar frank frank #include "daemon.ih"
string Daemon::askPassPhrase()
{
Tty tty;
tty.echo(Tty::OFF);
ifstream in;
Exception::open(in, "/dev/tty");
cout << "Enter passphrase: " << flush;
string passphrase;
getline(in, passphrase);
cout << endl;
return passphrase;
}
ssh-cron-1.01.00/daemon/run.cc 0000644 0001750 0001750 00000000524 12605015302 014742 0 ustar frank frank #include "daemon.ih"
void Daemon::run()
{
if (d_options.ipc())
ipc(); // handles commands to the daemon
else if (d_options.foreground())
childProcess(); // ssh-cron runs in the foreground
else
daemonize(); // ssh-cron runs in the background
}
ssh-cron-1.01.00/daemon/idmsg.cc 0000644 0001750 0001750 00000000152 12605015302 015236 0 ustar frank frank #include "daemon.ih"
ostream &Daemon::idmsg() const
{
return imsg << d_options.basename() << ": ";
}
ssh-cron-1.01.00/daemon/basename.cc 0000644 0001750 0001750 00000000170 12605015302 015706 0 ustar frank frank #include "daemon.ih"
ostream &Daemon::basename() const
{
return d_options.msg() << d_options.basename() << ": ";
}
ssh-cron-1.01.00/daemon/getpassphrase.cc 0000644 0001750 0001750 00000001164 12605015302 017010 0 ustar frank frank #include "daemon.ih"
void Daemon::getPassPhrase()
{
Tty tty;
tty.echo(Tty::OFF);
ifstream in;
Exception::open(in, "/dev/tty");
while (true)
{
cout << "Enter passphrase: " << flush;
string passphrase1;
getline(in, passphrase1);
cout << "\nEnter same passphrase again: " << flush;
string passphrase2;
getline(in, passphrase2);
cout << endl;
if (passphrase1 == passphrase2)
{
d_cron.setPassPhrase(passphrase1);
break;
}
cout << "Different passphrases. Try again\n\n";
}
}
ssh-cron-1.01.00/daemon/cleanup.cc 0000644 0001750 0001750 00000000327 12605015302 015566 0 ustar frank frank #include "daemon.ih"
void Daemon::cleanup() // only called by daemons
{
d_shmem.kill();
// when the child process ends it throws away its own pid file:
unlink(d_options.ipcFile().c_str());
}
ssh-cron-1.01.00/daemon/enterthread.cc 0000644 0001750 0001750 00000000265 12605015302 016445 0 ustar frank frank #include "daemon.ih"
void Daemon::enterThread(Daemon *obj)
{
Tty tty;
tty.echo(Tty::OFF);
cin.ignore(numeric_limits::max(), '\n');
kill(getpid(), SIGTERM);
}
ssh-cron-1.01.00/daemon/createipcfile.cc 0000644 0001750 0001750 00000001136 12605015302 016735 0 ustar frank frank #include "daemon.ih"
// called from daemonize()
void Daemon::createIPCfile()
{
string const &ipcFile = d_options.ipcFile();
unique_ptr buffer(new char[ipcFile.length() + 6 + 1]);
strcpy(buffer.get() + ipcFile.copy(buffer.get(), string::npos), "XXXXXX");
int fd = mkstemp(buffer.get());
if (fd != -1)
{
close(fd);
fd = rename(buffer.get(), d_options.ipcFile().c_str());
}
if (fd == -1)
fmsg << "cannot create ipc file `" << d_options.ipcFile() << '\'' <<
endl;
}
ssh-cron-1.01.00/daemon/childprocess.cc 0000644 0001750 0001750 00000001325 12605015302 016620 0 ustar frank frank #include "daemon.ih"
void Daemon::childProcess()
{
Signal::instance().add(SIGINT, *this);
Signal::instance().add(SIGTERM, *this);
thread waiter; // waits for Enter with --no-daemon
if (d_options.daemon())
{
prepareDaemon();
imsg << "daemon: starting the scheduler" << endl;
}
else
{
cout << "Press the `Enter' key to end `" << d_options.basename() <<
'\'' << endl;
waiter = thread(enterThread, this);
waiter.detach();
idmsg() << "starting the scheduler" << endl;
}
d_cron.fork();
if (d_options.daemon())
cleanup();
throw 0; // correctly end the child process at main
}
ssh-cron-1.01.00/daemon/signalhandler.cc 0000644 0001750 0001750 00000000157 12605015302 016753 0 ustar frank frank #include "daemon.ih"
void Daemon::signalHandler(size_t signal)
{
d_cron.stop(signal);
cerr << '\n';
}
ssh-cron-1.01.00/daemon/getipcinfo.cc 0000644 0001750 0001750 00000000655 12605015302 016272 0 ustar frank frank #include "daemon.ih"
Daemon::IPCInfo Daemon::getIPCInfo() const
{
ifstream ipcFile;
Exception::open(ipcFile, Options::instance().ipcFile());
IPCInfo info;
if (not (ipcFile >> info.shmemID >> info.pid))
fmsg << "corrupted " << Options::instance().ipcFile() << endl;
idmsg() << "IPC info: shared memory ID: " << info.shmemID <<
", daemon PID: " << info.pid << endl;
return info;
}
ssh-cron-1.01.00/daemon/daemonize.cc 0000644 0001750 0001750 00000002160 12633537213 016122 0 ustar frank frank #include "daemon.ih"
void Daemon::daemonize()
{
string const &ipcFile = d_options.ipcFile();
if (access(ipcFile.c_str(), F_OK) == 0)
{
bool remove = d_options.forced();
if (not remove)
{
wmsg << ipcFile << " is in the way. Remove it [Ny]? ";
string answer;
remove = getline(cin, answer)
&& (answer == "y" || answer == "yes");
}
if (not remove or unlink(ipcFile.c_str()) != 0)
fmsg << "cannot continue as " << ipcFile <<
" cannot be removed " << endl;
}
getPassPhrase();
createIPCfile(); // create it with access mode 0600,
// parentProcess() writes information to it
d_shmem = SharedMemory(1, SharedMemory::kB);// create the shared memory
try
{
SharedCondition::create(d_shmem); // create the shared condition
}
catch (exception const &exc)
{
unlink(ipcFile.c_str());
throw;
}
idmsg() << "starting the daemon" << endl;
fork();
}
ssh-cron-1.01.00/daemon/frame 0000644 0001750 0001750 00000000043 12605015302 014640 0 ustar frank frank #include "daemon.ih"
Daemon::
{
}
ssh-cron-1.01.00/daemon/terminate.cc 0000644 0001750 0001750 00000000341 12605015302 016123 0 ustar frank frank #include "daemon.ih"
void Daemon::terminate() const
{
basename() << "--terminate" << endl;
IPCInfo info = getIPCInfo();
idmsg() << "terminating process " << info.pid << endl;
kill(info.pid, SIGTERM);
}
ssh-cron-1.01.00/daemon/daemon.h 0000644 0001750 0001750 00000002671 12605015302 015250 0 ustar frank frank #ifndef INCLUDED_DAEMON_
#define INCLUDED_DAEMON_
#include
#include
#include
#include "../ipcfunction/ipcfunction.h"
#include "../crondata/crondata.h"
#include "../cron/cron.h"
class Options;
namespace FBB
{
class SharedCondition;
class SharedStream;
}
class Daemon: public IPCFunction, public FBB::Fork, public FBB::SignalHandler
{
struct IPCInfo;
Options &d_options;
CronData d_cronData;
Cron d_cron;
FBB::SharedMemory d_shmem;
public:
Daemon();
void run();
private:
std::ostream &idmsg() const; // imsg inserts basename :
std::ostream &basename() const; // options.msg() inserts basename :
void foreground(); // don't fork, just call the child process
void daemonize(); // run the daemon in the background
void ipc(); // do the other commands, involving ipc
void createIPCfile();
void cleanup();
void parentProcess() override;
void childProcess() override;
void signalHandler(size_t signum) override;
void terminate() const;
IPCInfo getIPCInfo() const;
void getPassPhrase();
std::string askPassPhrase();
void reload();
void listRequest();
bool list(std::istream &in);
static void enterThread(Daemon *obj);
};
#endif
ssh-cron-1.01.00/daemon/listrequest.cc 0000644 0001750 0001750 00000002021 12605015302 016514 0 ustar frank frank #include "daemon.ih"
void Daemon::listRequest()
{
basename() << "--list" << endl;
IPCInfo info = getIPCInfo();
SharedStream sharedStream(info.shmemID);
SharedCondition cond(sharedStream.attachSharedCondition(0));
cond.lock();
Cron::writeRequest(sharedStream, LIST);
Function function = LIST;
do
{
idmsg() << "notifying [" << nameOf(function) << "] the daemon " <<
endl;
cond.notify(); // notify the server (waiting remote process)
// now wait for the answer
cv_status status = cond.wait_for(chrono::seconds(2));
if (status == cv_status::no_timeout)
function = MORE;
else
{
cond.unlock();
fmsg << "--list: no response from process " << info.pid << endl;
}
}
while (list(sharedStream)); // process the reply
cond.unlock(); // allow the daemon to return to its waiting
// state
}
ssh-cron-1.01.00/documentation/ 0000755 0001750 0001750 00000000000 12605015302 015234 5 ustar frank frank ssh-cron-1.01.00/documentation/man/ 0000755 0001750 0001750 00000000000 12633537436 016031 5 ustar frank frank ssh-cron-1.01.00/documentation/man/ssh-cron.yo 0000644 0001750 0001750 00000032257 12633533267 020145 0 ustar frank frank gagmacrowarning(cron argument phrase key passphrase)
includefile(../../release.yo)
htmlbodyopt(text)(#27408B)
htmlbodyopt(bgcolor)(#FFFAF0)
gagmacrowarning(ssh-cron)
mailto(f.b.brokken@rug.nl)
DEFINEMACRO(lsoption)(3)(\
bf(--ARG1)=tt(ARG3) (bf(-ARG2))\
)
DEFINEMACRO(laoption)(2)(\
bf(--ARG1)=tt(ARG2)\
)
DEFINEMACRO(loption)(1)(\
bf(--ARG1)\
)
DEFINEMACRO(soption)(1)(\
bf(-ARG1)\
)
DEFINEMACRO(s)(0)(bf(ssh-cron))
DEFINEMACRO(S)(0)(bf(Ssh-Cron))
DELETEMACRO(tt)
DEFINEMACRO(tt)(1)(em(ARG1))
manpage(ssh-cron)(1)(_CurYrs_)(ssh-cron__CurVers_.tar.gz)
(ssh-cron - ssh-aware cron-like daemon)
manpagename(ssh-cron)(cron-like daemon able to use ssh-connections)
manpagesynopsis()
bf(ssh-cron) [OPTIONS] tt([crontab-file]) nl()
[OPTIONS] - cf. section bf(OPTIONS)nl()
[crontab-file] - file containing jobs to run.nl()
manpagedescription()
Consider the situation where a computer every now and then must access a
remote computer to do some useful things at that remote computer (like running
a bf(stealth)(1) file integrity scan). In order to do so the computer must be
allowed to make bf(ssh)(1) connections to the remote computer. But since the
commands are not executed by the user but by bf(cron)(1), the ssh-keys which
are required to access the remote computer cannot use passphrases.
This is an undesirable situation: if the computer running the tt(ssh) commands
gets compromised, then the remote computers are compromised as well, since the
attacker may access these remote systems using ssh keys not requiring pass
phrases.
S() offers a way out of this undesirable situation, while still allowing
commands to be executed on remote computers. Here's how this is realized:
itemization(
it() Normally, s() runs as a daemon program. When s() starts it first
reads and parses a crontab-like specification file. Following this,
s() spawns a child process, and terminates.
it() S()'s daemon process itself spawns an bf(ssh-agent)(1) child
process, executing all scheduled commands.
it() In addition, s()'s daemon defines communcation channels between
itself and its bf(ssh-agent)(1) child process;
it() S()'s daemon sends the command bf(ssh-add)(1) to its child process as
its first command to execute, and using normal user-interaction means
(e.g., using bf(ssh-askpass)(1)) em(ssh-agent) is provided with the
required passphrase(s) for the ssh key(s).
it() S()'s daemon now monitors the time, firing off scheduled commands at
their required moments in time. If these commands require access to
remote computers, then this access is granted, as em(ssh-agent) is able
to provide the passphrase(s).
it() If an s() daemon process is already running, then the tt(--reload)
option (see below), can be used to load the s() daemon with the
commands and environment variable settings from another
tt(crontab-file), replacing the currently stored commands and
environment settings by the ones provided in the reloaded file.
)
When shell control characters (like redirection symbols) must be used in
command specifications, they should be escaped. E.g., as in tt(echo hello
world \> /dev/null).
Users sharing a computer each define their own s() specification file. When a
user logs out and leaves the
system the daemon process continues to run, executing its scheduled commands
at their scheduled times, using ssh-keys whenever required.
If the accounts for which s() jobs are running are ever compromised,
the remote computers remain safe, as the passphrases of the available
ssh-keys remain unavailable.
To prevent unauthorized modifications of the commands scheduled by the s()
daemon themselves a passphrase is required when starting s()'s daemon
process. The passphrase itself is not stored by the daemon (instead, it
stores a bf(sha256)(1) hash value), which avoids access to the s() daemon's
passphrase by browsing the computer's memory. The passphrase may be empty,
but even then that empty passphrase must be provided when reloading s()
daemon's scheduled commands. The scheduled commands may be listed,
however. This is allowed without providing a passphrase since the file
containing the scheduled commands will usually also be available on the
computer. Likewise, since a user may always terminate his/her own programs an
s() daemon process can be terminated from another s() program using the
tt(--terminate) command line option.
The above-mentioned facilities are not supported by bf(crontab)(1) itself.
bf(Cron)(1), which is responsible for executing scheduled crontab commands,
has no access to the passphrases of ssh-keys (which are otherwise provided
em(ssh-agent)).
manpagesection(RETURN VALUE)
S() returns 0 if the daemon was successfully started. Otherwise 1 is
returned.
manpageoptions()
Where available, single letter options are listed between parentheses
following their associated long-option variants. Single letter options require
arguments if their associated long options also require arguments.
Several options have default values. Run tt(ssh-cron --help) for an overview
of the implemented default option values. Also, several options can be
specified in a configuration file (where this doesn't hold true, it is
explicitly mentioned at the relevant options).
The configuration file (not to be confused with the file containing the
scheduled commands, which is provided as s() command-line file argument)
ignores empty lines and all information on lines starting at a hash-mark
(tt(#), optionally preceded by blanks and/or tabs). The configuration file is
used to specify s()'s options using their long variants. However, in the
configuration file the initial hyphens of command-line options must be
omitted, and optionally a colon may be appended to these long options
names. Note that multi-word option arguments should not be surrounded by
quotes. Examples:
verb(
stdout
syslog-facility: LOCAL0
mailer: /usr/bin/mail -s "some subject" me@myhost.warpnet.nl
)
Command-line options always override configuration file options.
itemization(
it() laoption(agent)(agent)nl()
absolute path to the agent program (plus its argument(s)) providing the
ssh-keys.
By default tt(/usr/bin/ssh-agent /bin/bash) is used.
it() lsoption(config)(c)(path)nl()
config file containing long option specifications.
By default tt(~/.ssh-cron) is used.
This option cannot be specified in the configuration file.
it() loption(forced) (soption(f))nl()
When restarting s() and an existing (leftover) ipc-file file
exists, then the user is interactively given the opportunity to remove
the existing ipc-file during daemon-startup.
it() loption(help) (soption(h))nl()
basic usage information is written to the standard output
stream (only interpreted in combination with tt(--no-daemon)).
This option cannot be specified in the configuration file.
it() lsoption(ipc-file)(p)(path)nl()
when s() runs as a daemon, then tt(path) specifies the path of the file
holding the daemon's shared memory ID and process ID. The ipc file
must be available if s() is connecting to or starting a daemon process
(the former situation occurs with the options tt(--list, --reload),
and tt(--terminate)). If s() detects an existing tt(ipc-file) at
daemon startup and the option tt(--forced) was not specified, then the
user is interactively given the opportunity to remove the existing
file. If the existing ipc-file can or should not be removed, then the
daemon is not started. To end a daemon process use tt(ssh-cron
--terminate), or send a SIGINT (tt(ctrl-C)) or SIGTERM signal to the
process-id found as the second value in the tt(ipc-file).
By default tt(~/.ssh-cron.ipc) is used.
it() loption(list) (soption(l))nl()
list the currently defined environment settings and cron-commands (the
tt(crontab-file) argument must be omitted). This option is
incompatible with (--no-daemon, --reload,) and tt(--terminate).
This option cannot be specified in the configuration file.
it() lsoption(log)(L)(path)nl()
log messages are appended to tt(path). If tt(path) does not exist, it
is created first.
it() lsoption(mailer)(m)(command)nl()
information written to the standard output or standard error streams of
the commands executed by s() is sent by e-mail to the current
user. Use tt(--mailer) to redefine (or to suppress sending e-mail by
specifying an empty mailer command (i.e., tt(--mailer ""))).
By default tt(/usr/bin/mail -s \"Ssh-cron $*\" $USER@localhost) is
used, with tt($*) replaced by the exected command as specified in the
tt(crontab) file argument.
it() loption(no-daemon) nl()
s() is not run as a daemon. To properly end s() if not running as a
daemon, press the `Enter' key, enter tt(ctrl-C) or send s() a
tt(SIGTERM) signal. This option is incompatible with ( --list,
--reload,) and tt(--terminate).
This option cannot be specified in the configuration file.
it() loption(reload) (soption(r))nl()
reload the s() daemon with de cron-commands defined in the
tt(crontab-file) argument (which must be provided). This option is
incompatible with (--list, --no-daemon,) and tt(--terminate).
This option cannot be specified in the configuration file.
it() loption(stdout) (soption(s))nl()
in addition to using a log file and syslog messages send all messages
to the standard output. This option is not available if s() runs as a
daemon process.
This option cannot be specified in the configuration file.
it() loption(syslog)nl()
messages are sent to the syslog daemon when this option is specified.
By default syslog messages are written to the tt(DAEMON) facility with
priority tt(NOTICE).
it() laoption(syslog-facility)(facility)nl()
the facility that is used to write the syslog messages to. By default
this is tt(DAEMON). For an overview of facilities and their meanings,
see, e.g., bf(syslog)(3). With s() the facilities tt(DAEMON,
LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7), and
tt(USER) can be used.
By default facility tt(DAEMON) is used.
it() laoption(syslog-priority)(priority)nl()
the priority that is used to write the syslog messages to. By default
this is tt(NOTICE). For an overview of priorities and their meanings,
see, e.g., bf(syslog)(3). With s() all defined priorities can
be used. E.g., tt( EMERG, ALERT, CRIT, ERR, WARNING, NOTICE, INFO) and
tt(DEBUG).
By default priority tt(NOTICE) is used.
it() laoption(syslog-tag)(tag)nl()
syslog messages can be provided with a em(tag), which can be used to
filter them from the log-files. See also section tt(RSYSLOG
FILTERING) below.
By default the tag tt(SSH-CRON) is used.
it() loption(terminate) (soption(t))nl()
terminate a running s() daemon program, using the daemon's process ID
found in the ipc-file's second value. The tt(crontab-file) argument
must be omitted. This option is incompatible tt with (--list,
--nodaemon,) and tt(--reload)
.
This option cannot be specified in the configuration file.
it() loption(verbose)nl()
additional messages about s()'s mode of operation are sent to
s()'s log facilities (specified by tt(--log, --syslog,) and/or
tt(--stdout)).
it() loption(version) (soption(v))nl()
s()'s version number is written to the standard output stream.
This option cannot be specified in the configuration file.
)
manpagesection(RSYSLOG FILTERING)
When using bf(rsyslogd)(1) property based filters may be used to filter
syslog messages and write them to a file of your choice. E.g., to filter
messages starting with the syslog message tag (e.g., tt(SSH-CRON)) use
verb(
:syslogtag, isequal, "SSH-CRON:" /var/log/ssh-cron.log
:syslogtag, isequal, "SSH-CRON:" stop
)
Note that the colon is part of the tag, but is not specified with the
tt(syslog-tag) option.
This causes all messages having the tt(SSH-CRON:) tag to be written on
tt(/var/log/ssh-cron.log) after which they are discarded. More extensive
filtering is also supported, see, e.g.,
tt(http://www.rsyslog.com/doc/rsyslog_conf_filter.html) and
tt(http://www.rsyslog.com/doc/property_replacer.html)
manpageseealso()
bf(cron)(1), bf(crontab)(1), bf(crontab)(5), , bf(rsyslogd)(1), bf(ssh)(1),
bf(ssh-add)(1), bf(ssh-agent)(1), bf(ssh-askpass)(1), bf(stealth)(1),
bf(syslog)(3)
manpagebugs()
None reported.
manpagesection(COPYRIGHT)
This is free software, distributed under the terms of the `GNU General
Public License'. Copyright remains with the author. s() is available at
tt(https://fbb-git.github.io/ssh-cron/).
manpagesection(ORGANIZATION)
Center for Information Technology, University of Groningen.
manpageauthor()
Frank B. Brokken (bf(f.b.brokken@rug.nl)).
ssh-cron-1.01.00/icmake/ 0000755 0001750 0001750 00000000000 12633530165 013626 5 ustar frank frank ssh-cron-1.01.00/icmake/setopt 0000644 0001750 0001750 00000000341 12605015302 015053 0 ustar frank frank string setOpt(string install_im, string envvar)
{
list optvar;
string ret;
optvar = getenv(envvar);
if (optvar[0] == "1")
ret = optvar[1];
else
ret = install_im;
return ret;
}
ssh-cron-1.01.00/icmake/loginstall 0000644 0001750 0001750 00000001565 12633530165 015730 0 ustar frank frank // source and dest, absolute or reachable from g_cwd, should exist.
// files and links in source matching dest (if empty: all) are copied to dest
// and are logged in g_log
// Before they are logged, dest is created
void logInstall(string src, string pattern, string dest)
{
list entries;
int idx;
chdir(g_cwd);
md(dest);
src += "/";
dest += "/";
if (listlen(makelist(O_DIR, src)) == 0)
{
printf("Warning: ", src, " not found: can't install ", src, pattern,
" at ", dest, "\n");
return;
}
entries = findAll("f", src, pattern);
for (idx = listlen(entries); idx--; )
run("cp " + src + entries[idx] + " " + dest);
chdir(g_cwd);
entries = findAll("l", src, pattern);
for (idx = listlen(entries); idx--; )
run("cp " CPOPTS " " + src + entries[idx] + " " + dest);
}
ssh-cron-1.01.00/icmake/logzip 0000644 0001750 0001750 00000001656 12633530165 015065 0 ustar frank frank // names may be a series of files in src, not a wildcard.
// if it's empty then all files in src are used.
// the files are gzipped and logged in dest.
// src and dest do not have to end in /
void logZip(string src, string names, string dest)
{
list files;
int idx;
string file;
chdir(g_cwd);
md(dest);
dest += "/";
if (src != "")
{
if (listlen(makelist(O_DIR, src)) == 0)
{
printf("Warning: ", src, " not found: can't install ", src, names,
" at ", dest, "\n");
return;
}
chdir(src);
}
if (names == "")
files = makelist("*");
else
files = strtok(names, " ");
for (idx = listlen(files); idx--; )
{
file = files[idx];
run("gzip -n -9 < " + file + " > " + file + ".gz");
}
run("tar cf - *.gz | (cd " + g_cwd + "; cd " + dest + "; tar xf -)");
run("rm *.gz");
}
ssh-cron-1.01.00/icmake/clean 0000644 0001750 0001750 00000000436 12605015302 014624 0 ustar frank frank void clean(int dist)
{
run("rm -rf "
"build-stamp configure-stamp "
"options/SKEL "
"tmp/*.o tmp/*-stamp " +
"o */o release.yo tmp/lib*.a "
);
if (dist)
run("rm -rf tmp *.ih.gch */*.ih.gch");
exit(0);
}
ssh-cron-1.01.00/icmake/logfile 0000644 0001750 0001750 00000000257 12605015302 015164 0 ustar frank frank void logFile(string srcdir, string src, string destdir, string dest)
{
chdir(g_cwd);
md(destdir);
run("cp " + srcdir + "/" + src + " " + destdir + "/" + dest);
}
ssh-cron-1.01.00/icmake/findall 0000644 0001750 0001750 00000001074 12633530165 015164 0 ustar frank frank // assuming we're in g_cwd, all entries of type 'type' matching source/pattern
// are returned w/o final \n
list findAll(string type, string source, string pattern)
{
string cmd;
list entries;
list ret;
int idx;
chdir(source);
cmd = "find ./ -mindepth 1 -maxdepth 1 -type " + type;
if (pattern != "")
pattern = "-name '" + pattern + "'";
entries = backtick(cmd + " " + pattern + " -printf \"%f\\n\"");
for (idx = listlen(entries); idx--; )
ret += (list)cutEoln(entries[idx]);
chdir(g_cwd);
return ret;
}
ssh-cron-1.01.00/icmake/manpage 0000644 0001750 0001750 00000000545 12605015302 015153 0 ustar frank frank #define MANPAGE "../../tmp/man/" ${PROJECT} ".1"
void manpage()
{
md("tmp/man tmp/manhtml");
chdir("documentation/man");
if (PROJECT ".yo" younger MANPAGE || "release.yo" younger MANPAGE)
{
run("yodl2man -o " MANPAGE " " PROJECT);
run("yodl2html -o ../../tmp/manhtml/" PROJECT ".1.html " PROJECT);
}
exit(0);
}
ssh-cron-1.01.00/icmake/cuteoln 0000644 0001750 0001750 00000000233 12605015302 015206 0 ustar frank frank string cutEoln(string text)
{
int len;
len = strlen(text) - 1;
if (text[len] == "\n")
text = substr(text, 0, len);
return text;
}
ssh-cron-1.01.00/icmake/uninstall 0000644 0001750 0001750 00000000456 12605015302 015555 0 ustar frank frank void uninstall(string logfile)
{
int idx;
list entry;
string dir;
list line;
if (!exists(logfile))
{
printf("installation log file " + logfile + " not found\n");
exit(0);
}
run("icmake/remove " + logfile + " " + (string)g_echo);
exit(0);
}
ssh-cron-1.01.00/icmake/pathfile 0000644 0001750 0001750 00000000552 12605015302 015335 0 ustar frank frank list path_file(string path)
{
list ret;
int len;
int idx;
for (len = strlen(path), idx = len; idx--; )
{
if (path[idx] == "/")
{
ret =
(list)substr(path, 0, idx) + (list)substr(path, idx + 1, len);
return ret;
}
}
ret = (list)"" + (list)path;
return ret;
}
ssh-cron-1.01.00/icmake/github 0000644 0001750 0001750 00000000223 12605015302 015016 0 ustar frank frank void github()
{
run("cp -r release.yo tmp/manhtml/ssh-cron.1.html ../../wip");
run("cp changelog ../../wip/changelog.txt");
exit(0);
}
ssh-cron-1.01.00/icmake/md 0000644 0001750 0001750 00000000740 12605015302 014140 0 ustar frank frank // md: target should be a series of blank-delimited directories to be created
// If an element is a whildcard, the directory will always be created,
// using mkdir -p.
//
// uses: run()
void md(string target)
{
int idx;
list paths;
string dir;
if (!exists(target))
run("mkdir -p " + target);
else if (((int)stat(target)[0] & S_IFDIR) == 0)
{
printf(target + " exists, but is not a directory\n");
exit(1);
}
}
ssh-cron-1.01.00/icmake/log 0000755 0001750 0001750 00000000632 12605015302 014324 0 ustar frank frank #!/bin/bash
find tmp/install -type f -exec md5sum "{}" \; |
sed 's|tmp/install|'$1'|' > $2
find tmp/install -type l -exec printf "link %s\n" "{}" \; |
sed 's|tmp/install|'$1'|' >> $2
find tmp/install -type d -exec printf "dir %s\n" "{}" \; |
sed 's|tmp/install|'$1'|' >> $2
ssh-cron-1.01.00/icmake/remove 0000755 0001750 0001750 00000001170 12605015302 015036 0 ustar frank frank #!/bin/bash
g_echo=$2
rm_f()
{
[ $g_echo -ne 0 ] && echo rm $1
rm -f $1
}
rm_dir()
{
[ $g_echo -ne 0 ] && echo rmdir $1
rmdir --ignore-fail-on-non-empty -p $1
}
IFS="
"
for line in `cat $1`
do
field1=`echo $line | awk '{printf $1}'`
field2=`echo $line | awk '{printf $2}'`
if [ $field1 == "link" ] ; then
rm_f $field2
elif [ $field1 == "dir" ] ; then
rm_dir $field2
elif [ -e "$field2" ] ; then
if [ "$field1" != "`md5sum $field2 | awk '{printf $1}'`" ] ; then
echo $field2 changed, not removed
else
rm_f $field2
fi
fi
done
rm_f $1
ssh-cron-1.01.00/icmake/precompileheaders 0000644 0001750 0001750 00000001336 12633530165 017247 0 ustar frank frank string g_compiler;
int g_gch = 1;
void _precompile(string class)
{
string classIH;
classIH = class + ".ih";
if (classIH younger class + ".ih.gch")
run(g_compiler + " -x c++-header " + classIH);
}
void precompileHeaders()
{
int idx;
list classes;
string class;
if (!g_gch)
return;
classes = makelist(O_SUBDIR, "*");
g_compiler = setOpt(CXX, "CXX") + " " +
setOpt(CXXFLAGS, "CXXFLAGS") + " ";
_precompile("main"); // precompile the main program .ih file
for (idx = listlen(classes); idx--; )
{
class = classes[idx];
chdir(class);
_precompile(class);
chdir(g_cwd);
}
}
ssh-cron-1.01.00/icmake/special 0000644 0001750 0001750 00000000421 12605015302 015154 0 ustar frank frank void special()
{
if (! exists("release.yo") || "VERSION" newer "release.yo")
{
system("touch version.cc");
run("gcc -E VERSION.h | grep -v '#' | sed 's/\\\"//g' > "
"release.yo");
}
}
ssh-cron-1.01.00/icmake/run 0000644 0001750 0001750 00000000330 12605015302 014337 0 ustar frank frank int g_dryrun = setOpt("", "DRYRUN") != "";
void runP(int testValue, string cmd)
{
if (g_dryrun)
printf(cmd, "\n");
else
system(testValue, cmd);
}
void run(string cmd)
{
runP(0, cmd);
}
ssh-cron-1.01.00/icmake/install 0000644 0001750 0001750 00000003356 12605015302 015214 0 ustar frank frank
void install(string request, string dest)
{
string target;
int components = 0;
list pathsplit;
string base;
base = "tmp/install/";
md(base);
if (request == "x")
components = 63;
else
{
if (strfind(request, "b") != -1)
components |= 2;
if (strfind(request, "d") != -1)
components |= 4;
if (strfind(request, "m") != -1)
components |= 8;
}
if (components & 2)
{
target = base + BINARY;
pathsplit = path_file(target);
printf(" installing the executable `", target, "'\n");
logFile("tmp/bin", "binary", pathsplit[0], pathsplit[1]);
}
if (components & (4 | 8))
{
target = base + DOC "/";
if (components & 4)
{
printf(" installing changelog at `", target, "\n");
logZip("", "changelog", target );
printf(" installing the README file at `", target, "\n");
logZip("", "README", target );
}
if (components & 8)
{
printf(" installing the html-manual pages at `", target, "\n");
logInstall("tmp/manhtml", "", target);
}
}
if (components & 8)
{
target = base + MAN "/";
printf(" installing the manual pages below `", target, "'\n");
logZip("tmp/man", "ssh-cron.1", target);
}
chdir(g_cwd);
if (dest == "")
dest = "/";
else
md(dest);
dest = cutEoln(backtick("realpath " + dest)[0]);
if (g_logPath != "")
backtick("icmake/log " + dest + " " + g_logPath);
run("tar cf - -Ctmp/install . | tar xf - -C" + dest);
printf("\n Installation completed\n");
exit(0);
}
ssh-cron-1.01.00/icmake/backtick 0000644 0001750 0001750 00000000160 12605015302 015307 0 ustar frank frank list backtick(string arg)
{
list ret;
echo(OFF);
ret = `arg`;
echo(g_echo);
return ret;
}
ssh-cron-1.01.00/icmconf 0000644 0001750 0001750 00000001557 12633530127 013744 0 ustar frank frank #include "INSTALL.im"
#define ADD_LIBRARIES "pthread bobcat"
#define ADD_LIBRARY_PATHS ""
#define LIBRARY "modules"
#define MAIN "main.cc"
#define OBJ_EXT ".o"
#define PARSER_DIR "parser"
#define PARSFILES "inc/*"
#define PARSFLAGS ""
// "-V"
#define PARSGEN "bisonc++"
#define PARSOUT "parse.cc"
#define PARSSPEC "grammar"
#define REFRESH
#define SCANNER_DIR "scanner"
#define SCANFLAGS ""
#define SCANGEN "flexc++"
#define SCANOUT "lex.cc"
#define SCANSPEC "lexer"
#define SHAREDREQ ""
#define SOURCES "*.cc"
#define TMP_DIR "tmp"
#define USE_ALL "a"
#define USE_ECHO ON
#define USE_VERSION
#define DEFCOM "program"
ssh-cron-1.01.00/input 0000644 0001750 0001750 00000000532 12605015302 013445 0 ustar frank frank # comment
# comment
PATH = /usr/local/bin:/usr/bin:/bin
# min hr day-of-month month-of-year day-of-week cmnd
# */15 0 * * *
# 90 25 32 Jan,Feb Sun /usr/bin/hello world
# * * * * * ssh styx "date \> /tmp/date"
# * * * * * date \> /tmp/date
MORE="additional var"
0 0 1 1 0 noaction
ssh-cron-1.01.00/ipcfunction/ 0000755 0001750 0001750 00000000000 12633537420 014717 5 ustar frank frank ssh-cron-1.01.00/ipcfunction/data.cc 0000644 0001750 0001750 00000000405 12605015302 016123 0 ustar frank frank #include "ipcfunction.ih"
LinearMap IPCFunction::s_nameMap =
{
{NONE, "NONE"},
{DONE, "DONE"},
{LIST, "LIST"},
{MORE, "MORE"},
{RELOAD, "RELOAD"},
{TERMINATE, "TERMINATE"}
};
ssh-cron-1.01.00/ipcfunction/ipcfunction.h 0000644 0001750 0001750 00000000747 12605015302 017406 0 ustar frank frank #ifndef INCLUDED_IPCFUNCTION_
#define INCLUDED_IPCFUNCTION_
#include
struct IPCFunction
{
enum Function: unsigned int
{
NONE,
DONE,
LIST,
MORE,
RELOAD,
TERMINATE
};
private:
static FBB::LinearMap s_nameMap;
public:
static char const *nameOf(Function fun);
};
inline char const *IPCFunction::nameOf(Function fun)
{
return s_nameMap[fun];
}
#endif
ssh-cron-1.01.00/ipcfunction/frame 0000644 0001750 0001750 00000000055 12605015302 015721 0 ustar frank frank #include "ipcfunction.ih"
IPCFunction::
{
}
ssh-cron-1.01.00/ipcfunction/ipcfunction.ih 0000644 0001750 0001750 00000000057 12605015302 017551 0 ustar frank frank #include "ipcfunction.h"
using namespace FBB;
ssh-cron-1.01.00/main.cc 0000644 0001750 0001750 00000003220 12633532015 013621 0 ustar frank frank #include "main.ih"
// Room for Args initialization
namespace // the anonymous namespace can be used here
{
Arg::LongOption longOptions[] =
{
// only interpreted from the command-line
Arg::LongOption("help", 'h'),
Arg::LongOption("version", 'v'),
Arg::LongOption("list", 'l'),
Arg::LongOption("no-daemon", Arg::None),
Arg::LongOption("reload", 'r'),
Arg::LongOption("stdout", 's'),
Arg::LongOption("terminate", 't'),
Arg::LongOption("config", 'c'),
Arg::LongOption("forced", 'f'),
// all options below are also interpreted when specified by
// the config file
Arg::LongOption("agent", Arg::Required),
Arg::LongOption("ipc-file", 'i'),
Arg::LongOption("log", 'L'),
Arg::LongOption("mailer", 'm'),
Arg::LongOption("syslog", Arg::None),
Arg::LongOption("syslog-facility", Arg::Required),
Arg::LongOption("syslog-priority", Arg::Required),
Arg::LongOption("syslog-tag", Arg::Required),
Arg::LongOption("verbose", Arg::None),
};
auto longEnd = longOptions + sizeof(longOptions) / sizeof(longOptions[0]);
}
int main(int argc, char **argv)
try
{
ArgConfig &arg = ArgConfig::initialize("c:fhi:lL:m:rstv",
longOptions, longEnd, argc, argv);
arg.versionHelp(Options::usage, Icmbuild::version, 0);
Daemon daemon;
daemon.run();
}
catch (exception const &exc)
{
if (exc.what() != to_string(fmsg.id()))
cerr << exc.what() << endl;
return 1;
}
catch (int x)
{
return ArgConfig::instance().option("hv") ? 0 : 1;
}
ssh-cron-1.01.00/main.ih 0000644 0001750 0001750 00000000502 12605015302 013626 0 ustar frank frank #include
#include
#include
#include
#include "daemon/daemon.h"
#include "options/options.h"
namespace Icmbuild
{
extern char version[];
extern char years[];
extern char author[];
};
using namespace std;
using namespace FBB;
using namespace Icmbuild;
ssh-cron-1.01.00/options/ 0000755 0001750 0001750 00000000000 12633537420 014071 5 ustar frank frank ssh-cron-1.01.00/options/options.h 0000644 0001750 0001750 00000006712 12633535626 015751 0 ustar frank frank #ifndef INCLUDED_OPTIONS_
#define INCLUDED_OPTIONS_
#include
#include
#include
#include
#include
#include
#include "../ipcfunction/ipcfunction.h"
namespace FBB
{
class SyslogStream;
}
class Options: public IPCFunction
{
FBB::ArgConfig &d_arg;
std::unique_ptr d_syslog;
FBB::Log d_log;
FBB::MultiStreambuf d_multiStreambuf;
std::ostream d_msg; // d_msg handles all messages to
// syslog and/or d_log
std::string d_agent;
std::string d_IPCfile;
std::string d_mailer;
FBB::LinearMap::const_iterator
d_syslogFacility;
FBB::LinearMap::const_iterator
d_syslogPriority;
bool d_foreground;
bool d_list;
bool d_reload;
bool d_terminate;
bool d_forced;
Function d_ipcFunction = NONE;
static Options *s_options;
static FBB::Facility s_defaultSyslogFacility;
static FBB::Priority s_defaultSyslogPriority;
static char const s_defaultAgent[];
static char const s_defaultConfigFile[];
static char const s_defaultIPCfile[];
static char const s_defaultSyslogIdent[];
static char const s_defaultMailer[];
static FBB::LinearMap const
s_syslogFacilities;
static FBB::LinearMap const
s_syslogPriorities;
public:
static Options &instance();
Options(Options const &other) = delete;
bool foreground() const;
bool daemon() const;
bool ipc() const;
bool cronfile() const;
bool reload() const;
bool forced() const;
Function ipcFunction() const;
std::string const &agent() const;
std::string const &basename() const;
std::string const &ipcFile() const;
std::string const &mailer() const;
std::ostream &msg();
static void usage(std::string const &progname);
private:
Options();
bool setSyslog();
void checkAction() const;
void loadConfigFile();
std::string syslogTag() const;
FBB::Priority syslogPriority() const;
FBB::Facility syslogFacility() const;
};
inline std::ostream &Options::msg()
{
return d_msg;
}
inline bool Options::foreground() const
{
return d_foreground;
}
inline bool Options::daemon() const
{
return not d_foreground;
}
inline bool Options::forced() const
{
return d_forced;
}
inline bool Options::reload() const
{
return d_reload;
}
inline bool Options::ipc() const
{
return d_list || d_terminate || d_reload;
}
inline bool Options::cronfile() const
{
return d_arg.nArgs();
}
inline IPCFunction::Function Options::ipcFunction() const
{
return d_ipcFunction;
}
inline std::string const &Options::agent() const
{
return d_agent;
}
inline std::string const &Options::basename() const
{
return d_arg.basename();
}
inline std::string const &Options::ipcFile() const
{
return d_IPCfile;
}
inline std::string const &Options::mailer() const
{
return d_mailer;
}
#endif
ssh-cron-1.01.00/options/instance.cc 0000644 0001750 0001750 00000000213 12605015302 016165 0 ustar frank frank #include "options.ih"
Options &Options::instance()
{
if (s_options == 0)
s_options = new Options();
return *s_options;
}
ssh-cron-1.01.00/options/usage.cc 0000644 0001750 0001750 00000007675 12633533320 015516 0 ustar frank frank // usage.cc
#include "options.ih"
void Options::usage(std::string const &progname)
{
cout << "\n" <<
progname << " by " << author << "\n" <<
progname << " V" << version << " " << years << "\n"
"\n"
"Usage: " << progname << " [options] [crontab]\n"
"Where:\n"
" [options] - optional arguments (short options between parentheses,\n"
" option descriptions starting with (C) can only be used\n"
" on the command-line and are ignored when specified in "
"the\n"
" configuration file (see also option --config):\n"
" --agent agent - absolute path to the agent program providing\n"
" the ssh-keys\n"
" (default `" << s_defaultAgent << "')\n"
" --config (-c) path - (C) config file containing long option "
"specifications\n"
" (default `$HOME/" <<
s_defaultConfigFile << ")`\n"
" --forced (-f) - (C) When restarting " << progname <<
" an existing\n"
" (leftover) ipc-file is removed\n"
" --help (-h) - (C) provide this help\n"
" --ipc-file (-i) path - `path' is the path name of the file\n"
" containing the info used for IPC\n"
" (default `$HOME/" << s_defaultIPCfile << "')\n"
" --list (-l) - list the currently defined cron-commands\n"
" (the `crontab' file is only used to specify "
"options)\n"
" --log (-L) path - log messages are appended to `path'. If "
"path\n"
" does not exist, it is created first\n"
" --mailer (-m) command - `command' is the command mailing the\n"
" output of executed commands (default\n"
" `" << s_defaultMailer << "'\n"
" --no-daemon - (C) do not run as a daemon\n"
" --reload (-r) - (C) reload a running " << progname <<
" daemon\n"
" with the specifications in the crontab-file\n"
" --stdout (-s) - (C) logged messages are also written to "
"stdout\n"
" (only in combination with --no-daemon)\n"
" --syslog - write syslog messages\n"
" --syslog-facility fac - fac: syslog facility to use\n"
" (default `" << s_defaultSyslogFacility << "')\n"
" --syslog-priority pri - pri: syslog priority to use\n"
" (default `" << s_defaultSyslogPriority << "')\n"
" --syslog-tag id - id: identifier prefixed to syslog "
"messages\n"
" (default `" << s_defaultSyslogIdent << "')\n"
" --terminate (-t) - (C) terminate a running " << progname <<
" program\n"
" (the `crontab' file is only used to specify "
"options)\n"
" --verbose - logs additional information. Implies "
"--syslog\n"
" --version (-v) - (C) show version information and terminate\n"
"\n"
" crontab - crontab-like file specifying crontab commands and\n"
" (optional) environment variable definitions\n"
"\n";
}
ssh-cron-1.01.00/options/options1.cc 0000644 0001750 0001750 00000003454 12633535712 016164 0 ustar frank frank #include "options.ih"
Options::Options()
:
d_arg(ArgConfig::instance()),
d_msg(&d_multiStreambuf)
{
// --help and --version already handled by versionHelp, but if nothing
// is requested on the command line help is also provided.
if (
d_arg.nArgs() == 0 && d_arg.nOptions() == 0 &&
d_arg.nLongOptions() == 0
)
{
usage(d_arg.basename());
throw 0;
}
d_foreground = d_arg.option(0, "no-daemon");
if ((d_list = d_arg.option('l')))
d_ipcFunction = LIST;
if ((d_reload = d_arg.option('r')))
d_ipcFunction = RELOAD;
if ((d_terminate = d_arg.option('t')))
d_ipcFunction = TERMINATE;
d_forced = d_arg.option('f');
checkAction();
if (d_arg.option('s'))
{
if (d_foreground)
d_multiStreambuf.insert(cout);
else
wmsg << "--stdout ignored: " << d_arg.basename() <<
" runs as a daemon process" << endl;
}
loadConfigFile();
if (not d_arg.option(&d_agent, "agent"))
d_agent = s_defaultAgent;
if (not d_arg.option(&d_IPCfile, 'i'))
d_IPCfile = User().homedir() + s_defaultIPCfile;
string logName;
if (d_arg.option(&logName, 'L'))
{
d_log.open(logName);
if (not d_log)
fmsg << "could not open " << logName << endl;
d_multiStreambuf.insert(d_log);
}
if (not d_arg.option(&d_mailer, 'm'))
d_mailer = s_defaultMailer;
bool useSyslog = setSyslog();
if (not d_arg.option(0, "verbose")) // verbose messages appear in the
imsg.off(); // logs
else if (useSyslog || not logName.empty())
imsg.reset(d_msg);
else
wmsg << "--verbose ignored: --syslog or --log not specified" << endl;
}
ssh-cron-1.01.00/options/syslogpriority.cc 0000644 0001750 0001750 00000001036 12605015302 017507 0 ustar frank frank #include "options.ih"
Priority Options::syslogPriority() const
{
Priority priority;
string option;
if (not d_arg.option(&option, "syslog-priority"))
priority = s_defaultSyslogPriority;
else
{
LinearMap::const_iterator
iter = s_syslogPriorities.find(option);
if (iter == s_syslogPriorities.end())
fmsg << "syslog priority " << option << " not supported" << endl;
priority = iter->second;
}
return priority;
}
ssh-cron-1.01.00/options/checkaction.cc 0000644 0001750 0001750 00000001673 12605015302 016647 0 ustar frank frank #include "options.ih"
void Options::checkAction() const
{
// only one of these options may be specified
if (d_list + d_reload + d_terminate + d_foreground > 1)
{
fmsg << "incompatible options:";
if (d_list)
fmsg << " --list";
if (d_reload)
fmsg << " --reload";
if (d_terminate)
fmsg << " --terminate";
if (d_foreground)
fmsg << " --no-daemon";
fmsg << endl;
}
// if no argument then --list or --terminate are required
if (d_arg.nArgs() == 0)
{
if (not (d_list || d_terminate))
fmsg << "crontab file required" << endl;
}
else if (d_list || d_terminate)
// --list and --terminate cannot accept a crontab file
fmsg << "crontab file incompatible with --list and --terminate" <<
endl;
}
ssh-cron-1.01.00/options/options.ih 0000644 0001750 0001750 00000000530 12605015302 016071 0 ustar frank frank #include "options.h"
#include
#include
#include
#include
#include
void usage(std::string const &progname);
namespace Icmbuild
{
extern char version[];
extern char years[];
extern char author[];
};
using namespace std;
using namespace FBB;
using namespace Icmbuild;
ssh-cron-1.01.00/options/syslogfacility.cc 0000644 0001750 0001750 00000001031 12605015302 017425 0 ustar frank frank #include "options.ih"
Facility Options::syslogFacility() const
{
Facility facility;
string option;
if (not d_arg.option(&option, "syslog-facility"))
facility = s_defaultSyslogFacility;
else
{
LinearMap::const_iterator
iter = s_syslogFacilities.find(option);
if (iter == s_syslogFacilities.end())
fmsg << "syslog facility " << option << " not supported" << endl;
facility = iter->second;
}
return facility;
}
ssh-cron-1.01.00/options/data.cc 0000644 0001750 0001750 00000002572 12605015302 015304 0 ustar frank frank #include "options.ih"
Options *Options::s_options = 0;
char const Options::s_defaultAgent[] = "/usr/bin/ssh-agent /bin/bash";
char const Options::s_defaultIPCfile[] = ".ssh-cron.ipc";
char const Options::s_defaultConfigFile[] = ".ssh-cron";
char const Options::s_defaultMailer[] =
"/usr/bin/mail -s \"Ssh-cron $*\" $USER@localhost";
char const Options::s_defaultSyslogIdent[] = "SSH-CRON";
Facility Options::s_defaultSyslogFacility = Facility::DAEMON;
Priority Options::s_defaultSyslogPriority = Priority::NOTICE;
LinearMap const Options::s_syslogFacilities =
{
{"DAEMON", Facility::DAEMON},
{"LOCAL0", Facility::LOCAL0},
{"LOCAL1", Facility::LOCAL1},
{"LOCAL2", Facility::LOCAL2},
{"LOCAL3", Facility::LOCAL3},
{"LOCAL4", Facility::LOCAL4},
{"LOCAL5", Facility::LOCAL5},
{"LOCAL6", Facility::LOCAL6},
{"LOCAL7", Facility::LOCAL7},
{"USER", Facility::USER}
};
LinearMap const Options::s_syslogPriorities =
{
{"EMERG", Priority::EMERG},
{"ALERT", Priority::ALERT},
{"CRIT", Priority::CRIT},
{"ERR", Priority::ERR},
{"WARNING", Priority::WARNING},
{"NOTICE", Priority::NOTICE},
{"INFO", Priority::INFO},
{"DEBUG", Priority::DEBUG}
};
ssh-cron-1.01.00/options/syslogtag.cc 0000644 0001750 0001750 00000000257 12605015302 016405 0 ustar frank frank #include "options.ih"
string Options::syslogTag() const
{
string tag;
if (not d_arg.option(&tag, "syslog-tag"))
tag = s_defaultSyslogIdent;
return tag;
}
ssh-cron-1.01.00/options/loadconfigfile.cc 0000644 0001750 0001750 00000000675 12605015302 017342 0 ustar frank frank #include "options.ih"
void Options::loadConfigFile()
{
string configFile;
if (not d_arg.option(&configFile, 'c'))
{
configFile = User().homedir() + s_defaultConfigFile;
if (access(configFile.c_str(), R_OK) != 0)
configFile.clear();
}
if (not configFile.empty())
d_arg.open(configFile); // read the arg config file, which is also
// the cron-file
}
ssh-cron-1.01.00/options/frame 0000644 0001750 0001750 00000000045 12605015302 015072 0 ustar frank frank #include "options.ih"
Options::
{
}
ssh-cron-1.01.00/options/setsyslog.cc 0000644 0001750 0001750 00000000510 12605015302 016415 0 ustar frank frank #include "options.ih"
bool Options::setSyslog()
{
if (not d_arg.option(0, "syslog"))
return false;
d_syslog.reset(
new SyslogStream(
syslogTag(), syslogPriority(), syslogFacility()
)
);
d_multiStreambuf.insert(*d_syslog);
return true;
}
ssh-cron-1.01.00/parser/ 0000755 0001750 0001750 00000000000 12633537420 013672 5 ustar frank frank ssh-cron-1.01.00/parser/parser.h 0000644 0001750 0001750 00000002076 12605015302 015331 0 ustar frank frank // Generated by Bisonc++ V4.08.00 on Fri, 09 May 2014 11:23:30 +0200
#ifndef Parser_h_included
#define Parser_h_included
// $insert baseclass
#include "parserbase.h"
// $insert scanner.h
#include "../scanner/scanner.h"
class CronData;
#undef Parser
class Parser: public ParserBase
{
CronData &d_cronData;
// $insert scannerobject
Scanner d_scanner;
public:
Parser(std::istream &in, CronData &cronData);
int parse();
private:
void addSet(std::set &lhs, std::set const &rhs) const;
void error(char const *msg); // called on (syntax) errors
int lex(); // returns the next token from the
// lexical scanner.
void print(); // use, e.g., d_token, d_loc
// support functions for parse():
void executeAction(int ruleNr);
void errorRecovery();
int lookup(bool recovery);
void nextToken();
void print__();
void exceptionHandler__(std::exception const &exc);
};
#endif
ssh-cron-1.01.00/parser/parserpre.ih 0000644 0001750 0001750 00000000043 12605015302 016201 0 ustar frank frank #include
#include
ssh-cron-1.01.00/parser/addset.cc 0000644 0001750 0001750 00000000200 12605015302 015422 0 ustar frank frank #include "parser.ih"
void Parser::addSet(set &lhs, set const &rhs) const
{
lhs.insert(rhs.begin(), rhs.end());
}
ssh-cron-1.01.00/parser/parser1.cc 0000644 0001750 0001750 00000000167 12605015302 015547 0 ustar frank frank #include "parser.ih"
Parser::Parser(istream &in, CronData &cronData)
:
d_cronData(cronData),
d_scanner(in)
{}
ssh-cron-1.01.00/parser/inc/ 0000755 0001750 0001750 00000000000 12605015302 014430 5 ustar frank frank ssh-cron-1.01.00/parser/inc/line 0000644 0001750 0001750 00000000523 12605015302 015302 0 ustar frank frank _line_contents:
nameLine // either an option or an environment var
|
cronLine // time specification + action
|
error
;
_line_preamble:
{
d_cronData.reset(d_scanner.lineNr());
}
;
_opt_line_contents:
_line_preamble _line_contents
|
// empty
;
line:
_opt_line_contents '\n'
;
ssh-cron-1.01.00/parser/inc/cronline 0000644 0001750 0001750 00000001207 12605015302 016164 0 ustar frank frank _minutes:
time_numberedSpec
WS
{
d_cronData.setMinutes();
}
;
_hours:
time_numberedSpec
WS
{
d_cronData.setHours();
}
;
_dayOfMonth:
time_numberedSpec
WS
{
d_cronData.setDayOfMonth();
}
;
_monthOfYear:
time_spec
WS
{
d_cronData.setMonthOfYear();
}
;
_dayOfWeek:
time_spec
WS
{
d_cronData.setDayOfWeek();
}
;
_command:
token_noWs
opt_tokens
{
d_cronData.setCommand($1 + $2);
}
;
cronLine:
_minutes _hours _dayOfMonth _monthOfYear _dayOfWeek _command
{
d_cronData.process();
}
;
ssh-cron-1.01.00/parser/inc/ws 0000644 0001750 0001750 00000000041 12605015302 014777 0 ustar frank frank opt_ws:
WS
|
// empty
;
ssh-cron-1.01.00/parser/inc/time 0000644 0001750 0001750 00000000710 12605015302 015307 0 ustar frank frank _all:
'*' opt_nr_step // empty set indicates `all valid specifications
{
d_cronData.setAll($2);
}
;
_timeUnit:
nr_range
|
ID
{
d_cronData.addName(d_scanner.matched());
}
;
_timeSequence:
_timeSequence ',' _timeUnit
|
_timeUnit
;
//------------------------------------------------------------------
time_numberedSpec:
_all
|
nr_Sequence
;
time_spec:
_all
|
_timeSequence
;
ssh-cron-1.01.00/parser/inc/nr 0000644 0001750 0001750 00000000610 12605015302 014767 0 ustar frank frank nr:
NR
{
$$ = stol(d_scanner.matched());
}
;
opt_nr_step:
// empty
{
$$ = 1;
}
|
'/' nr
{
$$ = $2;
}
;
nr_add:
nr
{
d_cronData.addNr($1);
}
;
nr_range:
nr '-' nr opt_nr_step
{
d_cronData.addRange($1, $3, $4);
}
|
nr_add
;
nr_Sequence:
nr_Sequence ',' nr_range
|
nr_range
;
ssh-cron-1.01.00/parser/inc/token 0000644 0001750 0001750 00000001042 12605015302 015470 0 ustar frank frank _tokenNoWs:
NR
|
ID
|
'*'
|
'/'
|
','
|
'-'
|
CHAR
|
'='
;
_tokenAny:
WS
|
_tokenNoWs
;
_tokenMatched:
{
$$ = d_scanner.matched();
}
;
_tokenAnyMatched:
_tokenAny
_tokenMatched
{
$$ = $2;
}
;
token_noWs:
_tokenNoWs
_tokenMatched
{
$$ =$2;
}
;
tokens:
tokens _tokenAny
{
$$ += d_scanner.matched();
}
|
_tokenAnyMatched
{
$$ = $$;
}
;
opt_tokens:
tokens
|
{
$$ = string();
}
;
ssh-cron-1.01.00/parser/inc/nameline 0000644 0001750 0001750 00000000557 12605015302 016152 0 ustar frank frank // OK input is:
//
// ID = whatever
// the blanks around the = are optional and will be removed
_nameContents:
opt_ws '=' opt_tokens // ID =(contents-to-be-stripped)?
{
$$ = $3;
}
;
_nameID:
ID
{
$$ = d_scanner.matched();
}
;
nameLine:
_nameID _nameContents
{
d_cronData.setEnvVar($1, $2);
}
;
ssh-cron-1.01.00/parser/error.cc 0000644 0001750 0001750 00000000213 12605015302 015313 0 ustar frank frank #include "parser.ih"
void Parser::error(char const *msg)
{
emsg << msg << " at line " << d_cronData.lineNr() <<
endl;
}
ssh-cron-1.01.00/parser/grammar 0000644 0001750 0001750 00000000754 12605015302 015236 0 ustar frank frank %filenames parser
%scanner ../scanner/scanner.h
%baseclass-preinclude parserpre.ih
%polymorphic STRING: std::string; INT: int
%token WS NR ID CHAR
%type opt_tokens tokens token_noWs _tokenAnyMatched _tokenMatched
_nameContents _nameID nameLine
%type nr opt_nr_step
%%
startrule:
startrule line
|
// empty
;
%include inc/nr
%include inc/ws
%include inc/token
%include inc/nameline
%include inc/time
%include inc/cronline
%include inc/line
ssh-cron-1.01.00/parser/parserbase.h 0000644 0001750 0001750 00000016526 12605015302 016171 0 ustar frank frank // Generated by Bisonc++ V4.09.01 on Thu, 15 May 2014 09:30:55 +0200
#ifndef ParserBase_h_included
#define ParserBase_h_included
#include
#include
#include
// $insert preincludes
#include
#include "parserpre.ih"
namespace // anonymous
{
struct PI__;
}
// $insert polymorphic
enum class Tag__
{
INT,
STRING,
};
namespace Meta__
{
template
struct TypeOf;
template
struct TagOf;
// $insert polymorphicSpecializations
template <>
struct TagOf
{
static Tag__ const tag = Tag__::INT;
};
template <>
struct TagOf
{
static Tag__ const tag = Tag__::STRING;
};
template <>
struct TypeOf
{
typedef int type;
};
template <>
struct TypeOf
{
typedef std::string type;
};
// The Base class:
// Individual semantic value classes are derived from this class.
// This class offers a member returning the value's Tag__
// and two member templates get() offering const/non-const access to
// the actual semantic value type.
class Base
{
Tag__ d_tag;
protected:
Base(Tag__ tag);
public:
Base(Base const &other) = delete;
Tag__ tag() const;
template
typename TypeOf::type &get();
};
// The class Semantic is derived from Base. It stores a particular
// semantic value type.
template
class Semantic: public Base
{
typedef typename TypeOf::type DataType;
DataType d_data;
public:
// The default constructor and constructors for
// defined data types are available
Semantic();
Semantic(DataType const &data);
Semantic(DataType &&tmp);
DataType &data();
};
// The class Stype wraps the shared_ptr holding a pointer to Base.
// It becomes the polymorphic STYPE__
// It also wraps Base's get members, allowing constructions like
// $$.get to be used, rather than $$->get.
// Its operator= can be used to assign a Semantic *
// directly to the SType object. The free functions (in the parser's
// namespace (if defined)) semantic__ can be used to obtain a
// Semantic *.
struct SType: public std::shared_ptr
{
template
SType &operator=(Tp_ &&value);
Tag__ tag() const;
// this get()-member checks for 0-pointer and correct tag
// in shared_ptr, and resets the shared_ptr's Base *
// to point to Meta::__Semantic() if not
template
typename TypeOf::type &get();
// the data()-member does not check, and may result in a
// segfault if used incorrectly
template
typename TypeOf::type &data();
};
} // namespace Meta__
class ParserBase
{
public:
// $insert tokens
// Symbolic tokens:
enum Tokens__
{
WS = 257,
NR,
ID,
CHAR,
};
// $insert STYPE
typedef Meta__::SType STYPE__;
private:
int d_stackIdx__;
std::vector d_stateStack__;
std::vector d_valueStack__;
protected:
enum Return__
{
PARSE_ACCEPT__ = 0, // values used as parse()'s return values
PARSE_ABORT__ = 1
};
enum ErrorRecovery__
{
DEFAULT_RECOVERY_MODE__,
UNEXPECTED_TOKEN__,
};
bool d_debug__;
size_t d_nErrors__;
size_t d_requiredTokens__;
size_t d_acceptedTokens__;
int d_token__;
int d_nextToken__;
size_t d_state__;
STYPE__ *d_vsp__;
STYPE__ d_val__;
STYPE__ d_nextVal__;
ParserBase();
void ABORT() const;
void ACCEPT() const;
void ERROR() const;
void clearin();
bool debug() const;
void pop__(size_t count = 1);
void push__(size_t nextState);
void popToken__();
void pushToken__(int token);
void reduce__(PI__ const &productionInfo);
void errorVerbose__();
size_t top__() const;
public:
void setDebug(bool mode);
};
inline bool ParserBase::debug() const
{
return d_debug__;
}
inline void ParserBase::setDebug(bool mode)
{
d_debug__ = mode;
}
inline void ParserBase::ABORT() const
{
throw PARSE_ABORT__;
}
inline void ParserBase::ACCEPT() const
{
throw PARSE_ACCEPT__;
}
inline void ParserBase::ERROR() const
{
throw UNEXPECTED_TOKEN__;
}
// $insert polymorphicInline
namespace Meta__
{
inline Base::Base(Tag__ tag)
:
d_tag(tag)
{}
inline Tag__ Base::tag() const
{
return d_tag;
}
template
inline Semantic::Semantic()
:
Base(tg_),
d_data(typename TypeOf::type())
{}
template
inline Semantic::Semantic(typename TypeOf::type const &data)
:
Base(tg_),
d_data(data)
{}
template
inline Semantic::Semantic(typename TypeOf::type &&tmp)
:
Base(tg_),
d_data(std::move(tmp))
{}
template
inline typename TypeOf::type &Semantic::data()
{
return d_data;
}
template
inline typename TypeOf::type &Base::get()
{
return static_cast *>(this)->data();
}
inline Tag__ SType::tag() const
{
return std::shared_ptr::get()->tag();
}
template
inline typename TypeOf::type &SType::get()
{
// if we're not yet holding a (tg_) value, initialize to
// a Semantic holding a default value
if (std::shared_ptr::get() == 0 || tag() != tg_)
reset(new Semantic());
return std::shared_ptr::get()->get();
}
template
inline typename TypeOf::type &SType::data()
{
return std::shared_ptr::get()->get();
}
template
struct Assign;
template
struct Assign
{
static SType &assign(SType *lhs, Tp_ &&tp);
};
template
struct Assign
{
static SType &assign(SType *lhs, Tp_ const &tp);
};
template <>
struct Assign
{
static SType &assign(SType *lhs, SType const &tp);
};
template
inline SType &Assign::assign(SType *lhs, Tp_ &&tp)
{
lhs->reset(new Semantic::tag>(std::move(tp)));
return *lhs;
}
template
inline SType &Assign::assign(SType *lhs, Tp_ const &tp)
{
lhs->reset(new Semantic::tag>(tp));
return *lhs;
}
inline SType &Assign::assign(SType *lhs, SType const &tp)
{
return lhs->operator=(tp);
}
template
inline SType &SType::operator=(Tp_ &&rhs)
{
return Assign<
std::is_rvalue_reference::value,
typename std::remove_reference::type
>::assign(this, std::forward(rhs));
}
} // namespace Meta__
// As a convenience, when including ParserBase.h its symbols are available as
// symbols in the class Parser, too.
#define Parser ParserBase
#endif
ssh-cron-1.01.00/parser/parser.ih 0000644 0001750 0001750 00000001650 12605015302 015477 0 ustar frank frank // Generated by Bisonc++ V4.08.00 on Fri, 09 May 2014 11:23:30 +0200
// Include this file in the sources of the class Parser.
// $insert class.h
#include "parser.h"
#include
#include
#include "../options/options.h"
#include "../crondata/crondata.h"
// $insert lex
inline int Parser::lex()
{
return d_scanner.lex();
}
inline void Parser::print()
{
print__(); // displays tokens if --print was specified
}
inline void Parser::exceptionHandler__(std::exception const &exc)
{
throw; // re-implement to handle exceptions thrown by actions
}
// Add here includes that are only required for the compilation
// of Parser's sources.
// UN-comment the next using-declaration if you want to use
// int Parser's sources symbols from the namespace std without
// specifying std::
using namespace std;
using namespace FBB;
ssh-cron-1.01.00/parser/parse.cc 0000644 0001750 0001750 00000102602 12605015302 015301 0 ustar frank frank // Generated by Bisonc++ V4.09.01 on Thu, 15 May 2014 09:30:55 +0200
// $insert class.ih
#include "parser.ih"
// The FIRST element of SR arrays shown below uses `d_type', defining the
// state's type, and `d_lastIdx' containing the last element's index. If
// d_lastIdx contains the REQ_TOKEN bitflag (see below) then the state needs
// a token: if in this state d_token__ is _UNDETERMINED_, nextToken() will be
// called
// The LAST element of SR arrays uses `d_token' containing the last retrieved
// token to speed up the (linear) seach. Except for the first element of SR
// arrays, the field `d_action' is used to determine what to do next. If
// positive, it represents the next state (used with SHIFT); if zero, it
// indicates `ACCEPT', if negative, -d_action represents the number of the
// rule to reduce to.
// `lookup()' tries to find d_token__ in the current SR array. If it fails, and
// there is no default reduction UNEXPECTED_TOKEN__ is thrown, which is then
// caught by the error-recovery function.
// The error-recovery function will pop elements off the stack until a state
// having bit flag ERR_ITEM is found. This state has a transition on _error_
// which is applied. In this _error_ state, while the current token is not a
// proper continuation, new tokens are obtained by nextToken(). If such a
// token is found, error recovery is successful and the token is
// handled according to the error state's SR table and parsing continues.
// During error recovery semantic actions are ignored.
// A state flagged with the DEF_RED flag will perform a default
// reduction if no other continuations are available for the current token.
// The ACCEPT STATE never shows a default reduction: when it is reached the
// parser returns ACCEPT(). During the grammar
// analysis phase a default reduction may have been defined, but it is
// removed during the state-definition phase.
// So:
// s_x[] =
// {
// [_field_1_] [_field_2_]
//
// First element: {state-type, idx of last element},
// Other elements: {required token, action to perform},
// ( < 0: reduce,
// 0: ACCEPT,
// > 0: next state)
// Last element: {set to d_token__, action to perform}
// }
// When the --thread-safe option is specified, all static data are defined as
// const. If --thread-safe is not provided, the state-tables are not defined
// as const, since the lookup() function below will modify them
namespace // anonymous
{
char const author[] = "Frank B. Brokken (f.b.brokken@rug.nl)";
enum
{
STACK_EXPANSION = 5 // size to expand the state-stack with when
// full
};
enum ReservedTokens
{
PARSE_ACCEPT = 0, // `ACCEPT' TRANSITION
_UNDETERMINED_ = -2,
_EOF_ = -1,
_error_ = 256
};
enum StateType // modify statetype/data.cc when this enum changes
{
NORMAL,
ERR_ITEM,
REQ_TOKEN,
ERR_REQ, // ERR_ITEM | REQ_TOKEN
DEF_RED, // state having default reduction
ERR_DEF, // ERR_ITEM | DEF_RED
REQ_DEF, // REQ_TOKEN | DEF_RED
ERR_REQ_DEF // ERR_ITEM | REQ_TOKEN | DEF_RED
};
struct PI__ // Production Info
{
size_t d_nonTerm; // identification number of this production's
// non-terminal
size_t d_size; // number of elements in this production
};
struct SR__ // Shift Reduce info, see its description above
{
union
{
int _field_1_; // initializer, allowing initializations
// of the SR s_[] arrays
int d_type;
int d_token;
};
union
{
int _field_2_;
int d_lastIdx; // if negative, the state uses SHIFT
int d_action; // may be negative (reduce),
// postive (shift), or 0 (accept)
size_t d_errorState; // used with Error states
};
};
// $insert staticdata
// Productions Info Records:
PI__ const s_productionInfo[] =
{
{0, 0}, // not used: reduction values are negative
{271, 2}, // 1: startrule -> startrule line
{271, 0}, // 2: startrule ->
{273, 1}, // 3: nr (NR) -> NR
{274, 0}, // 4: opt_nr_step ->
{274, 2}, // 5: opt_nr_step ('/') -> '/' nr
{275, 1}, // 6: nr_add -> nr
{276, 4}, // 7: nr_range ('-') -> nr '-' nr opt_nr_step
{276, 1}, // 8: nr_range -> nr_add
{277, 3}, // 9: nr_Sequence (',') -> nr_Sequence ',' nr_range
{277, 1}, // 10: nr_Sequence -> nr_range
{278, 1}, // 11: opt_ws (WS) -> WS
{278, 0}, // 12: opt_ws ->
{279, 1}, // 13: _tokenNoWs (NR) -> NR
{279, 1}, // 14: _tokenNoWs (ID) -> ID
{279, 1}, // 15: _tokenNoWs ('*') -> '*'
{279, 1}, // 16: _tokenNoWs ('/') -> '/'
{279, 1}, // 17: _tokenNoWs (',') -> ','
{279, 1}, // 18: _tokenNoWs ('-') -> '-'
{279, 1}, // 19: _tokenNoWs (CHAR) -> CHAR
{279, 1}, // 20: _tokenNoWs ('=') -> '='
{280, 1}, // 21: _tokenAny (WS) -> WS
{280, 1}, // 22: _tokenAny -> _tokenNoWs
{281, 0}, // 23: _tokenMatched ->
{282, 2}, // 24: _tokenAnyMatched -> _tokenAny _tokenMatched
{283, 2}, // 25: token_noWs -> _tokenNoWs _tokenMatched
{284, 2}, // 26: tokens -> tokens _tokenAny
{284, 1}, // 27: tokens -> _tokenAnyMatched
{285, 1}, // 28: opt_tokens -> tokens
{285, 0}, // 29: opt_tokens ->
{286, 3}, // 30: _nameContents ('=') -> opt_ws '=' opt_tokens
{287, 1}, // 31: _nameID (ID) -> ID
{288, 2}, // 32: nameLine -> _nameID _nameContents
{289, 2}, // 33: _all ('*') -> '*' opt_nr_step
{290, 1}, // 34: _timeUnit -> nr_range
{290, 1}, // 35: _timeUnit (ID) -> ID
{291, 3}, // 36: _timeSequence (',') -> _timeSequence ',' _timeUnit
{291, 1}, // 37: _timeSequence -> _timeUnit
{292, 1}, // 38: time_numberedSpec -> _all
{292, 1}, // 39: time_numberedSpec -> nr_Sequence
{293, 1}, // 40: time_spec -> _all
{293, 1}, // 41: time_spec -> _timeSequence
{294, 2}, // 42: _minutes (WS) -> time_numberedSpec WS
{295, 2}, // 43: _hours (WS) -> time_numberedSpec WS
{296, 2}, // 44: _dayOfMonth (WS) -> time_numberedSpec WS
{297, 2}, // 45: _monthOfYear (WS) -> time_spec WS
{298, 2}, // 46: _dayOfWeek (WS) -> time_spec WS
{299, 2}, // 47: _command -> token_noWs opt_tokens
{300, 6}, // 48: cronLine -> _minutes _hours _dayOfMonth _monthOfYear _dayOfWeek _command
{301, 1}, // 49: _line_contents -> nameLine
{301, 1}, // 50: _line_contents -> cronLine
{301, 1}, // 51: _line_contents (_error_) -> _error_
{302, 0}, // 52: _line_preamble ->
{303, 2}, // 53: _opt_line_contents -> _line_preamble _line_contents
{303, 0}, // 54: _opt_line_contents ->
{272, 2}, // 55: line ('\x0a') -> _opt_line_contents '\x0a'
{304, 1}, // 56: startrule_$ -> startrule
};
// State info and SR__ transitions for each state.
SR__ s_0[] =
{
{ { DEF_RED}, { 2} },
{ { 271}, { 1} }, // startrule
{ { 0}, { -2} },
};
SR__ s_1[] =
{
{ { REQ_DEF}, { 6} },
{ { 272}, { 2} }, // line
{ { 303}, { 3} }, // _opt_line_contents
{ { 302}, { 4} }, // _line_preamble
{ { _EOF_}, { PARSE_ACCEPT} },
{ { 10}, { -54} }, // '\x0a'
{ { 0}, { -52} },
};
SR__ s_2[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -1} },
};
SR__ s_3[] =
{
{ { REQ_TOKEN}, { 2} },
{ { 10}, { 5} }, // '\x0a'
{ { 0}, { 0} },
};
SR__ s_4[] =
{
{ { ERR_REQ}, { 16} },
{ { 301}, { 6} }, // _line_contents
{ { 288}, { 7} }, // nameLine
{ { 300}, { 8} }, // cronLine
{ { _error_}, { 9} }, // _error_
{ { 287}, { 10} }, // _nameID
{ { 294}, { 11} }, // _minutes
{ { 259}, { 12} }, // ID
{ { 292}, { 13} }, // time_numberedSpec
{ { 289}, { 14} }, // _all
{ { 277}, { 15} }, // nr_Sequence
{ { 42}, { 16} }, // '*'
{ { 276}, { 17} }, // nr_range
{ { 273}, { 18} }, // nr
{ { 275}, { 19} }, // nr_add
{ { 258}, { 20} }, // NR
{ { 0}, { 0} },
};
SR__ s_5[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -55} },
};
SR__ s_6[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -53} },
};
SR__ s_7[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -49} },
};
SR__ s_8[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -50} },
};
SR__ s_9[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -51} },
};
SR__ s_10[] =
{
{ { REQ_DEF}, { 4} },
{ { 286}, { 21} }, // _nameContents
{ { 278}, { 22} }, // opt_ws
{ { 257}, { 23} }, // WS
{ { 0}, { -12} },
};
SR__ s_11[] =
{
{ { REQ_TOKEN}, { 10} },
{ { 295}, { 24} }, // _hours
{ { 292}, { 25} }, // time_numberedSpec
{ { 289}, { 14} }, // _all
{ { 277}, { 15} }, // nr_Sequence
{ { 42}, { 16} }, // '*'
{ { 276}, { 17} }, // nr_range
{ { 273}, { 18} }, // nr
{ { 275}, { 19} }, // nr_add
{ { 258}, { 20} }, // NR
{ { 0}, { 0} },
};
SR__ s_12[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -31} },
};
SR__ s_13[] =
{
{ { REQ_TOKEN}, { 2} },
{ { 257}, { 26} }, // WS
{ { 0}, { 0} },
};
SR__ s_14[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -38} },
};
SR__ s_15[] =
{
{ { REQ_DEF}, { 2} },
{ { 44}, { 27} }, // ','
{ { 0}, { -39} },
};
SR__ s_16[] =
{
{ { REQ_DEF}, { 3} },
{ { 274}, { 28} }, // opt_nr_step
{ { 47}, { 29} }, // '/'
{ { 0}, { -4} },
};
SR__ s_17[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -10} },
};
SR__ s_18[] =
{
{ { REQ_DEF}, { 2} },
{ { 45}, { 30} }, // '-'
{ { 0}, { -6} },
};
SR__ s_19[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -8} },
};
SR__ s_20[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -3} },
};
SR__ s_21[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -32} },
};
SR__ s_22[] =
{
{ { REQ_TOKEN}, { 2} },
{ { 61}, { 31} }, // '='
{ { 0}, { 0} },
};
SR__ s_23[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -11} },
};
SR__ s_24[] =
{
{ { REQ_TOKEN}, { 10} },
{ { 296}, { 32} }, // _dayOfMonth
{ { 292}, { 33} }, // time_numberedSpec
{ { 289}, { 14} }, // _all
{ { 277}, { 15} }, // nr_Sequence
{ { 42}, { 16} }, // '*'
{ { 276}, { 17} }, // nr_range
{ { 273}, { 18} }, // nr
{ { 275}, { 19} }, // nr_add
{ { 258}, { 20} }, // NR
{ { 0}, { 0} },
};
SR__ s_25[] =
{
{ { REQ_TOKEN}, { 2} },
{ { 257}, { 34} }, // WS
{ { 0}, { 0} },
};
SR__ s_26[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -42} },
};
SR__ s_27[] =
{
{ { REQ_TOKEN}, { 5} },
{ { 276}, { 35} }, // nr_range
{ { 273}, { 18} }, // nr
{ { 275}, { 19} }, // nr_add
{ { 258}, { 20} }, // NR
{ { 0}, { 0} },
};
SR__ s_28[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -33} },
};
SR__ s_29[] =
{
{ { REQ_TOKEN}, { 3} },
{ { 273}, { 36} }, // nr
{ { 258}, { 20} }, // NR
{ { 0}, { 0} },
};
SR__ s_30[] =
{
{ { REQ_TOKEN}, { 3} },
{ { 273}, { 37} }, // nr
{ { 258}, { 20} }, // NR
{ { 0}, { 0} },
};
SR__ s_31[] =
{
{ { REQ_DEF}, { 15} },
{ { 285}, { 38} }, // opt_tokens
{ { 284}, { 39} }, // tokens
{ { 282}, { 40} }, // _tokenAnyMatched
{ { 280}, { 41} }, // _tokenAny
{ { 257}, { 42} }, // WS
{ { 279}, { 43} }, // _tokenNoWs
{ { 258}, { 44} }, // NR
{ { 259}, { 45} }, // ID
{ { 42}, { 46} }, // '*'
{ { 47}, { 47} }, // '/'
{ { 44}, { 48} }, // ','
{ { 45}, { 49} }, // '-'
{ { 260}, { 50} }, // CHAR
{ { 61}, { 51} }, // '='
{ { 0}, { -29} },
};
SR__ s_32[] =
{
{ { REQ_TOKEN}, { 12} },
{ { 297}, { 52} }, // _monthOfYear
{ { 293}, { 53} }, // time_spec
{ { 289}, { 54} }, // _all
{ { 291}, { 55} }, // _timeSequence
{ { 42}, { 16} }, // '*'
{ { 290}, { 56} }, // _timeUnit
{ { 276}, { 57} }, // nr_range
{ { 259}, { 58} }, // ID
{ { 273}, { 18} }, // nr
{ { 275}, { 19} }, // nr_add
{ { 258}, { 20} }, // NR
{ { 0}, { 0} },
};
SR__ s_33[] =
{
{ { REQ_TOKEN}, { 2} },
{ { 257}, { 59} }, // WS
{ { 0}, { 0} },
};
SR__ s_34[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -43} },
};
SR__ s_35[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -9} },
};
SR__ s_36[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -5} },
};
SR__ s_37[] =
{
{ { REQ_DEF}, { 3} },
{ { 274}, { 60} }, // opt_nr_step
{ { 47}, { 29} }, // '/'
{ { 0}, { -4} },
};
SR__ s_38[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -30} },
};
SR__ s_39[] =
{
{ { REQ_DEF}, { 12} },
{ { 280}, { 61} }, // _tokenAny
{ { 257}, { 42} }, // WS
{ { 279}, { 43} }, // _tokenNoWs
{ { 258}, { 44} }, // NR
{ { 259}, { 45} }, // ID
{ { 42}, { 46} }, // '*'
{ { 47}, { 47} }, // '/'
{ { 44}, { 48} }, // ','
{ { 45}, { 49} }, // '-'
{ { 260}, { 50} }, // CHAR
{ { 61}, { 51} }, // '='
{ { 0}, { -28} },
};
SR__ s_40[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -27} },
};
SR__ s_41[] =
{
{ { DEF_RED}, { 2} },
{ { 281}, { 62} }, // _tokenMatched
{ { 0}, { -23} },
};
SR__ s_42[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -21} },
};
SR__ s_43[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -22} },
};
SR__ s_44[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -13} },
};
SR__ s_45[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -14} },
};
SR__ s_46[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -15} },
};
SR__ s_47[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -16} },
};
SR__ s_48[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -17} },
};
SR__ s_49[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -18} },
};
SR__ s_50[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -19} },
};
SR__ s_51[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -20} },
};
SR__ s_52[] =
{
{ { REQ_TOKEN}, { 12} },
{ { 298}, { 63} }, // _dayOfWeek
{ { 293}, { 64} }, // time_spec
{ { 289}, { 54} }, // _all
{ { 291}, { 55} }, // _timeSequence
{ { 42}, { 16} }, // '*'
{ { 290}, { 56} }, // _timeUnit
{ { 276}, { 57} }, // nr_range
{ { 259}, { 58} }, // ID
{ { 273}, { 18} }, // nr
{ { 275}, { 19} }, // nr_add
{ { 258}, { 20} }, // NR
{ { 0}, { 0} },
};
SR__ s_53[] =
{
{ { REQ_TOKEN}, { 2} },
{ { 257}, { 65} }, // WS
{ { 0}, { 0} },
};
SR__ s_54[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -40} },
};
SR__ s_55[] =
{
{ { REQ_DEF}, { 2} },
{ { 44}, { 66} }, // ','
{ { 0}, { -41} },
};
SR__ s_56[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -37} },
};
SR__ s_57[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -34} },
};
SR__ s_58[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -35} },
};
SR__ s_59[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -44} },
};
SR__ s_60[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -7} },
};
SR__ s_61[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -26} },
};
SR__ s_62[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -24} },
};
SR__ s_63[] =
{
{ { REQ_TOKEN}, { 12} },
{ { 299}, { 67} }, // _command
{ { 283}, { 68} }, // token_noWs
{ { 279}, { 69} }, // _tokenNoWs
{ { 258}, { 44} }, // NR
{ { 259}, { 45} }, // ID
{ { 42}, { 46} }, // '*'
{ { 47}, { 47} }, // '/'
{ { 44}, { 48} }, // ','
{ { 45}, { 49} }, // '-'
{ { 260}, { 50} }, // CHAR
{ { 61}, { 51} }, // '='
{ { 0}, { 0} },
};
SR__ s_64[] =
{
{ { REQ_TOKEN}, { 2} },
{ { 257}, { 70} }, // WS
{ { 0}, { 0} },
};
SR__ s_65[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -45} },
};
SR__ s_66[] =
{
{ { REQ_TOKEN}, { 7} },
{ { 290}, { 71} }, // _timeUnit
{ { 276}, { 57} }, // nr_range
{ { 259}, { 58} }, // ID
{ { 273}, { 18} }, // nr
{ { 275}, { 19} }, // nr_add
{ { 258}, { 20} }, // NR
{ { 0}, { 0} },
};
SR__ s_67[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -48} },
};
SR__ s_68[] =
{
{ { REQ_DEF}, { 15} },
{ { 285}, { 72} }, // opt_tokens
{ { 284}, { 39} }, // tokens
{ { 282}, { 40} }, // _tokenAnyMatched
{ { 280}, { 41} }, // _tokenAny
{ { 257}, { 42} }, // WS
{ { 279}, { 43} }, // _tokenNoWs
{ { 258}, { 44} }, // NR
{ { 259}, { 45} }, // ID
{ { 42}, { 46} }, // '*'
{ { 47}, { 47} }, // '/'
{ { 44}, { 48} }, // ','
{ { 45}, { 49} }, // '-'
{ { 260}, { 50} }, // CHAR
{ { 61}, { 51} }, // '='
{ { 0}, { -29} },
};
SR__ s_69[] =
{
{ { DEF_RED}, { 2} },
{ { 281}, { 73} }, // _tokenMatched
{ { 0}, { -23} },
};
SR__ s_70[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -46} },
};
SR__ s_71[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -36} },
};
SR__ s_72[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -47} },
};
SR__ s_73[] =
{
{ { DEF_RED}, { 1} },
{ { 0}, { -25} },
};
// State array:
SR__ *s_state[] =
{
s_0, s_1, s_2, s_3, s_4, s_5, s_6, s_7, s_8, s_9,
s_10, s_11, s_12, s_13, s_14, s_15, s_16, s_17, s_18, s_19,
s_20, s_21, s_22, s_23, s_24, s_25, s_26, s_27, s_28, s_29,
s_30, s_31, s_32, s_33, s_34, s_35, s_36, s_37, s_38, s_39,
s_40, s_41, s_42, s_43, s_44, s_45, s_46, s_47, s_48, s_49,
s_50, s_51, s_52, s_53, s_54, s_55, s_56, s_57, s_58, s_59,
s_60, s_61, s_62, s_63, s_64, s_65, s_66, s_67, s_68, s_69,
s_70, s_71, s_72, s_73,
};
} // anonymous namespace ends
// If the parsing function call uses arguments, then provide an overloaded
// function. The code below doesn't rely on parameters, so no arguments are
// required. Furthermore, parse uses a function try block to allow us to do
// ACCEPT and ABORT from anywhere, even from within members called by actions,
// simply throwing the appropriate exceptions.
ParserBase::ParserBase()
:
d_stackIdx__(-1),
// $insert debuginit
d_debug__(false),
d_nErrors__(0),
// $insert requiredtokens
d_requiredTokens__(0),
d_acceptedTokens__(d_requiredTokens__),
d_token__(_UNDETERMINED_),
d_nextToken__(_UNDETERMINED_)
{}
void Parser::print__()
{
// $insert print
}
void ParserBase::clearin()
{
d_token__ = d_nextToken__ = _UNDETERMINED_;
}
void ParserBase::push__(size_t state)
{
if (static_cast(d_stackIdx__ + 1) == d_stateStack__.size())
{
size_t newSize = d_stackIdx__ + STACK_EXPANSION;
d_stateStack__.resize(newSize);
d_valueStack__.resize(newSize);
}
++d_stackIdx__;
d_stateStack__[d_stackIdx__] = d_state__ = state;
*(d_vsp__ = &d_valueStack__[d_stackIdx__]) = d_val__;
}
void ParserBase::popToken__()
{
d_token__ = d_nextToken__;
d_val__ = d_nextVal__;
d_nextVal__ = STYPE__();
d_nextToken__ = _UNDETERMINED_;
}
void ParserBase::pushToken__(int token)
{
d_nextToken__ = d_token__;
d_nextVal__ = d_val__;
d_token__ = token;
}
void ParserBase::pop__(size_t count)
{
if (d_stackIdx__ < static_cast(count))
{
ABORT();
}
d_stackIdx__ -= count;
d_state__ = d_stateStack__[d_stackIdx__];
d_vsp__ = &d_valueStack__[d_stackIdx__];
}
inline size_t ParserBase::top__() const
{
return d_stateStack__[d_stackIdx__];
}
void Parser::executeAction(int production)
try
{
if (d_token__ != _UNDETERMINED_)
pushToken__(d_token__); // save an already available token
// save default non-nested block $$
if (int size = s_productionInfo[production].d_size)
d_val__ = d_vsp__[1 - size];
switch (production)
{
// $insert actioncases
case 3:
#line 3 "inc/nr"
{
d_val__.get() = stol(d_scanner.matched());
}
break;
case 4:
#line 10 "inc/nr"
{
d_val__.get() = 1;
}
break;
case 5:
#line 15 "inc/nr"
{
d_val__.get() = d_vsp__[0].data();
}
break;
case 6:
#line 22 "inc/nr"
{
d_cronData.addNr(d_vsp__[0].data());
}
break;
case 7:
#line 30 "inc/nr"
{
d_cronData.addRange(d_vsp__[-3].data(), d_vsp__[-1].data(), d_vsp__[0].data());
}
break;
case 23:
#line 26 "inc/token"
{
d_val__.get() = d_scanner.matched();
}
break;
case 24:
#line 35 "inc/token"
{
d_val__.get() = d_vsp__[0].data();
}
break;
case 25:
#line 43 "inc/token"
{
d_val__.get() =d_vsp__[0].data();
}
break;
case 26:
#line 50 "inc/token"
{
d_val__.get() += d_scanner.matched();
}
break;
case 27:
#line 55 "inc/token"
{
d_val__.get() = d_val__.get();
}
break;
case 29:
#line 63 "inc/token"
{
d_val__.get() = string();
}
break;
case 30:
#line 8 "inc/nameline"
{
d_val__.get() = d_vsp__[0].data();
}
break;
case 31:
#line 15 "inc/nameline"
{
d_val__.get() = d_scanner.matched();
}
break;
case 32:
#line 22 "inc/nameline"
{
d_cronData.setEnvVar(d_vsp__[-1].data(), d_vsp__[0].data());
}
break;
case 33:
#line 3 "inc/time"
{
d_cronData.setAll(d_vsp__[0].data());
}
break;
case 35:
#line 12 "inc/time"
{
d_cronData.addName(d_scanner.matched());
}
break;
case 42:
#line 4 "inc/cronline"
{
d_cronData.setMinutes();
}
break;
case 43:
#line 12 "inc/cronline"
{
d_cronData.setHours();
}
break;
case 44:
#line 20 "inc/cronline"
{
d_cronData.setDayOfMonth();
}
break;
case 45:
#line 28 "inc/cronline"
{
d_cronData.setMonthOfYear();
}
break;
case 46:
#line 36 "inc/cronline"
{
d_cronData.setDayOfWeek();
}
break;
case 47:
#line 44 "inc/cronline"
{
d_cronData.setCommand(d_vsp__[-1].data() + d_vsp__[0].data());
}
break;
case 48:
#line 51 "inc/cronline"
{
d_cronData.process();
}
break;
case 52:
#line 10 "inc/line"
{
d_cronData.reset(d_scanner.lineNr());
}
break;
}
}
catch (std::exception const &exc)
{
exceptionHandler__(exc);
}
inline void ParserBase::reduce__(PI__ const &pi)
{
d_token__ = pi.d_nonTerm;
pop__(pi.d_size);
}
// If d_token__ is _UNDETERMINED_ then if d_nextToken__ is _UNDETERMINED_ another
// token is obtained from lex(). Then d_nextToken__ is assigned to d_token__.
void Parser::nextToken()
{
if (d_token__ != _UNDETERMINED_) // no need for a token: got one
return; // already
if (d_nextToken__ != _UNDETERMINED_)
{
popToken__(); // consume pending token
}
else
{
++d_acceptedTokens__; // accept another token (see
// errorRecover())
d_token__ = lex();
if (d_token__ <= 0)
d_token__ = _EOF_;
}
print();
}
// if the final transition is negative, then we should reduce by the rule
// given by its positive value. Note that the `recovery' parameter is only
// used with the --debug option
int Parser::lookup(bool recovery)
{
// $insert threading
SR__ *sr = s_state[d_state__]; // get the appropriate state-table
int lastIdx = sr->d_lastIdx; // sentinel-index in the SR__ array
SR__ *lastElementPtr = sr + lastIdx;
lastElementPtr->d_token = d_token__; // set search-token
SR__ *elementPtr = sr + 1; // start the search at s_xx[1]
while (elementPtr->d_token != d_token__)
++elementPtr;
if (elementPtr == lastElementPtr) // reached the last element
{
if (elementPtr->d_action < 0) // default reduction
{
return elementPtr->d_action;
}
// No default reduction, so token not found, so error.
throw UNEXPECTED_TOKEN__;
}
// not at the last element: inspect the nature of the action
// (< 0: reduce, 0: ACCEPT, > 0: shift)
int action = elementPtr->d_action;
return action;
}
// When an error has occurred, pop elements off the stack until the top
// state has an error-item. If none is found, the default recovery
// mode (which is to abort) is activated.
//
// If EOF is encountered without being appropriate for the current state,
// then the error recovery will fall back to the default recovery mode.
// (i.e., parsing terminates)
void Parser::errorRecovery()
try
{
if (d_acceptedTokens__ >= d_requiredTokens__)// only generate an error-
{ // message if enough tokens
++d_nErrors__; // were accepted. Otherwise
error("Syntax error"); // simply skip input
}
// get the error state
while (not (s_state[top__()][0].d_type & ERR_ITEM))
{
pop__();
}
// In the error state, lookup a token allowing us to proceed.
// Continuation may be possible following multiple reductions,
// but eventuall a shift will be used, requiring the retrieval of
// a terminal token. If a retrieved token doesn't match, the catch below
// will ensure the next token is requested in the while(true) block
// implemented below:
int lastToken = d_token__; // give the unexpected token a
// chance to be processed
// again.
pushToken__(_error_); // specify _error_ as next token
push__(lookup(true)); // push the error state
d_token__ = lastToken; // reactivate the unexpected
// token (we're now in an
// ERROR state).
bool gotToken = true; // the next token is a terminal
while (true)
{
try
{
if (s_state[d_state__]->d_type & REQ_TOKEN)
{
gotToken = d_token__ == _UNDETERMINED_;
nextToken(); // obtain next token
}
int action = lookup(true);
if (action > 0) // push a new state
{
push__(action);
popToken__();
if (gotToken)
{
d_acceptedTokens__ = 0;
return;
}
}
else if (action < 0)
{
// no actions executed on recovery but save an already
// available token:
if (d_token__ != _UNDETERMINED_)
pushToken__(d_token__);
// next token is the rule's LHS
reduce__(s_productionInfo[-action]);
}
else
ABORT(); // abort when accepting during
// error recovery
}
catch (...)
{
if (d_token__ == _EOF_)
ABORT(); // saw inappropriate _EOF_
popToken__(); // failing token now skipped
}
}
}
catch (ErrorRecovery__) // This is: DEFAULT_RECOVERY_MODE
{
ABORT();
}
// The parsing algorithm:
// Initially, state 0 is pushed on the stack, and d_token__ as well as
// d_nextToken__ are initialized to _UNDETERMINED_.
//
// Then, in an eternal loop:
//
// 1. If a state does not have REQ_TOKEN no token is assigned to
// d_token__. If the state has REQ_TOKEN, nextToken() is called to
// determine d_nextToken__ and d_token__ is set to
// d_nextToken__. nextToken() will not call lex() unless d_nextToken__ is
// _UNDETERMINED_.
//
// 2. lookup() is called:
// d_token__ is stored in the final element's d_token field of the
// state's SR_ array.
//
// 3. The current token is looked up in the state's SR_ array
//
// 4. Depending on the result of the lookup() function the next state is
// shifted on the parser's stack, a reduction by some rule is applied,
// or the parsing function returns ACCEPT(). When a reduction is
// called for, any action that may have been defined for that
// reduction is executed.
//
// 5. An error occurs if d_token__ is not found, and the state has no
// default reduction. Error handling was described at the top of this
// file.
int Parser::parse()
try
{
push__(0); // initial state
clearin(); // clear the tokens.
while (true)
{
try
{
if (s_state[d_state__]->d_type & REQ_TOKEN)
nextToken(); // obtain next token
int action = lookup(false); // lookup d_token__ in d_state__
if (action > 0) // SHIFT: push a new state
{
push__(action);
popToken__(); // token processed
}
else if (action < 0) // REDUCE: execute and pop.
{
executeAction(-action);
// next token is the rule's LHS
reduce__(s_productionInfo[-action]);
}
else
ACCEPT();
}
catch (ErrorRecovery__)
{
errorRecovery();
}
}
}
catch (Return__ retValue)
{
return retValue;
}
ssh-cron-1.01.00/parser/frame 0000644 0001750 0001750 00000000043 12605015302 014671 0 ustar frank frank #include "parser.ih"
Parser::
{
}
ssh-cron-1.01.00/required 0000644 0001750 0001750 00000000714 12633527563 014152 0 ustar frank frank This file lists non-standard software only. Thus, standard utilities like cp,
mv, sed, etc, etc, are not explicitly mentioned. Neither is the g++ compiler
explicitly mentioned, but a fairly recent one is assumed.
Required software for building Ssh-cron 1.00.00
-----------------------------------------------
libbobcat-dev (>= 4.01.00),
To use the provided build-script:
icmake (>= 8.00.04)
To construct the man-page:
yodl (>= 3.06.0)
ssh-cron-1.01.00/scanner/ 0000755 0001750 0001750 00000000000 12633537420 014027 5 ustar frank frank ssh-cron-1.01.00/scanner/main.cc 0000644 0001750 0001750 00000000610 12605015302 015244 0 ustar frank frank //#include
//#include "scanner.h"
//
//using namespace std;
//
//int main()
//{
// Scanner scanner;
//
// while (int value = scanner.lex())
// {
// cout << "token: ";
// if (value < 1000)
// cout << static_cast(value);
// else
// cout << value;
//
// cout << ", matched: " << scanner.matched() << '\n';
// }
//}
ssh-cron-1.01.00/scanner/scannerbase.h 0000644 0001750 0001750 00000027161 12605015302 016460 0 ustar frank frank // Generated by Flexc++ V2.01.00 on Mon, 26 May 2014 16:06:55 +0200
#ifndef ScannerBASE_H_INCLUDED
#define ScannerBASE_H_INCLUDED
#include
#include
#include
#include