summaryrefslogtreecommitdiff
path: root/usr.bin/sendbug/sendbug.c
diff options
context:
space:
mode:
authorRay Lai <ray@cvs.openbsd.org>2007-03-27 04:15:01 +0000
committerRay Lai <ray@cvs.openbsd.org>2007-03-27 04:15:01 +0000
commit8f7d581b067d0eecf4adfc15c09860955f585d64 (patch)
tree613a04a14f3fa2a8f8d62b613ab50f78f3c8b11f /usr.bin/sendbug/sendbug.c
parentf5afe7c7ef5c9ed63bd49c183bf0f2a7cf3da563 (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.c53
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;