Some more functions for our BSD compatibility library.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18436 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-08-07 16:46:24 +00:00
parent 36788b7119
commit 275d9d80a9
10 changed files with 702 additions and 1 deletions
+3
View File
@@ -6,8 +6,11 @@ UseHeaders [ FDirName $(HAIKU_TOP) headers compatibility bsd ] : true ;
SharedLibrary libbsd.so :
err.c
fgetln.c
getpass.c
issetugid.c
progname.c
stringlist.c
unvis.c
vis.c
;
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, [email protected]
*/
#include <stdio.h>
#include <stdlib.h>
#define LINE_LENGTH 4096
char *
fgetln(FILE *stream, size_t *_length)
{
// TODO: this function is not thread-safe
static size_t sBufferSize;
static char *sBuffer;
size_t length, left;
char *line;
if (sBuffer == NULL) {
sBuffer = (char *)malloc(LINE_LENGTH);
if (sBuffer == NULL)
return NULL;
sBufferSize = LINE_LENGTH;
}
line = sBuffer;
left = sBufferSize;
for (;;) {
line = fgets(line, left, stream);
if (line == NULL) {
free(sBuffer);
sBuffer = NULL;
return NULL;
}
length = strlen(line);
if (line[length - 1] != '\n' && length == sBufferSize - 1) {
// more data is following, enlarge buffer
char *newBuffer = realloc(sBuffer, sBufferSize + LINE_LENGTH);
if (newBuffer == NULL) {
free(sBuffer);
sBuffer = NULL;
return NULL;
}
sBuffer = newBuffer;
sBufferSize += LINE_LENGTH;
line = sBuffer + length;
left += 1;
} else
break;
}
return sBuffer;
}
+54
View File
@@ -0,0 +1,54 @@
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, [email protected]
*/
#include <stdbool.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
char *
getpass(const char *prompt)
{
static char password[128];
struct termios termios;
bool changed = false;
// Turn off echo
if (tcgetattr(fileno(stdin), &termios) == 0) {
struct termios noEchoTermios = termios;
noEchoTermios.c_lflag &= ~(ECHO | ISIG);
changed = tcsetattr(fileno(stdin), TCSAFLUSH, &noEchoTermios) == 0;
}
// Show prompt
fputs(prompt, stdout);
fflush(stdout);
// Read password
if (fgets(password, sizeof(password), stdin) != NULL) {
size_t length = strlen(password);
if (password[length - 1] == '\n')
password[length - 1] = '\0';
if (changed) {
// Manually move to the next line
putchar('\n');
}
}
// Restore termios setting
if (changed)
tcsetattr(fileno(stdin), TCSAFLUSH, &termios);
return password;
}
+297
View File
@@ -0,0 +1,297 @@
/*-
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/gen/unvis.c,v 1.9 2004/08/02 08:46:23 stefanf Exp $");
#include <sys/types.h>
#include <ctype.h>
#include <vis.h>
/*
* decode driven by state machine
*/
#define S_GROUND 0 /* haven't seen escape char */
#define S_START 1 /* start decoding special sequence */
#define S_META 2 /* metachar started (M) */
#define S_META1 3 /* metachar more, regular char (-) */
#define S_CTRL 4 /* control char started (^) */
#define S_OCTAL2 5 /* octal digit 2 */
#define S_OCTAL3 6 /* octal digit 3 */
#define S_HEX2 7 /* hex digit 2 */
#define S_HTTP 0x080 /* %HEXHEX escape */
#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
#define ishex(c) ((((u_char)(c)) >= '0' && ((u_char)(c)) <= '9') || (((u_char)(c)) >= 'a' && ((u_char)(c)) <= 'f'))
/*
* unvis - decode characters previously encoded by vis
*/
int
unvis(char *cp, int c, int *astate, int flag)
{
if (flag & UNVIS_END) {
if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
*astate = S_GROUND;
return (UNVIS_VALID);
}
return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
}
switch (*astate & ~S_HTTP) {
case S_GROUND:
*cp = 0;
if (c == '\\') {
*astate = S_START;
return (0);
}
if (flag & VIS_HTTPSTYLE && c == '%') {
*astate = S_START | S_HTTP;
return (0);
}
*cp = c;
return (UNVIS_VALID);
case S_START:
if (*astate & S_HTTP) {
if (ishex(tolower(c))) {
*cp = isdigit(c) ? (c - '0') : (tolower(c) - 'a');
*astate = S_HEX2;
return (0);
}
}
switch(c) {
case '\\':
*cp = c;
*astate = S_GROUND;
return (UNVIS_VALID);
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
*cp = (c - '0');
*astate = S_OCTAL2;
return (0);
case 'M':
*cp = 0200;
*astate = S_META;
return (0);
case '^':
*astate = S_CTRL;
return (0);
case 'n':
*cp = '\n';
*astate = S_GROUND;
return (UNVIS_VALID);
case 'r':
*cp = '\r';
*astate = S_GROUND;
return (UNVIS_VALID);
case 'b':
*cp = '\b';
*astate = S_GROUND;
return (UNVIS_VALID);
case 'a':
*cp = '\007';
*astate = S_GROUND;
return (UNVIS_VALID);
case 'v':
*cp = '\v';
*astate = S_GROUND;
return (UNVIS_VALID);
case 't':
*cp = '\t';
*astate = S_GROUND;
return (UNVIS_VALID);
case 'f':
*cp = '\f';
*astate = S_GROUND;
return (UNVIS_VALID);
case 's':
*cp = ' ';
*astate = S_GROUND;
return (UNVIS_VALID);
case 'E':
*cp = '\033';
*astate = S_GROUND;
return (UNVIS_VALID);
case '\n':
/*
* hidden newline
*/
*astate = S_GROUND;
return (UNVIS_NOCHAR);
case '$':
/*
* hidden marker
*/
*astate = S_GROUND;
return (UNVIS_NOCHAR);
}
*astate = S_GROUND;
return (UNVIS_SYNBAD);
case S_META:
if (c == '-')
*astate = S_META1;
else if (c == '^')
*astate = S_CTRL;
else {
*astate = S_GROUND;
return (UNVIS_SYNBAD);
}
return (0);
case S_META1:
*astate = S_GROUND;
*cp |= c;
return (UNVIS_VALID);
case S_CTRL:
if (c == '?')
*cp |= 0177;
else
*cp |= c & 037;
*astate = S_GROUND;
return (UNVIS_VALID);
case S_OCTAL2: /* second possible octal digit */
if (isoctal(c)) {
/*
* yes - and maybe a third
*/
*cp = (*cp << 3) + (c - '0');
*astate = S_OCTAL3;
return (0);
}
/*
* no - done with current sequence, push back passed char
*/
*astate = S_GROUND;
return (UNVIS_VALIDPUSH);
case S_OCTAL3: /* third possible octal digit */
*astate = S_GROUND;
if (isoctal(c)) {
*cp = (*cp << 3) + (c - '0');
return (UNVIS_VALID);
}
/*
* we were done, push back passed char
*/
return (UNVIS_VALIDPUSH);
case S_HEX2: /* second mandatory hex digit */
if (ishex(tolower(c))) {
*cp = (isdigit(c) ? (*cp << 4) + (c - '0') : (*cp << 4) + (tolower(c) - 'a' + 10));
}
*astate = S_GROUND;
return (UNVIS_VALID);
default:
/*
* decoder in unknown state - (probably uninitialized)
*/
*astate = S_GROUND;
return (UNVIS_SYNBAD);
}
}
/*
* strunvis - decode src into dst
*
* Number of chars decoded into dst is returned, -1 on error.
* Dst is null terminated.
*/
int
strunvis(char *dst, const char *src)
{
char c;
char *start = dst;
int state = 0;
while ( (c = *src++) ) {
again:
switch (unvis(dst, c, &state, 0)) {
case UNVIS_VALID:
dst++;
break;
case UNVIS_VALIDPUSH:
dst++;
goto again;
case 0:
case UNVIS_NOCHAR:
break;
default:
return (-1);
}
}
if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
dst++;
*dst = '\0';
return (dst - start);
}
int
strunvisx(char *dst, const char *src, int flag)
{
char c;
char *start = dst;
int state = 0;
while ( (c = *src++) ) {
again:
switch (unvis(dst, c, &state, flag)) {
case UNVIS_VALID:
dst++;
break;
case UNVIS_VALIDPUSH:
dst++;
goto again;
case 0:
case UNVIS_NOCHAR:
break;
default:
return (-1);
}
}
if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
dst++;
*dst = '\0';
return (dst - start);
}