/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/plymouth.c

  • Committer: Teddy Hogeborn
  • Date: 2019-07-29 16:35:53 UTC
  • Revision ID: teddy@recompile.se-20190729163553-1i442i2cbx64c537
Make tests and man page examples match

Make the tests test_manual_page_example[1-5] match exactly what is
written in the manual page, and add comments to manual page as
reminders to keep tests and manual page examples in sync.

* mandos-ctl (Test_commands_from_options.test_manual_page_example_1):
  Remove "--verbose" option, since the manual does not have it as the
  first example, and change assertion to match.
* mandos-ctl.xml (EXAMPLE): Add comments to all examples documenting
  which test function they correspond to.  Also remove unnecessary
  quotes from option arguments in fourth example, and clarify language
  slightly in fifth example.

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-2018 Teddy Hogeborn
6
 
 * Copyright © 2010-2018 Björn Påhlsson
 
5
 * Copyright © 2010-2019 Teddy Hogeborn
 
6
 * Copyright © 2010-2019 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>
56
57
 
57
58
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>";
58
61
 
59
62
/* Used by Ubuntu 11.04 (Natty Narwahl) */
60
63
const char plymouth_old_old_pid[] = "/dev/.initramfs/plymouth.pid";
69
72
                                        "--mode=boot",
70
73
                                        "--attach-to-session",
71
74
                                        NULL };
 
75
bool debug = false;
72
76
 
73
77
static void termination_handler(__attribute__((unused))int signum){
74
78
  if(interrupted_by_signal){
77
81
  interrupted_by_signal = 1;
78
82
}
79
83
 
 
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
 
80
92
/* Function to use when printing errors */
81
93
__attribute__((format (gnu_printf, 3, 4)))
82
94
void error_plus(int status, int errnum, const char *formatstring,
159
171
 
160
172
__attribute__((nonnull (2, 3)))
161
173
bool exec_and_wait(pid_t *pid_return, const char *path,
162
 
                   const char * const *argv, bool interruptable,
 
174
                   const char * const * const argv, bool interruptable,
163
175
                   bool daemonize){
164
176
  int status;
165
177
  int ret;
166
178
  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
 
167
186
  pid = fork();
168
187
  if(pid == -1){
169
188
    error_plus(0, errno, "fork");
209
228
          and ((not interrupted_by_signal)
210
229
               or (not interruptable)));
211
230
  if(interrupted_by_signal and interruptable){
 
231
    if(debug){
 
232
      fprintf_plus(stderr, "Interrupted by signal\n");
 
233
    }
212
234
    return false;
213
235
  }
214
236
  if(ret == -1){
215
237
    error_plus(0, errno, "waitpid");
216
238
    return false;
217
239
  }
 
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
  }
218
249
  if(WIFEXITED(status) and (WEXITSTATUS(status) == 0)){
219
250
    return true;
220
251
  }
407
438
 
408
439
int main(__attribute__((unused))int argc,
409
440
         __attribute__((unused))char **argv){
410
 
  char *prompt;
 
441
  char *prompt = NULL;
411
442
  char *prompt_arg;
412
443
  pid_t plymouth_command_pid;
413
444
  int ret;
414
445
  bool bret;
415
446
 
 
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
  
416
495
  /* test -x /bin/plymouth */
417
496
  ret = access(plymouth_path, X_OK);
418
497
  if(ret == -1){
419
498
    /* Plymouth is probably not installed.  Don't print an error
420
499
       message, just exit. */
 
500
    if(debug){
 
501
      fprintf_plus(stderr, "Plymouth (%s) not found\n",
 
502
                   plymouth_path);
 
503
    }
421
504
    exit(EX_UNAVAILABLE);
422
505
  }
423
506
  
457
540
    }
458
541
    /* Plymouth is probably not running.  Don't print an error
459
542
       message, just exit. */
 
543
    if(debug){
 
544
      fprintf_plus(stderr, "Plymouth not running\n");
 
545
    }
460
546
    exit(EX_UNAVAILABLE);
461
547
  }
462
548
  
463
 
  prompt = makeprompt();
464
 
  ret = asprintf(&prompt_arg, "--prompt=%s", prompt);
465
 
  free(prompt);
 
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
  }
466
556
  if(ret == -1){
467
557
    error_plus(EX_OSERR, errno, "asprintf");
468
558
  }
469
559
  
470
560
  /* plymouth ask-for-password --prompt="$prompt" */
 
561
  if(debug){
 
562
    fprintf_plus(stderr, "Prompting for password via Plymouth\n");
 
563
  }
471
564
  bret = exec_and_wait(&plymouth_command_pid,
472
565
                       plymouth_path, (const char *[])
473
566
                       { plymouth_path, "ask-for-password",