Add support for askpass program for reading answers from the user.
This commit is contained in:
parent
eef82f7ed4
commit
019cefd3fb
@ -117,36 +117,103 @@ static const char *mpw_getenv(const char *variableName) {
|
|||||||
return envBuf? strdup( envBuf ): NULL;
|
return envBuf? strdup( envBuf ): NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *mpw_read_fd(int fd);
|
||||||
|
char *mpw_read_file(FILE *file);
|
||||||
|
|
||||||
|
/** Use the askpass program to prompt the user.
|
||||||
|
* @return A newly allocated string or NULL if askpass is not supported or an error occurred. */
|
||||||
|
static char *mpw_askpass(const char *prompt) {
|
||||||
|
|
||||||
|
const char *askpass = mpw_getenv( "MPW_ASKPASS" );
|
||||||
|
if (!askpass)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
int pipes[2];
|
||||||
|
if (pipe( pipes ) == ERR) {
|
||||||
|
wrn( "Couldn't pipe: %s\n", strerror( errno ) );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == ERR) {
|
||||||
|
wrn( "Couldn't fork for askpass:\n %s: %s\n", askpass, strerror( errno ) );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pid) {
|
||||||
|
// askpass fork
|
||||||
|
close( pipes[0] );
|
||||||
|
if (dup2( pipes[1], STDOUT_FILENO ) == ERR)
|
||||||
|
ftl( "Couldn't connect pipe to process: %s\n", strerror( errno ) );
|
||||||
|
|
||||||
|
else if (execl( askpass, askpass, prompt, NULL ) == ERR)
|
||||||
|
ftl( "Couldn't execute askpass:\n %s: %s\n", askpass, strerror( errno ) );
|
||||||
|
|
||||||
|
exit( EX_SOFTWARE );
|
||||||
|
}
|
||||||
|
|
||||||
|
close( pipes[1] );
|
||||||
|
char *answer = mpw_read_fd( pipes[0] );
|
||||||
|
close( pipes[0] );
|
||||||
|
int status;
|
||||||
|
if (waitpid( pid, &status, 0 ) == ERR) {
|
||||||
|
wrn( "Couldn't wait for askpass: %s\n", strerror( errno ) );
|
||||||
|
mpw_free_string( &answer );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WIFEXITED( status ) && WEXITSTATUS( status ) == EXIT_SUCCESS && answer && strlen( answer )) {
|
||||||
|
// Remove trailing newline.
|
||||||
|
if (answer[strlen( answer ) - 1] == '\n')
|
||||||
|
answer[strlen( answer ) - 1] = '\0';
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpw_free_string( &answer );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/** Ask the user a question.
|
/** Ask the user a question.
|
||||||
* @return A newly allocated string or NULL if an error occurred trying to read from the user. */
|
* @return A newly allocated string or NULL if an error occurred trying to read from the user. */
|
||||||
static const char *mpw_getline(const char *prompt) {
|
static const char *mpw_getline(const char *prompt) {
|
||||||
|
|
||||||
|
// Get answer from askpass.
|
||||||
|
char *answer = mpw_askpass( prompt );
|
||||||
|
if (answer)
|
||||||
|
return answer;
|
||||||
|
|
||||||
|
// Get password from terminal.
|
||||||
fprintf( stderr, "%s ", prompt );
|
fprintf( stderr, "%s ", prompt );
|
||||||
|
|
||||||
char *buf = NULL;
|
|
||||||
size_t bufSize = 0;
|
size_t bufSize = 0;
|
||||||
ssize_t lineSize = getline( &buf, &bufSize, stdin );
|
ssize_t lineSize = getline( &answer, &bufSize, stdin );
|
||||||
if (lineSize <= 1) {
|
if (lineSize <= 1) {
|
||||||
free( buf );
|
mpw_free_string( &answer );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the newline.
|
// Remove trailing newline.
|
||||||
buf[lineSize - 1] = '\0';
|
answer[lineSize - 1] = '\0';
|
||||||
return buf;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ask the user for a password.
|
/** Ask the user for a password.
|
||||||
* @return A newly allocated string or NULL if an error occurred trying to read from the user. */
|
* @return A newly allocated string or NULL if an error occurred trying to read from the user. */
|
||||||
static const char *mpw_getpass(const char *prompt) {
|
static const char *mpw_getpass(const char *prompt) {
|
||||||
|
|
||||||
char *passBuf = getpass( prompt );
|
// Get password from askpass.
|
||||||
if (!passBuf)
|
const char *password = mpw_askpass( prompt );
|
||||||
|
if (password)
|
||||||
|
return password;
|
||||||
|
|
||||||
|
// Get password from terminal.
|
||||||
|
char *answer = getpass( prompt );
|
||||||
|
if (!answer)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
char *buf = strdup( passBuf );
|
password = strdup( answer );
|
||||||
bzero( passBuf, strlen( passBuf ) );
|
bzero( answer, strlen( answer ) );
|
||||||
return buf;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the absolute path to the mpw configuration file with the given prefix name and file extension.
|
/** Get the absolute path to the mpw configuration file with the given prefix name and file extension.
|
||||||
@ -230,9 +297,27 @@ static bool mpw_mkdirs(const char *filePath) {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Read until EOF from the given file descriptor.
|
||||||
|
* @return A newly allocated string or NULL the read buffer couldn't be allocated. */
|
||||||
|
char *mpw_read_fd(int fd) {
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
size_t blockSize = 4096, bufSize = 0, bufOffset = 0;
|
||||||
|
ssize_t readSize = 0;
|
||||||
|
while ((mpw_realloc( &buf, &bufSize, blockSize )) &&
|
||||||
|
((readSize = read( fd, buf + bufOffset, blockSize )) > 0));
|
||||||
|
if (readSize == ERR)
|
||||||
|
dbg( "While reading: %s\n", strerror( errno ) );
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
/** Read the file contents of a given file.
|
/** Read the file contents of a given file.
|
||||||
* @return A newly allocated string or NULL the read buffer couldn't be allocated. */
|
* @return A newly allocated string or NULL the read buffer couldn't be allocated. */
|
||||||
static char *mpw_read_file(FILE *file) {
|
char *mpw_read_file(FILE *file) {
|
||||||
|
|
||||||
|
if (!file)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
size_t blockSize = 4096, bufSize = 0, bufOffset = 0, readSize = 0;
|
size_t blockSize = 4096, bufSize = 0, bufOffset = 0, readSize = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user