--- /dev/null
+/*
+ * Copyright notice from original mutt:
+ * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
+ * Copyright (C) 1999-2000 Thomas Roessler <roessler@does-not-exist.org>
+ *
+ * This file is part of mutt-ng, see http://www.muttng.org/.
+ * It's licensed under the GNU General Public License,
+ * please see the file GPL in the top level source directory.
+ */
+
+#include <stdlib.h>
+
+#include <lib-lib/macros.h>
+#include <lib-lib/mem.h>
+#include <lib-lib/str.h>
+
+#include "unix.h"
+
+/* Extract the real name from /etc/passwd's GECOS field.
+ * When set, honor the regular expression in rx,
+ * otherwise assume that the GECOS field is a comma-separated list.
+ * Replace "&" by a capitalized version of the user's login name.
+ */
+ssize_t mutt_gecos_name(char *dst, ssize_t n, struct passwd *pw, rx_t *rx)
+{
+ const char *p, *end;
+ ssize_t len;
+
+ *dst = '\0';
+ len = 0;
+
+ if (!pw->pw_gecos)
+ return 0;
+
+ if (rx) {
+ regmatch_t pat_match[1];
+
+ if (regexec(rx->rx, pw->pw_gecos, 1, pat_match, 0)) {
+ return 0;
+ }
+
+ p = pw->pw_gecos + pat_match[0].rm_so;
+ end = pw->pw_gecos + pat_match[0].rm_so;
+ } else {
+ p = pw->pw_gecos;
+ end = m_strchrnul(pw->pw_gecos, ',');
+ }
+
+ for (;;) {
+ const char *q = MIN(end, m_strchrnul(p, '&'));
+
+ len += m_strncpy(dst + len, n - len, p, q - p);
+ p = q + 1;
+
+ if (!p[-1] || p >= end)
+ break;
+
+ /* p[0] == '&' */
+ len += m_strcpy(dst + len, n - len, pw->pw_name);
+ }
+
+ return len;
+}