ssh-cron-1.02.00/build0000755000175000017500000000704713314143340013423 0ustar frankfrank#!/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/gitlab" 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 == "gitlab") gitlab(); 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" " gitlab - prepare gitlab's web-pages update\n" " (internal use only)\n" "\n" ); exit(1); } ssh-cron-1.02.00/changelog0000644000175000017500000000733613460034445014260 0ustar frankfrankssh-cron (1.02.00) * Requires bobcat >= 5.00.00 -- Frank B. Brokken Wed, 24 Apr 2019 12:22:31 +0200 ssh-cron (1.01.01) * Migrated from Github to Gitlab * Precompiled headers are used by default * INSTALL.im uses g++ and standards version c++17 -- Frank B. Brokken Mon, 25 Jun 2018 12:00:53 +0200 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.02.00/CLASSES0000644000175000017500000000027713314143340013414 0ustar frankfrankipcfunction cronentry options ipcfunction crondata options cronentry cron options scanner parser scanner options daemon parser options cron ssh-cron-1.02.00/Copyright-notice0000644000175000017500000000253013314143340015540 0ustar frankfrank-----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.02.00/cron/0000755000175000017500000000000013460260014013327 5ustar frankfrankssh-cron-1.02.00/cron/parentprocess.cc0000644000175000017500000000161713314143340016533 0ustar frankfrank#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.02.00/cron/requesthandler.cc0000644000175000017500000000014013314143340016657 0ustar frankfrank#include "cron.ih" void Cron::requestHandler(Cron *cronPtr) { cronPtr->handleRequests(); } ssh-cron-1.02.00/cron/scheduler.cc0000644000175000017500000000014613314143340015615 0ustar frankfrank#include "cron.ih" ostream &Cron::scheduler() const { return d_options.msg() << "scheduler: "; } ssh-cron-1.02.00/cron/data.cc0000644000175000017500000000011413314143340014543 0ustar frankfrank#include "cron.ih" string Cron::s_agent = "/usr/bin/ssh-agent /bin/bash"; ssh-cron-1.02.00/cron/stop.cc0000644000175000017500000000014413314143340014622 0ustar frankfrank#include "cron.ih" void Cron::stop(size_t signal) { d_run = false; kill(pid(), SIGTERM); } ssh-cron-1.02.00/cron/hmac2str.cc.stdby0000644000175000017500000000036713314143340016513 0ustar frankfrank#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.02.00/cron/handlerequests.cc0000644000175000017500000000345013314143340016667 0ustar frankfrank#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.02.00/cron/list.cc0000644000175000017500000000101513314143340014606 0ustar frankfrank#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.02.00/cron/reload.cc0000644000175000017500000000074313314143340015110 0ustar frankfrank#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.02.00/cron/runparentprocess.cc0000644000175000017500000000011313314143340017246 0ustar frankfrank#include "cron.ih" void Cron::runParentProcess() { parentProcess(); } ssh-cron-1.02.00/cron/childprocess.cc0000644000175000017500000000044313314143340016321 0ustar frankfrank#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.02.00/cron/execute.cc0000644000175000017500000000060613314143340015302 0ustar frankfrank#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.02.00/cron/definerunfunction.cc0000644000175000017500000000060313314143340017362 0ustar frankfrank#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.02.00/cron/call.cc0000644000175000017500000000062213314143340014551 0ustar frankfrank#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.02.00/cron/cron.ih0000644000175000017500000000133613314143340014615 0ustar frankfrank#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.02.00/cron/writerequest.cc0000644000175000017500000000034613314143340016404 0ustar frankfrank#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.02.00/cron/readrequest.cc0000644000175000017500000000055513314143340016167 0ustar frankfrank#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.02.00/cron/cron.h0000644000175000017500000000402113314143340014436 0ustar frankfrank#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.02.00/cron/cronloop.cc0000644000175000017500000000115113314143340015467 0ustar frankfrank#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.02.00/cron/cron1.cc0000644000175000017500000000016513314143340014662 0ustar frankfrank#include "cron.ih" Cron::Cron(CronData &cronData) : d_options(Options::instance()), d_cronData(cronData) {} ssh-cron-1.02.00/cron/runcronjobs.cc0000644000175000017500000000054713314143340016210 0ustar frankfrank#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.02.00/cron/sendcommand.cc0000644000175000017500000000014113314143340016122 0ustar frankfrank#include "cron.ih" void Cron::sendCommand(string line) { *d_toChild << line << endl; } ssh-cron-1.02.00/cron/childredirections.cc0000644000175000017500000000040513314143340017333 0ustar frankfrank#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.02.00/cron/idmsg.cc0000644000175000017500000000012713314143340014741 0ustar frankfrank#include "cron.ih" ostream &Cron::idmsg() const { return imsg << "scheduler: "; } ssh-cron-1.02.00/cron/hmac.cc0000644000175000017500000000033713460034534014557 0ustar frankfrank#include "cron.ih" string Cron::hmac(string const &passPhrase) { HMacBuf hmacbuf(passPhrase, "sha256"); ostream out(&hmacbuf); out << passPhrase << eoi; string hash = hmacbuf.hash(); return hash; } ssh-cron-1.02.00/cron/frame0000644000175000017500000000003713314143340014344 0ustar frankfrank#include "cron.ih" Cron:: { } ssh-cron-1.02.00/crondata/0000755000175000017500000000000013460260014014161 5ustar frankfrankssh-cron-1.02.00/crondata/insert.cc0000644000175000017500000000035613314143340016000 0ustar frankfrank#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.02.00/crondata/addnr.cc0000644000175000017500000000034713314143340015564 0ustar frankfrank#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.02.00/crondata/invalidrange.cc0000644000175000017500000000034113314143340017131 0ustar frankfrank#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.02.00/crondata/data.cc0000644000175000017500000000116013314143340015377 0ustar frankfrank#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.02.00/crondata/addrange.cc0000644000175000017500000000104613314143340016236 0ustar frankfrank#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.02.00/crondata/sethours.cc0000644000175000017500000000024313314143340016343 0ustar frankfrank#include "crondata.ih" void CronData::setHours() { d_next.setHours(assign()); d_entryName = "day of month"; d_entryBegin = 1; d_entryEnd = 32; } ssh-cron-1.02.00/crondata/reset.cc0000644000175000017500000000033613314143340015614 0ustar frankfrank#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.02.00/crondata/crondata.ih0000644000175000017500000000025513314143340016300 0ustar frankfrank#include "crondata.h" #include #include #include #include "../options/options.h" using namespace std; using namespace FBB; ssh-cron-1.02.00/crondata/addcroncommand.cc0000644000175000017500000000054713314143340017447 0ustar frankfrank#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.02.00/crondata/setdayofmonth.cc0000644000175000017500000000023013314143340017347 0ustar frankfrank#include "crondata.ih" void CronData::setDayOfMonth() { d_next.setDayOfMonth(assign()); d_entryName = "month of year"; d_entryEnd = 13; } ssh-cron-1.02.00/crondata/addname.cc0000644000175000017500000000016613314143340016064 0ustar frankfrank#include "crondata.ih" void CronData::addName(std::string const &name) { d_names.push_back(String::lc(name)); } ssh-cron-1.02.00/crondata/setmonthofyear.cc0000644000175000017500000000026413314143340017541 0ustar frankfrank#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.02.00/crondata/assign2.cc0000644000175000017500000000123513314143340016037 0ustar frankfrank#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.02.00/crondata/setenvvar.cc0000644000175000017500000000061713314143340016511 0ustar frankfrank#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.02.00/crondata/crondata1.cc0000644000175000017500000000017313314143340016345 0ustar frankfrank#include "crondata.ih" CronData::CronData() : d_entryName("minutes"), d_info(not Options::instance().reload()) {} ssh-cron-1.02.00/crondata/setminutes.cc0000644000175000017500000000021313314143340016664 0ustar frankfrank#include "crondata.ih" void CronData::setMinutes() { d_next.setMinutes(assign()); d_entryName = "hours"; d_entryEnd = 24; } ssh-cron-1.02.00/crondata/assign.cc0000644000175000017500000000104613314143340015755 0ustar frankfrank#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.02.00/crondata/setdayofweek.cc0000644000175000017500000000015013314143340017156 0ustar frankfrank#include "crondata.ih" void CronData::setDayOfWeek() { d_next.setDayOfWeek(assign(s_day, true)); } ssh-cron-1.02.00/crondata/process.cc0000644000175000017500000000031513314143340016145 0ustar frankfrank#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.02.00/crondata/setcommand.cc0000644000175000017500000000016213314143340016621 0ustar frankfrank#include "crondata.ih" void CronData::setCommand(std::string const &command) { d_next.setCommand(command); } ssh-cron-1.02.00/crondata/outofrange.cc0000644000175000017500000000030413314143340016636 0ustar frankfrank#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.02.00/crondata/setall.cc0000644000175000017500000000025113314143340015752 0ustar frankfrank#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.02.00/crondata/frame0000644000175000017500000000004713314143340015177 0ustar frankfrank#include "crondata.ih" CronData:: { } ssh-cron-1.02.00/crondata/crondata.h0000644000175000017500000000522513314143340016131 0ustar frankfrank#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.02.00/cronentry/0000755000175000017500000000000013460260014014411 5ustar frankfrankssh-cron-1.02.00/cronentry/insert.cc0000644000175000017500000000053313314143340016225 0ustar frankfrank#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.02.00/cronentry/cronentry.h0000644000175000017500000000532213314143340016607 0ustar frankfrank#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.02.00/cronentry/setenvironment.cc0000644000175000017500000000034613314143340020003 0ustar frankfrank#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.02.00/cronentry/operatorinsert.cc0000644000175000017500000000112213314143340017774 0ustar frankfrank#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.02.00/cronentry/showset.cc0000644000175000017500000000050313314143340016412 0ustar frankfrank#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.02.00/cronentry/frame0000644000175000017500000000005113314143340015422 0ustar frankfrank#include "cronentry.ih" CronEntry:: { } ssh-cron-1.02.00/cronentry/cronentry.ih0000644000175000017500000000010213314143340016747 0ustar frankfrank#include "cronentry.h" #include using namespace std; ssh-cron-1.02.00/crontab0000644000175000017500000000032413314143340013740 0ustar frankfrank# 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.02.00/daemon/0000755000175000017500000000000013460260014013631 5ustar frankfrankssh-cron-1.02.00/daemon/parentprocess.cc0000644000175000017500000000057313314143340017035 0ustar frankfrank#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.02.00/daemon/terminate.cc0000644000175000017500000000034113314143340016126 0ustar frankfrank#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.02.00/daemon/getpassphrase.cc0000644000175000017500000000116413314143340017013 0ustar frankfrank#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.02.00/daemon/enterthread.cc0000644000175000017500000000026513314143340016450 0ustar frankfrank#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.02.00/daemon/list.cc0000644000175000017500000000104413314143340015112 0ustar frankfrank#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.02.00/daemon/run.cc0000644000175000017500000000052413314143340014745 0ustar frankfrank#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.02.00/daemon/reload.cc0000644000175000017500000000242013314143340015404 0ustar frankfrank#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.02.00/daemon/listrequest.cc0000644000175000017500000000202113314143340016517 0ustar frankfrank#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.02.00/daemon/daemon.ih0000644000175000017500000000107713314143340015423 0ustar frankfrank#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.02.00/daemon/childprocess.cc0000644000175000017500000000132513314143340016623 0ustar frankfrank#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.02.00/daemon/daemon1.cc0000644000175000017500000000077513314143340015475 0ustar frankfrank#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.02.00/daemon/daemon.h0000644000175000017500000000267113314143340015253 0ustar frankfrank#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.02.00/daemon/createipcfile.cc0000644000175000017500000000113613314143340016740 0ustar frankfrank#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.02.00/daemon/basename.cc0000644000175000017500000000017013314143340015711 0ustar frankfrank#include "daemon.ih" ostream &Daemon::basename() const { return d_options.msg() << d_options.basename() << ": "; } ssh-cron-1.02.00/daemon/signalhandler.cc0000644000175000017500000000015713314143340016756 0ustar frankfrank#include "daemon.ih" void Daemon::signalHandler(size_t signal) { d_cron.stop(signal); cerr << '\n'; } ssh-cron-1.02.00/daemon/getipcinfo.cc0000644000175000017500000000065513314143340016275 0ustar frankfrank#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.02.00/daemon/idmsg.cc0000644000175000017500000000015213314143340015241 0ustar frankfrank#include "daemon.ih" ostream &Daemon::idmsg() const { return imsg << d_options.basename() << ": "; } ssh-cron-1.02.00/daemon/askpassphrase.cc0000644000175000017500000000044013314143340017006 0ustar frankfrank#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.02.00/daemon/cleanup.cc0000644000175000017500000000032713314143340015571 0ustar frankfrank#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.02.00/daemon/frame0000644000175000017500000000004313314143340014643 0ustar frankfrank#include "daemon.ih" Daemon:: { } ssh-cron-1.02.00/daemon/ipc.cc0000644000175000017500000000047113314143340014715 0ustar frankfrank#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.02.00/daemon/daemonize.cc0000644000175000017500000000216013314143340016112 0ustar frankfrank#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.02.00/documentation/0000755000175000017500000000000013314143340015237 5ustar frankfrankssh-cron-1.02.00/documentation/man/0000755000175000017500000000000013460034217016016 5ustar frankfrankssh-cron-1.02.00/documentation/man/ssh-cron.yo0000644000175000017500000003226013314143340020122 0ustar frankfrankgagmacrowarning(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 communication 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.gitlab.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.02.00/icmake/0000755000175000017500000000000013460034217013623 5ustar frankfrankssh-cron-1.02.00/icmake/setopt0000644000175000017500000000034113314143340015056 0ustar frankfrankstring 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.02.00/icmake/manpage0000644000175000017500000000054513314143340015156 0ustar frankfrank#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.02.00/icmake/findall0000644000175000017500000000107413314143340015155 0ustar frankfrank// 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.02.00/icmake/log0000755000175000017500000000063213314143340014327 0ustar frankfrank#!/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.02.00/icmake/pathfile0000644000175000017500000000055213314143340015340 0ustar frankfranklist 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.02.00/icmake/clean0000644000175000017500000000043613314143340014627 0ustar frankfrankvoid 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.02.00/icmake/uninstall0000644000175000017500000000045613314143340015560 0ustar frankfrankvoid 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.02.00/icmake/cuteoln0000644000175000017500000000023313314143340015211 0ustar frankfrankstring cutEoln(string text) { int len; len = strlen(text) - 1; if (text[len] == "\n") text = substr(text, 0, len); return text; } ssh-cron-1.02.00/icmake/run0000644000175000017500000000033013314143340014342 0ustar frankfrankint 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.02.00/icmake/md0000644000175000017500000000074013314143340014143 0ustar frankfrank// 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.02.00/icmake/gitlab0000644000175000017500000000022313314143340015001 0ustar frankfrankvoid gitlab() { run("cp -r release.yo tmp/manhtml/ssh-cron.1.html ../../wip"); run("cp changelog ../../wip/changelog.txt"); exit(0); } ssh-cron-1.02.00/icmake/remove0000755000175000017500000000117013314143340015041 0ustar frankfrank#!/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.02.00/icmake/precompileheaders0000644000175000017500000000133613314143340017240 0ustar frankfrankstring 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.02.00/icmake/backtick0000644000175000017500000000016013314143340015312 0ustar frankfranklist backtick(string arg) { list ret; echo(OFF); ret = `arg`; echo(g_echo); return ret; } ssh-cron-1.02.00/icmake/install0000644000175000017500000000335613314143340015217 0ustar frankfrank 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.02.00/icmake/logfile0000644000175000017500000000025713314143340015167 0ustar frankfrankvoid logFile(string srcdir, string src, string destdir, string dest) { chdir(g_cwd); md(destdir); run("cp " + srcdir + "/" + src + " " + destdir + "/" + dest); } ssh-cron-1.02.00/icmake/loginstall0000644000175000017500000000156513314143340015721 0ustar frankfrank// 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.02.00/icmake/special0000644000175000017500000000042113314143340015157 0ustar frankfrankvoid 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.02.00/icmake/logzip0000644000175000017500000000165613314143340015056 0ustar frankfrank// 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.02.00/icmconf0000644000175000017500000000167513314143340013740 0ustar frankfrank#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 IH ".ih" #define PRECOMP "-x c++-header" #define USE_ECHO ON #define USE_VERSION #define DEFCOM "program" ssh-cron-1.02.00/input0000644000175000017500000000053213314143340013450 0ustar frankfrank# 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.02.00/INSTALL0000644000175000017500000000751713314143340013431 0ustar frankfrankTo 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.02.00/INSTALL.im0000644000175000017500000000253213460034273014033 0ustar frankfrank // 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++2a -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.02.00/ipcfunction/0000755000175000017500000000000013460260014014707 5ustar frankfrankssh-cron-1.02.00/ipcfunction/data.cc0000644000175000017500000000040513314143340016126 0ustar frankfrank#include "ipcfunction.ih" LinearMap IPCFunction::s_nameMap = { {NONE, "NONE"}, {DONE, "DONE"}, {LIST, "LIST"}, {MORE, "MORE"}, {RELOAD, "RELOAD"}, {TERMINATE, "TERMINATE"} }; ssh-cron-1.02.00/ipcfunction/ipcfunction.ih0000644000175000017500000000005713314143340017554 0ustar frankfrank#include "ipcfunction.h" using namespace FBB; ssh-cron-1.02.00/ipcfunction/ipcfunction.h0000644000175000017500000000074713314143340017411 0ustar frankfrank#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.02.00/ipcfunction/frame0000644000175000017500000000005513314143340015724 0ustar frankfrank#include "ipcfunction.ih" IPCFunction:: { } ssh-cron-1.02.00/main.cc0000644000175000017500000000322013314143340013616 0ustar frankfrank#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.02.00/main.ih0000644000175000017500000000050213314143340013631 0ustar frankfrank#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.02.00/options/0000755000175000017500000000000013460260014014061 5ustar frankfrankssh-cron-1.02.00/options/syslogfacility.cc0000644000175000017500000000103113314143340017430 0ustar frankfrank#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.02.00/options/loadconfigfile.cc0000644000175000017500000000067513314143340017345 0ustar frankfrank#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.02.00/options/instance.cc0000644000175000017500000000021313314143340016170 0ustar frankfrank#include "options.ih" Options &Options::instance() { if (s_options == 0) s_options = new Options(); return *s_options; } ssh-cron-1.02.00/options/data.cc0000644000175000017500000000257213314143340015307 0ustar frankfrank#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.02.00/options/options1.cc0000644000175000017500000000343213460034226016152 0ustar frankfrank#include "options.ih" Options::Options() : d_arg(ArgConfig::instance()), d_msg(&d_multiBuf) { // --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_multiBuf.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_multiBuf.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.02.00/options/usage.cc0000644000175000017500000000767513314143340015513 0ustar frankfrank// 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.02.00/options/setsyslog.cc0000644000175000017500000000050213460034230016420 0ustar frankfrank#include "options.ih" bool Options::setSyslog() { if (not d_arg.option(0, "syslog")) return false; d_syslog.reset( new SyslogStream( syslogTag(), syslogPriority(), syslogFacility() ) ); d_multiBuf.insert(*d_syslog); return true; } ssh-cron-1.02.00/options/checkaction.cc0000644000175000017500000000167313314143340016652 0ustar frankfrank#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.02.00/options/options.h0000644000175000017500000000667013460034333015741 0ustar frankfrank#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::MultiBuf d_multiBuf; 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.02.00/options/options.ih0000644000175000017500000000053013314143340016074 0ustar frankfrank#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.02.00/options/syslogpriority.cc0000644000175000017500000000103613314143340017512 0ustar frankfrank#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.02.00/options/frame0000644000175000017500000000004513314143340015075 0ustar frankfrank#include "options.ih" Options:: { } ssh-cron-1.02.00/options/syslogtag.cc0000644000175000017500000000025713314143340016410 0ustar frankfrank#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.02.00/parser/0000755000175000017500000000000013460260014013662 5ustar frankfrankssh-cron-1.02.00/parser/parser.h0000644000175000017500000000207613314143340015334 0ustar frankfrank// 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.02.00/parser/parser1.cc0000644000175000017500000000016713314143340015552 0ustar frankfrank#include "parser.ih" Parser::Parser(istream &in, CronData &cronData) : d_cronData(cronData), d_scanner(in) {} ssh-cron-1.02.00/parser/error.cc0000644000175000017500000000021313314143340015316 0ustar frankfrank#include "parser.ih" void Parser::error(char const *msg) { emsg << msg << " at line " << d_cronData.lineNr() << endl; } ssh-cron-1.02.00/parser/parse.cc0000644000175000017500000010260213314143340015304 0ustar frankfrank// 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.02.00/parser/addset.cc0000644000175000017500000000020013314143340015425 0ustar frankfrank#include "parser.ih" void Parser::addSet(set &lhs, set const &rhs) const { lhs.insert(rhs.begin(), rhs.end()); } ssh-cron-1.02.00/parser/parserpre.ih0000644000175000017500000000004313314143340016204 0ustar frankfrank#include #include ssh-cron-1.02.00/parser/parser.ih0000644000175000017500000000165013314143340015502 0ustar frankfrank// 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.02.00/parser/inc/0000755000175000017500000000000013460034230014432 5ustar frankfrankssh-cron-1.02.00/parser/inc/ws0000644000175000017500000000004113314143340015002 0ustar frankfrankopt_ws: WS | // empty ; ssh-cron-1.02.00/parser/inc/line0000644000175000017500000000052313314143340015305 0ustar frankfrank_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.02.00/parser/inc/cronline0000644000175000017500000000120713314143340016167 0ustar frankfrank_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.02.00/parser/inc/time0000644000175000017500000000071013314143340015312 0ustar frankfrank_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.02.00/parser/inc/nr0000644000175000017500000000061013314143340014772 0ustar frankfranknr: 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.02.00/parser/inc/nameline0000644000175000017500000000055713314143340016155 0ustar frankfrank// 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.02.00/parser/inc/token0000644000175000017500000000104213314143340015473 0ustar frankfrank_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.02.00/parser/grammar0000644000175000017500000000075413314143340015241 0ustar frankfrank%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.02.00/parser/frame0000644000175000017500000000004313314143340014674 0ustar frankfrank#include "parser.ih" Parser:: { } ssh-cron-1.02.00/parser/parserbase.h0000644000175000017500000001652613314143340016174 0ustar frankfrank// 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.02.00/README0000644000175000017500000000272313314143340013252 0ustar frankfrankWelcome 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.02.00/README.protocol0000644000175000017500000000431313314143340015107 0ustar frankfrankWhen 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.02.00/required0000644000175000017500000000071413314143340014133 0ustar frankfrankThis 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.02.00/scanner/0000755000175000017500000000000013460260014014017 5ustar frankfrankssh-cron-1.02.00/scanner/lex.cc0000644000175000017500000003334713314143340015130 0ustar frankfrank// Generated by Flexc++ V2.01.00 on Mon, 26 May 2014 16:06:55 +0200 #include #include #include #include // $insert class_ih #include "scanner.ih" // s_ranges__: use (unsigned) characters as index to obtain // that character's range-number. // The range for EOF is defined in a constant in the // class header file size_t const ScannerBase::s_ranges__[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 5, 6, 7, 7, 7, 7, 7, 7, 8, 9,10,11,12,13,14,14, 14,14,14,14,14,14,14,14,15,15,15,16,17,17,17,18,18,18,18,18,18,18,18,18,18, 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,19,19,19,19,20,21,22,22,22, 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23, 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, 23,23,23,23,23,23, }; // s_dfa__ contains the rows of *all* DFAs ordered by start state. The // enum class StartCondition__ is defined in the baseclass header // StartCondition__::INITIAL is always 0. Each entry defines the row to // transit to if the column's character range was sensed. Row numbers are // relative to the used DFA, and d_dfaBase__ is set to the first row of // the subset to use. The row's final two values are respectively the // rule that may be matched at this state, and the rule's FINAL flag. If // the final value equals FINAL (= 1) then, if there's no continuation, // the rule is matched. If the BOL flag (8) is also set (so FINAL + BOL (= // 9) is set) then the rule only matches when d_atBOL is also true. int const ScannerBase::s_dfa__[][27] = { // INITIAL {-1, 1, 2, 3, 1, 3, 4, 3, 2, 3, 2, 2, 3, 2, 5, 3, 2, 3, 6, 3, 6, 3, 6, 3,-1, -1, 0}, // 0 {-1, 1,-1,-1, 1,-1, 7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1, 1, 0}, // 1 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1, 4, -1}, // 2 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1, 5, -1}, // 3 {-1, 7,-1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,-1, 5, 0}, // 4 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 5,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1, 2, -1}, // 5 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 6,-1,-1, 6,-1,-1,-1, 6,-1, 6,-1, 6,-1,-1, 3, -1}, // 6 {-1, 7,-1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,-1, -1, 0}, // 7 }; int const (*ScannerBase::s_dfaBase__[])[27] = { s_dfa__ + 0, }; size_t ScannerBase::s_istreamNr = 0; // $insert inputImplementation ScannerBase::Input::Input() : d_in(0), d_lineNr(1) {} ScannerBase::Input::Input(std::istream *iStream, size_t lineNr) : d_in(iStream), d_lineNr(lineNr) {} size_t ScannerBase::Input::get() { switch (size_t ch = next()) // get the next input char { case '\n': ++d_lineNr; // FALLING THROUGH default: return ch; } } size_t ScannerBase::Input::next() { size_t ch; if (d_deque.empty()) // deque empty: next char fm d_in { if (d_in == 0) return AT_EOF; ch = d_in->get(); return *d_in ? ch : static_cast(AT_EOF); } ch = d_deque.front(); d_deque.pop_front(); return ch; } void ScannerBase::Input::reRead(size_t ch) { if (ch < 0x100) { if (ch == '\n') --d_lineNr; d_deque.push_front(ch); } } void ScannerBase::Input::reRead(std::string const &str, size_t fm) { for (size_t idx = str.size(); idx-- > fm; ) reRead(str[idx]); } ScannerBase::ScannerBase(std::istream &in, std::ostream &out) : d_filename("-"), d_out(new std::ostream(out.rdbuf())), // $insert interactiveInit d_in(0), d_input(new std::istream(in.rdbuf())), d_dfaBase__(s_dfa__) {} void ScannerBase::switchStream__(std::istream &in, size_t lineNr) { d_input.close(); d_input = Input(new std::istream(in.rdbuf()), lineNr); } ScannerBase::ScannerBase(std::string const &infilename, std::string const &outfilename) : d_filename(infilename), d_out(outfilename == "-" ? new std::ostream(std::cout.rdbuf()) : outfilename == "" ? new std::ostream(std::cerr.rdbuf()) : new std::ofstream(outfilename)), d_input(new std::ifstream(infilename)), d_dfaBase__(s_dfa__) {} void ScannerBase::switchStreams(std::istream &in, std::ostream &out) { switchStream__(in, 1); switchOstream(out); } void ScannerBase::switchOstream(std::ostream &out) { *d_out << std::flush; d_out.reset(new std::ostream(out.rdbuf())); } // $insert debugFunctions void ScannerBase::setDebug(bool onOff) {} bool ScannerBase::debug() const { return false; } void ScannerBase::redo(size_t nChars) { size_t from = nChars >= length() ? 0 : length() - nChars; d_input.reRead(d_matched, from); d_matched.resize(from); } void ScannerBase::switchOstream(std::string const &outfilename) { *d_out << std::flush; d_out.reset( outfilename == "-" ? new std::ostream(std::cout.rdbuf()) : outfilename == "" ? new std::ostream(std::cerr.rdbuf()) : new std::ofstream(outfilename)); } void ScannerBase::switchIstream(std::string const &infilename) { d_input.close(); d_filename = infilename; d_input = Input(new std::ifstream(infilename)); d_atBOL = true; } void ScannerBase::switchStreams(std::string const &infilename, std::string const &outfilename) { switchOstream(outfilename); switchIstream(infilename); } void ScannerBase::pushStream(std::istream &istr) { std::istream *streamPtr = new std::istream(istr.rdbuf()); p_pushStream("(istream)", streamPtr); } void ScannerBase::pushStream(std::string const &name) { std::istream *streamPtr = new std::ifstream(name); if (!*streamPtr) { delete streamPtr; throw std::runtime_error("Cannot read " + name); } p_pushStream(name, streamPtr); } void ScannerBase::p_pushStream(std::string const &name, std::istream *streamPtr) { if (d_streamStack.size() == s_maxSizeofStreamStack__) { delete streamPtr; throw std::length_error("Max stream stack size exceeded"); } d_streamStack.push_back(StreamStruct{d_filename, d_input}); d_filename = name; d_input = Input(streamPtr); d_atBOL = true; } bool ScannerBase::popStream() { d_input.close(); if (d_streamStack.empty()) return false; StreamStruct &top = d_streamStack.back(); d_input = top.pushedInput; d_filename = top.pushedName; d_streamStack.pop_back(); return true; } // See the manual's section `Run-time operations' section for an explanation // of this member. ScannerBase::ActionType__ ScannerBase::actionType__(size_t range) { d_nextState = d_dfaBase__[d_state][range]; if (d_nextState != -1) // transition is possible return ActionType__::CONTINUE; if (knownFinalState()) // FINAL state reached return ActionType__::MATCH; if (d_matched.size()) return ActionType__::ECHO_FIRST; // no match, echo the 1st char return range != s_rangeOfEOF__ ? ActionType__::ECHO_CH : ActionType__::RETURN; } void ScannerBase::accept(size_t nChars) // old name: less { if (nChars < d_matched.size()) { d_input.reRead(d_matched, nChars); d_matched.resize(nChars); } } void ScannerBase::setMatchedSize(size_t length) { d_input.reRead(d_matched, length); // reread the tail section d_matched.resize(length); // return what's left } // At this point a rule has been matched. The next character is not part of // the matched rule and is sent back to the input. The final match length // is determined, the index of the matched rule is determined, and then // d_atBOL is updated. Finally the rule's index is returned. // The numbers behind the finalPtr assignments are explained in the // manual's `Run-time operations' section. size_t ScannerBase::matched__(size_t ch) { d_input.reRead(ch); FinalData *finalPtr; if (not d_atBOL) // not at BOL finalPtr = &d_final.std; // then use the std rule (3, 4) // at BOL else if (not available(d_final.std.rule)) // only a BOL rule avail. finalPtr = &d_final.bol; // use the BOL rule (6) else if (not available(d_final.bol.rule)) // only a std rule is avail. finalPtr = &d_final.std; // use the std rule (7) else if ( // Both are available (8) d_final.bol.length != // check lengths of matched texts d_final.std.length // unequal lengths, use the rule ) // having the longer match length finalPtr = d_final.bol.length > d_final.std.length ? &d_final.bol : &d_final.std; else // lengths are equal: use 1st rule finalPtr = d_final.bol.rule < d_final.std.rule ? &d_final.bol : &d_final.std; setMatchedSize(finalPtr->length); d_atBOL = d_matched.back() == '\n'; return finalPtr->rule; } size_t ScannerBase::getRange__(int ch) // using int to prevent casts { return ch == AT_EOF ? as(s_rangeOfEOF__) : s_ranges__[ch]; } // At this point d_nextState contains the next state and continuation is // possible. The just read char. is appended to d_match void ScannerBase::continue__(int ch) { d_state = d_nextState; if (ch != AT_EOF) d_matched += ch; } void ScannerBase::echoCh__(size_t ch) { *d_out << as(ch); d_atBOL = ch == '\n'; } // At this point there is no continuation. The last character is // pushed back into the input stream as well as all but the first char. in // the buffer. The first char. in the buffer is echoed to stderr. // If there isn't any 1st char yet then the current char doesn't fit any // rules and that char is then echoed void ScannerBase::echoFirst__(size_t ch) { d_input.reRead(ch); d_input.reRead(d_matched, 1); echoCh__(d_matched[0]); } // Update the rules associated with the current state, do this separately // for BOL and std rules. // If a rule was set, update the rule index and the current d_matched // length. void ScannerBase::updateFinals__() { size_t len = d_matched.size(); int const *rf = d_dfaBase__[d_state] + s_finIdx__; if (rf[0] != -1) // update to the latest std rule { d_final.std = FinalData { as(rf[0]), len }; } if (rf[1] != -1) // update to the latest bol rule { d_final.bol = FinalData { as(rf[1]), len }; } } void ScannerBase::reset__() { d_final = Final{ FinalData{s_unavailable, 0}, FinalData {s_unavailable, 0} }; d_state = 0; d_return = true; if (!d_more) d_matched.clear(); d_more = false; } int Scanner::executeAction__(size_t ruleIdx) try { switch (ruleIdx) { // $insert actions case 1: { #line 13 "lexer" return Parser::WS; } break; case 2: { #line 15 "lexer" return Parser::NR; } break; case 3: { #line 17 "lexer" return Parser::ID; } break; case 4: { #line 19 "lexer" return matched()[0]; } break; case 5: { #line 21 "lexer" return Parser::CHAR; } break; } noReturn__(); return 0; } catch (Leave__ value) { return static_cast(value); } int Scanner::lex__() { reset__(); preCode(); while (true) { size_t ch = get__(); // fetch next char size_t range = getRange__(ch); // determine the range updateFinals__(); // update the state's Final info switch (actionType__(range)) // determine the action { case ActionType__::CONTINUE: continue__(ch); continue; case ActionType__::MATCH: { d_token__ = executeAction__(matched__(ch)); if (return__()) { print(); postCode(PostEnum__::RETURN); return d_token__; } break; } case ActionType__::ECHO_FIRST: echoFirst__(ch); break; case ActionType__::ECHO_CH: echoCh__(ch); break; case ActionType__::RETURN: if (!popStream()) { postCode(PostEnum__::END); return 0; } postCode(PostEnum__::POP); continue; } // switch postCode(PostEnum__::WIP); reset__(); preCode(); } // while } void ScannerBase::print__() const { } ssh-cron-1.02.00/scanner/scanner.ih0000644000175000017500000000012113314143340015764 0ustar frankfrank#include "scanner.h" #include "../parser/parserbase.h" // end of scanner.ih ssh-cron-1.02.00/scanner/scanner.h0000644000175000017500000000303613314143340015623 0ustar frankfrank// Generated by Flexc++ V2.01.00 on Fri, 09 May 2014 09:50:28 +0200 #ifndef Scanner_H_INCLUDED_ #define Scanner_H_INCLUDED_ // $insert baseclass_h #include "scannerbase.h" // $insert classHead class Scanner: public ScannerBase { bool d_returnCommand = false; public: explicit Scanner(std::istream &in = std::cin, std::ostream &out = std::cout); Scanner(std::string const &infile, std::string const &outfile); // $insert lexFunctionDecl int lex(); private: int lex__(); int executeAction__(size_t ruleNr); void print(); void preCode(); // re-implement this function for code that must // be exec'ed before the patternmatching starts void postCode(PostEnum__ type); // re-implement this function for code that must // be exec'ed after the rules's actions. }; // $insert scannerConstructors inline Scanner::Scanner(std::istream &in, std::ostream &out) : ScannerBase(in, out) {} inline Scanner::Scanner(std::string const &infile, std::string const &outfile) : ScannerBase(infile, outfile) {} // $insert inlineLexFunction inline int Scanner::lex() { return lex__(); } inline void Scanner::preCode() { // optionally replace by your own code } inline void Scanner::postCode(PostEnum__ type) { // optionally replace by your own code } inline void Scanner::print() { print__(); } #endif // Scanner_H_INCLUDED_ ssh-cron-1.02.00/scanner/main.cc0000644000175000017500000000061013314143340015247 0ustar frankfrank//#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.02.00/scanner/lexer0000644000175000017500000000065413314143340015066 0ustar frankfrank%filenames scanner //%interactive //%debug ID [[:alpha:]_][[:alnum:]_-]* %% //%nowarn ^[ \t]*(#.*)? // ignore ws (+ comment) at BOL [ \t]+ return Parser::WS; [0-9]+ return Parser::NR; {ID} return Parser::ID; [*/,=\n-] return matched()[0]; . return Parser::CHAR; ssh-cron-1.02.00/scanner/scannerbase.h0000644000175000017500000002716113314143340016463 0ustar frankfrank// 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 #include #include class ScannerBase { // idx: rule, value: tail length (NO_INCREMENTS if no tail) typedef std::vector VectorInt; static size_t const s_unavailable = std::numeric_limits::max(); enum { AT_EOF = -1 }; protected: enum Leave__ {}; enum class ActionType__ { CONTINUE, // transition succeeded, go on ECHO_CH, // echo ch itself (d_matched empty) ECHO_FIRST, // echo d_matched[0], push back the rest MATCH, // matched a rule RETURN, // no further continuation, lex returns 0. }; enum class PostEnum__ { END, // postCode called when lex__() ends POP, // postCode called after switching files RETURN, // postCode called when lex__() returns WIP // postCode called when a non-returning rule // was matched }; public: enum class StartCondition__ { // $insert startCondNames INITIAL, }; private: struct FinalData { size_t rule; size_t length; }; struct Final { FinalData std; FinalData bol; }; // class Input encapsulates all input operations. // Its member get() returns the next input character // $insert inputInterface class Input { std::deque d_deque; // pending input chars std::istream *d_in; // ptr for easy streamswitching size_t d_lineNr; // line count public: Input(); // iStream: dynamically allocated Input(std::istream *iStream, size_t lineNr = 1); size_t get(); // the next range void reRead(size_t ch); // push back 'ch' (if < 0x100) // push back str from idx 'fmIdx' void reRead(std::string const &str, size_t fmIdx); size_t lineNr() const { return d_lineNr; } size_t nPending() const { return d_deque.size(); } void setPending(size_t size) { d_deque.erase(d_deque.begin(), d_deque.end() - size); } void close() // force closing the stream { delete d_in; d_in = 0; // switchStreams also closes } private: size_t next(); // obtain the next character }; protected: struct StreamStruct { std::string pushedName; Input pushedInput; }; private: std::vector d_streamStack; std::string d_filename; // name of the currently processed static size_t s_istreamNr; // file. With istreams it receives // the name "", where // # is the sequence number of the // istream (starting at 1) int d_startCondition = 0; int d_lopSC = 0; size_t d_state = 0; int d_nextState; std::shared_ptr d_out; bool d_atBOL = true; // the matched text starts at BOL Final d_final; // only used interactively: std::istream *d_in; // points to the input stream std::shared_ptr d_line; // holds line fm d_in Input d_input; std::string d_matched; // matched characters std::string d_lopMatched; // matched lop-rule characters std::string::iterator d_lopIter; std::string::iterator d_lopTail; std::string::iterator d_lopEnd; size_t d_lopPending; // # pending input chars at lop1__ bool d_return; // return after a rule's action bool d_more = false; // set to true by more() size_t (ScannerBase::*d_get)() = &ScannerBase::getInput; protected: std::istream *d_in__; int d_token__; // returned by lex__ int const (*d_dfaBase__)[27]; static int const s_dfa__[][27]; static int const (*s_dfaBase__[])[27]; enum: bool { s_interactive__ = false }; enum: size_t { s_rangeOfEOF__ = 24, s_finIdx__ = 25, s_nRules__ = 6, s_maxSizeofStreamStack__ = 10 }; static size_t const s_ranges__[]; static size_t const s_rf__[][2]; public: ScannerBase(ScannerBase const &other) = delete; ScannerBase &operator=(ScannerBase const &rhs) = delete; bool debug() const; std::string const &filename() const; std::string const &matched() const; size_t length() const; size_t lineNr() const; void setDebug(bool onOff); void switchOstream(std::ostream &out); void switchOstream(std::string const &outfilename); void switchStreams(std::istream &in, std::ostream &out = std::cout); void switchIstream(std::string const &infilename); void switchStreams(std::string const &infilename, std::string const &outfilename); // $insert interactiveDecl protected: ScannerBase(std::istream &in, std::ostream &out); ScannerBase(std::string const &infilename, std::string const &outfilename); StartCondition__ startCondition() const; // current start condition bool popStream(); std::ostream &out(); void begin(StartCondition__ startCondition); void echo() const; void leave(int retValue) const; // `accept(n)' returns all but the first `n' characters of the current // token back to the input stream, where they will be rescanned when the // scanner looks for the next match. // So, it matches n of the characters in the input buffer, and so it accepts // n characters, rescanning the rest. void accept(size_t nChars = 0); // former: less void redo(size_t nChars = 0); // rescan the last nChar // characters, reducing // length() by nChars void more(); void push(size_t ch); // push char to Input void push(std::string const &txt); // same: chars std::vector const &streamStack() const; void pushStream(std::istream &curStream); void pushStream(std::string const &curName); void setFilename(std::string const &name); void setMatched(std::string const &text); static std::string istreamName__(); // members used by lex__(): they end in __ and should not be used // otherwise. ActionType__ actionType__(size_t range); // next action bool return__(); // 'return' from codeblock size_t matched__(size_t ch); // handles a matched rule size_t getRange__(int ch); // convert char to range size_t get__(); // next character size_t state__() const; // current state void continue__(int ch); // handles a transition void echoCh__(size_t ch); // echoes ch, sets d_atBOL void echoFirst__(size_t ch); // handles unknown input void updateFinals__(); // update a state's Final info void noReturn__(); // d_return to false void print__() const; // optionally print token void pushFront__(size_t ch); // return char to Input void reset__(); // prepare for new cycle // next input stream: void switchStream__(std::istream &in, size_t lineNr); void lopf__(size_t tail); // matched fixed size tail void lop1__(int lopSC); // matched ab for a/b void lop2__(); // matches the LOP's b tail void lop3__(); // catch-all while matching b void lop4__(); // matches the LOP's a head private: size_t getInput(); size_t getLOP(); void p_pushStream(std::string const &name, std::istream *streamPtr); void setMatchedSize(size_t length); bool knownFinalState(); template static ReturnType constexpr as(ArgType value); static bool constexpr available(size_t value); static StartCondition__ constexpr SC(int sc); static int constexpr SC(StartCondition__ sc); }; template inline ReturnType constexpr ScannerBase::as(ArgType value) { return static_cast(value); } inline bool ScannerBase::knownFinalState() { return (d_atBOL && available(d_final.bol.rule)) || available(d_final.std.rule); } inline bool constexpr ScannerBase::available(size_t value) { return value != std::numeric_limits::max(); } inline ScannerBase::StartCondition__ constexpr ScannerBase::SC(int sc) { return as(sc); } inline int constexpr ScannerBase::SC(StartCondition__ sc) { return as(sc); } inline std::ostream &ScannerBase::out() { return *d_out; } inline void ScannerBase::push(size_t ch) { d_input.reRead(ch); } inline void ScannerBase::push(std::string const &str) { d_input.reRead(str, 0); } inline void ScannerBase::setFilename(std::string const &name) { d_filename = name; } inline void ScannerBase::setMatched(std::string const &text) { d_matched = text; } inline std::string const &ScannerBase::matched() const { return d_matched; } inline ScannerBase::StartCondition__ ScannerBase::startCondition() const { return SC(d_startCondition); } inline std::string const &ScannerBase::filename() const { return d_filename; } inline void ScannerBase::echo() const { *d_out << d_matched; } inline size_t ScannerBase::length() const { return d_matched.size(); } inline void ScannerBase::leave(int retValue) const { throw as(retValue); } inline size_t ScannerBase::lineNr() const { return d_input.lineNr(); } inline void ScannerBase::more() { d_more = true; } inline void ScannerBase::begin(StartCondition__ startCondition) { // d_state is reset to 0 by reset__() d_dfaBase__ = s_dfaBase__[d_startCondition = SC(startCondition)]; } inline size_t ScannerBase::state__() const { return d_state; } inline size_t ScannerBase::get__() { return (this->*d_get)(); } inline size_t ScannerBase::getInput() { return d_input.get(); } inline bool ScannerBase::return__() { return d_return; } inline void ScannerBase::noReturn__() { d_return = false; } #endif // ScannerBASE_H_INCLUDED ssh-cron-1.02.00/scanner/frame0000644000175000017500000000004513314143340015033 0ustar frankfrank#include "scanner.ih" Scanner:: { } ssh-cron-1.02.00/ssh-cron0000777000175000017500000000000013460260017015524 2ssh-cronustar frankfrankssh-cron-1.02.00/ssh-cron.xref0000644000175000017500000004305713314143340015021 0ustar frankfrankoxref by Frank B. Brokken (f.b.brokken@rug.nl) oxref V1.00.03 2012-2015 CREATED Mon, 14 Dec 2015 12:58:48 +0000 CROSS REFERENCE FOR: -fxs tmp/libmodules.a ---------------------------------------------------------------------- addCronCommand() Full name: CronData::addCronCommand() Source: addcroncommand.cc Used By: process.cc: CronData::process() addName(std::__cxx11::basic_string, std::allocator > const&) Full name: CronData::addName(std::__cxx11::basic_string, std::allocator > const&) Source: addname.cc Used By: parse.cc: Parser::executeAction(int) addNr(unsigned int) Full name: CronData::addNr(unsigned int) Source: addnr.cc Used By: parse.cc: Parser::executeAction(int) addRange(unsigned int, unsigned int, unsigned int) Full name: CronData::addRange(unsigned int, unsigned int, unsigned int) Source: addrange.cc Used By: parse.cc: Parser::executeAction(int) setall.cc: CronData::setAll(unsigned int) assign() Full name: CronData::assign() Source: assign.cc Used By: assign2.cc: CronData::assign(char const* const*, bool) setdayofmonth.cc: CronData::setDayOfMonth() sethours.cc: CronData::setHours() setminutes.cc: CronData::setMinutes() assign(char const* const*, bool) Full name: CronData::assign(char const* const*, bool) Source: assign2.cc Used By: setdayofweek.cc: CronData::setDayOfWeek() setmonthofyear.cc: CronData::setMonthOfYear() author Full name: Icmbuild::author Source: version.cc Used By: usage.cc: Options::usage(std::__cxx11::basic_string, std::allocator > const&) basename() const Full name: Daemon::basename() const Source: basename.cc Used By: list.cc: Daemon::list(std::istream&) listrequest.cc: Daemon::listRequest() reload.cc: Daemon::reload() terminate.cc: Daemon::terminate() const call(FBB::DateTime const&, CronEntry const&) Full name: Cron::call(FBB::DateTime const&, CronEntry const&) Source: call.cc Used By: runcronjobs.cc: Cron::runCronJobs() checkAction() const Full name: Options::checkAction() const Source: checkaction.cc Used By: options1.cc: Options::Options() childProcess() Full name: Daemon::childProcess() Source: childprocess.cc Used By: parentprocess.cc: Daemon::parentProcess() childProcess() Full name: Cron::childProcess() Source: childprocess.cc Used By: childredirections.cc: Cron::childRedirections() cleanup() Full name: Daemon::cleanup() Source: cleanup.cc Used By: childprocess.cc: Daemon::childProcess() createIPCfile() Full name: Daemon::createIPCfile() Source: createipcfile.cc Used By: daemonize.cc: Daemon::daemonize() Cron(CronData&) Full name: Cron::Cron(CronData&) Source: cron1.cc Used By: daemon1.cc: Daemon::Daemon() CronData() Full name: CronData::CronData() Source: crondata1.cc Used By: reload.cc: Cron::reload(std::istream&) daemon1.cc: Daemon::Daemon() cronLoop() Full name: Cron::cronLoop() Source: cronloop.cc Used By: parentprocess.cc: Cron::parentProcess() cxx11] Full name: Cron::s_agent[abi:cxx11] Source: data.cc Used By: childprocess.cc: Cron::childProcess() cxx11] Full name: Options::s_syslogPriorities[abi:cxx11] Source: data.cc Used By: syslogpriority.cc: Options::syslogPriority() const cxx11] Full name: Options::s_syslogFacilities[abi:cxx11] Source: data.cc Used By: syslogfacility.cc: Options::syslogFacility() const cxx11]() Full name: Daemon::askPassPhrase[abi:cxx11]() Source: askpassphrase.cc Used By: reload.cc: Daemon::reload() cxx11]() const Full name: Options::syslogTag[abi:cxx11]() const Source: syslogtag.cc Used By: setsyslog.cc: Options::setSyslog() daemonize() Full name: Daemon::daemonize() Source: daemonize.cc Used By: run.cc: Daemon::run() defineRunFunction() Full name: Cron::defineRunFunction() Source: definerunfunction.cc Used By: parentprocess.cc: Cron::parentProcess() enterThread(Daemon*) Full name: Daemon::enterThread(Daemon*) Source: enterthread.cc Used By: childprocess.cc: Daemon::childProcess() error(char const*) Full name: Parser::error(char const*) Source: error.cc Used By: parse.cc: Parser::errorRecovery() execute(CronEntry const&) Full name: Cron::execute(CronEntry const&) Source: execute.cc Used By: runcronjobs.cc: Cron::runCronJobs() getIPCInfo() const Full name: Daemon::getIPCInfo() const Source: getipcinfo.cc Used By: listrequest.cc: Daemon::listRequest() reload.cc: Daemon::reload() terminate.cc: Daemon::terminate() const getPassPhrase() Full name: Daemon::getPassPhrase() Source: getpassphrase.cc Used By: daemonize.cc: Daemon::daemonize() handleRequests() Full name: Cron::handleRequests() Source: handlerequests.cc Used By: requesthandler.cc: Cron::requestHandler(Cron*) hmac(std::__cxx11::basic_string, std::allocator > const&) Full name: Cron::hmac(std::__cxx11::basic_string, std::allocator > const&) Source: hmac.cc Used By: reload.cc: Cron::reload(std::istream&) getpassphrase.cc: Daemon::getPassPhrase() idmsg() const Full name: Daemon::idmsg() const Source: idmsg.cc Used By: childprocess.cc: Daemon::childProcess() daemonize.cc: Daemon::daemonize() getipcinfo.cc: Daemon::getIPCInfo() const list.cc: Daemon::list(std::istream&) listrequest.cc: Daemon::listRequest() reload.cc: Daemon::reload() terminate.cc: Daemon::terminate() const idmsg() const Full name: Cron::idmsg() const Source: idmsg.cc Used By: cronloop.cc: Cron::cronLoop() definerunfunction.cc: Cron::defineRunFunction() execute.cc: Cron::execute(CronEntry const&) handlerequests.cc: Cron::handleRequests() parentprocess.cc: Cron::parentProcess() reload.cc: Cron::reload(std::istream&) insert(std::ostream&) const Full name: CronEntry::insert(std::ostream&) const Source: insert.cc Used By: operatorinsert.cc: operator<<(std::ostream&, CronEntry const&) insert.cc: CronData::insert(std::ostream&) const insert(std::ostream&) const Full name: CronData::insert(std::ostream&) const Source: insert.cc Used By: parentprocess.cc: Daemon::parentProcess() reload.cc: Daemon::reload() instance() Full name: Options::instance() Source: instance.cc Used By: addcroncommand.cc: CronData::addCronCommand() crondata1.cc: CronData::CronData() setenvvar.cc: CronData::setEnvVar(std::__cxx11::basic_string, std::allocator > const&, std::__cxx11::basic_string, std::allocator > const&) cron1.cc: Cron::Cron(CronData&) handlerequests.cc: Cron::handleRequests() daemon1.cc: Daemon::Daemon() getipcinfo.cc: Daemon::getIPCInfo() const parentprocess.cc: Daemon::parentProcess() invalidRange(unsigned int, unsigned int) const Full name: CronData::invalidRange(unsigned int, unsigned int) const Source: invalidrange.cc Used By: addrange.cc: CronData::addRange(unsigned int, unsigned int, unsigned int) ipc() Full name: Daemon::ipc() Source: ipc.cc Used By: run.cc: Daemon::run() lex__() Full name: Scanner::lex__() Source: lex.cc Used By: parse.cc: Parser::nextToken() list(std::istream&) Full name: Daemon::list(std::istream&) Source: list.cc Used By: listrequest.cc: Daemon::listRequest() list(unsigned int*, int, FBB::SharedStream&) Full name: Cron::list(unsigned int*, int, FBB::SharedStream&) Source: list.cc Used By: handlerequests.cc: Cron::handleRequests() listRequest() Full name: Daemon::listRequest() Source: listrequest.cc Used By: ipc.cc: Daemon::ipc() loadConfigFile() Full name: Options::loadConfigFile() Source: loadconfigfile.cc Used By: options1.cc: Options::Options() operator<<(std::ostream&, CronEntry const&) Full name: operator<<(std::ostream&, CronEntry const&) Source: operatorinsert.cc Used By: addcroncommand.cc: CronData::addCronCommand() list.cc: Cron::list(unsigned int*, int, FBB::SharedStream&) Options() Full name: Options::Options() Source: options1.cc Used By: instance.cc: Options::instance() outOfRange(unsigned int) Full name: CronData::outOfRange(unsigned int) Source: outofrange.cc Used By: addnr.cc: CronData::addNr(unsigned int) assign.cc: CronData::assign() parentProcess() Full name: Cron::parentProcess() Source: parentprocess.cc Used By: childredirections.cc: Cron::childRedirections() parse() Full name: Parser::parse() Source: parse.cc Used By: reload.cc: Cron::reload(std::istream&) daemon1.cc: Daemon::Daemon() Parser(std::istream&, CronData&) Full name: Parser::Parser(std::istream&, CronData&) Source: parser1.cc Used By: reload.cc: Cron::reload(std::istream&) daemon1.cc: Daemon::Daemon() ParserBase() Full name: ParserBase::ParserBase() Source: parse.cc Used By: parser1.cc: Parser::Parser(std::istream&, CronData&) process() Full name: CronData::process() Source: process.cc Used By: parse.cc: Parser::executeAction(int) readRequest(std::istream&) Full name: Cron::readRequest(std::istream&) Source: readrequest.cc Used By: handlerequests.cc: Cron::handleRequests() list.cc: Daemon::list(std::istream&) reload() Full name: Daemon::reload() Source: reload.cc Used By: ipc.cc: Daemon::ipc() reload(std::istream&) Full name: Cron::reload(std::istream&) Source: reload.cc Used By: handlerequests.cc: Cron::handleRequests() requestHandler(Cron*) Full name: Cron::requestHandler(Cron*) Source: requesthandler.cc Used By: parentprocess.cc: Cron::parentProcess() reset(unsigned int) Full name: CronData::reset(unsigned int) Source: reset.cc Used By: parse.cc: Parser::executeAction(int) runCronJobs() Full name: Cron::runCronJobs() Source: runcronjobs.cc Used By: cronloop.cc: Cron::cronLoop() s_day Full name: CronData::s_day Source: data.cc Used By: setdayofweek.cc: CronData::setDayOfWeek() s_defaultAgent Full name: Options::s_defaultAgent Source: data.cc Used By: options1.cc: Options::Options() usage.cc: Options::usage(std::__cxx11::basic_string, std::allocator > const&) s_defaultConfigFile Full name: Options::s_defaultConfigFile Source: data.cc Used By: loadconfigfile.cc: Options::loadConfigFile() usage.cc: Options::usage(std::__cxx11::basic_string, std::allocator > const&) s_defaultIPCfile Full name: Options::s_defaultIPCfile Source: data.cc Used By: options1.cc: Options::Options() usage.cc: Options::usage(std::__cxx11::basic_string, std::allocator > const&) s_defaultMailer Full name: Options::s_defaultMailer Source: data.cc Used By: options1.cc: Options::Options() usage.cc: Options::usage(std::__cxx11::basic_string, std::allocator > const&) s_defaultSyslogFacility Full name: Options::s_defaultSyslogFacility Source: data.cc Used By: syslogfacility.cc: Options::syslogFacility() const usage.cc: Options::usage(std::__cxx11::basic_string, std::allocator > const&) s_defaultSyslogIdent Full name: Options::s_defaultSyslogIdent Source: data.cc Used By: syslogtag.cc: Options::syslogTag[abi:cxx11]() const usage.cc: Options::usage(std::__cxx11::basic_string, std::allocator > const&) s_defaultSyslogPriority Full name: Options::s_defaultSyslogPriority Source: data.cc Used By: syslogpriority.cc: Options::syslogPriority() const usage.cc: Options::usage(std::__cxx11::basic_string, std::allocator > const&) s_month Full name: CronData::s_month Source: data.cc Used By: setmonthofyear.cc: CronData::setMonthOfYear() s_nameMap Full name: IPCFunction::s_nameMap Source: data.cc Used By: handlerequests.cc: Cron::handleRequests() list.cc: Daemon::list(std::istream&) listrequest.cc: Daemon::listRequest() s_options Full name: Options::s_options Source: data.cc Used By: instance.cc: Options::instance() s_values Full name: CronData::s_values Source: data.cc Used By: assign.cc: CronData::assign() ScannerBase(std::istream&, std::ostream&) Full name: ScannerBase::ScannerBase(std::istream&, std::ostream&) Source: lex.cc Used By: parser1.cc: Parser::Parser(std::istream&, CronData&) scheduler() const Full name: Cron::scheduler() const Source: scheduler.cc Used By: execute.cc: Cron::execute(CronEntry const&) handlerequests.cc: Cron::handleRequests() parentprocess.cc: Cron::parentProcess() sendCommand(std::__cxx11::basic_string, std::allocator >) Full name: Cron::sendCommand(std::__cxx11::basic_string, std::allocator >) Source: sendcommand.cc Used By: execute.cc: Cron::execute(CronEntry const&) parentprocess.cc: Cron::parentProcess() setAll(unsigned int) Full name: CronData::setAll(unsigned int) Source: setall.cc Used By: parse.cc: Parser::executeAction(int) setCommand(std::__cxx11::basic_string, std::allocator > const&) Full name: CronData::setCommand(std::__cxx11::basic_string, std::allocator > const&) Source: setcommand.cc Used By: parse.cc: Parser::executeAction(int) setDayOfMonth() Full name: CronData::setDayOfMonth() Source: setdayofmonth.cc Used By: parse.cc: Parser::executeAction(int) setDayOfWeek() Full name: CronData::setDayOfWeek() Source: setdayofweek.cc Used By: parse.cc: Parser::executeAction(int) setEnvironment(unsigned int, unsigned int, std::vector, std::allocator >, std::allocator, std::allocator > > > const*) Full name: CronEntry::setEnvironment(unsigned int, unsigned int, std::vector, std::allocator >, std::allocator, std::allocator > > > const*) Source: setenvironment.cc Used By: addcroncommand.cc: CronData::addCronCommand() setEnvVar(std::__cxx11::basic_string, std::allocator > const&, std::__cxx11::basic_string, std::allocator > const&) Full name: CronData::setEnvVar(std::__cxx11::basic_string, std::allocator > const&, std::__cxx11::basic_string, std::allocator > const&) Source: setenvvar.cc Used By: parse.cc: Parser::executeAction(int) setHours() Full name: CronData::setHours() Source: sethours.cc Used By: parse.cc: Parser::executeAction(int) setMinutes() Full name: CronData::setMinutes() Source: setminutes.cc Used By: parse.cc: Parser::executeAction(int) setMonthOfYear() Full name: CronData::setMonthOfYear() Source: setmonthofyear.cc Used By: parse.cc: Parser::executeAction(int) setSyslog() Full name: Options::setSyslog() Source: setsyslog.cc Used By: options1.cc: Options::Options() showSet(std::ostream&, std::set, std::allocator > const&) Full name: CronEntry::showSet(std::ostream&, std::set, std::allocator > const&) Source: showset.cc Used By: insert.cc: CronEntry::insert(std::ostream&) const signalHandler(unsigned int) Full name: Daemon::signalHandler(unsigned int) Source: signalhandler.cc Used By: parentprocess.cc: Daemon::parentProcess() stop(unsigned int) Full name: Cron::stop(unsigned int) Source: stop.cc Used By: signalhandler.cc: Daemon::signalHandler(unsigned int) syslogFacility() const Full name: Options::syslogFacility() const Source: syslogfacility.cc Used By: setsyslog.cc: Options::setSyslog() syslogPriority() const Full name: Options::syslogPriority() const Source: syslogpriority.cc Used By: setsyslog.cc: Options::setSyslog() terminate() const Full name: Daemon::terminate() const Source: terminate.cc Used By: ipc.cc: Daemon::ipc() usage(std::__cxx11::basic_string, std::allocator > const&) Full name: Options::usage(std::__cxx11::basic_string, std::allocator > const&) Source: usage.cc Used By: options1.cc: Options::Options() version Full name: Icmbuild::version Source: version.cc Used By: usage.cc: Options::usage(std::__cxx11::basic_string, std::allocator > const&) writeRequest(std::ostream&, IPCFunction::Function) Full name: Cron::writeRequest(std::ostream&, IPCFunction::Function) Source: writerequest.cc Used By: handlerequests.cc: Cron::handleRequests() listrequest.cc: Daemon::listRequest() reload.cc: Daemon::reload() years Full name: Icmbuild::years Source: version.cc Used By: usage.cc: Options::usage(std::__cxx11::basic_string, std::allocator > const&) ssh-cron-1.02.00/VERSION0000644000175000017500000000015513460034475013451 0ustar frankfrank#define AUTHOR "Frank B. Brokken (f.b.brokken@rug.nl)"; #define VERSION "1.02.00" #define YEARS "2014-2019" ssh-cron-1.02.00/version.cc0000644000175000017500000000056313460034537014377 0ustar frankfrank// version.cc #include "main.ih" #include "icmconf" #ifdef USE_VERSION #include "VERSION" #endif #ifndef AUTHOR #define AUTHOR "" #endif #ifndef VERSION #define VERSION "0.00.00" #endif #ifndef YEARS #define YEARS "2012" #endif namespace Icmbuild { char version[] = VERSION; char years[] = YEARS; char author[] = AUTHOR; } ssh-cron-1.02.00/VERSION.h0000644000175000017500000000010413314143340013657 0ustar frankfrank#include "VERSION" SUBST(_CurVers_)(VERSION) SUBST(_CurYrs_)(YEARS)