diff options
author | Alexey Dokuchaev <danfe@FreeBSD.org> | 2017-02-02 20:30:50 +0000 |
---|---|---|
committer | Alexey Dokuchaev <danfe@FreeBSD.org> | 2017-02-02 20:30:50 +0000 |
commit | f73ff060d24b1d00b06e0ce2f94598bd0d2ff1fa (patch) | |
tree | 040591f1c9c37b426a4b58795061bab2242446d4 /libexec/getty/subr.c | |
parent | b3d5213675f4ee73e81a4c293ccb6214ad416168 (diff) | |
download | src-f73ff060d24b1d00b06e0ce2f94598bd0d2ff1fa.tar.gz src-f73ff060d24b1d00b06e0ce2f94598bd0d2ff1fa.zip |
Try to fix the old "he capability is stupid" bug in gettytab(5)/getty(8)
There is one capability explicitly documented in gettytab(5) as stupid: he.
And it is indeed. It was meant to facilitate system hostname modification,
but is hardly usable in practice because it allows very limited editing
(e.g., it depends on a particular hostname length, making it non-generic).
Replace it with simple implementation that treats ``he'' as POSIX extended
regular expression which is matched against the hostname. If there are no
parenthesized subexpressions in the pattern, entire matched string is used
as the final hostname. Otherwise, use the first matched subexpression.
If the pattern does not match, the original hostname is not modified.
Using regex(3) gives more freedom, does not complicate the code very much,
and makes a lot more sense, in turn making ``he'' less stupid and actually
useful (e.g., it is now possible to obtain node or domain names from the
original hostname string, without knowing it in advance).
Reviewed by: jilles, manpages (wblock)
Approved by: jilles (implied)
Differential Revision: https://reviews.freebsd.org/D9244
Notes
Notes:
svn path=/head/; revision=313107
Diffstat (limited to 'libexec/getty/subr.c')
-rw-r--r-- | libexec/getty/subr.c | 73 |
1 files changed, 39 insertions, 34 deletions
diff --git a/libexec/getty/subr.c b/libexec/getty/subr.c index 4716e97d7bff..2496b4c40b2f 100644 --- a/libexec/getty/subr.c +++ b/libexec/getty/subr.c @@ -43,6 +43,7 @@ static const char rcsid[] = #include <sys/time.h> #include <poll.h> +#include <regex.h> #include <stdlib.h> #include <string.h> #include <syslog.h> @@ -53,8 +54,6 @@ static const char rcsid[] = #include "pathnames.h" #include "extern.h" - - /* * Get a table entry. */ @@ -469,42 +468,48 @@ adelay(int ms, struct delayval *dp) char editedhost[MAXHOSTNAMELEN]; void -edithost(const char *pat) +edithost(const char *pattern) { - const char *host = HN; - char *res = editedhost; - - if (!pat) - pat = ""; - while (*pat) { - switch (*pat) { - - case '#': - if (*host) - host++; - break; - - case '@': - if (*host) - *res++ = *host++; - break; + regex_t regex; + regmatch_t *match; + int found; + + if (pattern == NULL || *pattern == '\0') + goto copyasis; + if (regcomp(®ex, pattern, REG_EXTENDED) != 0) + goto copyasis; + + match = calloc(regex.re_nsub + 1, sizeof(*match)); + if (match == NULL) { + regfree(®ex); + goto copyasis; + } - default: - *res++ = *pat; - break; + found = !regexec(®ex, HN, regex.re_nsub + 1, match, 0); + if (found) { + size_t subex, totalsize; - } - if (res == &editedhost[sizeof editedhost - 1]) { - *res = '\0'; - return; - } - pat++; + /* + * We found a match. If there were no parenthesized + * subexpressions in the pattern, use entire matched + * string as ``editedhost''; otherwise use the first + * matched subexpression. + */ + subex = !!regex.re_nsub; + totalsize = match[subex].rm_eo - match[subex].rm_so + 1; + strlcpy(editedhost, HN + match[subex].rm_so, totalsize > + sizeof(editedhost) ? sizeof(editedhost) : totalsize); } - if (*host) - strncpy(res, host, sizeof editedhost - (res - editedhost) - 1); - else - *res = '\0'; - editedhost[sizeof editedhost - 1] = '\0'; + free(match); + regfree(®ex); + if (found) + return; + /* + * In case of any errors, or if the pattern did not match, pass + * the original hostname as is. + */ + copyasis: + strlcpy(editedhost, HN, sizeof(editedhost)); } static struct speedtab { |