/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to plugins.d/splashy.c

  • Committer: Teddy Hogeborn
  • Date: 2008-12-10 01:26:02 UTC
  • mfrom: (237.1.2 mandos)
  • Revision ID: teddy@fukt.bsnet.se-20081210012602-vhz3h75xkj24t340
First version of a somewhat complete D-Bus server interface.  Also
change user/group name to "_mandos".

* debian/mandos.postinst: Rename old "mandos" user and group to
                          "_mandos"; create "_mandos" user and group
                          if none exist.
* debian/mandos-client.postinst: - '' -

* initramfs-tools-hook: Try "_mandos" before "mandos" as user and
                        group name.

* mandos (_datetime_to_dbus_struct): New; was previously local.
  (Client.started): Renamed to "last_started".  All users changed.
  (Client.started): New; boolean.
  (Client.dbus_object_path): New.
  (Client.check_command): Renamed to "checker_command".  All users
                          changed.
  (Client.__init__): Set and use "self.dbus_object_path".  Set
                     "self.started".
  (Client.start): Update "self.started".  Emit "self.PropertyChanged"
                  signals for both "started" and "last_started".
  (Client.stop): Update "self.started".  Emit "self.PropertyChanged"
                 signal for "started".
  (Client.checker_callback): Take additional "command" argument.  All
                             callers changed. Emit
                             "self.PropertyChanged" signal.
  (Client.bump_timeout): Emit "self.PropertyChanged" signal for
                         "last_checked_ok".
  (Client.start_checker): Emit "self.PropertyChanged" signal for
                          "checker_running".
  (Client.stop_checker): Emit "self.PropertyChanged" signal for
                         "checker_running".
  (Client.still_valid): Bug fix: use "getattr(self, started, False)"
                        instead of "self.started" in case this client
                        object is so new that the "started" attribute
                        has not been created yet.
  (Client.IntervalChanged, Client.CheckerIsRunning, Client.GetChecker,
  Client.GetCreated, Client.GetFingerprint, Client.GetHost,
  Client.GetInterval, Client.GetName, Client.GetStarted,
  Client.GetTimeout, Client.StateChanged, Client.TimeoutChanged):
  Removed; all callers changed.
  (Client.CheckerCompleted): Add "condition" and "command" arguments.
                             All callers changed.
  (Client.GetAllProperties, Client.PropertyChanged): New.
  (Client.StillValid): Renamed to "IsStillValid".
  (Client.StartChecker): Changed to its own function to avoid the
                         return value from "Client.start_checker()".
  (Client.Stop): Changed to its own function to avoid the return value
                 from "Client.stop()".
  (main): Try "_mandos" before "mandos" as user and group name.
          Removed inner function "remove_from_clients".  New inner
          class "MandosServer".

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*  -*- coding: utf-8 -*- */
2
2
/*
3
 
 * Splashy - Read a password from splashy and output it
4
 
 * 
5
 
 * Copyright © 2008-2018, 2021-2022 Teddy Hogeborn
6
 
 * Copyright © 2008-2018, 2021-2022 Björn Påhlsson
7
 
 * 
8
 
 * This file is part of Mandos.
9
 
 * 
10
 
 * Mandos is free software: you can redistribute it and/or modify it
11
 
 * under the terms of the GNU General Public License as published by
12
 
 * the Free Software Foundation, either version 3 of the License, or
13
 
 * (at your option) any later version.
14
 
 * 
15
 
 * Mandos is distributed in the hope that it will be useful, but
 
3
 * Passprompt - Read a password from splashy and output it
 
4
 * 
 
5
 * Copyright © 2008 Teddy Hogeborn
 
6
 * Copyright © 2008 Björn Påhlsson
 
7
 * 
 
8
 * This program is free software: you can redistribute it and/or
 
9
 * modify it under the terms of the GNU General Public License as
 
10
 * published by the Free Software Foundation, either version 3 of the
 
11
 * License, or (at your option) any later version.
 
12
 * 
 
13
 * This program is distributed in the hope that it will be useful, but
16
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
17
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
16
 * General Public License for more details.
19
17
 * 
20
18
 * You should have received a copy of the GNU General Public License
21
 
 * along with Mandos.  If not, see <http://www.gnu.org/licenses/>.
 
19
 * along with this program.  If not, see
 
20
 * <http://www.gnu.org/licenses/>.
22
21
 * 
23
 
 * Contact the authors at <mandos@recompile.se>.
 
22
 * Contact the authors at <https://www.fukt.bsnet.se/~belorn/> and
 
23
 * <https://www.fukt.bsnet.se/~teddy/>.
24
24
 */
25
25
 
26
 
#define _GNU_SOURCE             /* vasprintf(),
27
 
                                   program_invocation_short_name,
28
 
                                   asprintf(), TEMP_FAILURE_RETRY() */
29
 
#include <sys/types.h>          /* sig_atomic_t, pid_t, setuid(),
30
 
                                   geteuid(), setsid() */
31
 
#include <stdarg.h>             /* va_list, va_start(), vfprintf() */
32
 
#include <stdio.h>              /* vasprintf(), fprintf(), stderr,
33
 
                                   vfprintf(), asprintf() */
34
 
#include <errno.h>              /* program_invocation_short_name,
35
 
                                   errno, EACCES, ENOTDIR, ELOOP,
36
 
                                   ENOENT, ENAMETOOLONG, EMFILE,
37
 
                                   ENFILE, ENOMEM, ENOEXEC, EINVAL,
38
 
                                   E2BIG, EFAULT, EIO, ETXTBSY,
39
 
                                   EISDIR, ELIBBAD, EPERM, EINTR,
40
 
                                   ECHILD */
41
 
#include <string.h>             /* strerror(), memcmp() */
42
 
#include <error.h>              /* error() */
43
 
#include <stdlib.h>             /* free(), EXIT_FAILURE, getenv(),
44
 
                                   EXIT_SUCCESS, abort() */
 
26
#define _GNU_SOURCE             /* asprintf() */
 
27
#include <signal.h>             /* sig_atomic_t, struct sigaction,
 
28
                                   sigemptyset(), sigaddset(), SIGINT,
 
29
                                   SIGHUP, SIGTERM, sigaction,
 
30
                                   SIG_IGN, kill(), SIGKILL */
45
31
#include <stddef.h>             /* NULL */
46
 
#include <dirent.h>             /* DIR, opendir(), struct dirent,
47
 
                                   readdir(), closedir() */
48
 
#include <sysexits.h>           /* EX_OSERR, EX_OSFILE,
49
 
                                   EX_UNAVAILABLE */
50
 
#include <inttypes.h>           /* intmax_t, strtoimax() */
51
 
#include <iso646.h>             /* or, not, and */
52
 
#include <unistd.h>             /* ssize_t, readlink(), fork(),
53
 
                                   execl(), _exit(),
54
 
                                   TEMP_FAILURE_RETRY(), sleep(),
55
 
                                   setuid(), geteuid(), setsid(),
56
 
                                   chdir(), dup2(), STDERR_FILENO,
57
 
                                   STDOUT_FILENO, pause() */
58
 
#include <sys/stat.h>           /* struct stat, lstat(), S_ISLNK() */
59
 
#include <signal.h>             /* struct sigaction, sigemptyset(),
60
 
                                   sigaddset(), SIGINT, SIGHUP,
61
 
                                   SIGTERM, SIG_IGN, kill(), SIGKILL,
62
 
                                   SIG_DFL, raise() */
 
32
#include <stdlib.h>             /* getenv() */
 
33
#include <stdio.h>              /* asprintf(), perror() */
 
34
#include <stdlib.h>             /* EXIT_FAILURE, free(), strtoul(),
 
35
                                   EXIT_SUCCESS */
 
36
#include <sys/types.h>          /* pid_t, DIR, struct dirent,
 
37
                                   ssize_t */
 
38
#include <dirent.h>             /* opendir(), readdir(), closedir() */
 
39
#include <sys/stat.h>           /* struct stat, lstat(), S_ISLNK */
 
40
#include <iso646.h>             /* not, or, and */
 
41
#include <unistd.h>             /* readlink(), fork(), execl(),
 
42
                                   sleep(), dup2() STDERR_FILENO,
 
43
                                   STDOUT_FILENO, _exit() */
 
44
#include <string.h>             /* memcmp() */
 
45
#include <errno.h>              /* errno */
63
46
#include <sys/wait.h>           /* waitpid(), WIFEXITED(),
64
47
                                   WEXITSTATUS() */
65
48
 
66
49
sig_atomic_t interrupted_by_signal = 0;
67
 
int signal_received;
68
 
 
69
 
/* Function to use when printing errors */
70
 
__attribute__((format (gnu_printf, 3, 4)))
71
 
void error_plus(int status, int errnum, const char *formatstring,
72
 
                ...){
73
 
  va_list ap;
74
 
  char *text;
75
 
  int ret;
76
 
  
77
 
  va_start(ap, formatstring);
78
 
  ret = vasprintf(&text, formatstring, ap);
79
 
  if(ret == -1){
80
 
    fprintf(stderr, "Mandos plugin %s: ",
81
 
            program_invocation_short_name);
82
 
    vfprintf(stderr, formatstring, ap);
83
 
    fprintf(stderr, ": ");
84
 
    fprintf(stderr, "%s\n", strerror(errnum));
85
 
    error(status, errno, "vasprintf while printing error");
86
 
    return;
87
 
  }
88
 
  fprintf(stderr, "Mandos plugin ");
89
 
  error(status, errnum, "%s", text);
90
 
  free(text);
91
 
}
92
 
 
93
 
 
94
 
static void termination_handler(int signum){
95
 
  if(interrupted_by_signal){
96
 
    return;
97
 
  }
 
50
 
 
51
static void termination_handler(__attribute__((unused))int signum){
98
52
  interrupted_by_signal = 1;
99
 
  signal_received = signum;
100
53
}
101
54
 
102
55
int main(__attribute__((unused))int argc,
103
56
         __attribute__((unused))char **argv){
104
57
  int ret = 0;
 
58
  
 
59
  /* Create prompt string */
105
60
  char *prompt = NULL;
106
 
  DIR *proc_dir = NULL;
107
 
  pid_t splashy_pid = 0;
108
 
  pid_t splashy_command_pid = 0;
109
 
  int exitstatus = EXIT_FAILURE;
110
 
  
111
 
  /* Create prompt string */
112
61
  {
113
62
    const char *const cryptsource = getenv("cryptsource");
114
63
    const char *const crypttarget = getenv("crypttarget");
131
80
      }
132
81
    }
133
82
    if(ret == -1){
134
 
      prompt = NULL;
135
 
      exitstatus = EX_OSERR;
136
 
      goto failure;
 
83
      return EXIT_FAILURE;
137
84
    }
138
85
  }
139
86
  
140
87
  /* Find splashy process */
 
88
  pid_t splashy_pid = 0;
141
89
  {
142
90
    const char splashy_name[] = "/sbin/splashy";
143
 
    proc_dir = opendir("/proc");
 
91
    DIR *proc_dir = opendir("/proc");
144
92
    if(proc_dir == NULL){
145
 
      int e = errno;
146
 
      error_plus(0, errno, "opendir");
147
 
      switch(e){
148
 
      case EACCES:
149
 
      case ENOTDIR:
150
 
      case ELOOP:
151
 
      case ENOENT:
152
 
      default:
153
 
        exitstatus = EX_OSFILE;
154
 
        break;
155
 
      case ENAMETOOLONG:
156
 
      case EMFILE:
157
 
      case ENFILE:
158
 
      case ENOMEM:
159
 
        exitstatus = EX_OSERR;
160
 
        break;
161
 
      }
162
 
      goto failure;
 
93
      free(prompt);
 
94
      perror("opendir");
 
95
      return EXIT_FAILURE;
163
96
    }
164
97
    for(struct dirent *proc_ent = readdir(proc_dir);
165
98
        proc_ent != NULL;
166
99
        proc_ent = readdir(proc_dir)){
167
 
      pid_t pid;
168
 
      {
169
 
        intmax_t tmpmax;
170
 
        char *tmp;
171
 
        errno = 0;
172
 
        tmpmax = strtoimax(proc_ent->d_name, &tmp, 10);
173
 
        if(errno != 0 or tmp == proc_ent->d_name or *tmp != '\0'
174
 
           or tmpmax != (pid_t)tmpmax){
175
 
          /* Not a process */
176
 
          continue;
177
 
        }
178
 
        pid = (pid_t)tmpmax;
 
100
      pid_t pid = (pid_t) strtoul(proc_ent->d_name, NULL, 10);
 
101
      if(pid == 0){
 
102
        /* Not a process */
 
103
        continue;
179
104
      }
180
105
      /* Find the executable name by doing readlink() on the
181
106
         /proc/<pid>/exe link */
185
110
        char *exe_link;
186
111
        ret = asprintf(&exe_link, "/proc/%s/exe", proc_ent->d_name);
187
112
        if(ret == -1){
188
 
          error_plus(0, errno, "asprintf");
189
 
          exitstatus = EX_OSERR;
190
 
          goto failure;
 
113
          perror("asprintf");
 
114
          free(prompt);
 
115
          closedir(proc_dir);
 
116
          return EXIT_FAILURE;
191
117
        }
192
118
        
193
119
        /* Check that it refers to a symlink owned by root:root */
194
120
        struct stat exe_stat;
195
121
        ret = lstat(exe_link, &exe_stat);
196
122
        if(ret == -1){
197
 
          if(errno == ENOENT){
198
 
            free(exe_link);
199
 
            continue;
200
 
          }
201
 
          int e = errno;
202
 
          error_plus(0, errno, "lstat");
 
123
          perror("lstat");
203
124
          free(exe_link);
204
 
          switch(e){
205
 
          case EACCES:
206
 
          case ENOTDIR:
207
 
          case ELOOP:
208
 
          default:
209
 
            exitstatus = EX_OSFILE;
210
 
            break;
211
 
          case ENAMETOOLONG:
212
 
            exitstatus = EX_OSERR;
213
 
            break;
214
 
          }
215
 
          goto failure;
 
125
          free(prompt);
 
126
          closedir(proc_dir);
 
127
          return EXIT_FAILURE;
216
128
        }
217
129
        if(not S_ISLNK(exe_stat.st_mode)
218
130
           or exe_stat.st_uid != 0
232
144
      }
233
145
    }
234
146
    closedir(proc_dir);
235
 
    proc_dir = NULL;
236
147
  }
237
148
  if(splashy_pid == 0){
238
 
    exitstatus = EX_UNAVAILABLE;
239
 
    goto failure;
 
149
    free(prompt);
 
150
    return EXIT_FAILURE;
240
151
  }
241
152
  
242
153
  /* Set up the signal handler */
245
156
      new_action = { .sa_handler = termination_handler,
246
157
                     .sa_flags = 0 };
247
158
    sigemptyset(&new_action.sa_mask);
248
 
    ret = sigaddset(&new_action.sa_mask, SIGINT);
249
 
    if(ret == -1){
250
 
      error_plus(0, errno, "sigaddset");
251
 
      exitstatus = EX_OSERR;
252
 
      goto failure;
253
 
    }
254
 
    ret = sigaddset(&new_action.sa_mask, SIGHUP);
255
 
    if(ret == -1){
256
 
      error_plus(0, errno, "sigaddset");
257
 
      exitstatus = EX_OSERR;
258
 
      goto failure;
259
 
    }
260
 
    ret = sigaddset(&new_action.sa_mask, SIGTERM);
261
 
    if(ret == -1){
262
 
      error_plus(0, errno, "sigaddset");
263
 
      exitstatus = EX_OSERR;
264
 
      goto failure;
265
 
    }
 
159
    sigaddset(&new_action.sa_mask, SIGINT);
 
160
    sigaddset(&new_action.sa_mask, SIGHUP);
 
161
    sigaddset(&new_action.sa_mask, SIGTERM);
266
162
    ret = sigaction(SIGINT, NULL, &old_action);
267
163
    if(ret == -1){
268
 
      error_plus(0, errno, "sigaction");
269
 
      exitstatus = EX_OSERR;
270
 
      goto failure;
 
164
      perror("sigaction");
 
165
      free(prompt);
 
166
      return EXIT_FAILURE;
271
167
    }
272
168
    if(old_action.sa_handler != SIG_IGN){
273
169
      ret = sigaction(SIGINT, &new_action, NULL);
274
170
      if(ret == -1){
275
 
        error_plus(0, errno, "sigaction");
276
 
        exitstatus = EX_OSERR;
277
 
        goto failure;
 
171
        perror("sigaction");
 
172
        free(prompt);
 
173
        return EXIT_FAILURE;
278
174
      }
279
175
    }
280
176
    ret = sigaction(SIGHUP, NULL, &old_action);
281
177
    if(ret == -1){
282
 
      error_plus(0, errno, "sigaction");
283
 
      exitstatus = EX_OSERR;
284
 
      goto failure;
 
178
      perror("sigaction");
 
179
      free(prompt);
 
180
      return EXIT_FAILURE;
285
181
    }
286
182
    if(old_action.sa_handler != SIG_IGN){
287
183
      ret = sigaction(SIGHUP, &new_action, NULL);
288
184
      if(ret == -1){
289
 
        error_plus(0, errno, "sigaction");
290
 
        exitstatus = EX_OSERR;
291
 
        goto failure;
 
185
        perror("sigaction");
 
186
        free(prompt);
 
187
        return EXIT_FAILURE;
292
188
      }
293
189
    }
294
190
    ret = sigaction(SIGTERM, NULL, &old_action);
295
191
    if(ret == -1){
296
 
      error_plus(0, errno, "sigaction");
297
 
      exitstatus = EX_OSERR;
298
 
      goto failure;
 
192
      perror("sigaction");
 
193
      free(prompt);
 
194
      return EXIT_FAILURE;
299
195
    }
300
196
    if(old_action.sa_handler != SIG_IGN){
301
197
      ret = sigaction(SIGTERM, &new_action, NULL);
302
198
      if(ret == -1){
303
 
        error_plus(0, errno, "sigaction");
304
 
        exitstatus = EX_OSERR;
305
 
        goto failure;
 
199
        perror("sigaction");
 
200
        free(prompt);
 
201
        return EXIT_FAILURE;
306
202
      }
307
203
    }
308
204
  }
309
205
  
310
 
  if(interrupted_by_signal){
311
 
    goto failure;
312
 
  }
313
 
  
314
206
  /* Fork off the splashy command to prompt for password */
315
 
  splashy_command_pid = fork();
316
 
  if(splashy_command_pid != 0 and interrupted_by_signal){
317
 
    goto failure;
318
 
  }
319
 
  if(splashy_command_pid == -1){
320
 
    error_plus(0, errno, "fork");
321
 
    exitstatus = EX_OSERR;
322
 
    goto failure;
323
 
  }
324
 
  /* Child */
325
 
  if(splashy_command_pid == 0){
326
 
    if(not interrupted_by_signal){
 
207
  pid_t splashy_command_pid = 0;
 
208
  if(not interrupted_by_signal){
 
209
    splashy_command_pid = fork();
 
210
    if(splashy_command_pid == -1){
 
211
      if(not interrupted_by_signal){
 
212
        perror("fork");
 
213
      }
 
214
      return EXIT_FAILURE;
 
215
    }
 
216
    /* Child */
 
217
    if(splashy_command_pid == 0){
327
218
      const char splashy_command[] = "/sbin/splashy_update";
328
 
      execl(splashy_command, splashy_command, prompt, (char *)NULL);
329
 
      int e = errno;
330
 
      error_plus(0, errno, "execl");
331
 
      switch(e){
332
 
      case EACCES:
333
 
      case ENOENT:
334
 
      case ENOEXEC:
335
 
      case EINVAL:
336
 
        _exit(EX_UNAVAILABLE);
337
 
      case ENAMETOOLONG:
338
 
      case E2BIG:
339
 
      case ENOMEM:
340
 
      case EFAULT:
341
 
      case EIO:
342
 
      case EMFILE:
343
 
      case ENFILE:
344
 
      case ETXTBSY:
345
 
      default:
346
 
        _exit(EX_OSERR);
347
 
      case ENOTDIR:
348
 
      case ELOOP:
349
 
      case EISDIR:
350
 
#ifdef ELIBBAD
351
 
      case ELIBBAD:             /* Linux only */
352
 
#endif
353
 
      case EPERM:
354
 
        _exit(EX_OSFILE);
 
219
      ret = execl(splashy_command, splashy_command, prompt,
 
220
                  (char *)NULL);
 
221
      if(not interrupted_by_signal){
 
222
        perror("execl");
355
223
      }
 
224
      free(prompt);
 
225
      _exit(EXIT_FAILURE);
356
226
    }
357
 
    free(prompt);
358
 
    _exit(EXIT_FAILURE);
359
227
  }
360
228
  
361
229
  /* Parent */
362
230
  free(prompt);
363
 
  prompt = NULL;
364
 
  
365
 
  if(interrupted_by_signal){
366
 
    goto failure;
367
 
  }
368
231
  
369
232
  /* Wait for command to complete */
370
 
  {
 
233
  if(not interrupted_by_signal and splashy_command_pid != 0){
371
234
    int status;
372
 
    do {
373
 
      ret = waitpid(splashy_command_pid, &status, 0);
374
 
    } while(ret == -1 and errno == EINTR
375
 
            and not interrupted_by_signal);
376
 
    if(interrupted_by_signal){
377
 
      goto failure;
378
 
    }
 
235
    ret = waitpid(splashy_command_pid, &status, 0);
379
236
    if(ret == -1){
380
 
      error_plus(0, errno, "waitpid");
 
237
      if(errno != EINTR){
 
238
        perror("waitpid");
 
239
      }
381
240
      if(errno == ECHILD){
382
241
        splashy_command_pid = 0;
383
242
      }
384
243
    } else {
385
244
      /* The child process has exited */
386
245
      splashy_command_pid = 0;
387
 
      if(WIFEXITED(status) and WEXITSTATUS(status) == 0){
 
246
      if(not interrupted_by_signal and WIFEXITED(status)
 
247
         and WEXITSTATUS(status)==0){
388
248
        return EXIT_SUCCESS;
389
249
      }
390
250
    }
391
251
  }
392
 
  
393
 
 failure:
394
 
  
395
 
  free(prompt);
396
 
  
397
 
  if(proc_dir != NULL){
398
 
    TEMP_FAILURE_RETRY(closedir(proc_dir));
399
 
  }
400
 
  
401
 
  if(splashy_command_pid != 0){
402
 
    TEMP_FAILURE_RETRY(kill(splashy_command_pid, SIGTERM));
403
 
    
404
 
    TEMP_FAILURE_RETRY(kill(splashy_pid, SIGTERM));
405
 
    sleep(2);
406
 
    while(TEMP_FAILURE_RETRY(kill(splashy_pid, 0)) == 0){
407
 
      TEMP_FAILURE_RETRY(kill(splashy_pid, SIGKILL));
408
 
      sleep(1);
409
 
    }
410
 
    pid_t new_splashy_pid = (pid_t)TEMP_FAILURE_RETRY(fork());
411
 
    if(new_splashy_pid == 0){
412
 
      /* Child; will become new splashy process */
413
 
      
414
 
      /* Make the effective user ID (root) the only user ID instead of
415
 
         the real user ID (_mandos) */
416
 
      ret = setuid(geteuid());
417
 
      if(ret == -1){
418
 
        error_plus(0, errno, "setuid");
419
 
      }
420
 
      
421
 
      setsid();
422
 
      ret = chdir("/");
423
 
      if(ret == -1){
424
 
        error_plus(0, errno, "chdir");
425
 
      }
426
 
/*       if(fork() != 0){ */
427
 
/*      _exit(EXIT_SUCCESS); */
428
 
/*       } */
429
 
      ret = dup2(STDERR_FILENO, STDOUT_FILENO); /* replace stdout */
430
 
      if(ret == -1){
431
 
        error_plus(0, errno, "dup2");
432
 
        _exit(EX_OSERR);
433
 
      }
434
 
      
435
 
      execl("/sbin/splashy", "/sbin/splashy", "boot", (char *)NULL);
436
 
      {
437
 
        int e = errno;
438
 
        error_plus(0, errno, "execl");
439
 
        switch(e){
440
 
        case EACCES:
441
 
        case ENOENT:
442
 
        case ENOEXEC:
443
 
        default:
444
 
          _exit(EX_UNAVAILABLE);
445
 
        case ENAMETOOLONG:
446
 
        case E2BIG:
447
 
        case ENOMEM:
448
 
          _exit(EX_OSERR);
449
 
        case ENOTDIR:
450
 
        case ELOOP:
451
 
          _exit(EX_OSFILE);
452
 
        }
453
 
      }
454
 
    }
455
 
  }
456
 
  
457
 
  if(interrupted_by_signal){
458
 
    struct sigaction signal_action;
459
 
    sigemptyset(&signal_action.sa_mask);
460
 
    signal_action.sa_handler = SIG_DFL;
461
 
    ret = (int)TEMP_FAILURE_RETRY(sigaction(signal_received,
462
 
                                            &signal_action, NULL));
463
 
    if(ret == -1){
464
 
      error_plus(0, errno, "sigaction");
465
 
    }
466
 
    do {
467
 
      ret = raise(signal_received);
468
 
    } while(ret != 0 and errno == EINTR);
469
 
    if(ret != 0){
470
 
      error_plus(0, errno, "raise");
471
 
      abort();
472
 
    }
473
 
    TEMP_FAILURE_RETRY(pause());
474
 
  }
475
 
  
476
 
  return exitstatus;
 
252
  kill(splashy_pid, SIGTERM);
 
253
  if(interrupted_by_signal and splashy_command_pid != 0){
 
254
    kill(splashy_command_pid, SIGTERM);
 
255
  }
 
256
  sleep(2);
 
257
  while(kill(splashy_pid, 0) == 0){
 
258
    kill(splashy_pid, SIGKILL);
 
259
    sleep(1);
 
260
  }
 
261
  pid_t new_splashy_pid = fork();
 
262
  if(new_splashy_pid == 0){
 
263
    /* Child; will become new splashy process */
 
264
    
 
265
    /* Make the effective user ID (root) the only user ID instead of
 
266
       the real user ID (mandos) */
 
267
    ret = setuid(geteuid());
 
268
    if(ret == -1){
 
269
      perror("setuid");
 
270
    }
 
271
    
 
272
    setsid();
 
273
    ret = chdir("/");
 
274
/*     if(fork() != 0){ */
 
275
/*       _exit(EXIT_SUCCESS); */
 
276
/*     } */
 
277
    ret = dup2(STDERR_FILENO, STDOUT_FILENO); /* replace our stdout */
 
278
    if(ret == -1){
 
279
      perror("dup2");
 
280
      _exit(EXIT_FAILURE);
 
281
    }
 
282
    
 
283
    execl("/sbin/splashy", "/sbin/splashy", "boot", (char *)NULL);
 
284
    if(not interrupted_by_signal){
 
285
      perror("execl");
 
286
    }
 
287
    _exit(EXIT_FAILURE);
 
288
  }
 
289
  
 
290
  return EXIT_FAILURE;
477
291
}