Skip to content

Commit 8082761

Browse files
committed
FEAT: new request-password native which reads line with hidden input and avoids command history
related to: Oldes/Rebol-issues#476 Oldes/Rebol-issues#1388 Oldes/Rebol-issues#1400
1 parent ce2711a commit 8082761

File tree

5 files changed

+106
-4
lines changed

5 files changed

+106
-4
lines changed

src/boot/natives.reb

+4
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,10 @@ request-dir: native [
942942
/keep "Keep previous directory path"
943943
]
944944

945+
request-password: native [
946+
{Asks user for input without echoing, and the entered password is not stored in the command history.}
947+
]
948+
945949
ascii?: native [
946950
{Returns TRUE if value or string is in ASCII character range (below 128).}
947951
value [any-string! char! integer!]

src/core/n-io.c

+24
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,30 @@ static REBSER *Read_All_File(char *fname)
11441144
}
11451145

11461146

1147+
/***********************************************************************
1148+
**
1149+
*/ REBNATIVE(request_password)
1150+
/*
1151+
***********************************************************************/
1152+
{
1153+
REBREQ req = {0};
1154+
REBSER *str;
1155+
1156+
OS_REQUEST_PASSWORD(&req);
1157+
1158+
if (req.file.path == NULL) return R_NONE;
1159+
1160+
#ifdef TO_WINDOWS
1161+
str = Decode_UTF_String(req.file.path, req.file.size, 16, 0, 0);
1162+
#else
1163+
str = Decode_UTF_String(req.file.path, req.file.size, 8, 0, 0);
1164+
#endif
1165+
FREE_MEM(req.file.path);
1166+
SET_STRING(D_RET, str);
1167+
return R_RET;
1168+
}
1169+
1170+
11471171
/***********************************************************************
11481172
**
11491173
*/ REBNATIVE(get_env)

src/mezz/mezz-files.reb

+8-4
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,14 @@ input: func [
8888
][
8989
system/ports/input: port: open [scheme: 'console]
9090
]
91-
if hide [ modify port 'echo false ]
92-
if line: read port [ line: to string! line ]
93-
if hide [ modify port 'echo true ]
94-
line
91+
either hide [
92+
request-password
93+
][
94+
all [
95+
line: read port
96+
to string! line
97+
]
98+
]
9599
]
96100

97101
ask: func [

src/os/posix/host-lib.c

+34
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
#include <string.h>
6363
#include <errno.h>
6464
#include <signal.h> //for kill
65+
#include <unistd.h> //for request-password
6566

6667
#ifndef timeval // for older systems
6768
#include <sys/time.h>
@@ -1370,5 +1371,38 @@ static int Try_Browser(char *browser, REBCHR *url)
13701371
return FALSE;
13711372
}
13721373

1374+
/***********************************************************************
1375+
**
1376+
*/ void OS_Request_Password(REBREQ *req)
1377+
/*
1378+
***********************************************************************/
1379+
{
1380+
REBCNT size = 64;
1381+
REBCNT pos = 0;
1382+
REBYTE *str = malloc(size);
1383+
REBYTE c;
1384+
1385+
req->file.path = NULL;
1386+
1387+
while (read(STDIN_FILENO, &c, 1) && c != '\r') {
1388+
if (c == 27) { // ESC
1389+
free(str);
1390+
return;
1391+
}
1392+
if (c == 127) { // backspace
1393+
// UTF-8 aware skip back one char
1394+
while (pos != 0 && (str[--pos] & 0xC0) == 0x80) {}
1395+
continue;
1396+
}
1397+
str[pos++] = c;
1398+
if (pos+1 == size) {
1399+
size += 64;
1400+
str = realloc(str, size);
1401+
}
1402+
}
1403+
req->file.path = str;
1404+
req->file.size = pos;
1405+
str[pos++] = 0; // null terminate the tail.. just in case
1406+
}
13731407

13741408

src/os/win32/host-lib.c

+36
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161

6262
#include <stdlib.h>
6363
#include <stdio.h>
64+
#include <conio.h> // used for OS_Request_Password
6465
#include <windows.h>
6566
#include <process.h>
6667
#include <ShlObj.h> // used for OS_Request_Dir
@@ -1434,3 +1435,38 @@ static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPAR
14341435
SHGetPathFromIDList(lpItem, fr->files);
14351436
return TRUE;
14361437
}
1438+
1439+
1440+
/***********************************************************************
1441+
**
1442+
*/ void OS_Request_Password(REBREQ *req)
1443+
/*
1444+
***********************************************************************/
1445+
{
1446+
REBCNT size = 64;
1447+
REBCNT pos = 0;
1448+
REBUNI *str = (REBUNI*)malloc(size * sizeof(REBUNI));
1449+
REBUNI c;
1450+
1451+
req->file.path = NULL;
1452+
1453+
while ((c = _getwch()) != '\r') {
1454+
if (c == 27) { // ESC
1455+
free(str);
1456+
return;
1457+
}
1458+
if (c == 127) { // backspace
1459+
if (pos > 0) pos--;
1460+
continue;
1461+
}
1462+
str[pos++] = c;
1463+
if (pos+1 == size) {
1464+
size += 64;
1465+
str = (REBUNI*)realloc(str, size * sizeof(REBUNI));
1466+
}
1467+
}
1468+
req->file.path = (REBYTE*)str;
1469+
req->file.size = pos * sizeof(REBUNI);
1470+
str[pos++] = 0;
1471+
}
1472+

0 commit comments

Comments
 (0)