~ubuntu-branches/ubuntu/dapper/gnupg2/dapper

« back to all changes in this revision

Viewing changes to g10/status.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-03-29 10:30:32 UTC
  • Revision ID: james.westby@ubuntu.com-20050329103032-sj42n2ain3ipx310
Tags: upstream-1.9.15
ImportĀ upstreamĀ versionĀ 1.9.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* status.c
 
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2002,
 
3
 *               2003 Free Software Foundation, Inc.
 
4
 *
 
5
 * This file is part of GnuPG.
 
6
 *
 
7
 * GnuPG is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * GnuPG is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
20
 */
 
21
 
 
22
#include <config.h>
 
23
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
#include <errno.h>
 
27
#include <unistd.h>
 
28
#include <signal.h>
 
29
 
 
30
#include "gpg.h"
 
31
#include "util.h"
 
32
#include "status.h"
 
33
#include "ttyio.h"
 
34
#include "options.h"
 
35
#include "main.h"
 
36
#include "i18n.h"
 
37
#include "cipher.h" /* for progress functions */
 
38
 
 
39
#define CONTROL_D ('D' - 'A' + 1)
 
40
 
 
41
 
 
42
 
 
43
static FILE *statusfp;
 
44
 
 
45
 
 
46
static void
 
47
progress_cb (void *ctx, const char *what, int printchar, int current, int total)
 
48
{
 
49
  char buf[150];
 
50
  
 
51
  if (printchar == '\n')
 
52
    printchar = 'X';
 
53
  
 
54
  sprintf (buf, "%.20s %c %d %d", what, printchar, current, total);
 
55
  write_status_text (STATUS_PROGRESS, buf);
 
56
}
 
57
 
 
58
static const char *
 
59
get_status_string ( int no ) 
 
60
{
 
61
    const char *s;
 
62
 
 
63
    switch( no ) {
 
64
      case STATUS_ENTER  : s = "ENTER"; break;
 
65
      case STATUS_LEAVE  : s = "LEAVE"; break;
 
66
      case STATUS_ABORT  : s = "ABORT"; break;
 
67
      case STATUS_GOODSIG: s = "GOODSIG"; break;
 
68
      case STATUS_KEYEXPIRED: s = "KEYEXPIRED"; break;
 
69
      case STATUS_KEYREVOKED: s = "KEYREVOKED"; break;
 
70
      case STATUS_BADSIG : s = "BADSIG"; break;
 
71
      case STATUS_ERRSIG : s = "ERRSIG"; break;
 
72
      case STATUS_BADARMOR : s = "BADARMOR"; break;
 
73
      case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA"; break;
 
74
      case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED"; break;
 
75
      case STATUS_TRUST_NEVER    : s = "TRUST_NEVER"; break;
 
76
      case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL"; break;
 
77
      case STATUS_TRUST_FULLY    : s = "TRUST_FULLY"; break;
 
78
      case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE"; break;
 
79
      case STATUS_GET_BOOL       : s = "GET_BOOL"; break;
 
80
      case STATUS_GET_LINE       : s = "GET_LINE"; break;
 
81
      case STATUS_GET_HIDDEN     : s = "GET_HIDDEN"; break;
 
82
      case STATUS_GOT_IT         : s = "GOT_IT"; break;
 
83
      case STATUS_SHM_INFO       : s = "SHM_INFO"; break;
 
84
      case STATUS_SHM_GET        : s = "SHM_GET"; break;
 
85
      case STATUS_SHM_GET_BOOL   : s = "SHM_GET_BOOL"; break;
 
86
      case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN"; break;
 
87
      case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE"; break;
 
88
      case STATUS_VALIDSIG       : s = "VALIDSIG"; break;
 
89
      case STATUS_SIG_ID         : s = "SIG_ID"; break;
 
90
      case STATUS_ENC_TO         : s = "ENC_TO"; break;
 
91
      case STATUS_NODATA         : s = "NODATA"; break;
 
92
      case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE"; break;
 
93
      case STATUS_NO_PUBKEY      : s = "NO_PUBKEY"; break;
 
94
      case STATUS_NO_SECKEY      : s = "NO_SECKEY"; break;
 
95
      case STATUS_NEED_PASSPHRASE_SYM: s = "NEED_PASSPHRASE_SYM"; break;
 
96
      case STATUS_DECRYPTION_FAILED: s = "DECRYPTION_FAILED"; break;
 
97
      case STATUS_DECRYPTION_OKAY: s = "DECRYPTION_OKAY"; break;
 
98
      case STATUS_MISSING_PASSPHRASE: s = "MISSING_PASSPHRASE"; break;
 
99
      case STATUS_GOOD_PASSPHRASE : s = "GOOD_PASSPHRASE"; break;
 
100
      case STATUS_GOODMDC        : s = "GOODMDC"; break;
 
101
      case STATUS_BADMDC         : s = "BADMDC"; break;
 
102
      case STATUS_ERRMDC         : s = "ERRMDC"; break;
 
103
      case STATUS_IMPORTED       : s = "IMPORTED"; break;
 
104
      case STATUS_IMPORT_OK      : s = "IMPORT_OK"; break;
 
105
      case STATUS_IMPORT_CHECK   : s = "IMPORT_CHECK"; break;
 
106
      case STATUS_IMPORT_RES     : s = "IMPORT_RES"; break;
 
107
      case STATUS_FILE_START     : s = "FILE_START"; break;
 
108
      case STATUS_FILE_DONE      : s = "FILE_DONE"; break;
 
109
      case STATUS_FILE_ERROR     : s = "FILE_ERROR"; break;
 
110
      case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION"; break;
 
111
      case STATUS_END_DECRYPTION : s = "END_DECRYPTION"; break;
 
112
      case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION"; break;
 
113
      case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION"; break;
 
114
      case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM"; break;
 
115
      case STATUS_PROGRESS       : s = "PROGRESS"; break;
 
116
      case STATUS_SIG_CREATED    : s = "SIG_CREATED"; break;
 
117
      case STATUS_SESSION_KEY    : s = "SESSION_KEY"; break;
 
118
      case STATUS_NOTATION_NAME  : s = "NOTATION_NAME" ; break;
 
119
      case STATUS_NOTATION_DATA  : s = "NOTATION_DATA" ; break;
 
120
      case STATUS_POLICY_URL     : s = "POLICY_URL" ; break;
 
121
      case STATUS_BEGIN_STREAM   : s = "BEGIN_STREAM"; break;
 
122
      case STATUS_END_STREAM     : s = "END_STREAM"; break;
 
123
      case STATUS_KEY_CREATED    : s = "KEY_CREATED"; break;
 
124
      case STATUS_USERID_HINT    : s = "USERID_HINT"; break;
 
125
      case STATUS_UNEXPECTED     : s = "UNEXPECTED"; break;
 
126
      case STATUS_INV_RECP       : s = "INV_RECP"; break;
 
127
      case STATUS_NO_RECP        : s = "NO_RECP"; break;
 
128
      case STATUS_ALREADY_SIGNED : s = "ALREADY_SIGNED"; break;
 
129
      case STATUS_SIGEXPIRED     : s = "SIGEXPIRED deprecated-use-keyexpired-instead"; break;
 
130
      case STATUS_EXPSIG         : s = "EXPSIG"; break;
 
131
      case STATUS_EXPKEYSIG      : s = "EXPKEYSIG"; break;
 
132
      case STATUS_REVKEYSIG      : s = "REVKEYSIG"; break;
 
133
      case STATUS_ATTRIBUTE      : s = "ATTRIBUTE"; break;
 
134
      default: s = "?"; break;
 
135
    }
 
136
    return s;
 
137
}
 
138
 
 
139
void
 
140
set_status_fd ( int fd )
 
141
{
 
142
    static int last_fd = -1;
 
143
 
 
144
    if ( fd != -1 && last_fd == fd )
 
145
        return;
 
146
 
 
147
    if ( statusfp && statusfp != stdout && statusfp != stderr )
 
148
        fclose (statusfp);
 
149
    statusfp = NULL;
 
150
    if ( fd == -1 ) 
 
151
        return;
 
152
 
 
153
    if( fd == 1 )
 
154
        statusfp = stdout;
 
155
    else if( fd == 2 )
 
156
        statusfp = stderr;
 
157
    else
 
158
        statusfp = fdopen( fd, "w" );
 
159
    if( !statusfp ) {
 
160
        log_fatal("can't open fd %d for status output: %s\n",
 
161
                  fd, strerror(errno));
 
162
    }
 
163
    last_fd = fd;
 
164
    gcry_set_progress_handler (progress_cb, NULL);
 
165
}
 
166
 
 
167
int
 
168
is_status_enabled()
 
169
{
 
170
    return !!statusfp;
 
171
}
 
172
 
 
173
void
 
174
write_status ( int no )
 
175
{
 
176
    write_status_text( no, NULL );
 
177
}
 
178
 
 
179
void
 
180
write_status_text ( int no, const char *text)
 
181
{
 
182
    if( !statusfp )
 
183
        return;  /* not enabled */
 
184
 
 
185
    fputs ( "[GNUPG:] ", statusfp );
 
186
    fputs ( get_status_string (no), statusfp );
 
187
    if( text ) {
 
188
        putc ( ' ', statusfp );
 
189
        for (; *text; text++) {
 
190
            if (*text == '\n')
 
191
                fputs ( "\\n", statusfp );
 
192
            else if (*text == '\r')
 
193
                fputs ( "\\r", statusfp );
 
194
            else 
 
195
                putc ( *(const byte *)text,  statusfp );
 
196
        }
 
197
    }
 
198
    putc ('\n',statusfp);
 
199
    fflush (statusfp);
 
200
}
 
201
 
 
202
 
 
203
/*
 
204
 * Write a status line with a buffer using %XX escapes.  If WRAP is >
 
205
 * 0 wrap the line after this length.  If STRING is not NULL it will
 
206
 * be prepended to the buffer, no escaping is done for string.
 
207
 * A wrap of -1 forces spaces not to be encoded as %20.
 
208
 */
 
209
void
 
210
write_status_text_and_buffer ( int no, const char *string,
 
211
                               const char *buffer, size_t len, int wrap )
 
212
{
 
213
    const char *s, *text;
 
214
    int esc, first;
 
215
    int lower_limit = ' ';
 
216
    size_t n, count, dowrap;
 
217
 
 
218
    if( !statusfp )
 
219
        return;  /* not enabled */
 
220
    
 
221
    if (wrap == -1) {
 
222
        lower_limit--;
 
223
        wrap = 0;
 
224
    }
 
225
 
 
226
    text = get_status_string (no);
 
227
    count = dowrap = first = 1;
 
228
    do {
 
229
        if (dowrap) {
 
230
            fprintf (statusfp, "[GNUPG:] %s ", text );
 
231
            count = dowrap = 0;
 
232
            if (first && string) {
 
233
                fputs (string, statusfp);
 
234
                count += strlen (string);
 
235
            }
 
236
            first = 0;
 
237
        }
 
238
        for (esc=0, s=buffer, n=len; n && !esc; s++, n-- ) {
 
239
            if ( *s == '%' || *(const byte*)s <= lower_limit 
 
240
                           || *(const byte*)s == 127 ) 
 
241
                esc = 1;
 
242
            if ( wrap && ++count > wrap ) {
 
243
                dowrap=1;
 
244
                break;
 
245
            }
 
246
        }
 
247
        if (esc) {
 
248
            s--; n++;
 
249
        }
 
250
        if (s != buffer) 
 
251
            fwrite (buffer, s-buffer, 1, statusfp );
 
252
        if ( esc ) {
 
253
            fprintf (statusfp, "%%%02X", *(const byte*)s );
 
254
            s++; n--;
 
255
        }
 
256
        buffer = s;
 
257
        len = n;
 
258
        if ( dowrap && len )
 
259
            putc ( '\n', statusfp );
 
260
    } while ( len );
 
261
 
 
262
    putc ('\n',statusfp);
 
263
    fflush (statusfp);
 
264
}
 
265
 
 
266
void
 
267
write_status_buffer ( int no, const char *buffer, size_t len, int wrap )
 
268
{
 
269
    write_status_text_and_buffer (no, NULL, buffer, len, wrap);
 
270
}
 
271
 
 
272
 
 
273
 
 
274
static int
 
275
myread(int fd, void *buf, size_t count)
 
276
{
 
277
    int rc;
 
278
    do {
 
279
        rc = read( fd, buf, count );
 
280
    } while ( rc == -1 && errno == EINTR );
 
281
    if ( !rc && count ) {
 
282
        static int eof_emmited=0;
 
283
        if ( eof_emmited < 3 ) {
 
284
            *(char*)buf = CONTROL_D;
 
285
            rc = 1;
 
286
            eof_emmited++;
 
287
        }
 
288
        else { /* Ctrl-D not caught - do something reasonable */
 
289
#ifdef HAVE_DOSISH_SYSTEM
 
290
            raise (SIGINT);  /* nothing to hangup under DOS */
 
291
#else
 
292
            raise (SIGHUP); /* no more input data */
 
293
#endif
 
294
        }
 
295
    }    
 
296
    return rc;
 
297
}
 
298
 
 
299
 
 
300
 
 
301
/****************
 
302
 * Request a string from the client over the command-fd
 
303
 * If bool, returns static string on true (do not free) or NULL for false
 
304
 */
 
305
static char *
 
306
do_get_from_fd( const char *keyword, int hidden, int bool )
 
307
{
 
308
    int i, len;
 
309
    char *string;
 
310
 
 
311
    write_status_text( bool? STATUS_GET_BOOL :
 
312
                       hidden? STATUS_GET_HIDDEN : STATUS_GET_LINE, keyword );
 
313
 
 
314
    for( string = NULL, i = len = 200; ; i++ ) {
 
315
        if( i >= len-1 ) {
 
316
            char *save = string;
 
317
            len += 100;
 
318
            string = hidden? xmalloc_secure ( len ) : xmalloc ( len );
 
319
            if( save )
 
320
                memcpy(string, save, i );
 
321
            else
 
322
                i=0;
 
323
        }
 
324
        /* Hmmm: why not use our read_line function here */
 
325
        if( myread( opt.command_fd, string+i, 1) != 1 || string[i] == '\n'  )
 
326
            break;
 
327
        else if ( string[i] == CONTROL_D ) {
 
328
            /* found ETX - cancel the line and return a sole ETX */
 
329
            string[0] = CONTROL_D;
 
330
            i=1;
 
331
            break;
 
332
        }
 
333
    }
 
334
    string[i] = 0;
 
335
 
 
336
    write_status( STATUS_GOT_IT );
 
337
 
 
338
    if( bool )   /* Fixme: is this correct??? */
 
339
        return (string[0] == 'Y' || string[0] == 'y') ? "" : NULL;
 
340
 
 
341
    return string;
 
342
}
 
343
 
 
344
 
 
345
 
 
346
int
 
347
cpr_enabled()
 
348
{
 
349
    if( opt.command_fd != -1 )
 
350
        return 1;
 
351
    return 0;
 
352
}
 
353
 
 
354
char *
 
355
cpr_get_no_help( const char *keyword, const char *prompt )
 
356
{
 
357
    char *p;
 
358
 
 
359
    if( opt.command_fd != -1 )
 
360
        return do_get_from_fd ( keyword, 0, 0 );
 
361
    for(;;) {
 
362
        p = tty_get( prompt );
 
363
        return p;
 
364
    }
 
365
}
 
366
 
 
367
char *
 
368
cpr_get( const char *keyword, const char *prompt )
 
369
{
 
370
    char *p;
 
371
 
 
372
    if( opt.command_fd != -1 )
 
373
        return do_get_from_fd ( keyword, 0, 0 );
 
374
    for(;;) {
 
375
        p = tty_get( prompt );
 
376
        if( *p=='?' && !p[1] && !(keyword && !*keyword)) {
 
377
            xfree (p);
 
378
            display_online_help( keyword );
 
379
        }
 
380
        else
 
381
            return p;
 
382
    }
 
383
}
 
384
 
 
385
 
 
386
char *
 
387
cpr_get_utf8( const char *keyword, const char *prompt )
 
388
{
 
389
    char *p;
 
390
    p = cpr_get( keyword, prompt );
 
391
    if( p ) {
 
392
        char *utf8 = native_to_utf8( p );
 
393
        xfree ( p );
 
394
        p = utf8;
 
395
    }
 
396
    return p;
 
397
}
 
398
 
 
399
char *
 
400
cpr_get_hidden( const char *keyword, const char *prompt )
 
401
{
 
402
    char *p;
 
403
 
 
404
    if( opt.command_fd != -1 )
 
405
        return do_get_from_fd ( keyword, 1, 0 );
 
406
    for(;;) {
 
407
        p = tty_get_hidden( prompt );
 
408
        if( *p == '?' && !p[1] ) {
 
409
            xfree (p);
 
410
            display_online_help( keyword );
 
411
        }
 
412
        else
 
413
            return p;
 
414
    }
 
415
}
 
416
 
 
417
void
 
418
cpr_kill_prompt(void)
 
419
{
 
420
    if( opt.command_fd != -1 )
 
421
        return;
 
422
    tty_kill_prompt();
 
423
    return;
 
424
}
 
425
 
 
426
int
 
427
cpr_get_answer_is_yes( const char *keyword, const char *prompt )
 
428
{
 
429
    int yes;
 
430
    char *p;
 
431
 
 
432
    if( opt.command_fd != -1 )
 
433
        return !!do_get_from_fd ( keyword, 0, 1 );
 
434
    for(;;) {
 
435
        p = tty_get( prompt );
 
436
        trim_spaces(p); /* it is okay to do this here */
 
437
        if( *p == '?' && !p[1] ) {
 
438
            xfree (p);
 
439
            display_online_help( keyword );
 
440
        }
 
441
        else {
 
442
            tty_kill_prompt();
 
443
            yes = answer_is_yes(p);
 
444
            xfree (p);
 
445
            return yes;
 
446
        }
 
447
    }
 
448
}
 
449
 
 
450
int
 
451
cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt )
 
452
{
 
453
    int yes;
 
454
    char *p;
 
455
 
 
456
    if( opt.command_fd != -1 )
 
457
        return !!do_get_from_fd ( keyword, 0, 1 );
 
458
    for(;;) {
 
459
        p = tty_get( prompt );
 
460
        trim_spaces(p); /* it is okay to do this here */
 
461
        if( *p == '?' && !p[1] ) {
 
462
            xfree (p);
 
463
            display_online_help( keyword );
 
464
        }
 
465
        else {
 
466
            tty_kill_prompt();
 
467
            yes = answer_is_yes_no_quit(p);
 
468
            xfree (p);
 
469
            return yes;
 
470
        }
 
471
    }
 
472
}