From owner-freebsd-hackers@FreeBSD.ORG Mon Aug 4 19:07:24 2003 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 98E2337B401 for ; Mon, 4 Aug 2003 19:07:24 -0700 (PDT) Received: from bspu.secna.ru (ns2.uni-altai.ru [80.247.102.1]) by mx1.FreeBSD.org (Postfix) with ESMTP id D89E943FA3 for ; Mon, 4 Aug 2003 19:07:21 -0700 (PDT) (envelope-from swp@uni-altai.ru) Received: from bspu.secna.ru (smmsp@localhost [127.0.0.1]) by bspu.secna.ru (8.12.9/8.12.9) with ESMTP id h7527bFl003734; Tue, 5 Aug 2003 09:07:37 +0700 (NOVST) Received: (from root@localhost) by bspu.secna.ru (8.12.9/8.12.9/Submit) id h7527au7003733; Tue, 5 Aug 2003 09:07:36 +0700 (NOVST) (envelope-from swp) Date: Tue, 5 Aug 2003 09:07:36 +0700 From: "mitrohin a.s." To: Simon Barner Message-ID: <20030805020736.GA1805@bspu.secna.ru> References: <20030730224505.GD531@zi025.glhnet.mhn.de> <1059607242.64020.5.camel@mjtdev1.dand06.au.bytecraft.au.com> <3F285560.2090607@acm.org> <1059608748.64020.10.camel@mjtdev1.dand06.au.bytecraft.au.com> <002201c356fa$4a66a700$1200a8c0@gsicomp.on.ca> <20030731134343.GB1323@zi025.glhnet.mhn.de> <1059693358.64020.31.camel@mjtdev1.dand06.au.bytecraft.au.com> <20030801153142.GA487@zi025.glhnet.mhn.de> <3F2B75E2.FBC18052@mindspring.com> <20030804003331.GA408@zi025.glhnet.mhn.de> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20030804003331.GA408@zi025.glhnet.mhn.de> User-Agent: Mutt/1.5.1i cc: freebsd-hackers@freebsd.org Subject: Re: [patch] Re: getfsent(3) and spaces in fstab X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: swp@uni-altai.ru List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 05 Aug 2003 02:07:24 -0000 On Mon, Aug 04, 2003 at 02:33:31AM +0200, Simon Barner wrote: > Hi Terry, > > > You need to add '\\' to the list of characters that can be escaped, > > or you've just traded the inability to specify '\t' or ' ' for an > > inability to speciy '\\'. > > Oh yes, I have overlook this special case. I revised my patch in order > to get this right. > > Simon helo. imho - expensive algorithm... i want to see anything more simple... like "gtok()" instead "es_strsep() + remove_escapes()"? #include #include #include char *gtok(char **s, char const *delim) { int quoted, escaped; static char const esc_set[] = { 't', 'r', 'n', 'a', 0 }; static char const esc_rep[] = { '\t', '\r', '\n', '\a', 0 }; char *tok, *r, *w, *p; if (!s || !*s || !*(tok = *s + strspn(*s, delim)) || *tok == '#') return NULL; for (quoted = escaped = 0, r = w = tok; *r; r++) { if (!escaped) { if (*r == '\\') { escaped = 1; continue; } if (*r == '\"') { quoted ^= -1; continue; } if (!quoted && strchr(delim, *r)) { r++; break; } } else { escaped = 0; if ((p = strchr(esc_set, *r)) != NULL) { *w++ = esc_rep[p - esc_set]; continue; } } *w++ = *r; } *w = 0; *s = r; return tok; } #if 0 main() { char *s, *t, buf[0x1000]; while (fgets(buf, sizeof buf, stdin)) for (s = buf; t = gtok(&s, " \t\r\n"); ) printf("\"%s\"\n", t); return 0; } #endif /swp > --- fstab.c.orig Fri Aug 1 17:18:00 2003 > +++ fstab.c Mon Aug 4 01:46:55 2003 > @@ -49,6 +49,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -84,6 +85,140 @@ > _fs_fstab.fs_spec = buf; > } > > +/* > + * Get next token from string *stringp, where tokens are possibly-empty > + * strings separated by characters from delim. > + * > + * Writes NULs into the string at *stringp to end tokens. > + * delim need not remain constant from call to call. > + * On return, *stringp points past the last NUL written (if there might > + * be further tokens), or is NULL (if there are definitely no more tokens). > + * > + * If *stringp is NULL, es_strsep returns NULL. > + * > + * In contrast to strsep(3), es_strsep will allow escaped delimiters > + * within a token. These escaped characters as well as the special case > + * '\\' will be converted appropriately ('\' -> ', '\\' -> '\' > + * > + */ > +char * > +es_strsep(char **stringp, const char *delim) > +{ > + bool escaped=false; > + char *s, *t, *u; > + int i; > + > + > + if (*stringp == '\0') /* empty string */ > + return NULL; > + s = *stringp; > + s += strspn (s, delim); /* skip delimiters */ > + > + if (*s == '\0') /* string consists only of delimiters */ > + return NULL; > + > + /* > + * skip a string consisting of non-delimiters, > + * escapted delimiters or '\\' > + */ > + for (t = s; *t != '\0'; ++t) { > + if (*t == '\\') { > + if (escaped) { /* convert \\ to \ */ > + --t; > + u = t; > + escaped = false; > + while (u[0] != '\0') { > + u[0] = u[1]; > + ++u; > + } > + } else /* start \-Sequence */ > + escaped = true; > + continue; > + } > + > + /* search for delimiter */ > + for (i=0; delim[i] != '\0'; ++i) { > + if (*t == delim[i]) > + break; > + } > + > + /* un-escaped delimiter found => end of token */ > + if (!escaped && delim[i] != '\0') > + break; > + > + /* escaped delimiter found => remove / */ > + if (escaped) { > + --t; > + u = t; > + escaped = false; > + while (u[0] != '\0') { > + u[0] = u[1]; > + ++u; > + } > + } > + } > + > + if (*t != '\0') { > + *t = '\0'; /* end current token */ > + *stringp = t+1; /* *t != '\0' => *(t+1) is valid */ > + } else > + *stringp = 0; /* end of string reached */ > + > + return s; /* return current token */ > +} > + > +/* > + * This function converts escaped characters: > + * '\' -> '', '\\' -> '\' > + * > + * If there are unescaped delimiters, 'false' will be return to indicate > + * an error, otherwise remove_escape returns 'true'. > + */ > +bool remove_escapes (char **s, const char* delim) { > + bool escaped=false; > + char *t, *u; > + int i; > + > + for (t = *s; *t != '\0'; ++t) { > + if (*t == '\\') { > + if (escaped) { /* convert \\ to \ */ > + --t; > + u = t; > + escaped = false; > + while (u[0] != '\0') { > + u[0] = u[1]; > + ++u; > + } > + } else /* start \-Sequence */ > + escaped = true; > + continue; > + } > + > + /* search for delimiter */ > + for (i=0; delim[i] != '\0'; ++i) { > + if (*t == delim[i]) > + break; > + } > + > + /* un-escaped delimiter found => error */ > + if (!escaped && delim[i] != '\0') > + return false; > + > + /* escaped delimiter found => remove / */ > + if (escaped) { > + --t; > + u = t; > + escaped = false; > + while (u[0] != '\0') { > + u[0] = u[1]; > + ++u; > + } > + } > + } > + > + return true; > +} > + > static int > fstabscan() > { > @@ -101,9 +236,19 @@ > ++LineNo; > if (*line == '#' || *line == '\n') > continue; > - if (!strpbrk(p, " \t")) { > + > + /* escapted white-spaces only are allowed in old-style format */ > + cp = p; > + while ((cp = strpbrk(cp, " \t")) != 0 && > + cp != p && cp[-1] == '\\') > + ++cp; > + if (cp == 0) { > _fs_fstab.fs_spec = strsep(&p, ":\n"); > + if (!remove_escapes (&_fs_fstab.fs_spec, " \t")) > + goto bad; > _fs_fstab.fs_file = strsep(&p, ":\n"); > + if (!remove_escapes (&_fs_fstab.fs_file, " \t")) > + goto bad; > fixfsfile(); > _fs_fstab.fs_type = strsep(&p, ":\n"); > if (_fs_fstab.fs_type) { > @@ -124,13 +269,15 @@ > goto bad; > } > /* OLD_STYLE_FSTAB */ > - while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0') > + while ((cp = es_strsep(&p, " \t\n")) != NULL && *cp == '\0') > ; > _fs_fstab.fs_spec = cp; > if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#') > continue; > - while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0') > + while ((cp = es_strsep(&p, " \t\n")) != NULL && *cp == '\0') > ; > + if (cp == 0) > + goto bad; > _fs_fstab.fs_file = cp; > fixfsfile(); > while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')