diff options
Diffstat (limited to 'ident.c')
-rw-r--r-- | ident.c | 104 |
1 files changed, 77 insertions, 27 deletions
@@ -9,7 +9,9 @@ static struct strbuf git_default_name = STRBUF_INIT; static struct strbuf git_default_email = STRBUF_INIT; -static char git_default_date[50]; +static struct strbuf git_default_date = STRBUF_INIT; +static int default_email_is_bogus; +static int default_name_is_bogus; #define IDENT_NAME_GIVEN 01 #define IDENT_MAIL_GIVEN 02 @@ -23,6 +25,25 @@ static int author_ident_explicitly_given; #define get_gecos(struct_passwd) ((struct_passwd)->pw_gecos) #endif +static struct passwd *xgetpwuid_self(int *is_bogus) +{ + struct passwd *pw; + + errno = 0; + pw = getpwuid(getuid()); + if (!pw) { + static struct passwd fallback; + fallback.pw_name = "unknown"; +#ifndef NO_GECOS_IN_PWENT + fallback.pw_gecos = "Unknown"; +#endif + pw = &fallback; + if (is_bogus) + *is_bogus = 1; + } + return pw; +} + static void copy_gecos(const struct passwd *w, struct strbuf *name) { char *src; @@ -70,25 +91,52 @@ static int add_mailname_host(struct strbuf *buf) return 0; } -static void add_domainname(struct strbuf *out) +static int canonical_name(const char *host, struct strbuf *out) +{ + int status = -1; + +#ifndef NO_IPV6 + struct addrinfo hints, *ai; + memset (&hints, '\0', sizeof (hints)); + hints.ai_flags = AI_CANONNAME; + if (!getaddrinfo(host, NULL, &hints, &ai)) { + if (ai && strchr(ai->ai_canonname, '.')) { + strbuf_addstr(out, ai->ai_canonname); + status = 0; + } + freeaddrinfo(ai); + } +#else + struct hostent *he = gethostbyname(host); + if (he && strchr(he->h_name, '.')) { + strbuf_addstr(out, he->h_name); + status = 0; + } +#endif /* NO_IPV6 */ + + return status; +} + +static void add_domainname(struct strbuf *out, int *is_bogus) { char buf[1024]; - struct hostent *he; if (gethostname(buf, sizeof(buf))) { warning("cannot get host name: %s", strerror(errno)); strbuf_addstr(out, "(none)"); + *is_bogus = 1; return; } if (strchr(buf, '.')) strbuf_addstr(out, buf); - else if ((he = gethostbyname(buf)) && strchr(he->h_name, '.')) - strbuf_addstr(out, he->h_name); - else + else if (canonical_name(buf, out) < 0) { strbuf_addf(out, "%s.(none)", buf); + *is_bogus = 1; + } } -static void copy_email(const struct passwd *pw, struct strbuf *email) +static void copy_email(const struct passwd *pw, struct strbuf *email, + int *is_bogus) { /* * Make up a fake email address @@ -99,13 +147,13 @@ static void copy_email(const struct passwd *pw, struct strbuf *email) if (!add_mailname_host(email)) return; /* read from "/etc/mailname" (Debian) */ - add_domainname(email); + add_domainname(email, is_bogus); } -static const char *ident_default_name(void) +const char *ident_default_name(void) { if (!git_default_name.len) { - copy_gecos(xgetpwuid_self(), &git_default_name); + copy_gecos(xgetpwuid_self(&default_name_is_bogus), &git_default_name); strbuf_trim(&git_default_name); } return git_default_name.buf; @@ -121,7 +169,8 @@ const char *ident_default_email(void) committer_ident_explicitly_given |= IDENT_MAIL_GIVEN; author_ident_explicitly_given |= IDENT_MAIL_GIVEN; } else - copy_email(xgetpwuid_self(), &git_default_email); + copy_email(xgetpwuid_self(&default_email_is_bogus), + &git_default_email, &default_email_is_bogus); strbuf_trim(&git_default_email); } return git_default_email.buf; @@ -129,9 +178,9 @@ const char *ident_default_email(void) static const char *ident_default_date(void) { - if (!git_default_date[0]) - datestamp(git_default_date, sizeof(git_default_date)); - return git_default_date; + if (!git_default_date.len) + datestamp(&git_default_date); + return git_default_date.buf; } static int crud(unsigned char c) @@ -292,7 +341,6 @@ const char *fmt_ident(const char *name, const char *email, const char *date_str, int flag) { static struct strbuf ident = STRBUF_INIT; - char date[50]; int strict = (flag & IDENT_STRICT); int want_date = !(flag & IDENT_NO_DATE); int want_name = !(flag & IDENT_NO_NAME); @@ -310,23 +358,19 @@ const char *fmt_ident(const char *name, const char *email, fputs(env_hint, stderr); die("empty ident name (for <%s>) not allowed", email); } - pw = xgetpwuid_self(); + pw = xgetpwuid_self(NULL); name = pw->pw_name; } - if (strict && email == git_default_email.buf && - strstr(email, "(none)")) { + if (want_name && strict && + name == git_default_name.buf && default_name_is_bogus) { fputs(env_hint, stderr); - die("unable to auto-detect email address (got '%s')", email); + die("unable to auto-detect name (got '%s')", name); } - if (want_date) { - if (date_str && date_str[0]) { - if (parse_date(date_str, date, sizeof(date)) < 0) - die("invalid date format: %s", date_str); - } - else - strcpy(date, ident_default_date()); + if (strict && email == git_default_email.buf && default_email_is_bogus) { + fputs(env_hint, stderr); + die("unable to auto-detect email address (got '%s')", email); } strbuf_reset(&ident); @@ -339,8 +383,14 @@ const char *fmt_ident(const char *name, const char *email, strbuf_addch(&ident, '>'); if (want_date) { strbuf_addch(&ident, ' '); - strbuf_addstr_without_crud(&ident, date); + if (date_str && date_str[0]) { + if (parse_date(date_str, &ident) < 0) + die("invalid date format: %s", date_str); + } + else + strbuf_addstr(&ident, ident_default_date()); } + return ident.buf; } |