Index: gettytab.5 =================================================================== --- gettytab.5 +++ gettytab.5 @@ -28,7 +28,7 @@ .\" from: @(#)gettytab.5 8.4 (Berkeley) 4/19/94 .\" $FreeBSD$ .\" " -.Dd April 19, 1994 +.Dd January 19, 2017 .Dt GETTYTAB 5 .Os .Sh NAME @@ -118,7 +118,7 @@ .Em NOT hangup line on last close .It "he str" Ta Dv NULL Ta -.No "hostname editing string" +.No "hostname editing regular expression" .It "hn str hostname hostname" .It "ht bool false terminal has real tabs" .It "hw bool false do cts/rts hardware flow control" @@ -302,18 +302,13 @@ table entry. In either case it may be edited with the .Va \&he -string. -A '@' in the -.Va \&he -string causes one character from the real hostname to -be copied to the final hostname. -A '#' in the -.Va \&he -string causes the next character of the real hostname -to be skipped. -Each character that -is neither '@' nor '#' is copied into the final hostname. -Surplus '@' and '#' characters are ignored. +POSIX +.Dq extended +regular expression, which is matched against the hostname. +If there were no parenthesized subexpressions in the pattern, +entire matched string is used as final hostname. +Otherwise, all matched subexpressions are concatenated together. +If pattern did not match, original hostname is not modified. .It \&%t The tty name. .It "\&%m, \&%r, \&%s, \&%v" @@ -528,10 +523,6 @@ The terminal driver should support sane delay settings. .Pp The -.Va \&he -capability is stupid. -.Pp -The .Xr termcap 5 format is horrid, something more rational should have been chosen. Index: subr.c =================================================================== --- subr.c +++ subr.c @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -53,8 +54,6 @@ #include "pathnames.h" #include "extern.h" - - /* * Get a table entry. */ @@ -469,42 +468,78 @@ char editedhost[MAXHOSTNAMELEN]; void -edithost(const char *pat) +edithost(const char *pattern) { - const char *host = HN; - char *res = editedhost; + regex_t regex; + regmatch_t *match; + int found; - if (!pat) - pat = ""; - while (*pat) { - switch (*pat) { + if (pattern == NULL || *pattern == '\0') + goto copyasis; - case '#': - if (*host) - host++; - break; + if (regcomp(®ex, pattern, REG_EXTENDED) != 0) + goto copyasis; - case '@': - if (*host) - *res++ = *host++; - break; + 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 totalsize; + /* + * We found a match. If there were no parenthesized + * subexpressions in the pattern, use entire matched + * string as ``editedhost''. Otherwise, concatenate + * all matched subexpressions together. + */ + if (regex.re_nsub == 0) { + totalsize = match[0].rm_eo - match[0].rm_so + 1; + strlcpy(editedhost, HN + match[0].rm_so, + totalsize > sizeof(editedhost) ? + sizeof(editedhost) : totalsize); + } else { + char *position; + int i; + + position = editedhost; + totalsize = 0; + for (i = 1; i <= regex.re_nsub; i++) { + size_t size; + + size = match[i].rm_eo - match[i].rm_so; + totalsize += size; + + /* + * If we exceed ``editedhost'' buffer, + * truncate current subexpression, copy + * what fits in ``editedhost'', break + * the loop, and terminate the string. + */ + if (totalsize >= sizeof(editedhost)) + size -= (totalsize - + sizeof(editedhost) + 1); + memcpy(position, HN + match[i].rm_so, size); + position += size; + if (totalsize >= sizeof(editedhost)) + break; + } + *position = '\0'; } - if (res == &editedhost[sizeof editedhost - 1]) { - *res = '\0'; - return; - } - pat++; } - 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 pattern did not match, pass + * the original hostname as is. + */ + copyasis: + strlcpy(editedhost, HN, sizeof(editedhost)); } static struct speedtab {