From 42cd8e12d76f3896674c96abb370ebfab469476e Mon Sep 17 00:00:00 2001 From: jakob <> Date: Tue, 20 Jul 1999 16:38:57 +0000 Subject: [PATCH] Added fparseln from NetBSD. ok deraadt@ --- src/lib/libutil/Makefile | 7 +- src/lib/libutil/fparseln.3 | 143 +++++++++++++++++++++ src/lib/libutil/fparseln.c | 225 ++++++++++++++++++++++++++++++++++ src/lib/libutil/shlib_version | 2 +- src/lib/libutil/util.h | 13 +- 5 files changed, 385 insertions(+), 5 deletions(-) create mode 100644 src/lib/libutil/fparseln.3 create mode 100644 src/lib/libutil/fparseln.c diff --git a/src/lib/libutil/Makefile b/src/lib/libutil/Makefile index cb39be88..2c6cf13d 100644 --- a/src/lib/libutil/Makefile +++ b/src/lib/libutil/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.16 1998/06/08 20:28:23 brian Exp $ +# $OpenBSD: Makefile,v 1.17 1999/07/20 16:38:56 jakob Exp $ # $NetBSD: Makefile,v 1.8 1996/05/16 07:03:28 thorpej Exp $ LIB= util @@ -7,11 +7,12 @@ CFLAGS+=-DLIBC_SCCS HDRS= util.h scsi.h SRCS= getmaxpartitions.c getrawpartition.c login.c login_tty.c logout.c \ logwtmp.c opendev.c passwd.c pty.c readlabel.c scsi.c login_fbtab.c \ - uucplock.c + uucplock.c fparseln.c # XXX need login_fbtab.3 MAN= getmaxpartitions.3 getrawpartition.3 login.3 opendev.3 openpty.3 \ - pw_init.3 pw_lock.3 readlabelfs.3 scsi.3 pw_getconf.3 uucplock.3 + pw_init.3 pw_lock.3 readlabelfs.3 scsi.3 pw_getconf.3 uucplock.3 \ + fparseln.3 MLINKS+=login.3 logout.3 MLINKS+=login.3 logwtmp.3 diff --git a/src/lib/libutil/fparseln.3 b/src/lib/libutil/fparseln.3 new file mode 100644 index 00000000..a8853341 --- /dev/null +++ b/src/lib/libutil/fparseln.3 @@ -0,0 +1,143 @@ +.\" $OpenBSD: fparseln.3,v 1.1 1999/07/20 16:38:56 jakob Exp $ +.\" $NetBSD: fparseln.3,v 1.7 1999/07/02 15:49:12 simonb Exp $ +.\" +.\" Copyright (c) 1997 Christos Zoulas. 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 Christos Zoulas. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +.\" +.Dd December 1, 1997 +.Dt FPARSELN 3 +.Os +.Sh NAME +.Nm fparseln +.Nd return the next logical line from a stream +.Sh SYNOPSIS +.Fd #include +.Ft "char *" +.Fo "fparseln" +.Fa "FILE *stream" "size_t *len" "size_t *lineno" +.Fa "const char delim[3]" "int flags" +.Fc +.Sh DESCRIPTION +The +.Fn fparseln +function +returns a pointer to the next logical line from the stream referenced by +.Fa stream . +This string is null terminated and it is dynamicaly allocated on each +invocation. It is the responsibility of the caller to free the pointer. +.Pp +By default, if a character is escaped, both it and the preceeding escape +character will be present in the returned string. +Various +.Fa flags +alter this behaviour. +.Pp +The meaning of the arguments is as follows: +.Bl -tag -width "lineno" +.It Fa stream +The stream to read from. +.It Fa len +If not +.Dv NULL , +the length of the string is stored in the memory location to which it +points. +.It Fa lineno +If not +.Dv NULL , +the value of the memory location to which is pointed to, is incremented +by the number of lines actually read from the file. +.It Fa delim +Contains the escape, continuation, and comment characters. +If a character is +.Dv NUL +then processing for that character is disabled. +If +.Dv NULL , +all characters default to values specified below. +The contents of +.Fa delim +is as follows: +.Bl -tag -width "delim[0]" +.It Fa delim[0] +The escape character, which defaults to +.Ql \e , +is used to remove any special meaning from the next character. +.It Fa delim[1] +The continuation character, which defaults to +.Ql \e , +is used to indicate that the next line should be concatenated with the +current one if this character is the last character on the current line +and is not escaped. +.It Fa delim[2] +The comment character, which defaults to +.Ql # , +if not escaped indicates the beginning of a comment that extends until the +end of the current line. +.El +.It Fa flags +If non-zero, alter the operation of +.Fn fparseln . +The various flags, which may be +.Tn OR Ns 'ed +together, are: +.Bl -tag -width "FPARSELN_UNESCCOMM" +.It Dv FPARSELN_UNESCCOMM +Remove escape preceeding an escaped comment. +.It Dv FPARSELN_UNESCCONT +Remove escape preceeding an escaped continuation. +.It Dv FPARSELN_UNESCESC +Remove escape preceeding an escaped escape. +.It Dv FPARSELN_UNESCREST +Remove escape preceeding any other character. +.It Dv FPARSELN_UNESCALL +All of the above. +.El +.Sh RETURN VALUES +Upon successful completion a pointer to the parsed line is returned; +otherwise, +.Dv NULL +is returned. +.Pp +The +.Fn fparseln +function uses internally +.Xr fgetln 3 , +so all error conditions that apply to +.Xr fgetln 3 , +apply to +.Fn fparseln . +In addition +.Fn fparseln +may set +.Va errno +to +.Er ENOMEM +and return +.Dv NULL +if it runs out of memory. +.Sh SEE ALSO +.Xr fgetln 3 diff --git a/src/lib/libutil/fparseln.c b/src/lib/libutil/fparseln.c new file mode 100644 index 00000000..e09ce8fb --- /dev/null +++ b/src/lib/libutil/fparseln.c @@ -0,0 +1,225 @@ +/* $OpenBSD: fparseln.c,v 1.1 1999/07/20 16:38:56 jakob Exp $ +/* $NetBSD: fparseln.c,v 1.7 1999/07/02 15:49:12 simonb Exp $ */ + +/* + * Copyright (c) 1997 Christos Zoulas. 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 Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 rcsid[] = "$OpenBSD: fparseln.c,v 1.1 1999/07/20 16:38:56 jakob Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include +#include + +static int isescaped __P((const char *, const char *, int)); + +/* isescaped(): + * Return true if the character in *p that belongs to a string + * that starts in *sp, is escaped by the escape character esc. + */ +static int +isescaped(sp, p, esc) + const char *sp, *p; + int esc; +{ + const char *cp; + size_t ne; + + /* No escape character */ + if (esc == '\0') + return 1; + + /* Count the number of escape characters that precede ours */ + for (ne = 0, cp = p; --cp >= sp && *cp == esc; ne++) + continue; + + /* Return true if odd number of escape characters */ + return (ne & 1) != 0; +} + + +/* fparseln(): + * Read a line from a file parsing continuations ending in \ + * and eliminating trailing newlines, or comments starting with + * the comment char. + */ +char * +fparseln(fp, size, lineno, str, flags) + FILE *fp; + size_t *size; + size_t *lineno; + const char str[3]; + int flags; +{ + static const char dstr[3] = { '\\', '\\', '#' }; + + size_t s, len; + char *buf; + char *ptr, *cp; + int cnt; + char esc, con, nl, com; + + len = 0; + buf = NULL; + cnt = 1; + + if (str == NULL) + str = dstr; + + esc = str[0]; + con = str[1]; + com = str[2]; + /* + * XXX: it would be cool to be able to specify the newline character, + * but unfortunately, fgetln does not let us + */ + nl = '\n'; + + while (cnt) { + cnt = 0; + + if (lineno) + (*lineno)++; + + if ((ptr = fgetln(fp, &s)) == NULL) + break; + + if (s && com) { /* Check and eliminate comments */ + for (cp = ptr; cp < ptr + s; cp++) + if (*cp == com && !isescaped(ptr, cp, esc)) { + s = cp - ptr; + cnt = s == 0 && buf == NULL; + break; + } + } + + if (s && nl) { /* Check and eliminate newlines */ + cp = &ptr[s - 1]; + + if (*cp == nl) + s--; /* forget newline */ + } + + if (s && con) { /* Check and eliminate continuations */ + cp = &ptr[s - 1]; + + if (*cp == con && !isescaped(ptr, cp, esc)) { + s--; /* forget escape */ + cnt = 1; + } + } + + if (s == 0 && buf != NULL) + continue; + + if ((cp = realloc(buf, len + s + 1)) == NULL) { + free(buf); + return NULL; + } + buf = cp; + + (void) memcpy(buf + len, ptr, s); + len += s; + buf[len] = '\0'; + } + + if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL && + strchr(buf, esc) != NULL) { + ptr = cp = buf; + while (cp[0] != '\0') { + int skipesc; + + while (cp[0] != '\0' && cp[0] != esc) + *ptr++ = *cp++; + if (cp[0] == '\0' || cp[1] == '\0') + break; + + skipesc = 0; + if (cp[1] == com) + skipesc += (flags & FPARSELN_UNESCCOMM); + if (cp[1] == con) + skipesc += (flags & FPARSELN_UNESCCONT); + if (cp[1] == esc) + skipesc += (flags & FPARSELN_UNESCESC); + if (cp[1] != com && cp[1] != con && cp[1] != esc) + skipesc = (flags & FPARSELN_UNESCREST); + + if (skipesc) + cp++; + else + *ptr++ = *cp++; + *ptr++ = *cp++; + } + *ptr = '\0'; + len = strlen(buf); + } + + if (size) + *size = len; + return buf; +} + +#ifdef TEST + +int main __P((int, char **)); + +int +main(argc, argv) + int argc; + char **argv; +{ + char *ptr; + size_t size, line; + + line = 0; + while ((ptr = fparseln(stdin, &size, &line, NULL, + FPARSELN_UNESCALL)) != NULL) + printf("line %d (%d) |%s|\n", line, size, ptr); + return 0; +} + +/* + +# This is a test +line 1 +line 2 \ +line 3 # Comment +line 4 \# Not comment \\\\ + +# And a comment \ +line 5 \\\ +line 6 + +*/ + +#endif /* TEST */ diff --git a/src/lib/libutil/shlib_version b/src/lib/libutil/shlib_version index f89dbabf..cd1b568c 100644 --- a/src/lib/libutil/shlib_version +++ b/src/lib/libutil/shlib_version @@ -1,2 +1,2 @@ major=4 -minor=2 +minor=3 diff --git a/src/lib/libutil/util.h b/src/lib/libutil/util.h index 3f40ce91..dba5e6f0 100644 --- a/src/lib/libutil/util.h +++ b/src/lib/libutil/util.h @@ -1,4 +1,4 @@ -/* $OpenBSD: util.h,v 1.8 1998/06/08 20:28:28 brian Exp $ */ +/* $OpenBSD: util.h,v 1.9 1999/07/20 16:38:57 jakob Exp $ */ /* $NetBSD: util.h,v 1.2 1996/05/16 07:00:22 thorpej Exp $ */ /*- @@ -38,6 +38,7 @@ #ifndef _UTIL_H_ #define _UTIL_H_ +#include #include #include #include @@ -45,6 +46,15 @@ #include #include +/* + * fparseln() specific operation flags. + */ +#define FPARSELN_UNESCESC 0x01 +#define FPARSELN_UNESCCONT 0x02 +#define FPARSELN_UNESCCOMM 0x04 +#define FPARSELN_UNESCREST 0x08 +#define FPARSELN_UNESCALL 0x0f + /* * opendev() specific operation flags. */ @@ -52,6 +62,7 @@ #define OPENDEV_DRCT 0x02 /* Try to open the device directly. */ __BEGIN_DECLS +char *fparseln __P((FILE *, size_t *, size_t *, const char[3], int)); void login __P((struct utmp *)); int login_tty __P((int)); int logout __P((const char *));