From e850194c83985396435b01b70d2db00b6d3af02e Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 10 Dec 2015 16:33:05 -0500 Subject: ident: make xgetpwuid_self() a static local helper This function is defined in wrapper.c, but nobody besides ident.c uses it. And nobody is likely to in the future, either, as anything that cares about the user's name should be going through the ident code. Moving it here is a cleanup of the global namespace, but it will also enable further cleanups inside ident.c. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- ident.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'ident.c') diff --git a/ident.c b/ident.c index 5ff1aadaa..d7c70e28d 100644 --- a/ident.c +++ b/ident.c @@ -23,6 +23,18 @@ static int author_ident_explicitly_given; #define get_gecos(struct_passwd) ((struct_passwd)->pw_gecos) #endif +static struct passwd *xgetpwuid_self(void) +{ + struct passwd *pw; + + errno = 0; + pw = getpwuid(getuid()); + if (!pw) + die(_("unable to look up current user in the passwd file: %s"), + errno ? strerror(errno) : _("no such user")); + return pw; +} + static void copy_gecos(const struct passwd *w, struct strbuf *name) { char *src; -- cgit v1.2.1 From 19ce497cf594a3c01af33a65b27b19e7459212d6 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 10 Dec 2015 16:35:36 -0500 Subject: ident: keep a flag for bogus default_email If we have to deduce the user's email address and can't come up with something plausible for the hostname, we simply write "(none)" or ".(none)" in the hostname. Later, our strict-check is forced to use strstr to look for this magic string. This is probably not a problem in practice, but it's rather ugly. Let's keep an extra flag that tells us the email is bogus, and check that instead. We could get away with simply setting the global in add_domainname(); it only gets called to write into git_default_email. However, let's make the code a little more obvious to future readers by actually passing a pointer to our "bogus" flag down the call-chain. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- ident.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'ident.c') diff --git a/ident.c b/ident.c index d7c70e28d..085cfbe23 100644 --- a/ident.c +++ b/ident.c @@ -10,6 +10,7 @@ static struct strbuf git_default_name = STRBUF_INIT; static struct strbuf git_default_email = STRBUF_INIT; static struct strbuf git_default_date = STRBUF_INIT; +static int default_email_is_bogus; #define IDENT_NAME_GIVEN 01 #define IDENT_MAIL_GIVEN 02 @@ -82,7 +83,7 @@ static int add_mailname_host(struct strbuf *buf) return 0; } -static void add_domainname(struct strbuf *out) +static void add_domainname(struct strbuf *out, int *is_bogus) { char buf[1024]; struct hostent *he; @@ -90,17 +91,21 @@ static void add_domainname(struct strbuf *out) 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 { 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 @@ -111,7 +116,7 @@ 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); } const char *ident_default_name(void) @@ -133,7 +138,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(), &git_default_email, + &default_email_is_bogus); strbuf_trim(&git_default_email); } return git_default_email.buf; @@ -325,8 +331,7 @@ const char *fmt_ident(const char *name, const char *email, name = pw->pw_name; } - if (strict && email == git_default_email.buf && - strstr(email, "(none)")) { + 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); } -- cgit v1.2.1 From 92bcbb9b338dd27f0fd4245525093c4bce867f3d Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 10 Dec 2015 16:41:29 -0500 Subject: ident: loosen getpwuid error in non-strict mode If the user has not specified an identity and we have to turn to getpwuid() to find the username or gecos field, we die immediately when getpwuid fails (e.g., because the user does not exist). This is OK for making a commit, where we have set IDENT_STRICT and would want to bail on bogus input. But for something like a reflog, where the ident is "best effort", it can be pain. For instance, even running "git clone" with a UID that is not in /etc/passwd will result in git barfing, just because we can't find an ident to put in the reflog. Instead of dying in xgetpwuid_self, we can instead return a fallback value, and set a "bogus" flag. For the username in an email, we already have a "default_email_is_bogus" flag. For the name field, we introduce (and check) a matching "default_name_is_bogus" flag. As a bonus, this means you now get the usual "tell me who you are" advice instead of just a "no such user" error. No tests, as this is dependent on configuration outside of git's control. However, I did confirm that it behaves sensibly when I delete myself from the local /etc/passwd (reflogs get written, and commits complain). Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- ident.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'ident.c') diff --git a/ident.c b/ident.c index 085cfbe23..bb1b17435 100644 --- a/ident.c +++ b/ident.c @@ -11,6 +11,7 @@ static struct strbuf git_default_name = STRBUF_INIT; static struct strbuf git_default_email = STRBUF_INIT; 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 @@ -24,15 +25,22 @@ static int author_ident_explicitly_given; #define get_gecos(struct_passwd) ((struct_passwd)->pw_gecos) #endif -static struct passwd *xgetpwuid_self(void) +static struct passwd *xgetpwuid_self(int *is_bogus) { struct passwd *pw; errno = 0; pw = getpwuid(getuid()); - if (!pw) - die(_("unable to look up current user in the passwd file: %s"), - errno ? strerror(errno) : _("no such user")); + 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; } @@ -122,7 +130,7 @@ static void copy_email(const struct passwd *pw, struct strbuf *email, 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; @@ -138,8 +146,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, - &default_email_is_bogus); + 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; @@ -327,10 +335,16 @@ 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 (want_name && strict && + name == git_default_name.buf && default_name_is_bogus) { + fputs(env_hint, stderr); + die("unable to auto-detect name (got '%s')", name); + } + 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); -- cgit v1.2.1