summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/makemap/makemap.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/makemap/makemap.c')
-rw-r--r--contrib/sendmail/makemap/makemap.c989
1 files changed, 989 insertions, 0 deletions
diff --git a/contrib/sendmail/makemap/makemap.c b/contrib/sendmail/makemap/makemap.c
new file mode 100644
index 0000000..53b5865
--- /dev/null
+++ b/contrib/sendmail/makemap/makemap.c
@@ -0,0 +1,989 @@
+/*
+ * Copyright (c) 1998 Sendmail, Inc. All rights reserved.
+ * Copyright (c) 1992 Eric P. Allman. All rights reserved.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ *
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)makemap.c 8.62 (Berkeley) 6/24/98";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#ifndef ISC_UNIX
+# include <sys/file.h>
+#endif
+#include "sendmail.h"
+#include "pathnames.h"
+
+#ifdef NDBM
+# include <ndbm.h>
+#endif
+
+#ifdef NEWDB
+# include <db.h>
+# ifndef DB_VERSION_MAJOR
+# define DB_VERSION_MAJOR 1
+# endif
+#endif
+
+enum type { T_DBM, T_BTREE, T_HASH, T_ERR, T_UNKNOWN };
+
+union dbent
+{
+#ifdef NDBM
+ datum dbm;
+#endif
+#ifdef NEWDB
+ DBT db;
+#endif
+ struct
+ {
+ char *data;
+ size_t size;
+ } xx;
+};
+
+uid_t RealUid;
+gid_t RealGid;
+char *RealUserName;
+uid_t RunAsUid;
+uid_t RunAsGid;
+char *RunAsUserName;
+int Verbose = 2;
+bool DontInitGroups = TRUE;
+long DontBlameSendmail = DBS_SAFE;
+u_char tTdvect[100];
+uid_t TrustedFileUid = 0;
+
+#define BUFSIZE 1024
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *progname;
+ char *cfile;
+ bool inclnull = FALSE;
+ bool notrunc = FALSE;
+ bool allowreplace = FALSE;
+ bool allowdups = FALSE;
+ bool verbose = FALSE;
+ bool foldcase = TRUE;
+ int exitstat;
+ int opt;
+ char *typename;
+ char *mapname;
+ char *ext;
+ int lineno;
+ int st;
+ int mode;
+ int putflags;
+ long dbcachesize = 1024 * 1024;
+ enum type type;
+ int fd;
+ int sff = SFF_ROOTOK|SFF_REGONLY;
+ struct passwd *pw;
+ union
+ {
+#ifdef NDBM
+ DBM *dbm;
+#endif
+#ifdef NEWDB
+ DB *db;
+#endif
+ void *dbx;
+ } dbp;
+ union dbent key, val;
+#ifdef NEWDB
+# if DB_VERSION_MAJOR < 2
+ BTREEINFO bti;
+ HASHINFO hinfo;
+# else
+ DB_INFO dbinfo;
+# endif
+#endif
+ char ibuf[BUFSIZE];
+ char fbuf[MAXNAME];
+ char dbuf[MAXNAME];
+#ifdef NDBM
+ char pbuf[MAXNAME];
+#endif
+#if _FFR_TRUSTED_FILE_OWNER
+ FILE *cfp;
+ char buf[MAXLINE];
+#endif
+ static char rnamebuf[MAXNAME]; /* holds RealUserName */
+ struct stat std;
+#ifdef NDBM
+ struct stat stp;
+#endif
+ extern char *optarg;
+ extern int optind;
+
+ progname = argv[0];
+ cfile = _PATH_SENDMAILCF;
+
+ RunAsUid = RealUid = getuid();
+ RunAsGid = RealGid = getgid();
+ pw = getpwuid(RealUid);
+ if (pw != NULL)
+ {
+ if (strlen(pw->pw_name) > MAXNAME - 1)
+ pw->pw_name[MAXNAME] = 0;
+ sprintf(rnamebuf, "%s", pw->pw_name);
+ }
+ else
+ sprintf(rnamebuf, "Unknown UID %d", (int) RealUid);
+ RunAsUserName = RealUserName = rnamebuf;
+
+#if _FFR_NEW_MAKEMAP_FLAGS
+#define OPTIONS "C:Nc:dforsv"
+#else
+#define OPTIONS "C:Ndforsv"
+#endif
+ while ((opt = getopt(argc, argv, OPTIONS)) != EOF)
+ {
+ switch (opt)
+ {
+ case 'C':
+ cfile = optarg;
+ break;
+
+ case 'N':
+ inclnull = TRUE;
+ break;
+
+#if _FFR_NEW_MAKEMAP_FLAGS
+ case 'c':
+ dbcachesize = atol(optarg);
+ break;
+#endif
+
+ case 'd':
+ allowdups = TRUE;
+ break;
+
+ case 'f':
+ foldcase = FALSE;
+ break;
+
+ case 'o':
+ notrunc = TRUE;
+ break;
+
+ case 'r':
+ allowreplace = TRUE;
+ break;
+
+ case 's':
+ DontBlameSendmail |= DBS_MAPINUNSAFEDIRPATH|DBS_WRITEMAPTOHARDLINK|DBS_WRITEMAPTOSYMLINK|DBS_LINKEDMAPINWRITABLEDIR;
+ break;
+
+ case 'v':
+ verbose = TRUE;
+ break;
+
+ default:
+ type = T_ERR;
+ break;
+ }
+ }
+
+ if (!bitset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
+ sff |= SFF_NOSLINK;
+ if (!bitset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
+ sff |= SFF_NOHLINK;
+ if (!bitset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
+ sff |= SFF_NOWLINK;
+
+ argc -= optind;
+ argv += optind;
+ if (argc != 2)
+ type = T_ERR;
+ else
+ {
+ typename = argv[0];
+ mapname = argv[1];
+ ext = NULL;
+
+ if (strcmp(typename, "dbm") == 0)
+ {
+ type = T_DBM;
+ }
+ else if (strcmp(typename, "btree") == 0)
+ {
+ type = T_BTREE;
+ ext = ".db";
+ }
+ else if (strcmp(typename, "hash") == 0)
+ {
+ type = T_HASH;
+ ext = ".db";
+ }
+ else
+ type = T_UNKNOWN;
+ }
+
+#if _FFR_TRUSTED_FILE_OWNER
+ if ((cfp = fopen(cfile, "r")) == NULL)
+ {
+ fprintf(stderr, "mailstats: ");
+ perror(cfile);
+ exit(EX_NOINPUT);
+ }
+ while (fgets(buf, sizeof(buf), cfp) != NULL)
+ {
+ register char *b;
+
+ if ((b = strchr(buf, '\n')) != NULL)
+ *b = '\0';
+
+ b = buf;
+ switch (*b++)
+ {
+ case 'O': /* option */
+ if (strncasecmp(b, " TrustedFileOwner", 17) == 0 &&
+ !(isascii(b[17]) && isalnum(b[17])))
+ {
+ b = strchr(b, '=');
+ if (b == NULL)
+ continue;
+ while (isascii(*++b) && isspace(*b))
+ continue;
+ if (isascii(*b) && isdigit(*b))
+ TrustedFileUid = atoi(b);
+ else
+ {
+ register struct passwd *pw;
+
+ TrustedFileUid = 0;
+ pw = getpwnam(b);
+ if (pw == NULL)
+ fprintf(stderr,
+ "TrustedFileOwner: unknown user %s", b);
+ else
+ TrustedFileUid = pw->pw_uid;
+ }
+
+# ifdef UID_MAX
+ if (TrustedFileUid > UID_MAX)
+ {
+ syserr("TrustedFileOwner: uid value (%ld) > UID_MAX (%ld)",
+ TrustedFileUid, UID_MAX);
+ TrustedFileUid = 0;
+ }
+# endif
+ break;
+ }
+
+
+ default:
+ continue;
+ }
+ }
+ (void) fclose(cfp);
+#endif
+ switch (type)
+ {
+ case T_ERR:
+#if _FFR_NEW_MAKEMAP_FLAGS
+ fprintf(stderr,
+ "Usage: %s [-N] [-c cachesize] [-d] [-f] [-o] [-r] [-s] [-v] type mapname\n",
+ progname);
+#else
+ fprintf(stderr, "Usage: %s [-N] [-d] [-f] [-o] [-r] [-s] [-v] type mapname\n", progname);
+#endif
+ exit(EX_USAGE);
+
+ case T_UNKNOWN:
+ fprintf(stderr, "%s: Unknown database type %s\n",
+ progname, typename);
+ exit(EX_USAGE);
+
+#ifndef NDBM
+ case T_DBM:
+#endif
+#ifndef NEWDB
+ case T_BTREE:
+ case T_HASH:
+#endif
+ fprintf(stderr, "%s: Type %s not supported in this version\n",
+ progname, typename);
+ exit(EX_UNAVAILABLE);
+
+#ifdef NEWDB
+ case T_BTREE:
+# if DB_VERSION_MAJOR < 2
+ bzero(&bti, sizeof bti);
+# else
+ bzero(&dbinfo, sizeof dbinfo);
+# endif
+ if (allowdups)
+ {
+# if DB_VERSION_MAJOR < 2
+ bti.flags |= R_DUP;
+# else
+ dbinfo.flags |= DB_DUP;
+# endif
+ }
+ if (allowdups || allowreplace)
+ putflags = 0;
+ else
+ {
+# if DB_VERSION_MAJOR < 2
+ putflags = R_NOOVERWRITE;
+# else
+ putflags = DB_NOOVERWRITE;
+# endif
+ }
+ break;
+
+ case T_HASH:
+# if DB_VERSION_MAJOR < 2
+ bzero(&hinfo, sizeof hinfo);
+# else
+ bzero(&dbinfo, sizeof dbinfo);
+# endif
+ if (allowreplace)
+ putflags = 0;
+ else
+ {
+# if DB_VERSION_MAJOR < 2
+ putflags = R_NOOVERWRITE;
+# else
+ putflags = DB_NOOVERWRITE;
+# endif
+ }
+ break;
+#endif
+#ifdef NDBM
+ case T_DBM:
+ if (allowdups)
+ {
+ fprintf(stderr, "%s: Type %s does not support -d (allow dups)\n",
+ progname, typename);
+ exit(EX_UNAVAILABLE);
+ }
+ if (allowreplace)
+ putflags = DBM_REPLACE;
+ else
+ putflags = DBM_INSERT;
+ break;
+#endif
+ }
+
+ /*
+ ** Adjust file names.
+ */
+
+ if (ext != NULL)
+ {
+ int el, fl;
+
+ el = strlen(ext);
+ fl = strlen(mapname);
+ if (el + fl + 1 >= sizeof fbuf)
+ {
+ fprintf(stderr, "%s: file name too long", mapname);
+ exit(EX_USAGE);
+ }
+ if (fl < el || strcmp(&mapname[fl - el], ext) != 0)
+ {
+ strcpy(fbuf, mapname);
+ strcat(fbuf, ext);
+ mapname = fbuf;
+ }
+ }
+
+ if (!notrunc)
+ sff |= SFF_CREAT;
+ switch (type)
+ {
+#ifdef NEWDB
+ case T_BTREE:
+ case T_HASH:
+ if (strlen(mapname) >= sizeof dbuf)
+ {
+ fprintf(stderr,
+ "%s: map name too long\n", mapname);
+ exit(EX_USAGE);
+ }
+ strcpy(dbuf, mapname);
+ if ((st = safefile(dbuf, RealUid, RealGid, RealUserName,
+ sff, S_IWUSR, &std)) != 0)
+ {
+ fprintf(stderr,
+ "%s: could not create: %s\n",
+ dbuf, errstring(st));
+ exit(EX_CANTCREAT);
+ }
+ break;
+#endif
+#ifdef NDBM
+ case T_DBM:
+ if (strlen(mapname) + 5 > sizeof dbuf)
+ {
+ fprintf(stderr,
+ "%s: map name too long\n", mapname);
+ exit(EX_USAGE);
+ }
+ sprintf(dbuf, "%s.dir", mapname);
+ if ((st = safefile(dbuf, RealUid, RealGid, RealUserName,
+ sff, S_IWUSR, &std)) != 0)
+ {
+ fprintf(stderr,
+ "%s: could not create: %s\n",
+ dbuf, errstring(st));
+ exit(EX_CANTCREAT);
+ }
+ sprintf(pbuf, "%s.pag", mapname);
+ if ((st = safefile(pbuf, RealUid, RealGid, RealUserName,
+ sff, S_IWUSR, &stp)) != 0)
+ {
+ fprintf(stderr,
+ "%s: could not create: %s\n",
+ pbuf, errstring(st));
+ exit(EX_CANTCREAT);
+ }
+ break;
+#endif
+ default:
+ fprintf(stderr,
+ "%s: internal error: type %d\n",
+ progname,
+ type);
+ exit(EX_SOFTWARE);
+ }
+
+ /*
+ ** Create the database.
+ */
+
+ mode = O_RDWR;
+ if (!notrunc)
+ mode |= O_CREAT|O_TRUNC;
+#if O_EXLOCK
+ mode |= O_EXLOCK;
+#else
+ /* pre-lock the database */
+ fd = safeopen(dbuf, mode & ~O_TRUNC, 0644, sff);
+ if (fd < 0)
+ {
+ fprintf(stderr, "%s: cannot create type %s map %s\n",
+ progname, typename, mapname);
+ exit(EX_CANTCREAT);
+ }
+#endif
+ switch (type)
+ {
+#ifdef NDBM
+ case T_DBM:
+ dbp.dbm = dbm_open(mapname, mode, 0644);
+ if (dbp.dbm != NULL &&
+ dbm_dirfno(dbp.dbm) == dbm_pagfno(dbp.dbm))
+ {
+ fprintf(stderr, "dbm map %s: cannot run with GDBM\n",
+ mapname);
+ dbm_close(dbp.dbm);
+ exit(EX_CONFIG);
+ }
+ if (dbp.dbm != NULL &&
+ (filechanged(dbuf, dbm_dirfno(dbp.dbm), &std) ||
+ filechanged(pbuf, dbm_pagfno(dbp.dbm), &stp)))
+ {
+ fprintf(stderr,
+ "dbm map %s: file changed after open\n",
+ mapname);
+ dbm_close(dbp.dbm);
+ exit(EX_CANTCREAT);
+ }
+ if (geteuid() == 0 && TrustedFileUid != 0)
+ {
+ if (fchown(dbm_dirfno(dbp.dbm), TrustedFileUid, -1) < 0 ||
+ fchown(dbm_pagfno(dbp.dbm), TrustedFileUid, -1) < 0)
+ {
+ fprintf(stderr,
+ "WARNING: ownership change on %s failed: %s",
+ mapname, errstring(errno));
+ }
+ }
+
+ break;
+#endif
+
+#ifdef NEWDB
+ case T_HASH:
+ /* tweak some parameters for performance */
+# if DB_VERSION_MAJOR < 2
+ hinfo.nelem = 4096;
+ hinfo.cachesize = dbcachesize;
+# else
+ dbinfo.h_nelem = 4096;
+ dbinfo.db_cachesize = dbcachesize;
+# endif
+
+# if DB_VERSION_MAJOR < 2
+ dbp.db = dbopen(mapname, mode, 0644, DB_HASH, &hinfo);
+# else
+ {
+ int flags = 0;
+
+ if (bitset(O_CREAT, mode))
+ flags |= DB_CREATE;
+ if (bitset(O_TRUNC, mode))
+ flags |= DB_TRUNCATE;
+
+ dbp.db = NULL;
+ errno = db_open(mapname, DB_HASH, flags, 0644,
+ NULL, &dbinfo, &dbp.db);
+ }
+# endif
+ if (dbp.db != NULL)
+ {
+ int fd;
+
+# if DB_VERSION_MAJOR < 2
+ fd = dbp.db->fd(dbp.db);
+# else
+ fd = -1;
+ errno = dbp.db->fd(dbp.db, &fd);
+# endif
+ if (filechanged(dbuf, fd, &std))
+ {
+ fprintf(stderr,
+ "db map %s: file changed after open\n",
+ mapname);
+# if DB_VERSION_MAJOR < 2
+ dbp.db->close(dbp.db);
+# else
+ errno = dbp.db->close(dbp.db, 0);
+# endif
+ exit(EX_CANTCREAT);
+ }
+ (void) (*dbp.db->sync)(dbp.db, 0);
+ if (geteuid() == 0 && TrustedFileUid != 0)
+ {
+ if (fchown(fd, TrustedFileUid, -1) < 0)
+ {
+ fprintf(stderr,
+ "WARNING: ownership change on %s failed: %s",
+ mapname, errstring(errno));
+ }
+ }
+ }
+ break;
+
+ case T_BTREE:
+ /* tweak some parameters for performance */
+# if DB_VERSION_MAJOR < 2
+ bti.cachesize = dbcachesize;
+# else
+ dbinfo.db_cachesize = dbcachesize;
+# endif
+
+# if DB_VERSION_MAJOR < 2
+ dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, &bti);
+# else
+ {
+ int flags = 0;
+
+ if (bitset(O_CREAT, mode))
+ flags |= DB_CREATE;
+ if (bitset(O_TRUNC, mode))
+ flags |= DB_TRUNCATE;
+
+ dbp.db = NULL;
+ errno = db_open(mapname, DB_BTREE, flags, 0644,
+ NULL, &dbinfo, &dbp.db);
+ }
+# endif
+ if (dbp.db != NULL)
+ {
+ int fd;
+
+# if DB_VERSION_MAJOR < 2
+ fd = dbp.db->fd(dbp.db);
+# else
+ fd = -1;
+ errno = dbp.db->fd(dbp.db, &fd);
+# endif
+ if (filechanged(dbuf, fd, &std))
+ {
+ fprintf(stderr,
+ "db map %s: file changed after open\n",
+ mapname);
+# if DB_VERSION_MAJOR < 2
+ dbp.db->close(dbp.db);
+# else
+ errno = dbp.db->close(dbp.db, 0);
+# endif
+ exit(EX_CANTCREAT);
+ }
+ (void) (*dbp.db->sync)(dbp.db, 0);
+ if (geteuid() == 0 && TrustedFileUid != 0)
+ {
+ if (fchown(fd, TrustedFileUid, -1) < 0)
+ {
+ fprintf(stderr,
+ "WARNING: ownership change on %s failed: %s",
+ mapname, errstring(errno));
+ }
+ }
+ }
+ break;
+#endif
+
+ default:
+ fprintf(stderr, "%s: internal error: type %d\n",
+ progname, type);
+ exit(EX_SOFTWARE);
+ }
+
+ if (dbp.dbx == NULL)
+ {
+ fprintf(stderr, "%s: cannot open type %s map %s\n",
+ progname, typename, mapname);
+ exit(EX_CANTCREAT);
+ }
+
+ /*
+ ** Copy the data
+ */
+
+ lineno = 0;
+ exitstat = EX_OK;
+ while (fgets(ibuf, sizeof ibuf, stdin) != NULL)
+ {
+ register char *p;
+
+ lineno++;
+
+ /*
+ ** Parse the line.
+ */
+
+ p = strchr(ibuf, '\n');
+ if (p != NULL)
+ *p = '\0';
+ else if (!feof(stdin))
+ {
+ fprintf(stderr, "%s: %s: line %d: line too long (%ld bytes max)\n",
+ progname, mapname, lineno, (long) sizeof ibuf);
+ continue;
+ }
+
+ if (ibuf[0] == '\0' || ibuf[0] == '#')
+ continue;
+ if (isascii(ibuf[0]) && isspace(ibuf[0]))
+ {
+ fprintf(stderr, "%s: %s: line %d: syntax error (leading space)\n",
+ progname, mapname, lineno);
+ continue;
+ }
+#ifdef NEWDB
+ if (type == T_HASH || type == T_BTREE)
+ {
+ bzero(&key.db, sizeof key.db);
+ bzero(&val.db, sizeof val.db);
+ }
+#endif
+
+ key.xx.data = ibuf;
+ for (p = ibuf; *p != '\0' && !(isascii(*p) && isspace(*p)); p++)
+ {
+ if (foldcase && isascii(*p) && isupper(*p))
+ *p = tolower(*p);
+ }
+ key.xx.size = p - key.xx.data;
+ if (inclnull)
+ key.xx.size++;
+ if (*p != '\0')
+ *p++ = '\0';
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (*p == '\0')
+ {
+ fprintf(stderr, "%s: %s: line %d: no RHS for LHS %s\n",
+ progname, mapname, lineno, key.xx.data);
+ continue;
+ }
+ val.xx.data = p;
+ val.xx.size = strlen(p);
+ if (inclnull)
+ val.xx.size++;
+
+ /*
+ ** Do the database insert.
+ */
+
+ if (verbose)
+ {
+ printf("key=`%s', val=`%s'\n", key.xx.data, val.xx.data);
+ }
+
+ switch (type)
+ {
+#ifdef NDBM
+ case T_DBM:
+ st = dbm_store(dbp.dbm, key.dbm, val.dbm, putflags);
+ break;
+#endif
+
+#ifdef NEWDB
+ case T_BTREE:
+ case T_HASH:
+# if DB_VERSION_MAJOR < 2
+ st = (*dbp.db->put)(dbp.db, &key.db, &val.db, putflags);
+# else
+ errno = (*dbp.db->put)(dbp.db, NULL, &key.db,
+ &val.db, putflags);
+ switch (errno)
+ {
+ case DB_KEYEXIST:
+ st = 1;
+ break;
+
+ case 0:
+ st = 0;
+ break;
+
+ default:
+ st = -1;
+ break;
+ }
+# endif
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if (st < 0)
+ {
+ fprintf(stderr, "%s: %s: line %d: key %s: put error\n",
+ progname, mapname, lineno, key.xx.data);
+ perror(mapname);
+ exitstat = EX_IOERR;
+ }
+ else if (st > 0)
+ {
+ fprintf(stderr,
+ "%s: %s: line %d: key %s: duplicate key\n",
+ progname, mapname, lineno, key.xx.data);
+ }
+ }
+
+ /*
+ ** Now close the database.
+ */
+
+ switch (type)
+ {
+#ifdef NDBM
+ case T_DBM:
+ dbm_close(dbp.dbm);
+ break;
+#endif
+
+#ifdef NEWDB
+ case T_HASH:
+ case T_BTREE:
+# if DB_VERSION_MAJOR < 2
+ if ((*dbp.db->close)(dbp.db) < 0)
+# else
+ if ((errno = (*dbp.db->close)(dbp.db, 0)) != 0)
+# endif
+ {
+ fprintf(stderr, "%s: %s: error on close\n",
+ progname, mapname);
+ perror(mapname);
+ exitstat = EX_IOERR;
+ }
+#endif
+ default:
+ break;
+ }
+
+#if !O_EXLOCK
+ /* release locks */
+ close(fd);
+#endif
+
+ exit (exitstat);
+}
+ /*
+** LOCKFILE -- lock a file using flock or (shudder) fcntl locking
+**
+** Parameters:
+** fd -- the file descriptor of the file.
+** filename -- the file name (for error messages).
+** ext -- the filename extension.
+** type -- type of the lock. Bits can be:
+** LOCK_EX -- exclusive lock.
+** LOCK_NB -- non-blocking.
+**
+** Returns:
+** TRUE if the lock was acquired.
+** FALSE otherwise.
+*/
+
+bool
+lockfile(fd, filename, ext, type)
+ int fd;
+ char *filename;
+ char *ext;
+ int type;
+{
+# if !HASFLOCK
+ int action;
+ struct flock lfd;
+ extern int errno;
+
+ bzero(&lfd, sizeof lfd);
+ if (bitset(LOCK_UN, type))
+ lfd.l_type = F_UNLCK;
+ else if (bitset(LOCK_EX, type))
+ lfd.l_type = F_WRLCK;
+ else
+ lfd.l_type = F_RDLCK;
+ if (bitset(LOCK_NB, type))
+ action = F_SETLK;
+ else
+ action = F_SETLKW;
+
+ if (fcntl(fd, action, &lfd) >= 0)
+ return TRUE;
+
+ /*
+ ** On SunOS, if you are testing using -oQ/tmp/mqueue or
+ ** -oA/tmp/aliases or anything like that, and /tmp is mounted
+ ** as type "tmp" (that is, served from swap space), the
+ ** previous fcntl will fail with "Invalid argument" errors.
+ ** Since this is fairly common during testing, we will assume
+ ** that this indicates that the lock is successfully grabbed.
+ */
+
+ if (errno == EINVAL)
+ return TRUE;
+
+# else /* HASFLOCK */
+
+ if (flock(fd, type) >= 0)
+ return TRUE;
+
+# endif
+
+ return FALSE;
+}
+
+/*VARARGS1*/
+void
+#ifdef __STDC__
+message(const char *msg, ...)
+#else
+message(msg, va_alist)
+ const char *msg;
+ va_dcl
+#endif
+{
+ const char *m;
+ VA_LOCAL_DECL
+
+ m = msg;
+ if (isascii(m[0]) && isdigit(m[0]) &&
+ isascii(m[1]) && isdigit(m[1]) &&
+ isascii(m[2]) && isdigit(m[2]) && m[3] == ' ')
+ m += 4;
+ VA_START(msg);
+ vfprintf(stderr, m, ap);
+ VA_END;
+ fprintf(stderr, "\n");
+}
+
+/*VARARGS1*/
+void
+#ifdef __STDC__
+syserr(const char *msg, ...)
+#else
+syserr(msg, va_alist)
+ const char *msg;
+ va_dcl
+#endif
+{
+ const char *m;
+ VA_LOCAL_DECL
+
+ m = msg;
+ if (isascii(m[0]) && isdigit(m[0]) &&
+ isascii(m[1]) && isdigit(m[1]) &&
+ isascii(m[2]) && isdigit(m[2]) && m[3] == ' ')
+ m += 4;
+ VA_START(msg);
+ vfprintf(stderr, m, ap);
+ VA_END;
+ fprintf(stderr, "\n");
+}
+
+const char *
+errstring(err)
+ int err;
+{
+ static char errstr[64];
+#if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+#endif
+
+ /* handle pseudo-errors internal to sendmail */
+ switch (err)
+ {
+ case E_SM_OPENTIMEOUT:
+ return "Timeout on file open";
+
+ case E_SM_NOSLINK:
+ return "Symbolic links not allowed";
+
+ case E_SM_NOHLINK:
+ return "Hard links not allowed";
+
+ case E_SM_REGONLY:
+ return "Regular files only";
+
+ case E_SM_ISEXEC:
+ return "Executable files not allowed";
+
+ case E_SM_WWDIR:
+ return "World writable directory";
+
+ case E_SM_GWDIR:
+ return "Group writable directory";
+
+ case E_SM_FILECHANGE:
+ return "File changed after open";
+
+ case E_SM_WWFILE:
+ return "World writable file";
+
+ case E_SM_GWFILE:
+ return "Group writable file";
+ }
+
+#if HASSTRERROR
+ return strerror(err);
+#else
+ if (err < 0 || err >= sys_nerr)
+ {
+ sprintf(errstr, "Error %d", err);
+ return errstr;
+ }
+ return sys_errlist[err];
+#endif
+}
OpenPOWER on IntegriCloud