Code

Merge branch 'jn/gitweb-unspecified-action' into maint-1.7.8
[git.git] / ident.c
diff --git a/ident.c b/ident.c
index 9e2438826dfce158e04549933d5c588dd6abcf5c..f619619b82379c2d205c7d7ea101049e373ab90a 100644 (file)
--- a/ident.c
+++ b/ident.c
@@ -9,6 +9,12 @@
 
 static char git_default_date[50];
 
+#ifdef NO_GECOS_IN_PWENT
+#define get_gecos(ignored) "&"
+#else
+#define get_gecos(struct_passwd) ((struct_passwd)->pw_gecos)
+#endif
+
 static void copy_gecos(const struct passwd *w, char *name, size_t sz)
 {
        char *src, *dst;
@@ -20,7 +26,7 @@ static void copy_gecos(const struct passwd *w, char *name, size_t sz)
         * with commas.  Also & stands for capitalized form of the login name.
         */
 
-       for (len = 0, dst = name, src = w->pw_gecos; len < sz; src++) {
+       for (len = 0, dst = name, src = get_gecos(w); len < sz; src++) {
                int ch = *src;
                if (ch != '&') {
                        *dst++ = ch;
@@ -34,6 +40,7 @@ static void copy_gecos(const struct passwd *w, char *name, size_t sz)
                        *dst++ = toupper(*w->pw_name);
                        memcpy(dst, w->pw_name + 1, nlen - 1);
                        dst += nlen - 1;
+                       len += nlen;
                }
        }
        if (len < sz)
@@ -43,6 +50,54 @@ static void copy_gecos(const struct passwd *w, char *name, size_t sz)
 
 }
 
+static int add_mailname_host(char *buf, size_t len)
+{
+       FILE *mailname;
+
+       mailname = fopen("/etc/mailname", "r");
+       if (!mailname) {
+               if (errno != ENOENT)
+                       warning("cannot open /etc/mailname: %s",
+                               strerror(errno));
+               return -1;
+       }
+       if (!fgets(buf, len, mailname)) {
+               if (ferror(mailname))
+                       warning("cannot read /etc/mailname: %s",
+                               strerror(errno));
+               fclose(mailname);
+               return -1;
+       }
+       /* success! */
+       fclose(mailname);
+       return 0;
+}
+
+static void add_domainname(char *buf, size_t len)
+{
+       struct hostent *he;
+       size_t namelen;
+       const char *domainname;
+
+       if (gethostname(buf, len)) {
+               warning("cannot get host name: %s", strerror(errno));
+               strlcpy(buf, "(none)", len);
+               return;
+       }
+       namelen = strlen(buf);
+       if (memchr(buf, '.', namelen))
+               return;
+
+       he = gethostbyname(buf);
+       buf[namelen++] = '.';
+       buf += namelen;
+       len -= namelen;
+       if (he && (domainname = strchr(he->h_name, '.')))
+               strlcpy(buf, domainname + 1, len);
+       else
+               strlcpy(buf, "(none)", len);
+}
+
 static void copy_email(const struct passwd *pw)
 {
        /*
@@ -54,35 +109,29 @@ static void copy_email(const struct passwd *pw)
                die("Your sysadmin must hate you!");
        memcpy(git_default_email, pw->pw_name, len);
        git_default_email[len++] = '@';
-       gethostname(git_default_email + len, sizeof(git_default_email) - len);
-       if (!strchr(git_default_email+len, '.')) {
-               struct hostent *he = gethostbyname(git_default_email + len);
-               char *domainname;
-
-               len = strlen(git_default_email);
-               git_default_email[len++] = '.';
-               if (he && (domainname = strchr(he->h_name, '.')))
-                       strlcpy(git_default_email + len, domainname + 1,
-                               sizeof(git_default_email) - len);
-               else
-                       strlcpy(git_default_email + len, "(none)",
-                               sizeof(git_default_email) - len);
-       }
+
+       if (!add_mailname_host(git_default_email + len,
+                               sizeof(git_default_email) - len))
+               return; /* read from "/etc/mailname" (Debian) */
+       add_domainname(git_default_email + len,
+                       sizeof(git_default_email) - len);
 }
 
-static void setup_ident(void)
+static void setup_ident(const char **name, const char **emailp)
 {
        struct passwd *pw = NULL;
 
        /* Get the name ("gecos") */
-       if (!git_default_name[0]) {
+       if (!*name && !git_default_name[0]) {
                pw = getpwuid(getuid());
                if (!pw)
                        die("You don't exist. Go away!");
                copy_gecos(pw, git_default_name, sizeof(git_default_name));
        }
+       if (!*name)
+               *name = git_default_name;
 
-       if (!git_default_email[0]) {
+       if (!*emailp && !git_default_email[0]) {
                const char *email = getenv("EMAIL");
 
                if (email && email[0]) {
@@ -97,6 +146,8 @@ static void setup_ident(void)
                        copy_email(pw);
                }
        }
+       if (!*emailp)
+               *emailp = git_default_email;
 
        /* And set the default date */
        if (!git_default_date[0])
@@ -192,11 +243,7 @@ const char *fmt_ident(const char *name, const char *email,
        int warn_on_no_name = (flag & IDENT_WARN_ON_NO_NAME);
        int name_addr_only = (flag & IDENT_NO_DATE);
 
-       setup_ident();
-       if (!name)
-               name = git_default_name;
-       if (!email)
-               email = git_default_email;
+       setup_ident(&name, &email);
 
        if (!*name) {
                struct passwd *pw;
@@ -217,8 +264,10 @@ const char *fmt_ident(const char *name, const char *email,
        }
 
        strcpy(date, git_default_date);
-       if (!name_addr_only && date_str)
-               parse_date(date_str, date, sizeof(date));
+       if (!name_addr_only && date_str && date_str[0]) {
+               if (parse_date(date_str, date, sizeof(date)) < 0)
+                       die("invalid date format: %s", date_str);
+       }
 
        i = copy(buffer, sizeof(buffer), 0, name);
        i = add_raw(buffer, sizeof(buffer), i, " <");