/mandos/release

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

« back to all changes in this revision

Viewing changes to plugins.d/plymouth.c

  • Committer: Teddy Hogeborn
  • Date: 2019-03-18 22:29:25 UTC
  • mto: This revision was merged to the branch mainline in revision 382.
  • Revision ID: teddy@recompile.se-20190318222925-jvhek84dgcfgj6g3
mandos-ctl: Refactor tests

* mandos-ctl: Where the clients names "foo" and "barbar" do not refer
              to the actual mock clients in the TestCommand class,
              change all occurrences of these names to "client1" and
              "client2" (or just "client" when only one is used) .
              Also change all test doubles to use correct terminology;
              some things called mocks are actually stubs or spies,
              and rename all true mocks to have "mock" in their names.
              Also eliminate duplicate values in tests; derive values
              from previously defined values whenever possible.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
/*
3
3
 * Plymouth - Read a password from Plymouth and output it
4
4
 * 
5
 
 * Copyright © 2010-2019 Teddy Hogeborn
6
 
 * Copyright © 2010-2019 Björn Påhlsson
 
5
 * Copyright © 2010-2018 Teddy Hogeborn
 
6
 * Copyright © 2010-2018 Björn Påhlsson
7
7
 * 
8
8
 * This file is part of Mandos.
9
9
 * 
53
53
#include <errno.h>              /* TEMP_FAILURE_RETRY */
54
54
#include <argz.h>               /* argz_count(), argz_extract() */
55
55
#include <stdarg.h>             /* va_list, va_start(), ... */
56
 
#include <argp.h>
57
56
 
58
57
sig_atomic_t interrupted_by_signal = 0;
59
 
const char *argp_program_version = "plymouth " VERSION;
60
 
const char *argp_program_bug_address = "<mandos@recompile.se>";
61
58
 
62
59
/* Used by Ubuntu 11.04 (Natty Narwahl) */
63
60
const char plymouth_old_old_pid[] = "/dev/.initramfs/plymouth.pid";
72
69
                                        "--mode=boot",
73
70
                                        "--attach-to-session",
74
71
                                        NULL };
75
 
bool debug = false;
76
72
 
77
73
static void termination_handler(__attribute__((unused))int signum){
78
74
  if(interrupted_by_signal){
81
77
  interrupted_by_signal = 1;
82
78
}
83
79
 
84
 
__attribute__((format (gnu_printf, 2, 3), nonnull))
85
 
int fprintf_plus(FILE *stream, const char *format, ...){
86
 
  va_list ap;
87
 
  va_start (ap, format);
88
 
  fprintf(stream, "Mandos plugin %s: ", program_invocation_short_name);
89
 
  return vfprintf(stream, format, ap);
90
 
}
91
 
 
92
80
/* Function to use when printing errors */
93
81
__attribute__((format (gnu_printf, 3, 4)))
94
82
void error_plus(int status, int errnum, const char *formatstring,
171
159
 
172
160
__attribute__((nonnull (2, 3)))
173
161
bool exec_and_wait(pid_t *pid_return, const char *path,
174
 
                   const char * const * const argv, bool interruptable,
 
162
                   const char * const *argv, bool interruptable,
175
163
                   bool daemonize){
176
164
  int status;
177
165
  int ret;
178
166
  pid_t pid;
179
 
  if(debug){
180
 
    for(const char * const *arg = argv; *arg != NULL; arg++){
181
 
      fprintf_plus(stderr, "exec_and_wait arg: %s\n", *arg);
182
 
    }
183
 
    fprintf_plus(stderr, "exec_and_wait end of args\n");
184
 
  }
185
 
 
186
167
  pid = fork();
187
168
  if(pid == -1){
188
169
    error_plus(0, errno, "fork");
228
209
          and ((not interrupted_by_signal)
229
210
               or (not interruptable)));
230
211
  if(interrupted_by_signal and interruptable){
231
 
    if(debug){
232
 
      fprintf_plus(stderr, "Interrupted by signal\n");
233
 
    }
234
212
    return false;
235
213
  }
236
214
  if(ret == -1){
237
215
    error_plus(0, errno, "waitpid");
238
216
    return false;
239
217
  }
240
 
  if(debug){
241
 
    if(WIFEXITED(status)){
242
 
      fprintf_plus(stderr, "exec_and_wait exited: %d\n",
243
 
                   WEXITSTATUS(status));
244
 
    } else if(WIFSIGNALED(status)) {
245
 
      fprintf_plus(stderr, "exec_and_wait signaled: %d\n",
246
 
                   WTERMSIG(status));
247
 
    }
248
 
  }
249
218
  if(WIFEXITED(status) and (WEXITSTATUS(status) == 0)){
250
219
    return true;
251
220
  }
438
407
 
439
408
int main(__attribute__((unused))int argc,
440
409
         __attribute__((unused))char **argv){
441
 
  char *prompt = NULL;
 
410
  char *prompt;
442
411
  char *prompt_arg;
443
412
  pid_t plymouth_command_pid;
444
413
  int ret;
445
414
  bool bret;
446
415
 
447
 
  {
448
 
    struct argp_option options[] = {
449
 
      { .name = "prompt", .key = 128, .arg = "PROMPT",
450
 
        .doc = "The prompt to show" },
451
 
      { .name = "debug", .key = 129,
452
 
        .doc = "Debug mode" },
453
 
      { .name = NULL }
454
 
    };
455
 
    
456
 
    __attribute__((nonnull(3)))
457
 
    error_t parse_opt (int key, char *arg, __attribute__((unused))
458
 
                       struct argp_state *state){
459
 
      errno = 0;
460
 
      switch (key){
461
 
      case 128:                 /* --prompt */
462
 
        prompt = arg;
463
 
        if(debug){
464
 
          fprintf_plus(stderr, "Custom prompt \"%s\"\n", prompt);
465
 
        }
466
 
        break;
467
 
      case 129:                 /* --debug */
468
 
        debug = true;
469
 
        break;
470
 
      default:
471
 
        return ARGP_ERR_UNKNOWN;
472
 
      }
473
 
      return errno;
474
 
    }
475
 
    
476
 
    struct argp argp = { .options = options, .parser = parse_opt,
477
 
                         .args_doc = "",
478
 
                         .doc = "Mandos plymouth -- Read and"
479
 
                         " output a password" };
480
 
    ret = argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, NULL);
481
 
    switch(ret){
482
 
    case 0:
483
 
      break;
484
 
    case ENOMEM:
485
 
    default:
486
 
      errno = ret;
487
 
      error_plus(0, errno, "argp_parse");
488
 
      return EX_OSERR;
489
 
    case EINVAL:
490
 
      error_plus(0, errno, "argp_parse");
491
 
      return EX_USAGE;
492
 
    }
493
 
  }
494
 
  
495
416
  /* test -x /bin/plymouth */
496
417
  ret = access(plymouth_path, X_OK);
497
418
  if(ret == -1){
498
419
    /* Plymouth is probably not installed.  Don't print an error
499
420
       message, just exit. */
500
 
    if(debug){
501
 
      fprintf_plus(stderr, "Plymouth (%s) not found\n",
502
 
                   plymouth_path);
503
 
    }
504
421
    exit(EX_UNAVAILABLE);
505
422
  }
506
423
  
540
457
    }
541
458
    /* Plymouth is probably not running.  Don't print an error
542
459
       message, just exit. */
543
 
    if(debug){
544
 
      fprintf_plus(stderr, "Plymouth not running\n");
545
 
    }
546
460
    exit(EX_UNAVAILABLE);
547
461
  }
548
462
  
549
 
  if(prompt != NULL){
550
 
    ret = asprintf(&prompt_arg, "--prompt=%s", prompt);
551
 
  } else {
552
 
    char *made_prompt = makeprompt();
553
 
    ret = asprintf(&prompt_arg, "--prompt=%s", made_prompt);
554
 
    free(made_prompt);
555
 
  }
 
463
  prompt = makeprompt();
 
464
  ret = asprintf(&prompt_arg, "--prompt=%s", prompt);
 
465
  free(prompt);
556
466
  if(ret == -1){
557
467
    error_plus(EX_OSERR, errno, "asprintf");
558
468
  }
559
469
  
560
470
  /* plymouth ask-for-password --prompt="$prompt" */
561
 
  if(debug){
562
 
    fprintf_plus(stderr, "Prompting for password via Plymouth\n");
563
 
  }
564
471
  bret = exec_and_wait(&plymouth_command_pid,
565
472
                       plymouth_path, (const char *[])
566
473
                       { plymouth_path, "ask-for-password",