+ return (a);
+}
+\f/*
+** FINDUSER -- find the password entry for a user.
+**
+** This looks a lot like getpwnam, except that it may want to
+** do some fancier pattern matching in /etc/passwd.
+**
+** This routine contains most of the time of many sendmail runs.
+** It deserves to be optimized.
+**
+** Parameters:
+** name -- the name to match against.
+**
+** Returns:
+** A pointer to a pw struct.
+** NULL if name is unknown or ambiguous.
+**
+** Side Effects:
+** may modify name.
+*/
+
+struct passwd *
+finduser(name)
+ char *name;
+{
+ register struct passwd *pw;
+ register char *p;
+ extern struct passwd *getpwent();
+ extern struct passwd *getpwnam();
+
+ /* map upper => lower case */
+ for (p = name; *p != '\0'; p++)
+ {
+ if (isascii(*p) && isupper(*p))
+ *p = tolower(*p);
+ }
+
+ /* look up this login name using fast path */
+ if ((pw = getpwnam(name)) != NULL)
+ return (pw);
+
+ /* search for a matching full name instead */
+ for (p = name; *p != '\0'; p++)
+ {
+ if (*p == (SpaceSub & 0177) || *p == '_')
+ *p = ' ';
+ }
+ (void) setpwent();
+ while ((pw = getpwent()) != NULL)
+ {
+ char buf[MAXNAME];
+
+ buildfname(pw->pw_gecos, pw->pw_name, buf);
+ if (index(buf, ' ') != NULL && !strcasecmp(buf, name))
+ {
+ message(Arpa_Info, "sending to login name %s", pw->pw_name);
+ return (pw);
+ }
+ }
+ return (NULL);
+}
+\f/*
+** WRITABLE -- predicate returning if the file is writable.
+**
+** This routine must duplicate the algorithm in sys/fio.c.
+** Unfortunately, we cannot use the access call since we
+** won't necessarily be the real uid when we try to
+** actually open the file.
+**
+** Notice that ANY file with ANY execute bit is automatically
+** not writable. This is also enforced by mailfile.
+**
+** Parameters:
+** s -- pointer to a stat struct for the file.
+**
+** Returns:
+** TRUE -- if we will be able to write this file.
+** FALSE -- if we cannot write this file.
+**
+** Side Effects:
+** none.
+*/
+
+bool
+writable(s)
+ register struct stat *s;
+{
+ int euid, egid;
+ int bits;
+
+ if (bitset(0111, s->st_mode))
+ return (FALSE);
+ euid = getruid();
+ egid = getrgid();
+ if (geteuid() == 0)
+ {
+ if (bitset(S_ISUID, s->st_mode))
+ euid = s->st_uid;
+ if (bitset(S_ISGID, s->st_mode))
+ egid = s->st_gid;
+ }
+
+ if (euid == 0)
+ return (TRUE);
+ bits = S_IWRITE;
+ if (euid != s->st_uid)
+ {
+ bits >>= 3;
+ if (egid != s->st_gid)
+ bits >>= 3;
+ }
+ return ((s->st_mode & bits) != 0);