Subversion Repositories public

Rev

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
}