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 #include "status.h"
40
41
42 /* A variable with a function to be used to return the current assuan
43 * context for a CTRL variable. This needs to be set using the
44 * set_assuan_ctx_func function. */
45 static assuan_context_t (*the_assuan_ctx_func)(ctrl_t ctrl);
46
47
48 /* Set FUNC to be used as a mapping function from CTRL to an assuan
49 * context. Pass NULL for FUNC to disable the use of the assuan
50 * context in this module. */
51 void
set_assuan_context_func(assuan_context_t (* func)(ctrl_t ctrl))52 set_assuan_context_func (assuan_context_t (*func)(ctrl_t ctrl))
53 {
54 the_assuan_ctx_func = func;
55 }
56
57
58 /* Helper function to print an assuan status line using a printf
59 format string. */
60 gpg_error_t
vprint_assuan_status(assuan_context_t ctx,const char * keyword,const char * format,va_list arg_ptr)61 vprint_assuan_status (assuan_context_t ctx,
62 const char *keyword,
63 const char *format, va_list arg_ptr)
64 {
65 int rc;
66 char *buf;
67
68 rc = gpgrt_vasprintf (&buf, format, arg_ptr);
69 if (rc < 0)
70 return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
71 rc = assuan_write_status (ctx, keyword, buf);
72 xfree (buf);
73 return rc;
74 }
75
76
77 /* Helper function to print an assuan status line using a printf
78 format string. */
79 gpg_error_t
print_assuan_status(assuan_context_t ctx,const char * keyword,const char * format,...)80 print_assuan_status (assuan_context_t ctx,
81 const char *keyword,
82 const char *format, ...)
83 {
84 va_list arg_ptr;
85 gpg_error_t err;
86
87 va_start (arg_ptr, format);
88 err = vprint_assuan_status (ctx, keyword, format, arg_ptr);
89 va_end (arg_ptr);
90 return err;
91 }
92
93
94 /* Helper function to print a list of strings as an assuan status
95 * line. KEYWORD is the first item on the status line. ARG_PTR is a
96 * list of strings which are all separated by a space in the output.
97 * The last argument must be a NULL. Linefeeds and carriage returns
98 * characters (which are not allowed in an Assuan status line) are
99 * silently quoted in C-style. */
100 gpg_error_t
vprint_assuan_status_strings(assuan_context_t ctx,const char * keyword,va_list arg_ptr)101 vprint_assuan_status_strings (assuan_context_t ctx,
102 const char *keyword, va_list arg_ptr)
103 {
104 gpg_error_t err = 0;
105 const char *text;
106 char buf[950], *p;
107 size_t n;
108
109 p = buf;
110 n = 0;
111 while ((text = va_arg (arg_ptr, const char *)) && n < DIM (buf)-3 )
112 {
113 if (n)
114 {
115 *p++ = ' ';
116 n++;
117 }
118 for ( ; *text && n < DIM (buf)-3; n++, text++)
119 {
120 if (*text == '\n')
121 {
122 *p++ = '\\';
123 *p++ = 'n';
124 n++;
125 }
126 else if (*text == '\r')
127 {
128 *p++ = '\\';
129 *p++ = 'r';
130 n++;
131 }
132 else
133 *p++ = *text;
134 }
135 }
136 *p = 0;
137 err = assuan_write_status (ctx, keyword, buf);
138
139 return err;
140 }
141
142
143 /* See vprint_assuan_status_strings. */
144 gpg_error_t
print_assuan_status_strings(assuan_context_t ctx,const char * keyword,...)145 print_assuan_status_strings (assuan_context_t ctx, const char *keyword, ...)
146 {
147 va_list arg_ptr;
148 gpg_error_t err;
149
150 va_start (arg_ptr, keyword);
151 err = vprint_assuan_status_strings (ctx, keyword, arg_ptr);
152 va_end (arg_ptr);
153 return err;
154 }
155
156
157 /* This function is similar to print_assuan_status but takes a CTRL
158 * arg instead of an assuan context as first argument. */
159 gpg_error_t
status_printf(ctrl_t ctrl,const char * keyword,const char * format,...)160 status_printf (ctrl_t ctrl, const char *keyword, const char *format, ...)
161 {
162 gpg_error_t err;
163 va_list arg_ptr;
164 assuan_context_t ctx;
165
166 if (!ctrl || !the_assuan_ctx_func || !(ctx = the_assuan_ctx_func (ctrl)))
167 return 0;
168
169 va_start (arg_ptr, format);
170 err = vprint_assuan_status (ctx, keyword, format, arg_ptr);
171 va_end (arg_ptr);
172 return err;
173 }
174
175
176 /* Same as status_printf but takes a status number instead of a
177 * keyword. */
178 gpg_error_t
status_no_printf(ctrl_t ctrl,int no,const char * format,...)179 status_no_printf (ctrl_t ctrl, int no, const char *format, ...)
180 {
181 gpg_error_t err;
182 va_list arg_ptr;
183 assuan_context_t ctx;
184
185 if (!ctrl || !the_assuan_ctx_func || !(ctx = the_assuan_ctx_func (ctrl)))
186 return 0;
187
188 va_start (arg_ptr, format);
189 err = vprint_assuan_status (ctx, get_status_string (no), format, arg_ptr);
190 va_end (arg_ptr);
191 return err;
192 }
193