agent: Avoid appending a '\0' byte to the response of READKEY
[gnupg.git] / common / asshelp2.c
1 /* asshelp2.c - More helper functions for Assuan
2  * Copyright (C) 2012 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * This file is free software; you can redistribute it and/or modify
7  * it under the terms of either
8  *
9  *   - the GNU Lesser General Public License as published by the Free
10  *     Software Foundation; either version 3 of the License, or (at
11  *     your option) any later version.
12  *
13  * or
14  *
15  *   - the GNU General Public License as published by the Free
16  *     Software Foundation; either version 2 of the License, or (at
17  *     your option) any later version.
18  *
19  * or both in parallel, as here.
20  *
21  * This file is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, see <https://www.gnu.org/licenses/>.
28  */
29
30 #include <config.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <assuan.h>
36
37 #include "util.h"
38 #include "asshelp.h"
39
40 /* Helper function to print an assuan status line using a printf
41    format string.  */
42 gpg_error_t
43 vprint_assuan_status (assuan_context_t ctx,
44                       const char *keyword,
45                       const char *format, va_list arg_ptr)
46 {
47   int rc;
48   char *buf;
49
50   rc = gpgrt_vasprintf (&buf, format, arg_ptr);
51   if (rc < 0)
52     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
53   rc = assuan_write_status (ctx, keyword, buf);
54   xfree (buf);
55   return rc;
56 }
57
58
59 /* Helper function to print an assuan status line using a printf
60    format string.  */
61 gpg_error_t
62 print_assuan_status (assuan_context_t ctx,
63                      const char *keyword,
64                      const char *format, ...)
65 {
66   va_list arg_ptr;
67   gpg_error_t err;
68
69   va_start (arg_ptr, format);
70   err = vprint_assuan_status (ctx, keyword, format, arg_ptr);
71   va_end (arg_ptr);
72   return err;
73 }
74
75
76 /* Helper function to print a list of strings as an assuan status
77  * line.  KEYWORD is the first item on the status line.  ARG_PTR is a
78  * list of strings which are all separated by a space in the output.
79  * The last argument must be a NULL.  Linefeeds and carriage returns
80  * characters (which are not allowed in an Assuan status line) are
81  * silently quoted in C-style.  */
82 gpg_error_t
83 vprint_assuan_status_strings (assuan_context_t ctx,
84                               const char *keyword, va_list arg_ptr)
85 {
86   gpg_error_t err = 0;
87   const char *text;
88   char buf[950], *p;
89   size_t n;
90
91   p = buf;
92   n = 0;
93   while ((text = va_arg (arg_ptr, const char *)) && n < DIM (buf)-3 )
94     {
95       if (n)
96         {
97           *p++ = ' ';
98           n++;
99         }
100       for ( ; *text && n < DIM (buf)-3; n++, text++)
101         {
102           if (*text == '\n')
103             {
104               *p++ = '\\';
105               *p++ = 'n';
106               n++;
107             }
108           else if (*text == '\r')
109             {
110               *p++ = '\\';
111               *p++ = 'r';
112               n++;
113             }
114           else
115             *p++ = *text;
116         }
117     }
118   *p = 0;
119   err = assuan_write_status (ctx, keyword, buf);
120
121   return err;
122 }
123
124
125 /* See vprint_assuan_status_strings.  */
126 gpg_error_t
127 print_assuan_status_strings (assuan_context_t ctx, const char *keyword, ...)
128 {
129   va_list arg_ptr;
130   gpg_error_t err;
131
132   va_start (arg_ptr, keyword);
133   err = vprint_assuan_status_strings (ctx, keyword, arg_ptr);
134   va_end (arg_ptr);
135   return err;
136 }