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