Rev 102 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
45 | luk | 1 | |
2 | /// inotify cron table manipulator main file |
||
3 | /** |
||
4 | * \file ict-main.cpp |
||
102 | luk | 5 | * |
45 | luk | 6 | * inotify cron system |
102 | luk | 7 | * |
108 | luk | 8 | * Copyright (C) 2006, 2007, 2008, 2012 Lukas Jelinek, <lukas@aiken.cz> |
102 | luk | 9 | * |
45 | luk | 10 | * This program is free software; you can use it, redistribute |
11 | * it and/or modify it under the terms of the GNU General Public |
||
12 | * License, version 2 (see LICENSE-GPL). |
||
102 | luk | 13 | * |
14 | * Credits: |
||
15 | * kolter (fix for segfaulting on --user) |
||
108 | luk | 16 | * Christian Ruppert (new include to build with GCC 4.4+) |
102 | luk | 17 | * |
45 | luk | 18 | */ |
19 | |||
102 | luk | 20 | |
45 | luk | 21 | #include <argp.h> |
22 | #include <pwd.h> |
||
23 | #include <string> |
||
24 | #include <unistd.h> |
||
25 | #include <sys/stat.h> |
||
26 | #include <sys/wait.h> |
||
67 | luk | 27 | #include <sys/inotify.h> |
69 | luk | 28 | #include <fcntl.h> |
83 | luk | 29 | #include <stdlib.h> |
30 | #include <limits.h> |
||
100 | luk | 31 | #include <cstring> |
108 | luk | 32 | #include <cstdio> |
45 | luk | 33 | |
69 | luk | 34 | #include "inotify-cxx.h" |
35 | #include "appargs.h" |
||
36 | |||
55 | luk | 37 | #include "incron.h" |
45 | luk | 38 | #include "incrontab.h" |
69 | luk | 39 | #include "incroncfg.h" |
45 | luk | 40 | |
69 | luk | 41 | |
42 | /// Alternative editor |
||
67 | luk | 43 | #define INCRON_ALT_EDITOR "/etc/alternatives/editor" |
45 | luk | 44 | |
69 | luk | 45 | /// Default (hard-wired) editor |
45 | luk | 46 | #define INCRON_DEFAULT_EDITOR "vim" |
47 | |||
69 | luk | 48 | /// incrontab version string |
49 | #define INCRONTAB_VERSION INCRONTAB_NAME " " INCRON_VERSION |
||
45 | luk | 50 | |
69 | luk | 51 | /// incrontab description string |
52 | #define INCRONTAB_DESCRIPTION "incrontab - inotify cron table manipulator\n" \ |
||
100 | luk | 53 | "(c) Lukas Jelinek, 2006, 2007, 208" |
45 | luk | 54 | |
69 | luk | 55 | /// incrontab help string |
56 | #define INCRONTAB_HELP INCRONTAB_DESCRIPTION "\n\n" \ |
||
57 | "usage: incrontab [<options>] <operation>\n" \ |
||
58 | " incrontab [<options>] <FILE-TO-IMPORT>\n\n" \ |
||
59 | "<operation> may be one of the following:\n" \ |
||
60 | " -?, --about gives short information about program\n" \ |
||
61 | " -h, --help prints this help text\n" \ |
||
62 | " -l, --list lists user table\n" \ |
||
63 | " -r, --remove removes user table\n" \ |
||
108 | luk | 64 | " -e, --edit provides editing user table\n" \ |
69 | luk | 65 | " -t, --types list supported event types\n" \ |
66 | " -d, --reload request incrond to reload user table\n" \ |
||
67 | " -V, --version prints program version\n\n" \ |
||
68 | "\n" \ |
||
69 | "These options may be used:\n" \ |
||
70 | " -u <USER>, --user=<USER> overrides current user (requires root privileges)\n" \ |
||
71 | " -f <FILE>, --config=<FILE> overrides default configuration file (requires root privileges)\n\n" \ |
||
100 | luk | 72 | "For reporting bugs please use http://bts.aiken.cz\n" |
45 | luk | 73 | |
74 | |||
75 | |||
102 | luk | 76 | |
49 | luk | 77 | /// Copies a file to an user table. |
78 | /** |
||
69 | luk | 79 | * \param[in] rPath path to file |
80 | * \param[in] rUser user name |
||
49 | luk | 81 | * \return true = success, false = failure |
82 | */ |
||
69 | luk | 83 | bool copy_from_file(const std::string& rPath, const std::string& rUser) |
45 | luk | 84 | { |
69 | luk | 85 | fprintf(stderr, "copying table from file '%s'\n", rPath.c_str()); |
102 | luk | 86 | |
69 | luk | 87 | IncronTab tab; |
88 | std::string s(rPath); |
||
45 | luk | 89 | if (s == "-") |
90 | s = "/dev/stdin"; |
||
91 | if (!tab.Load(s)) { |
||
69 | luk | 92 | fprintf(stderr, "cannot load table from file '%s'\n", rPath.c_str()); |
45 | luk | 93 | return false; |
94 | } |
||
102 | luk | 95 | |
69 | luk | 96 | std::string out(IncronTab::GetUserTablePath(rUser)); |
45 | luk | 97 | if (!tab.Save(out)) { |
69 | luk | 98 | fprintf(stderr, "cannot create table for user '%s'\n", rUser.c_str()); |
45 | luk | 99 | return false; |
100 | } |
||
102 | luk | 101 | |
45 | luk | 102 | return true; |
103 | } |
||
104 | |||
49 | luk | 105 | /// Removes an user table. |
106 | /** |
||
69 | luk | 107 | * \param[in] rUser user name |
49 | luk | 108 | * \return true = success, false = failure |
102 | luk | 109 | */ |
69 | luk | 110 | bool remove_table(const std::string& rUser) |
45 | luk | 111 | { |
69 | luk | 112 | fprintf(stderr, "removing table for user '%s'\n", rUser.c_str()); |
102 | luk | 113 | |
69 | luk | 114 | std::string tp(IncronTab::GetUserTablePath(rUser)); |
102 | luk | 115 | |
73 | luk | 116 | if (unlink(tp.c_str()) != 0) { |
117 | if (errno == ENOENT) { |
||
118 | fprintf(stderr, "table for user '%s' does not exist\n", rUser.c_str()); |
||
119 | return true; |
||
120 | } |
||
121 | else { |
||
122 | fprintf(stderr, "cannot remove table for user '%s': %s\n", rUser.c_str(), strerror(errno)); |
||
123 | return false; |
||
124 | } |
||
45 | luk | 125 | } |
73 | luk | 126 | |
102 | luk | 127 | fprintf(stderr, "table for user '%s' successfully removed\n", rUser.c_str()); |
45 | luk | 128 | return true; |
129 | } |
||
130 | |||
49 | luk | 131 | /// Lists an user table. |
132 | /** |
||
69 | luk | 133 | * \param[in] rUser user name |
49 | luk | 134 | * \return true = success, false = failure |
135 | */ |
||
69 | luk | 136 | bool list_table(const std::string& rUser) |
45 | luk | 137 | { |
69 | luk | 138 | std::string tp(IncronTab::GetUserTablePath(rUser)); |
102 | luk | 139 | |
69 | luk | 140 | FILE* f = fopen(tp.c_str(), "r"); |
141 | if (f == NULL) { |
||
45 | luk | 142 | if (errno == ENOENT) { |
69 | luk | 143 | fprintf(stderr, "no table for %s\n", rUser.c_str()); |
45 | luk | 144 | return true; |
145 | } |
||
146 | else { |
||
69 | luk | 147 | fprintf(stderr, "cannot read table for '%s': %s\n", rUser.c_str(), strerror(errno)); |
45 | luk | 148 | return false; |
149 | } |
||
150 | } |
||
102 | luk | 151 | |
65 | luk | 152 | char s[1024]; |
153 | while (fgets(s, 1024, f) != NULL) { |
||
154 | fputs(s, stdout); |
||
155 | } |
||
102 | luk | 156 | |
65 | luk | 157 | fclose(f); |
102 | luk | 158 | |
65 | luk | 159 | return true; |
45 | luk | 160 | } |
161 | |||
49 | luk | 162 | /// Allows to edit an user table. |
163 | /** |
||
69 | luk | 164 | * \param[in] rUser user name |
49 | luk | 165 | * \return true = success, false = failure |
102 | luk | 166 | * |
49 | luk | 167 | * \attention This function is very complex and may contain |
168 | * various bugs including security ones. Please keep |
||
169 | * it in mind.. |
||
170 | */ |
||
69 | luk | 171 | bool edit_table(const std::string& rUser) |
45 | luk | 172 | { |
69 | luk | 173 | std::string tp(IncronTab::GetUserTablePath(rUser)); |
102 | luk | 174 | |
69 | luk | 175 | struct passwd* ppwd = getpwnam(rUser.c_str()); |
45 | luk | 176 | if (ppwd == NULL) { |
69 | luk | 177 | fprintf(stderr, "cannot find user '%s': %s\n", rUser.c_str(), strerror(errno)); |
45 | luk | 178 | return false; |
179 | } |
||
102 | luk | 180 | |
45 | luk | 181 | uid_t uid = ppwd->pw_uid; |
61 | luk | 182 | uid_t gid = ppwd->pw_gid; |
102 | luk | 183 | |
45 | luk | 184 | char s[NAME_MAX]; |
185 | strcpy(s, "/tmp/incron.table-XXXXXX"); |
||
102 | luk | 186 | |
45 | luk | 187 | uid_t iu = geteuid(); |
61 | luk | 188 | uid_t ig = getegid(); |
55 | luk | 189 | |
63 | luk | 190 | if (setegid(gid) != 0 || seteuid(uid) != 0) { |
69 | luk | 191 | fprintf(stderr, "cannot change effective UID/GID for user '%s': %s\n", rUser.c_str(), strerror(errno)); |
45 | luk | 192 | return false; |
193 | } |
||
102 | luk | 194 | |
45 | luk | 195 | int fd = mkstemp(s); |
196 | if (fd == -1) { |
||
197 | fprintf(stderr, "cannot create temporary file: %s\n", strerror(errno)); |
||
198 | return false; |
||
199 | } |
||
102 | luk | 200 | |
61 | luk | 201 | bool ok = false; |
202 | FILE* out = NULL; |
||
203 | FILE* in = NULL; |
||
204 | time_t mt = (time_t) 0; |
||
205 | const char* e = NULL; |
||
69 | luk | 206 | std::string ed; |
102 | luk | 207 | |
63 | luk | 208 | if (setegid(ig) != 0 || seteuid(iu) != 0) { |
61 | luk | 209 | fprintf(stderr, "cannot change effective UID/GID: %s\n", strerror(errno)); |
45 | luk | 210 | close(fd); |
61 | luk | 211 | goto end; |
45 | luk | 212 | } |
102 | luk | 213 | |
61 | luk | 214 | out = fdopen(fd, "w"); |
45 | luk | 215 | if (out == NULL) { |
216 | fprintf(stderr, "cannot write to temporary file: %s\n", strerror(errno)); |
||
217 | close(fd); |
||
61 | luk | 218 | goto end; |
45 | luk | 219 | } |
102 | luk | 220 | |
61 | luk | 221 | in = fopen(tp.c_str(), "r"); |
45 | luk | 222 | if (in == NULL) { |
223 | if (errno == ENOENT) { |
||
224 | in = fopen("/dev/null", "r"); |
||
225 | if (in == NULL) { |
||
69 | luk | 226 | fprintf(stderr, "cannot get empty table for '%s': %s\n", rUser.c_str(), strerror(errno)); |
45 | luk | 227 | fclose(out); |
61 | luk | 228 | goto end; |
45 | luk | 229 | } |
230 | } |
||
231 | else { |
||
69 | luk | 232 | fprintf(stderr, "cannot read old table for '%s': %s\n", rUser.c_str(), strerror(errno)); |
45 | luk | 233 | fclose(out); |
61 | luk | 234 | goto end; |
45 | luk | 235 | } |
236 | } |
||
102 | luk | 237 | |
45 | luk | 238 | char buf[1024]; |
239 | while (fgets(buf, 1024, in) != NULL) { |
||
240 | fputs(buf, out); |
||
241 | } |
||
242 | fclose(in); |
||
243 | fclose(out); |
||
102 | luk | 244 | |
45 | luk | 245 | struct stat st; |
246 | if (stat(s, &st) != 0) { |
||
247 | fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno)); |
||
61 | luk | 248 | goto end; |
45 | luk | 249 | } |
102 | luk | 250 | |
67 | luk | 251 | mt = st.st_mtime; // save modification time for detecting its change |
102 | luk | 252 | |
67 | luk | 253 | // Editor selecting algorithm: |
254 | // 1. Check EDITOR environment variable |
||
255 | // 2. Check VISUAL environment variable |
||
69 | luk | 256 | // 3. Try to get from configuration |
257 | // 4. Check presence of /etc/alternatives/editor |
||
258 | // 5. Use hard-wired editor |
||
102 | luk | 259 | |
61 | luk | 260 | e = getenv("EDITOR"); |
67 | luk | 261 | if (e == NULL) { |
262 | e = getenv("VISUAL"); |
||
263 | if (e == NULL) { |
||
102 | luk | 264 | |
69 | luk | 265 | if (!IncronCfg::GetValue("editor", ed)) |
266 | throw InotifyException("configuration is corrupted", EINVAL); |
||
102 | luk | 267 | |
69 | luk | 268 | if (!ed.empty()) { |
269 | e = ed.c_str(); |
||
270 | } |
||
271 | else { |
||
272 | if (access(INCRON_ALT_EDITOR, X_OK) == 0) |
||
273 | e = INCRON_ALT_EDITOR; |
||
274 | else |
||
275 | e = INCRON_DEFAULT_EDITOR; |
||
276 | } |
||
67 | luk | 277 | } |
278 | } |
||
102 | luk | 279 | |
67 | luk | 280 | // this block is explicite due to gotos' usage simplification |
61 | luk | 281 | { |
282 | pid_t pid = fork(); |
||
283 | if (pid == 0) { |
||
63 | luk | 284 | if (setgid(gid) != 0 || setuid(uid) != 0) { |
69 | luk | 285 | fprintf(stderr, "cannot set user '%s': %s\n", rUser.c_str(), strerror(errno)); |
61 | luk | 286 | goto end; |
102 | luk | 287 | } |
288 | |||
75 | luk | 289 | execlp(e, e, s, (const char*) NULL); |
61 | luk | 290 | _exit(1); |
45 | luk | 291 | } |
61 | luk | 292 | else if (pid > 0) { |
293 | int status; |
||
294 | if (wait(&status) != pid) { |
||
295 | perror("error while waiting for editor"); |
||
296 | goto end; |
||
297 | } |
||
298 | if (!(WIFEXITED(status)) || WEXITSTATUS(status) != 0) { |
||
299 | perror("editor finished with error"); |
||
300 | goto end; |
||
301 | } |
||
45 | luk | 302 | } |
61 | luk | 303 | else { |
304 | perror("cannot start editor"); |
||
305 | goto end; |
||
306 | } |
||
45 | luk | 307 | } |
102 | luk | 308 | |
45 | luk | 309 | if (stat(s, &st) != 0) { |
310 | fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno)); |
||
61 | luk | 311 | goto end; |
45 | luk | 312 | } |
102 | luk | 313 | |
45 | luk | 314 | if (st.st_mtime == mt) { |
315 | fprintf(stderr, "table unchanged\n"); |
||
61 | luk | 316 | ok = true; |
317 | goto end; |
||
45 | luk | 318 | } |
102 | luk | 319 | |
61 | luk | 320 | { |
69 | luk | 321 | IncronTab ict; |
63 | luk | 322 | if (ict.Load(s) && ict.Save(tp)) { |
323 | if (chmod(tp.c_str(), S_IRUSR | S_IWUSR) != 0) { |
||
324 | fprintf(stderr, "cannot change mode of temporary file: %s\n", strerror(errno)); |
||
325 | } |
||
326 | } |
||
327 | else { |
||
61 | luk | 328 | fprintf(stderr, "cannot move temporary table: %s\n", strerror(errno)); |
329 | goto end; |
||
330 | } |
||
102 | luk | 331 | |
45 | luk | 332 | } |
102 | luk | 333 | |
61 | luk | 334 | ok = true; |
45 | luk | 335 | fprintf(stderr, "table updated\n"); |
102 | luk | 336 | |
337 | end: |
||
338 | |||
61 | luk | 339 | unlink(s); |
340 | return ok; |
||
45 | luk | 341 | } |
342 | |||
343 | |||
67 | luk | 344 | /// Prints the list of all available inotify event types. |
345 | void list_types() |
||
346 | { |
||
347 | printf( "IN_ACCESS,IN_MODIFY,IN_ATTRIB,IN_CLOSE_WRITE,"\ |
||
348 | "IN_CLOSE_NOWRITE,IN_OPEN,IN_MOVED_FROM,IN_MOVED_TO,"\ |
||
349 | "IN_CREATE,IN_DELETE,IN_DELETE_SELF,IN_CLOSE,IN_MOVE,"\ |
||
350 | "IN_ONESHOT,IN_ALL_EVENTS"); |
||
102 | luk | 351 | |
67 | luk | 352 | #ifdef IN_DONT_FOLLOW |
353 | printf(",IN_DONT_FOLLOW"); |
||
354 | #endif // IN_DONT_FOLLOW |
||
355 | |||
356 | #ifdef IN_ONLYDIR |
||
357 | printf(",IN_ONLYDIR"); |
||
358 | #endif // IN_ONLYDIR |
||
359 | |||
360 | #ifdef IN_MOVE_SELF |
||
361 | printf(",IN_MOVE_SELF"); |
||
362 | #endif // IN_MOVE_SELF |
||
102 | luk | 363 | |
67 | luk | 364 | printf("\n"); |
365 | } |
||
366 | |||
69 | luk | 367 | /// Reloads an user table. |
368 | /** |
||
369 | * \param[in] rUser user name |
||
370 | * \return true = success, false = otherwise |
||
371 | */ |
||
372 | bool reload_table(const std::string& rUser) |
||
373 | { |
||
374 | fprintf(stderr, "requesting table reload for user '%s'...\n", rUser.c_str()); |
||
102 | luk | 375 | |
69 | luk | 376 | std::string tp(IncronTab::GetUserTablePath(rUser)); |
102 | luk | 377 | |
69 | luk | 378 | int fd = open(tp.c_str(), O_WRONLY | O_APPEND); |
379 | if (fd == -1) { |
||
380 | if (errno == ENOENT) { |
||
381 | fprintf(stderr, "no table for '%s'\n", rUser.c_str()); |
||
382 | return true; |
||
383 | } |
||
384 | else { |
||
385 | fprintf(stderr, "cannot access table for '%s': %s\n", rUser.c_str(), strerror(errno)); |
||
386 | return false; |
||
387 | } |
||
388 | } |
||
102 | luk | 389 | |
69 | luk | 390 | close(fd); |
102 | luk | 391 | |
69 | luk | 392 | fprintf(stderr, "request done\n"); |
102 | luk | 393 | |
69 | luk | 394 | return true; |
395 | } |
||
67 | luk | 396 | |
45 | luk | 397 | int main(int argc, char** argv) |
398 | { |
||
69 | luk | 399 | AppArgs::Init(); |
400 | |||
401 | if (!( AppArgs::AddOption("about", '?', AAT_NO_VALUE, false) |
||
402 | && AppArgs::AddOption("help", 'h', AAT_NO_VALUE, false) |
||
403 | && AppArgs::AddOption("list", 'l', AAT_NO_VALUE, false) |
||
404 | && AppArgs::AddOption("remove", 'r', AAT_NO_VALUE, false) |
||
405 | && AppArgs::AddOption("edit", 'e', AAT_NO_VALUE, false) |
||
406 | && AppArgs::AddOption("types", 't', AAT_NO_VALUE, false) |
||
407 | && AppArgs::AddOption("reload", 'd', AAT_NO_VALUE, false) |
||
408 | && AppArgs::AddOption("user", 'u', AAT_MANDATORY_VALUE, false) |
||
79 | luk | 409 | && AppArgs::AddOption("config", 'f', AAT_MANDATORY_VALUE, false) |
410 | && AppArgs::AddOption("version", 'V', AAT_NO_VALUE, false))) |
||
69 | luk | 411 | { |
412 | fprintf(stderr, "error while initializing application"); |
||
413 | return 1; |
||
414 | } |
||
102 | luk | 415 | |
69 | luk | 416 | AppArgs::Parse(argc, argv); |
102 | luk | 417 | |
69 | luk | 418 | if (AppArgs::ExistsOption("help")) { |
419 | fprintf(stderr, "%s\n", INCRONTAB_HELP); |
||
420 | return 0; |
||
421 | } |
||
102 | luk | 422 | |
69 | luk | 423 | if (AppArgs::ExistsOption("about")) { |
424 | fprintf(stderr, "%s\n", INCRONTAB_DESCRIPTION); |
||
425 | return 0; |
||
426 | } |
||
102 | luk | 427 | |
69 | luk | 428 | if (AppArgs::ExistsOption("version")) { |
429 | fprintf(stderr, "%s\n", INCRONTAB_VERSION); |
||
430 | return 0; |
||
431 | } |
||
102 | luk | 432 | |
69 | luk | 433 | bool oper = AppArgs::ExistsOption("list") |
434 | || AppArgs::ExistsOption("remove") |
||
435 | || AppArgs::ExistsOption("edit") |
||
436 | || AppArgs::ExistsOption("types") |
||
437 | || AppArgs::ExistsOption("reload"); |
||
438 | |||
102 | luk | 439 | size_t vals = AppArgs::GetValueCount(); |
440 | |||
69 | luk | 441 | if (!oper && vals == 0) { |
442 | fprintf(stderr, "invalid arguments - specify operation or source file\n"); |
||
45 | luk | 443 | return 1; |
444 | } |
||
102 | luk | 445 | |
69 | luk | 446 | if (oper && vals > 0) { |
447 | fprintf(stderr, "invalid arguments - operation and source file cannot be combined\n"); |
||
45 | luk | 448 | return 1; |
449 | } |
||
102 | luk | 450 | |
45 | luk | 451 | uid_t uid = getuid(); |
102 | luk | 452 | |
69 | luk | 453 | std::string user; |
454 | bool chuser = AppArgs::GetOption("user", user); |
||
102 | luk | 455 | |
69 | luk | 456 | if (uid != 0 && chuser) { |
457 | fprintf(stderr, "cannot override user to '%s': insufficient privileges\n", user.c_str()); |
||
45 | luk | 458 | return 1; |
459 | } |
||
102 | luk | 460 | |
461 | struct passwd* ppwd = NULL; |
||
462 | |||
463 | if (chuser) { |
||
464 | if ((ppwd = getpwnam(user.c_str())) != NULL) { |
||
465 | if ( setenv("LOGNAME", ppwd->pw_name, 1) != 0 |
||
466 | || setenv("USER", ppwd->pw_name, 1) != 0 |
||
467 | || setenv("USERNAME", ppwd->pw_name, 1) != 0 |
||
468 | || setenv("HOME", ppwd->pw_dir, 1) != 0 |
||
469 | || setenv("SHELL", ppwd->pw_shell, 1) != 0) |
||
470 | { |
||
471 | perror("cannot set environment variables"); |
||
472 | return 1; |
||
473 | } |
||
474 | } else { |
||
475 | fprintf(stderr, "user '%s' not found\n", user.c_str()); |
||
476 | return 1; |
||
477 | } |
||
478 | } else { |
||
479 | ppwd = getpwuid(uid); |
||
45 | luk | 480 | if (ppwd == NULL) { |
481 | fprintf(stderr, "cannot determine current user\n"); |
||
482 | return 1; |
||
483 | } |
||
102 | luk | 484 | user = ppwd->pw_name; |
45 | luk | 485 | } |
102 | luk | 486 | |
69 | luk | 487 | try { |
102 | luk | 488 | |
69 | luk | 489 | IncronCfg::Init(); |
102 | luk | 490 | |
69 | luk | 491 | std::string cfg(INCRON_CONFIG); |
492 | if (AppArgs::GetOption("config", cfg)) { |
||
493 | if (uid != 0) { |
||
494 | fprintf(stderr, "insufficient privileges to use custom configuration (will use default)\n"); |
||
495 | } |
||
496 | else if (euidaccess(cfg.c_str(), R_OK) != 0) { |
||
497 | perror("cannot read configuration file (will use default)"); |
||
498 | } |
||
499 | } |
||
102 | luk | 500 | |
69 | luk | 501 | IncronCfg::Load(cfg); |
102 | luk | 502 | |
69 | luk | 503 | if (!IncronTab::CheckUser(user)) { |
504 | fprintf(stderr, "user '%s' is not allowed to use incron\n", user.c_str()); |
||
505 | return 1; |
||
506 | } |
||
102 | luk | 507 | |
69 | luk | 508 | if (!oper) { |
509 | std::string file; |
||
510 | if (!AppArgs::GetValue(0, file) |
||
511 | || !copy_from_file(file, user)) |
||
512 | { |
||
45 | luk | 513 | return 1; |
69 | luk | 514 | } |
515 | } |
||
516 | else { |
||
517 | if (AppArgs::ExistsOption("list")) { |
||
518 | if (!list_table(user)) |
||
519 | return 1; |
||
520 | } |
||
521 | else if (AppArgs::ExistsOption("remove")) { |
||
522 | if (!remove_table(user)) |
||
523 | return 1; |
||
524 | } |
||
525 | else if (AppArgs::ExistsOption("edit")) { |
||
526 | if (!edit_table(user)) |
||
527 | return 1; |
||
528 | } |
||
529 | else if (AppArgs::ExistsOption("types")) { |
||
530 | list_types(); |
||
531 | } |
||
532 | else if (AppArgs::ExistsOption("reload")) { |
||
533 | if (!reload_table(user)) |
||
534 | return 1; |
||
535 | } |
||
536 | else { |
||
537 | fprintf(stderr, "invalid usage\n"); |
||
45 | luk | 538 | return 1; |
69 | luk | 539 | } |
540 | } |
||
102 | luk | 541 | |
542 | return 0; |
||
543 | |||
69 | luk | 544 | } catch (InotifyException e) { |
545 | fprintf(stderr, "*** unhandled exception occurred ***\n"); |
||
546 | fprintf(stderr, "%s\n", e.GetMessage().c_str()); |
||
547 | fprintf(stderr, "error: (%i) %s\n", e.GetErrorNumber(), strerror(e.GetErrorNumber())); |
||
102 | luk | 548 | |
69 | luk | 549 | return 1; |
45 | luk | 550 | } |
551 | } |