diff options
author | Ray Lai <ray@cvs.openbsd.org> | 2007-03-27 04:15:01 +0000 |
---|---|---|
committer | Ray Lai <ray@cvs.openbsd.org> | 2007-03-27 04:15:01 +0000 |
commit | 8f7d581b067d0eecf4adfc15c09860955f585d64 (patch) | |
tree | 613a04a14f3fa2a8f8d62b613ab50f78f3c8b11f /usr.bin/sendbug/sendbug.c | |
parent | f5afe7c7ef5c9ed63bd49c183bf0f2a7cf3da563 (diff) |
Replace some scary pointer code. The new code is O(n^2) for strings
of '&', but gecos fields are usually short and most do not have '&'
so the impact should be minimal. In return we get clearer and safer
code.
OK moritz@.
Diffstat (limited to 'usr.bin/sendbug/sendbug.c')
-rw-r--r-- | usr.bin/sendbug/sendbug.c | 53 |
1 files changed, 29 insertions, 24 deletions
diff --git a/usr.bin/sendbug/sendbug.c b/usr.bin/sendbug/sendbug.c index df4a4fd387c..ac59d25f411 100644 --- a/usr.bin/sendbug/sendbug.c +++ b/usr.bin/sendbug/sendbug.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sendbug.c,v 1.32 2007/03/27 03:40:44 ray Exp $ */ +/* $OpenBSD: sendbug.c,v 1.33 2007/03/27 04:15:00 ray Exp $ */ /* * Written by Ray Lai <ray@cyth.net>. @@ -285,41 +285,46 @@ sendmail(const char *tmppath) void init(void) { - size_t amp, len, namelen; - const char *src; + size_t amp, len, gecoslen, namelen; int sysname[2]; - char *dst, *cp; + char ch, *cp; if ((pw = getpwuid(getuid())) == NULL) err(1, "getpwuid"); namelen = strlen(pw->pw_name); /* Count number of '&'. */ - for (amp = 0, src = pw->pw_gecos; *src && *src != ','; ++src) - if (*src == '&') + for (amp = 0, cp = pw->pw_gecos; *cp && *cp != ','; ++cp) + if (*cp == '&') ++amp; + + /* Truncate gecos to full name. */ + gecoslen = cp - pw->pw_gecos; + pw->pw_gecos[gecoslen] = '\0'; + /* Expanded str = orig str - '&' chars + concatenated logins. */ - len = (src - pw->pw_gecos) - amp + (amp * namelen); - if ((fullname = malloc(len + 1)) == NULL) + len = gecoslen - amp + (amp * namelen) + 1; + if ((fullname = malloc(len)) == NULL) err(1, "malloc"); - dst = fullname; - src = pw->pw_gecos; - while (*src != ',' && *src != '\0') { - /* Copy text up to ',' or '&' and skip. */ - len = strcspn(src, ",&"); - memcpy(dst, src, len); - dst += len; - src += len; - /* Replace '&' with login. */ - if (*src == '&') { - memcpy(dst, pw->pw_name, namelen); - *dst = toupper((unsigned char)*dst); - dst += namelen; - ++src; - } + /* Upper case first char of login. */ + ch = pw->pw_name[0]; + pw->pw_name[0] = toupper((unsigned char)pw->pw_name[0]); + + cp = pw->pw_gecos; + fullname[0] = '\0'; + while (cp != NULL) { + char *token; + + token = strsep(&cp, "&"); + if (token != pw->pw_gecos && + strlcat(fullname, pw->pw_name, len) >= len) + errx(1, "truncated string"); + if (strlcat(fullname, token, len) >= len) + errx(1, "truncated string"); } - *dst = '\0'; + /* Restore case of first char of login. */ + pw->pw_name[0] = ch; sysname[0] = CTL_KERN; sysname[1] = KERN_OSTYPE; |