diff --git a/include/unistd.h b/include/unistd.h index 9f3191c7c28..8b4ea99def6 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -469,6 +469,8 @@ int syncfs(int fd); int profil(FAR unsigned short *buf, size_t bufsiz, size_t offset, unsigned int scale); +FAR char *getpass(FAR const char *prompt); + #if CONFIG_FORTIFY_SOURCE > 0 fortify_function(getcwd) FAR char *getcwd(FAR char *buf, size_t size) diff --git a/libs/libc/libc.csv b/libs/libc/libc.csv index 7abee30e04c..0631e6cf310 100644 --- a/libs/libc/libc.csv +++ b/libs/libc/libc.csv @@ -105,6 +105,7 @@ "getoptindp","unistd.h","","FAR int *" "getoptoptp","unistd.h","","FAR int *" "getpriority","sys/resource.h","","int","int","id_t" +"getpass","unistd.h","","FAR const char *" "getpwnam_r","pwd.h","","int","FAR const char *","FAR struct passwd *","FAR char *","size_t","FAR struct passwd **" "getpwuid_r","pwd.h","","int","uid_t","FAR struct passwd *","FAR char *","size_t","FAR struct passwd **" "getrandom","sys/random.h","!defined(CONFIG_BUILD_KERNEL)","ssize_t","FAR void *","size_t","unsigned int" diff --git a/libs/libc/unistd/CMakeLists.txt b/libs/libc/unistd/CMakeLists.txt index a7a2a41171b..2f5ae816850 100644 --- a/libs/libc/unistd/CMakeLists.txt +++ b/libs/libc/unistd/CMakeLists.txt @@ -64,7 +64,8 @@ set(SRCS lib_getpgrp.c lib_getpgid.c lib_lockf.c - lib_flock.c) + lib_flock.c + lib_getpass.c) if(NOT CONFIG_SCHED_USER_IDENTITY) list( diff --git a/libs/libc/unistd/Make.defs b/libs/libc/unistd/Make.defs index 965bf8d0ffc..ca12a650583 100644 --- a/libs/libc/unistd/Make.defs +++ b/libs/libc/unistd/Make.defs @@ -32,7 +32,7 @@ CSRCS += lib_setrlimit.c lib_getrlimit.c lib_setpriority.c lib_getpriority.c CSRCS += lib_futimes.c lib_lutimes.c lib_gethostname.c lib_sethostname.c CSRCS += lib_fchownat.c lib_linkat.c lib_readlinkat.c lib_symlinkat.c CSRCS += lib_unlinkat.c lib_usleep.c lib_getpgrp.c lib_getpgid.c -CSRCS += lib_lockf.c lib_flock.c +CSRCS += lib_lockf.c lib_flock.c lib_getpass.c ifneq ($(CONFIG_SCHED_USER_IDENTITY),y) CSRCS += lib_setuid.c lib_setgid.c lib_getuid.c lib_getgid.c diff --git a/libs/libc/unistd/lib_getpass.c b/libs/libc/unistd/lib_getpass.c new file mode 100644 index 00000000000..e323fb42fd8 --- /dev/null +++ b/libs/libc/unistd/lib_getpass.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * libs/libc/unistd/lib_getpass.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static char g_password[128]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +FAR char *getpass(FAR const char *prompt) +{ + struct termios s; + struct termios t; + ssize_t total_bytes_read = 0; + ssize_t bytes_read; + int fd; + + if ((fd = open("/dev/console", O_RDONLY | O_NOCTTY)) < 0) + { + fd = STDIN_FILENO; + } + + tcgetattr(fd, &t); + s = t; + t.c_lflag &= ~(ECHO | ISIG); + t.c_lflag |= ICANON; + t.c_iflag &= ~(INLCR | IGNCR); + t.c_iflag |= ICRNL; + tcsetattr(fd, TCSAFLUSH, &t); + tcdrain(fd); + + if (write(STDERR_FILENO, prompt, strlen(prompt)) != strlen(prompt)) + { + return 0; + } + + while ((bytes_read = read(fd, g_password + total_bytes_read, + sizeof(g_password) - total_bytes_read)) > 0) + { + if (bytes_read > 0 && g_password[total_bytes_read] == '\n') + { + break; + } + + total_bytes_read += bytes_read; + } + + if (total_bytes_read >= 0) + { + if (total_bytes_read > 0 && g_password[total_bytes_read - 1] == '\n') + { + total_bytes_read--; + } + + g_password[total_bytes_read] = 0; + } + + tcsetattr(fd, TCSAFLUSH, &s); + + if (fd > STDERR_FILENO) + { + close(fd); + } + + return g_password; +}