1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ Implementation of tty.h -- creating prompt, and asking questions.
4 * Copyright (c) 2012 - 2020 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
5 * SPDX-License-Identifier: ISC
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #define su_FILE tty_prompts
23 #ifndef mx_HAVE_AMALGAMATION
30 #include "mx/file-streams.h"
32 #include "mx/termios.h"
33 #include "mx/ui-str.h"
36 # include "mx/colour.h"
40 #include "su/code-in.h"
43 mx_tty_yesorno(char const * volatile prompt
, boole noninteract_default
){
47 if(!(n_psonce
& n_PSO_INTERACTIVE
) || (n_pstate
& n_PS_ROBOT
))
48 rv
= noninteract_default
;
56 quest
= noninteract_default
? _("[yes]/no? ") : _("[no]/yes? ");
58 prompt
= _("Continue");
59 prompt
= savecatsep(prompt
, ' ', quest
);
61 mx_fs_linepool_aquire(&ldat
, &lsize
);
62 while(n_go_input(n_GO_INPUT_CTX_DEFAULT
| n_GO_INPUT_NL_ESC
, prompt
,
63 &ldat
, &lsize
, NIL
,NIL
) >= 0){
66 x
= n_boolify(ldat
, UZ_MAX
, noninteract_default
);
72 mx_fs_linepool_release(ldat
, lsize
);
81 mx_tty_getuser(char const * volatile query
) /* TODO v15-compat obsolete */
90 mx_fs_linepool_aquire(&ldat
, &lsize
);
91 if(n_go_input(n_GO_INPUT_CTX_DEFAULT
| n_GO_INPUT_NL_ESC
, query
,
92 &ldat
, &lsize
, NIL
, NIL
) >= 0)
96 mx_fs_linepool_release(ldat
, lsize
);
103 mx_tty_getpass(char const *query
){
110 if(n_psonce
& n_PSO_TTYANY
){
112 query
= _("Password: ");
114 mx_termios_cmdx(mx_TERMIOS_CMD_PUSH
| mx_TERMIOS_CMD_PASSWORD
);
116 fputs(query
, mx_tty_fp
);
119 mx_fs_linepool_aquire(&ldat
, &lsize
);
120 if(readline_restart(mx_tty_fp
, &ldat
, &lsize
, 0) >= 0)
121 pass
= savestr(ldat
);
122 mx_fs_linepool_release(ldat
, lsize
);
124 mx_termios_cmdx(mx_TERMIOS_CMD_POP
| mx_TERMIOS_CMD_PASSWORD
);
126 putc('\n', mx_tty_fp
);
132 #endif /* mx_HAVE_NET */
135 mx_tty_getfilename(struct n_string
*store
,
136 BITENUM_IS(u32
,n_go_input_flags
) gif
,
137 char const *prompt_or_nil
, char const *init_content_or_nil
){
142 if((n_psonce
& (n_PSO_INTERACTIVE
| n_PSO_GETFILENAME_QUOTE_NOTED
)
143 ) == n_PSO_INTERACTIVE
){
144 n_psonce
|= n_PSO_GETFILENAME_QUOTE_NOTED
;
146 _("# All file names need to be sh(1)ell-style quoted, everywhere\n"));
149 store
= n_string_trunc(store
, 0);
150 if((cp
= n_go_input_cp(gif
, prompt_or_nil
, init_content_or_nil
)) != NIL
)
151 rv
= n_shexp_unquote_one(store
, cp
);
160 mx_tty_create_prompt(struct n_string
*store
, char const *xprompt
,
161 BITENUM_IS(u32
,n_go_input_flags
) gif
){
162 struct n_visual_info_ctx vic
;
167 ASSERT(n_psonce
& n_PSO_INTERACTIVE
);
169 #ifdef mx_HAVE_ERRORS
170 if(!(n_psonce
& n_PSO_ERRORS_NOTED
) && n_pstate_err_cnt
> 0){
171 n_psonce
|= n_PSO_ERRORS_NOTED
;
172 n_err(_("There are messages in the error ring, "
173 "manageable via `errors' command\n"));
178 n_string_trunc(store
, 0);
180 if(gif
& n_GO_INPUT_PROMPT_NONE
){
185 if(!(gif
& n_GO_INPUT_NL_FOLLOW
)){
188 if((x
= n_cnd_if_exists())){
189 if(store
->s_len
!= 0)
190 store
= n_string_push_c(store
, '#');
192 store
= n_string_push_cp(store
, _("WHITEOUT#"));
193 store
= n_string_push_cp(store
, _("NEED `endif'"));
197 if((poff
= store
->s_len
) != 0){
199 store
= n_string_push_c(store
, '#');
200 store
= n_string_push_c(store
, ' ');
203 cp
= (gif
& n_GO_INPUT_PROMPT_EVAL
)
204 ? (gif
& n_GO_INPUT_NL_FOLLOW
? ok_vlook(prompt2
) : ok_vlook(prompt
))
206 if(cp
!= NIL
&& *cp
!= '\0'){
207 BITENUM_IS(u32
,n_shexp_state
) shs
;
209 store
= n_string_push_cp(store
, cp
);
210 in
.s
= n_string_cp(store
);
213 store
= n_string_drop_ownership(store
);
215 shs
= n_shexp_parse_token((n_SHEXP_PARSE_LOG
|
216 n_SHEXP_PARSE_IGNORE_EMPTY
| n_SHEXP_PARSE_QUOTE_AUTO_FIXED
|
217 n_SHEXP_PARSE_QUOTE_AUTO_DSQ
), store
, &in
, NIL
);
218 if((shs
& n_SHEXP_STATE_ERR_MASK
) || !(shs
& n_SHEXP_STATE_STOP
)){
219 store
= n_string_clear(store
);
220 store
= n_string_take_ownership(store
, out
.s
, out
.l
+1, out
.l
);
222 n_err(_("*prompt2?* evaluation failed, actively unsetting it\n"));
223 if(gif
& n_GO_INPUT_NL_FOLLOW
)
234 /* Make all printable TODO not know, we want to pass through ESC/CSI! */
236 in
.s
= n_string_cp(store
);
238 makeprint(&in
, &out
);
239 store
= n_string_assign_buf(store
, out
.s
, out
.l
);
243 /* We need the visual width.. */
244 su_mem_set(&vic
, 0, sizeof vic
);
245 vic
.vic_indat
= n_string_cp(store
);
246 vic
.vic_inlen
= store
->s_len
;
247 for(pwidth
= 0; vic
.vic_inlen
> 0;){
248 /* but \[ .. \] is not taken into account */
249 if(vic
.vic_indat
[0] == '\\' && vic
.vic_inlen
> 1 &&
250 vic
.vic_indat
[1] == '['){
253 i
= P2UZ(vic
.vic_indat
- store
->s_dat
);
254 store
= n_string_cut(store
, i
, 2);
255 cp
= &n_string_cp(store
)[i
];
256 i
= store
->s_len
- i
;
259 n_err(_("Open \\[ sequence not closed in *prompt2?*\n"));
262 if(cp
[0] == '\\' && cp
[1] == ']')
265 i
= P2UZ(cp
- store
->s_dat
);
266 store
= n_string_cut(store
, i
, 2);
267 vic
.vic_indat
= &n_string_cp(store
)[i
];
268 vic
.vic_inlen
= store
->s_len
- i
;
269 }else if(!n_visual_info(&vic
, n_VISUAL_INFO_WIDTH_QUERY
|
270 n_VISUAL_INFO_ONE_CHAR
)){
271 n_err(_("Character set error in evaluation of *prompt2?*\n"));
274 pwidth
+= S(u32
,vic
.vic_vi_width
);
275 vic
.vic_indat
= vic
.vic_oudat
;
276 vic
.vic_inlen
= vic
.vic_oulen
;
280 /* And there may be colour support, too */
281 #ifdef mx_HAVE_COLOUR
282 if(mx_COLOUR_IS_ACTIVE()){
283 struct mx_colour_pen
*ccp
;
284 struct str
const *rsp
, *psp
, *esp
;
287 if((rsp
= mx_colour_reset_to_str()) != NIL
&&
288 (ccp
= mx_colour_pen_create(mx_COLOUR_ID_MLE_PROMPT
, NIL
)) != NIL
&&
289 (psp
= mx_colour_pen_to_str(ccp
)) != NIL
){
290 store
= n_string_insert_buf(store
, poff
, psp
->s
, psp
->l
);
291 store
= n_string_push_buf(store
, rsp
->s
, rsp
->l
);
294 if(poff
> 0 && rsp
!= NIL
&&
295 (((ccp
= mx_colour_pen_create(mx_COLOUR_ID_MLE_ERROR
, NIL
)
297 (esp
= mx_colour_pen_to_str(ccp
)) != NIL
) || (esp
= psp
) != NIL
)){
298 store
= n_string_insert_buf(store
, poff
, rsp
->s
, rsp
->l
);
299 store
= n_string_unshift_buf(store
, esp
->s
, esp
->l
);
302 #endif /* mx_HAVE_COLOUR */
309 #include "su/code-ou.h"