summaryrefslogtreecommitdiff
path: root/ident.c
diff options
context:
space:
mode:
Diffstat (limited to 'ident.c')
-rw-r--r--ident.c152
1 files changed, 110 insertions, 42 deletions
diff --git a/ident.c b/ident.c
index 1d9b6e7..6e12582 100644
--- a/ident.c
+++ b/ident.c
@@ -9,13 +9,18 @@
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;
+
+static int ident_use_config_only;
#define IDENT_NAME_GIVEN 01
#define IDENT_MAIL_GIVEN 02
#define IDENT_ALL_GIVEN (IDENT_NAME_GIVEN|IDENT_MAIL_GIVEN)
static int committer_ident_explicitly_given;
static int author_ident_explicitly_given;
+static int ident_config_given;
#ifdef NO_GECOS_IN_PWENT
#define get_gecos(ignored) "&"
@@ -23,6 +28,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;
@@ -55,7 +79,7 @@ static int add_mailname_host(struct strbuf *buf)
strerror(errno));
return -1;
}
- if (strbuf_getline(&mailnamebuf, mailname, '\n') == EOF) {
+ if (strbuf_getline(&mailnamebuf, mailname) == EOF) {
if (ferror(mailname))
warning("cannot read /etc/mailname: %s",
strerror(errno));
@@ -70,25 +94,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 +150,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 +172,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 +181,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,41 +344,44 @@ 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);
- if (want_name && !name)
- name = ident_default_name();
- if (!email)
- email = ident_default_email();
-
- if (want_name && !*name) {
- struct passwd *pw;
-
- if (strict) {
- if (name == git_default_name.buf)
+ if (want_name) {
+ int using_default = 0;
+ if (!name) {
+ name = ident_default_name();
+ using_default = 1;
+ if (strict && default_name_is_bogus) {
fputs(env_hint, stderr);
- die("empty ident name (for <%s>) not allowed", email);
+ die("unable to auto-detect name (got '%s')", name);
+ }
+ if (strict && ident_use_config_only
+ && !(ident_config_given & IDENT_NAME_GIVEN))
+ die("user.useConfigOnly set but no name given");
+ }
+ if (!*name) {
+ struct passwd *pw;
+ if (strict) {
+ if (using_default)
+ fputs(env_hint, stderr);
+ die("empty ident name (for <%s>) not allowed", email);
+ }
+ pw = xgetpwuid_self(NULL);
+ name = pw->pw_name;
}
- pw = xgetpwuid_self();
- name = pw->pw_name;
- }
-
- if (strict && email == git_default_email.buf &&
- strstr(email, "(none)")) {
- fputs(env_hint, stderr);
- die("unable to auto-detect email address (got '%s')", email);
}
- 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);
+ if (!email) {
+ email = ident_default_email();
+ if (strict && default_email_is_bogus) {
+ fputs(env_hint, stderr);
+ die("unable to auto-detect email address (got '%s')", email);
}
- else
- strcpy(date, ident_default_date());
+ if (strict && ident_use_config_only
+ && !(ident_config_given & IDENT_MAIL_GIVEN))
+ die("user.useConfigOnly set but no mail given");
}
strbuf_reset(&ident);
@@ -339,8 +394,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;
}
@@ -394,6 +455,11 @@ int author_ident_sufficiently_given(void)
int git_ident_config(const char *var, const char *value, void *data)
{
+ if (!strcmp(var, "user.useconfigonly")) {
+ ident_use_config_only = git_config_bool(var, value);
+ return 0;
+ }
+
if (!strcmp(var, "user.name")) {
if (!value)
return config_error_nonbool(var);
@@ -401,6 +467,7 @@ int git_ident_config(const char *var, const char *value, void *data)
strbuf_addstr(&git_default_name, value);
committer_ident_explicitly_given |= IDENT_NAME_GIVEN;
author_ident_explicitly_given |= IDENT_NAME_GIVEN;
+ ident_config_given |= IDENT_NAME_GIVEN;
return 0;
}
@@ -411,6 +478,7 @@ int git_ident_config(const char *var, const char *value, void *data)
strbuf_addstr(&git_default_email, value);
committer_ident_explicitly_given |= IDENT_MAIL_GIVEN;
author_ident_explicitly_given |= IDENT_MAIL_GIVEN;
+ ident_config_given |= IDENT_MAIL_GIVEN;
return 0;
}