Subversion Repositories public

Compare Revisions

Ignore whitespace Rev 102 → Rev 101

/incron/trunk/Doxyfile
File deleted
/incron/trunk/VERSION
File deleted
\ No newline at end of file
/incron/trunk/incron.conf.5
1,4 → 1,4
.TH "incron.conf" "5" "0.5.9" "Lukas Jelinek" "incron documentation"
.TH "incron.conf" "5" "0.5.8" "Lukas Jelinek" "incron documentation"
.SH "NAME"
/etc/incron.conf \- main config file for inotify cron (incron)
.SH "DESCRIPTION"
39,6 → 39,6
.SH "SEE ALSO"
incrond(8), incrontab(1), incrontab(5)
.SH "AUTHOR"
Lukas Jelinek <lukas@aiken.cz> (please report bugs to http://bts.aiken.cz or <bugs@aiken.cz>).
Lukas Jelinek <lukas@aiken.cz>
.SH "COPYING"
This program is free software. It can be used, redistributed and/or modified under the terms of the GNU General Public License, version 2.
/incron/trunk/ict-main.cpp
2,21 → 2,18
/// inotify cron table manipulator main file
/**
* \file ict-main.cpp
*
*
* inotify cron system
*
*
* Copyright (C) 2006, 2007, 2008 Lukas Jelinek, <lukas@aiken.cz>
*
*
* This program is free software; you can use it, redistribute
* it and/or modify it under the terms of the GNU General Public
* License, version 2 (see LICENSE-GPL).
*
* Credits:
* kolter (fix for segfaulting on --user)
*
*
*/
 
 
#include <argp.h>
#include <pwd.h>
#include <string>
69,10 → 66,10
" -u <USER>, --user=<USER> overrides current user (requires root privileges)\n" \
" -f <FILE>, --config=<FILE> overrides default configuration file (requires root privileges)\n\n" \
"For reporting bugs please use http://bts.aiken.cz\n"
 
 
 
 
/// Copies a file to an user table.
/**
* \param[in] rPath path to file
82,7 → 79,7
bool copy_from_file(const std::string& rPath, const std::string& rUser)
{
fprintf(stderr, "copying table from file '%s'\n", rPath.c_str());
 
IncronTab tab;
std::string s(rPath);
if (s == "-")
91,13 → 88,13
fprintf(stderr, "cannot load table from file '%s'\n", rPath.c_str());
return false;
}
 
std::string out(IncronTab::GetUserTablePath(rUser));
if (!tab.Save(out)) {
fprintf(stderr, "cannot create table for user '%s'\n", rUser.c_str());
return false;
}
 
return true;
}
 
105,13 → 102,13
/**
* \param[in] rUser user name
* \return true = success, false = failure
*/
*/
bool remove_table(const std::string& rUser)
{
fprintf(stderr, "removing table for user '%s'\n", rUser.c_str());
 
std::string tp(IncronTab::GetUserTablePath(rUser));
 
if (unlink(tp.c_str()) != 0) {
if (errno == ENOENT) {
fprintf(stderr, "table for user '%s' does not exist\n", rUser.c_str());
123,7 → 120,7
}
}
 
fprintf(stderr, "table for user '%s' successfully removed\n", rUser.c_str());
fprintf(stderr, "table for user '%s' successfully removed\n", rUser.c_str());
return true;
}
 
135,7 → 132,7
bool list_table(const std::string& rUser)
{
std::string tp(IncronTab::GetUserTablePath(rUser));
 
FILE* f = fopen(tp.c_str(), "r");
if (f == NULL) {
if (errno == ENOENT) {
147,14 → 144,14
return false;
}
}
 
char s[1024];
while (fgets(s, 1024, f) != NULL) {
fputs(s, stdout);
}
 
fclose(f);
 
return true;
}
 
162,7 → 159,7
/**
* \param[in] rUser user name
* \return true = success, false = failure
*
*
* \attention This function is very complex and may contain
* various bugs including security ones. Please keep
* it in mind..
170,19 → 167,19
bool edit_table(const std::string& rUser)
{
std::string tp(IncronTab::GetUserTablePath(rUser));
 
struct passwd* ppwd = getpwnam(rUser.c_str());
if (ppwd == NULL) {
fprintf(stderr, "cannot find user '%s': %s\n", rUser.c_str(), strerror(errno));
return false;
}
 
uid_t uid = ppwd->pw_uid;
uid_t gid = ppwd->pw_gid;
 
char s[NAME_MAX];
strcpy(s, "/tmp/incron.table-XXXXXX");
 
uid_t iu = geteuid();
uid_t ig = getegid();
 
190,13 → 187,13
fprintf(stderr, "cannot change effective UID/GID for user '%s': %s\n", rUser.c_str(), strerror(errno));
return false;
}
 
int fd = mkstemp(s);
if (fd == -1) {
fprintf(stderr, "cannot create temporary file: %s\n", strerror(errno));
return false;
}
 
bool ok = false;
FILE* out = NULL;
FILE* in = NULL;
203,13 → 200,13
time_t mt = (time_t) 0;
const char* e = NULL;
std::string ed;
 
if (setegid(ig) != 0 || seteuid(iu) != 0) {
fprintf(stderr, "cannot change effective UID/GID: %s\n", strerror(errno));
close(fd);
goto end;
}
 
out = fdopen(fd, "w");
if (out == NULL) {
fprintf(stderr, "cannot write to temporary file: %s\n", strerror(errno));
216,7 → 213,7
close(fd);
goto end;
}
 
in = fopen(tp.c_str(), "r");
if (in == NULL) {
if (errno == ENOENT) {
233,7 → 230,7
goto end;
}
}
 
char buf[1024];
while (fgets(buf, 1024, in) != NULL) {
fputs(buf, out);
240,15 → 237,15
}
fclose(in);
fclose(out);
 
struct stat st;
if (stat(s, &st) != 0) {
fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno));
goto end;
}
 
mt = st.st_mtime; // save modification time for detecting its change
 
// Editor selecting algorithm:
// 1. Check EDITOR environment variable
// 2. Check VISUAL environment variable
255,15 → 252,15
// 3. Try to get from configuration
// 4. Check presence of /etc/alternatives/editor
// 5. Use hard-wired editor
 
e = getenv("EDITOR");
if (e == NULL) {
e = getenv("VISUAL");
if (e == NULL) {
 
if (!IncronCfg::GetValue("editor", ed))
throw InotifyException("configuration is corrupted", EINVAL);
 
if (!ed.empty()) {
e = ed.c_str();
}
275,7 → 272,7
}
}
}
 
// this block is explicite due to gotos' usage simplification
{
pid_t pid = fork();
283,8 → 280,8
if (setgid(gid) != 0 || setuid(uid) != 0) {
fprintf(stderr, "cannot set user '%s': %s\n", rUser.c_str(), strerror(errno));
goto end;
}
 
}
execlp(e, e, s, (const char*) NULL);
_exit(1);
}
304,18 → 301,18
goto end;
}
}
 
if (stat(s, &st) != 0) {
fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno));
goto end;
}
 
if (st.st_mtime == mt) {
fprintf(stderr, "table unchanged\n");
ok = true;
goto end;
}
 
{
IncronTab ict;
if (ict.Load(s) && ict.Save(tp)) {
327,14 → 324,14
fprintf(stderr, "cannot move temporary table: %s\n", strerror(errno));
goto end;
}
 
}
 
ok = true;
fprintf(stderr, "table updated\n");
 
end:
 
end:
unlink(s);
return ok;
}
347,7 → 344,7
"IN_CLOSE_NOWRITE,IN_OPEN,IN_MOVED_FROM,IN_MOVED_TO,"\
"IN_CREATE,IN_DELETE,IN_DELETE_SELF,IN_CLOSE,IN_MOVE,"\
"IN_ONESHOT,IN_ALL_EVENTS");
 
#ifdef IN_DONT_FOLLOW
printf(",IN_DONT_FOLLOW");
#endif // IN_DONT_FOLLOW
359,7 → 356,7
#ifdef IN_MOVE_SELF
printf(",IN_MOVE_SELF");
#endif // IN_MOVE_SELF
 
printf("\n");
}
 
371,9 → 368,9
bool reload_table(const std::string& rUser)
{
fprintf(stderr, "requesting table reload for user '%s'...\n", rUser.c_str());
 
std::string tp(IncronTab::GetUserTablePath(rUser));
 
int fd = open(tp.c_str(), O_WRONLY | O_APPEND);
if (fd == -1) {
if (errno == ENOENT) {
385,11 → 382,11
return false;
}
}
 
close(fd);
 
fprintf(stderr, "request done\n");
 
return true;
}
 
411,24 → 408,24
fprintf(stderr, "error while initializing application");
return 1;
}
 
AppArgs::Parse(argc, argv);
 
if (AppArgs::ExistsOption("help")) {
fprintf(stderr, "%s\n", INCRONTAB_HELP);
return 0;
}
 
if (AppArgs::ExistsOption("about")) {
fprintf(stderr, "%s\n", INCRONTAB_DESCRIPTION);
return 0;
}
 
if (AppArgs::ExistsOption("version")) {
fprintf(stderr, "%s\n", INCRONTAB_VERSION);
return 0;
}
 
bool oper = AppArgs::ExistsOption("list")
|| AppArgs::ExistsOption("remove")
|| AppArgs::ExistsOption("edit")
435,58 → 432,57
|| AppArgs::ExistsOption("types")
|| AppArgs::ExistsOption("reload");
 
size_t vals = AppArgs::GetValueCount();
 
size_t vals = AppArgs::GetValueCount();
if (!oper && vals == 0) {
fprintf(stderr, "invalid arguments - specify operation or source file\n");
return 1;
}
 
if (oper && vals > 0) {
fprintf(stderr, "invalid arguments - operation and source file cannot be combined\n");
return 1;
}
 
uid_t uid = getuid();
 
std::string user;
bool chuser = AppArgs::GetOption("user", user);
 
if (uid != 0 && chuser) {
fprintf(stderr, "cannot override user to '%s': insufficient privileges\n", user.c_str());
return 1;
}
 
struct passwd* ppwd = NULL;
 
if (chuser) {
if ((ppwd = getpwnam(user.c_str())) != NULL) {
if ( setenv("LOGNAME", ppwd->pw_name, 1) != 0
|| setenv("USER", ppwd->pw_name, 1) != 0
|| setenv("USERNAME", ppwd->pw_name, 1) != 0
|| setenv("HOME", ppwd->pw_dir, 1) != 0
|| setenv("SHELL", ppwd->pw_shell, 1) != 0)
{
perror("cannot set environment variables");
return 1;
}
} else {
fprintf(stderr, "user '%s' not found\n", user.c_str());
return 1;
}
} else {
ppwd = getpwuid(uid);
struct passwd pwd;
if (!chuser) {
struct passwd* ppwd = getpwuid(uid);
if (ppwd == NULL) {
fprintf(stderr, "cannot determine current user\n");
return 1;
}
user = ppwd->pw_name;
memcpy(&pwd, ppwd, sizeof(pwd));
user = pwd.pw_name;
}
 
else if (getpwnam(user.c_str()) == NULL) {
fprintf(stderr, "user '%s' not found\n", user.c_str());
return 1;
}
else if ( setenv("LOGNAME", pwd.pw_name, 1) != 0
|| setenv("USER", pwd.pw_name, 1) != 0
|| setenv("USERNAME", pwd.pw_name, 1) != 0
|| setenv("HOME", pwd.pw_dir, 1) != 0
|| setenv("SHELL", pwd.pw_shell, 1) != 0)
{
perror("cannot set environment variables");
return 1;
}
try {
 
IncronCfg::Init();
 
std::string cfg(INCRON_CONFIG);
if (AppArgs::GetOption("config", cfg)) {
if (uid != 0) {
496,14 → 492,14
perror("cannot read configuration file (will use default)");
}
}
 
IncronCfg::Load(cfg);
 
if (!IncronTab::CheckUser(user)) {
fprintf(stderr, "user '%s' is not allowed to use incron\n", user.c_str());
return 1;
}
 
if (!oper) {
std::string file;
if (!AppArgs::GetValue(0, file)
537,14 → 533,14
return 1;
}
}
 
return 0;
 
return 0;
} catch (InotifyException e) {
fprintf(stderr, "*** unhandled exception occurred ***\n");
fprintf(stderr, "%s\n", e.GetMessage().c_str());
fprintf(stderr, "error: (%i) %s\n", e.GetErrorNumber(), strerror(e.GetErrorNumber()));
 
return 1;
}
}
/incron/trunk/incrontab.5
1,4 → 1,4
.TH "incrontab" "5" "0.5.9" "Lukas Jelinek" "incron documentation"
.TH "incrontab" "5" "0.5.8" "Lukas Jelinek" "incron documentation"
.SH "NAME"
incrontab \- tables for driving inotify cron (incron)
.SH "DESCRIPTION"
93,6 → 93,6
.SH "SEE ALSO"
incrond(8), incrontab(1), incron.conf(5)
.SH "AUTHOR"
Lukas Jelinek <lukas@aiken.cz> (please report bugs to http://bts.aiken.cz or <bugs@aiken.cz>).
Lukas Jelinek <lukas@aiken.cz>
.SH "COPYING"
This program is free software. It can be used, redistributed and/or modified under the terms of the GNU General Public License, version 2.
/incron/trunk/CHANGELOG
1,10 → 1,3
0.5.9 2009-06-21
* spaces in event-related file names now handled correctly (#0000174)
* crashing on 'incrontab --user' fixed (#0000187)
* man pages improved (bug reporting info as of #0000407)
* Makefile improved ('release-clean' also removes 'doc')
 
 
0.5.8 2008-12-29
* more includes added for GCC 4.3 compatibility (#0000178)
* typo in help messages fixed (#0000172)
/incron/trunk/LICENSE-X11
1,4 → 1,4
Copyright (c) 2006, 2007, 2008, 2009 Lukas Jelinek
Copyright (c) 2006, 2007, 2008 Lukas Jelinek
 
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
/incron/trunk/README
1,7 → 1,7
 
inotify cron system
 
(c) Lukas Jelinek, 2006, 2007, 2008, 2009
(c) Lukas Jelinek, 2006, 2007, 2008
 
1. About
2. Requirements
20,7 → 20,6
The difference is that the inotify cron handles filesystem events
rather than time periods.
 
 
2. Requirements
* Linux kernel 2.6.13 or later (with inotify compiled in)
* inotify headers (inotify.h, sometimes inotify-syscalls.h) installed in
46,13 → 45,7
/etc/incron.conf (you can also use -f <config> for one-time
use of a custom configuration file).
 
Making a release of the source tree relies on the 'VERSION' file.
The file should contain only a simple version string such as '0.5.9'
or (if you wish) something more comlex (e.g. '0.5.9-improved').
The doxygen program must be installed and its control file 'Doxygen'
created for generating the API documentation.
 
 
4. How to use
The incron daemon (incrond) must be run under root (typically from
runlevel script etc.). It loads the current user tables and hooks
/incron/trunk/incrond.8
1,4 → 1,4
.TH "incrond" "8" "0.5.9" "Lukas Jelinek" "incron documentation"
.TH "incrond" "8" "0.5.8" "Lukas Jelinek" "incron documentation"
.SH "NAME"
incrond \- inotify cron (incron) daemon
 
32,6 → 32,6
.SH "BUGS"
incrond is currently not resistent against looping. Recursive monitoring (whole subtrees) has not been implemented yet.
.SH "AUTHOR"
Lukas Jelinek <lukas@aiken.cz> (please report bugs to http://bts.aiken.cz or <bugs@aiken.cz>).
Lukas Jelinek <lukas@aiken.cz>
.SH "COPYING"
This program is free software. It can be used, redistributed and/or modified under the terms of the GNU General Public License, version 2.
/incron/trunk/usertable.cpp
2,19 → 2,18
/// inotify cron daemon user tables implementation
/**
* \file usertable.cpp
*
*
* inotify cron system
*
*
* Copyright (C) 2006, 2007, 2008 Lukas Jelinek, <lukas@aiken.cz>
*
*
* This program is free software; you can use it, redistribute
* it and/or modify it under the terms of the GNU General Public
* License, version 2 (see LICENSE-GPL).
*
*
* Credits:
* David Santinoli (supplementary groups)
* Boris Lechner (spaces in event-related file names)
*
*
*/
 
 
30,7 → 29,6
 
#include "usertable.h"
#include "incroncfg.h"
#include "incrontab.h"
 
#ifdef IN_DONT_FOLLOW
#define DONT_FOLLOW(mask) InotifyEvent::IsType(mask, IN_DONT_FOLLOW)
80,17 → 78,17
while (read(m_pPoll[0].fd, &c, 1) > 0) {}
m_pPoll[0].revents = 0;
}
 
// process table management events if any
if (m_pPoll[1].revents & POLLIN) {
ProcessMgmtEvents();
ProcessMgmtEvents();
m_pPoll[1].revents = 0;
}
 
InotifyEvent evt;
 
for (size_t i=2; i<m_size; i++) {
 
// process events if occurred
if (m_pPoll[i].revents & POLLIN) {
FDUT_MAP::iterator it = m_maps.find(m_pPoll[i].fd);
97,7 → 95,7
if (it != m_maps.end()) {
Inotify* pIn = ((*it).second)->GetInotify();
pIn->WaitForEvents(true);
 
// process events for this object
while (pIn->GetEvent(evt)) {
((*it).second)->OnEvent(evt);
106,10 → 104,10
m_pPoll[i].revents = 0;
}
}
 
return pipe;
}
 
void EventDispatcher::Register(UserTable* pTab)
{
if (pTab != NULL) {
123,7 → 121,7
}
}
}
 
void EventDispatcher::Unregister(UserTable* pTab)
{
FDUT_MAP::iterator it = m_maps.find(pTab->GetInotify()->GetDescriptor());
138,21 → 136,21
// delete old data if exists
if (m_pPoll != NULL)
delete[] m_pPoll;
 
// allocate memory
m_size = m_maps.size() + 2;
m_pPoll = new struct pollfd[m_size];
 
// add pipe descriptor
m_pPoll[0].fd = m_iPipeFd;
m_pPoll[0].events = POLLIN;
m_pPoll[0].revents = 0;
 
// add table management descriptor
m_pPoll[1].fd = m_iMgmtFd;
m_pPoll[1].events = POLLIN;
m_pPoll[1].revents = 0;
 
// add all inotify descriptors
FDUT_MAP::iterator it = m_maps.begin();
for (size_t i=2; i<m_size; i++, it++) {
165,9 → 163,9
void EventDispatcher::ProcessMgmtEvents()
{
m_pIn->WaitForEvents(true);
 
InotifyEvent e;
 
while (m_pIn->GetEvent(e)) {
if (e.GetWatch() == m_pSys) {
if (e.IsType(IN_DELETE_SELF) || e.IsType(IN_UNMOUNT)) {
238,7 → 236,7
m_fSysTable(fSysTable)
{
m_pEd = pEd;
 
m_in.SetNonBlock(true);
m_in.SetCloseOnExec(true);
}
247,22 → 245,22
{
Dispose();
}
 
void UserTable::Load()
{
m_tab.Load(m_fSysTable
? IncronTab::GetSystemTablePath(m_user)
: IncronTab::GetUserTablePath(m_user));
 
int cnt = m_tab.GetCount();
for (int i=0; i<cnt; i++) {
IncronTabEntry& rE = m_tab.GetEntry(i);
InotifyWatch* pW = new InotifyWatch(rE.GetPath(), rE.GetMask());
 
// warning only - permissions may change later
if (!(m_fSysTable || MayAccess(rE.GetPath(), DONT_FOLLOW(rE.GetMask()))))
syslog(LOG_WARNING, "access denied on %s - events will be discarded silently", rE.GetPath().c_str());
 
try {
m_in.Add(pW);
m_map.insert(IWCE_MAP::value_type(pW, &rE));
274,7 → 272,7
delete pW;
}
}
 
m_pEd->Register(this);
}
 
281,12 → 279,12
void UserTable::Dispose()
{
m_pEd->Unregister(this);
 
IWCE_MAP::iterator it = m_map.begin();
while (it != m_map.end()) {
InotifyWatch* pW = (*it).first;
m_in.Remove(pW);
 
PROC_MAP::iterator it2 = s_procMap.begin();
while (it2 != s_procMap.end()) {
if ((*it2).second.pWatch == pW) {
298,27 → 296,27
it2++;
}
}
 
delete pW;
it++;
}
 
m_map.clear();
}
 
void UserTable::OnEvent(InotifyEvent& rEvt)
{
InotifyWatch* pW = rEvt.GetWatch();
IncronTabEntry* pE = FindEntry(pW);
 
// no entry found - this shouldn't occur
if (pE == NULL)
return;
 
// discard event if user has no access rights to watch path
if (!(m_fSysTable || MayAccess(pW->GetPath(), DONT_FOLLOW(rEvt.GetMask()))))
return;
 
std::string cmd;
const std::string& cs = pE->GetCmd();
size_t pos = 0;
338,7 → 336,7
oldpos = pos + 2;
}
else if (cs[px] == '#') { // file name
cmd.append(IncronTabEntry::GetSafePath(rEvt.GetName()));
cmd.append(rEvt.GetName());
oldpos = pos + 2;
}
else if (cs[px] == '%') { // mask symbols
363,9 → 361,9
cmd.append(cs.substr(oldpos, pos-oldpos));
oldpos = pos + 1;
}
}
}
cmd.append(cs.substr(oldpos));
 
int argc;
char** argv;
if (!PrepareArgs(cmd, argc, argv)) {
372,18 → 370,18
syslog(LOG_ERR, "cannot prepare command arguments");
return;
}
 
if (m_fSysTable)
syslog(LOG_INFO, "(system::%s) CMD (%s)", m_user.c_str(), cmd.c_str());
else
syslog(LOG_INFO, "(%s) CMD (%s)", m_user.c_str(), cmd.c_str());
 
if (pE->IsNoLoop())
pW->SetEnabled(false);
 
pid_t pid = fork();
if (pid == 0) {
 
// for system table
if (m_fSysTable) {
if (execvp(argv[0], argv) != 0) // exec failed
407,16 → 405,16
pd.onDone = NULL;
pd.pWatch = NULL;
}
 
s_procMap.insert(PROC_MAP::value_type(pid, pd));
}
else {
if (pE->IsNoLoop())
pW->SetEnabled(true);
 
syslog(LOG_ERR, "cannot fork process: %s", strerror(errno));
}
 
CleanupArgs(argc, argv);
}
 
425,7 → 423,7
IWCE_MAP::iterator it = m_map.find(pWatch);
if (it == m_map.end())
return NULL;
 
return (*it).second;
}
 
433,20 → 431,20
{
if (rCmd.empty())
return false;
 
StringTokenizer tok(rCmd, ' ', '\\');
std::deque<std::string> args;
while (tok.HasMoreTokens()) {
args.push_back(tok.GetNextToken());
}
 
if (args.empty())
return false;
 
argc = (int) args.size();
argv = new char*[argc+1];
argv[argc] = NULL;
 
for (int i=0; i<argc; i++) {
const std::string& s = args[i];
size_t len = s.length();
453,7 → 451,7
argv[i] = new char[len+1];
strcpy(argv[i], s.c_str());
}
 
return true;
}
 
462,7 → 460,7
for (int i=0; i<argc; i++) {
delete[] argv[i];
}
 
delete[] argv;
}
 
478,7 → 476,7
(*pd.onDone)(pd.pWatch);
s_procMap.erase(it);
}
}
}
}
 
bool UserTable::MayAccess(const std::string& rPath, bool fNoFollow) const
490,25 → 488,25
: stat(rPath.c_str(), &st);
if (res != 0)
return false; // retrieving permissions failed
 
// file accessible to everyone
if (st.st_mode & S_IRWXO)
return true;
 
// retrieve user data
struct passwd* pwd = getpwnam(m_user.c_str());
 
// root may always access
if (pwd->pw_uid == 0)
return true;
 
// file accessible to group
// file accesible to group
if (st.st_mode & S_IRWXG) {
 
// user's primary group
if (pwd != NULL && pwd->pw_gid == st.st_gid)
return true;
 
// now check group database
struct group *gr = getgrgid(st.st_gid);
if (gr != NULL) {
521,13 → 519,13
}
}
}
 
// file accessible to owner
if (st.st_mode & S_IRWXU) {
if (st.st_mode & S_IRWXU) {
if (pwd != NULL && pwd->pw_uid == st.st_uid)
return true;
}
 
return false; // no access right found
}
 
541,11 → 539,11
{
goto failed;
}
 
if (pwd->pw_uid != 0) {
if (pwd->pw_uid != 0) {
if (clearenv() != 0)
goto failed;
 
if ( setenv("LOGNAME", pwd->pw_name, 1) != 0
|| setenv("USER", pwd->pw_name, 1) != 0
|| setenv("USERNAME", pwd->pw_name, 1) != 0
556,11 → 554,11
goto failed;
}
}
 
execvp(argv[0], argv); // this may return only on failure
 
failed:
 
syslog(LOG_ERR, "cannot exec process: %s", strerror(errno));
_exit(1);
}
/incron/trunk/COPYING
1,6 → 1,6
inotify cron system
Copyright (C) 2006,2007,2008,2009 Lukas Jelinek, <lukas@aiken.cz>
Copyright (C) 2006,2007,2008 Lukas Jelinek, <lukas@aiken.cz>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License,
/incron/trunk/incron.h
2,18 → 2,18
/// inotify cron basic definition file
/**
* \file incron.h
*
*
* inotify cron system
*
* Copyright (C) 2006, 2007, 2008, 2009 Lukas Jelinek, <lukas@aiken.cz>
*
*
* Copyright (C) 2006, 2007, 2008 Lukas Jelinek, <lukas@aiken.cz>
*
* This program is free software; you can use it, redistribute
* it and/or modify it under the terms of the GNU General Public
* License, version 2 (see LICENSE-GPL).
*
*
*/
 
 
#ifndef _INCRON_H_
#define _INCRON_H_
 
27,7 → 27,7
#define INCRONTAB_NAME "incrontab"
 
/// Application version (release)
#define INCRON_VERSION "0.5.9"
#define INCRON_VERSION "0.5.8"
 
/// Address for sending bugs
#define INCRON_BUG_ADDRESS "<bugs@aiken.cz>"
/incron/trunk/incrontab.1
1,4 → 1,4
.TH "incrontab" "1" "0.5.9" "Lukas Jelinek" "incron documentation"
.TH "incrontab" "1" "0.5.8" "Lukas Jelinek" "incron documentation"
.SH "NAME"
incrontab \- table manipulator for inotify cron (incron)
.SH "SYNOPSIS"
48,6 → 48,6
.SH "SEE ALSO"
incrond(8), incrontab(5), incron.conf(5)
.SH "AUTHOR"
Lukas Jelinek <lukas@aiken.cz> (please report bugs to http://bts.aiken.cz or <bugs@aiken.cz>).
Lukas Jelinek <lukas@aiken.cz>
.SH "COPYING"
This program is free software. It can be used, redistributed and/or modified under the terms of the GNU General Public License, version 2.
/incron/trunk/Makefile
99,7 → 99,6
rm -rf $(RELEASEDIR)
 
release-clean:
rm -rf doc
rm -f $(RELEASE).tar.bz2
rm -f $(RELEASE).tar.gz
rm -f $(RELEASE).zip