/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/password-prompt.c

  • Committer: Teddy Hogeborn
  • Date: 2016-06-03 17:27:03 UTC
  • Revision ID: teddy@recompile.se-20160603172703-mc6tjor6rhq4xy74
mandos: Bug fix: Do multiprocessing cleanup correctly on exit

* mandos (main): Save module "multiprocessing" and open file "wnull"
                 as scope variables accessible by function cleanup(),
                 since the module and global variable may not be
                 accessible when the cleanup() function is run as
                 scheduled by atexit().

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
/*
3
3
 * Password-prompt - Read a password from the terminal and print it
4
4
 * 
5
 
 * Copyright © 2008-2019 Teddy Hogeborn
6
 
 * Copyright © 2008-2019 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
 
5
 * Copyright © 2008-2016 Teddy Hogeborn
 
6
 * Copyright © 2008-2016 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
22
 * Contact the authors at <mandos@recompile.se>.
24
23
 */
27
26
 
28
27
#include <termios.h>            /* struct termios, tcsetattr(),
29
28
                                   TCSAFLUSH, tcgetattr(), ECHO */
30
 
#include <unistd.h>             /* access(), struct termios,
31
 
                                   tcsetattr(), STDIN_FILENO,
32
 
                                   TCSAFLUSH, tcgetattr(), ECHO,
33
 
                                   readlink() */
 
29
#include <unistd.h>             /* struct termios, tcsetattr(),
 
30
                                   STDIN_FILENO, TCSAFLUSH,
 
31
                                   tcgetattr(), ECHO, readlink() */
34
32
#include <signal.h>             /* sig_atomic_t, raise(), struct
35
33
                                   sigaction, sigemptyset(),
36
34
                                   sigaction(), sigaddset(), SIGINT,
111
109
     from the terminal.  Password-prompt will exit if it detects
112
110
     plymouth since plymouth performs the same functionality.
113
111
   */
114
 
  if(access("/run/plymouth/pid", R_OK) == 0){
115
 
    return true;
116
 
  }
117
 
  
118
112
  __attribute__((nonnull))
119
113
  int is_plymouth(const struct dirent *proc_entry){
120
114
    int ret;
221
215
  if(ret == -1){
222
216
    error_plus(1, errno, "scandir");
223
217
  }
224
 
  {
225
 
    int i = ret;
226
 
    while(i--){
227
 
      free(direntries[i]);
228
 
    }
229
 
  }
230
218
  free(direntries);
231
219
  return ret > 0;
232
220
}
239
227
  struct termios t_new, t_old;
240
228
  char *buffer = NULL;
241
229
  char *prefix = NULL;
242
 
  char *prompt = NULL;
243
230
  int status = EXIT_SUCCESS;
244
231
  struct sigaction old_action,
245
232
    new_action = { .sa_handler = termination_handler,
249
236
      { .name = "prefix", .key = 'p',
250
237
        .arg = "PREFIX", .flags = 0,
251
238
        .doc = "Prefix shown before the prompt", .group = 2 },
252
 
      { .name = "prompt", .key = 129,
253
 
        .arg = "PROMPT", .flags = 0,
254
 
        .doc = "The prompt to show", .group = 2 },
255
239
      { .name = "debug", .key = 128,
256
240
        .doc = "Debug mode", .group = 3 },
257
241
      /*
270
254
    error_t parse_opt (int key, char *arg, struct argp_state *state){
271
255
      errno = 0;
272
256
      switch (key){
273
 
      case 'p':                 /* --prefix */
 
257
      case 'p':
274
258
        prefix = arg;
275
259
        break;
276
 
      case 128:                 /* --debug */
 
260
      case 128:
277
261
        debug = true;
278
262
        break;
279
 
      case 129:                 /* --prompt */
280
 
        prompt = arg;
281
 
        break;
282
263
        /*
283
264
         * These reproduce what we would get without ARGP_NO_HELP
284
265
         */
286
267
        argp_state_help(state, state->out_stream,
287
268
                        (ARGP_HELP_STD_HELP | ARGP_HELP_EXIT_ERR)
288
269
                        & ~(unsigned int)ARGP_HELP_EXIT_OK);
289
 
        __builtin_unreachable();
290
270
      case -3:                  /* --usage */
291
271
        argp_state_help(state, state->out_stream,
292
272
                        ARGP_HELP_USAGE | ARGP_HELP_EXIT_ERR);
293
 
        __builtin_unreachable();
294
273
      case 'V':                 /* --version */
295
274
        fprintf(state->out_stream, "%s\n", argp_program_version);
296
275
        exit(argp_err_exit_status);
439
418
    if(prefix){
440
419
      fprintf(stderr, "%s ", prefix);
441
420
    }
442
 
    if(prompt != NULL){
443
 
      fprintf(stderr, "%s: ", prompt);
444
 
    } else {
 
421
    {
445
422
      const char *cryptsource = getenv("CRYPTTAB_SOURCE");
446
423
      const char *crypttarget = getenv("CRYPTTAB_NAME");
447
424
      /* Before cryptsetup 1.1.0~rc2 */
522
499
    }
523
500
    if(sret < 0){
524
501
      int e = errno;
525
 
      if(errno != EINTR){
526
 
        if(not feof(stdin)){
527
 
          error_plus(0, errno, "getline");
528
 
          switch(e){
529
 
          case EBADF:
530
 
            status = EX_UNAVAILABLE;
531
 
            break;
532
 
          case EIO:
533
 
          case EINVAL:
534
 
          default:
535
 
            status = EX_IOERR;
536
 
            break;
537
 
          }
538
 
          break;
539
 
        } else {
540
 
          clearerr(stdin);
 
502
      if(errno != EINTR and not feof(stdin)){
 
503
        error_plus(0, errno, "getline");
 
504
        switch(e){
 
505
        case EBADF:
 
506
          status = EX_UNAVAILABLE;
 
507
          break;
 
508
        case EIO:
 
509
        case EINVAL:
 
510
        default:
 
511
          status = EX_IOERR;
 
512
          break;
541
513
        }
 
514
        break;
542
515
      }
543
516
    }
544
517
    /* if(sret == 0), then the only sensible thing to do is to retry