diff options
Diffstat (limited to 'gnu/libexec/uucp/libunix/init.c')
| -rw-r--r-- | gnu/libexec/uucp/libunix/init.c | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/gnu/libexec/uucp/libunix/init.c b/gnu/libexec/uucp/libunix/init.c new file mode 100644 index 000000000000..d4a137762813 --- /dev/null +++ b/gnu/libexec/uucp/libunix/init.c @@ -0,0 +1,394 @@ +/* init.c + Initialize the system dependent routines. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#include "uucp.h" + +#include "uudefs.h" +#include "uuconf.h" +#include "system.h" +#include "sysdep.h" + +#include <errno.h> +#include <pwd.h> + +#if HAVE_FCNTL_H +#include <fcntl.h> +#else +#if HAVE_SYS_FILE_H +#include <sys/file.h> +#endif +#endif + +#ifndef O_RDONLY +#define O_RDONLY 0 +#define O_WRONLY 1 +#define O_RDWR 2 +#endif + +#if ! HAVE_GETHOSTNAME && HAVE_UNAME +#include <sys/utsname.h> +#endif + +/* Use getcwd in preference to getwd; if we have neither, we will be + using a getcwd replacement. */ +#if HAVE_GETCWD +#undef HAVE_GETWD +#define HAVE_GETWD 0 +#else /* ! HAVE_GETCWD */ +#if ! HAVE_GETWD +#undef HAVE_GETCWD +#define HAVE_GETCWD 1 +#endif /* ! HAVE_GETWD */ +#endif /* ! HAVE_GETCWD */ + +#if HAVE_GETWD +/* Get a value for MAXPATHLEN. */ +#if HAVE_SYS_PARAMS_H +#include <sys/params.h> +#endif + +#if HAVE_LIMITS_H +#include <limits.h> +#endif + +#ifndef MAXPATHLEN +#ifdef PATH_MAX +#define MAXPATHLEN PATH_MAX +#else /* ! defined (PATH_MAX) */ +#define MAXPATHLEN 1024 +#endif /* ! defined (PATH_MAX) */ +#endif /* ! defined (MAXPATHLEN) */ +#endif /* HAVE_GETWD */ + +/* External functions. */ +#ifndef getlogin +extern char *getlogin (); +#endif +#if GETPWNAM_DECLARATION_OK +#ifndef getpwnam +extern struct passwd *getpwnam (); +#endif +#endif +#if GETPWUID_DECLARATION_OK +#ifndef getpwuid +extern struct passwd *getpwuid (); +#endif +#endif +#if HAVE_GETCWD +#ifndef getcwd +extern char *getcwd (); +#endif +#endif +#if HAVE_GETWD +#ifndef getwd +extern char *getwd (); +#endif +#endif +#if HAVE_SYSCONF +#ifndef sysconf +extern long sysconf (); +#endif +#endif + +/* Initialize the system dependent routines. We will probably be running + suid to uucp, so we make sure that nothing is obviously wrong. We + save the login name since we will be losing the real uid. */ +static char *zSlogin; + +/* The UUCP spool directory. */ +const char *zSspooldir; + +/* The UUCP lock directory. */ +const char *zSlockdir; + +/* The local UUCP name. */ +const char *zSlocalname; + +/* We save the current directory since we will do a chdir to the + spool directory. */ +char *zScwd; + +/* The maximum length of a system name is controlled by the type of spool + directory we use. */ +#if SPOOLDIR_V2 || SPOOLDIR_BSD42 || SPOOLDIR_BSD43 || SPOOLDIR_ULTRIX +size_t cSysdep_max_name_len = 7; +#endif +#if SPOOLDIR_HDB || SPOOLDIR_SVR4 +size_t cSysdep_max_name_len = 14; +#endif +#if SPOOLDIR_TAYLOR +#if HAVE_LONG_FILE_NAMES +size_t cSysdep_max_name_len = 255; +#else /* ! HAVE_LONG_FILE_NAMES */ +size_t cSysdep_max_name_len = 14; +#endif /* ! HAVE_LONG_FILE_NAMES */ +#endif /* SPOOLDIR_TAYLOR */ + +/* Initialize the system dependent routines. */ + +void +usysdep_initialize (puuconf,iflags) + pointer puuconf; + int iflags; +{ + int cdescs; + int o; + int iuuconf; + char *z; + struct passwd *q; + + ulog_id (getpid ()); + + /* Close everything but stdin, stdout and stderr. */ +#if HAVE_GETDTABLESIZE + cdescs = getdtablesize (); +#else +#if HAVE_SYSCONF + cdescs = sysconf (_SC_OPEN_MAX); +#else +#ifdef OPEN_MAX + cdescs = OPEN_MAX; +#else +#ifdef NOFILE + cdescs = NOFILE; +#else + cdescs = 20; +#endif /* ! defined (NOFILE) */ +#endif /* ! defined (OPEN_MAX) */ +#endif /* ! HAVE_SYSCONF */ +#endif /* ! HAVE_GETDTABLESIZE */ + + for (o = 3; o < cdescs; o++) + (void) close (o); + + /* Make sure stdin, stdout and stderr are open. */ + if (fcntl (0, F_GETFD, 0) < 0 + && open ((char *) "/dev/null", O_RDONLY, 0) != 0) + exit (EXIT_FAILURE); + if (fcntl (1, F_GETFD, 0) < 0 + && open ((char *) "/dev/null", O_WRONLY, 0) != 1) + exit (EXIT_FAILURE); + if (fcntl (2, F_GETFD, 0) < 0 + && open ((char *) "/dev/null", O_WRONLY, 0) != 2) + exit (EXIT_FAILURE); + + iuuconf = uuconf_spooldir (puuconf, &zSspooldir); + if (iuuconf != UUCONF_SUCCESS) + ulog_uuconf (LOG_FATAL, puuconf, iuuconf); + + iuuconf = uuconf_lockdir (puuconf, &zSlockdir); + if (iuuconf != UUCONF_SUCCESS) + ulog_uuconf (LOG_FATAL, puuconf, iuuconf); + + iuuconf = uuconf_localname (puuconf, &zSlocalname); + if (iuuconf == UUCONF_NOT_FOUND) + { +#if HAVE_GETHOSTNAME + char ab[256]; + + if (gethostname (ab, sizeof ab - 1) < 0) + ulog (LOG_FATAL, "gethostname: %s", strerror (errno)); + ab[sizeof ab - 1] = '\0'; + ab[strcspn (ab, ".")] = '\0'; + zSlocalname = zbufcpy (ab); +#else /* ! HAVE_GETHOSTNAME */ +#if HAVE_UNAME + struct utsname s; + + if (uname (&s) < 0) + ulog (LOG_FATAL, "uname: %s", strerror (errno)); + zSlocalname = zbufcpy (s.nodename); +#else /* ! HAVE_UNAME */ + ulog (LOG_FATAL, "Don't know how to get local node name"); +#endif /* ! HAVE_UNAME */ +#endif /* ! HAVE_GETHOSTNAME */ + } + else if (iuuconf != UUCONF_SUCCESS) + ulog_uuconf (LOG_FATAL, puuconf, iuuconf); + + /* We always set our file modes to exactly what we want. */ + umask (0); + + /* Get the login name, making sure that it matches the uid. Many + systems truncate the getlogin return value to 8 characters, but + keep the full name in the password file, so we prefer the name in + the password file. */ + z = getenv ("LOGNAME"); + if (z == NULL) + z = getenv ("USER"); + if (z == NULL) + z = getlogin (); + if (z == NULL) + q = NULL; + else + { + q = getpwnam (z); + if (q != NULL) + z = q->pw_name; + } + if (q == NULL || q->pw_uid != getuid ()) + { + q = getpwuid (getuid ()); + if (q == NULL) + z = NULL; + else + z = q->pw_name; + } + if (z != NULL) + zSlogin = zbufcpy (z); + + /* On some old systems, an suid program run by root is started with + an euid of 0. If this happens, we look up the uid we should have + and set ourselves to it manually. This means that on such a + system root will not be able to uucp or uux files that are not + readable by uucp. */ + if ((iflags & INIT_SUID) != 0 + && geteuid () == 0) + { + q = getpwnam (OWNER); + if (q != NULL) + setuid (q->pw_uid); + } + + if ((iflags & INIT_GETCWD) != 0) + { + const char *zenv; + struct stat senv, sdot; + + /* Get the current working directory. We have to get it now, + since we're about to do a chdir. We use PWD if it's defined + and if it really names the working directory, since if it's + not the same as whatever getcwd returns it's probably more + appropriate. */ + zenv = getenv ("PWD"); + if (zenv != NULL + && stat ((char *) zenv, &senv) == 0 + && stat ((char *) ".", &sdot) == 0 + && senv.st_ino == sdot.st_ino + && senv.st_dev == sdot.st_dev) + zScwd = zbufcpy (zenv); + else + { + +#if HAVE_GETCWD + { + size_t c; + + c = 128; + while (TRUE) + { + zScwd = (char *) xmalloc (c); + if (getcwd (zScwd, c) != NULL) + break; + xfree ((pointer) zScwd); + zScwd = NULL; + if (errno != ERANGE) + break; + c <<= 1; + } + } +#endif /* HAVE_GETCWD */ + +#if HAVE_GETWD + zScwd = (char *) xmalloc (MAXPATHLEN); + if (getwd (zScwd) == NULL) + { + xfree ((pointer) zScwd); + zScwd = NULL; + } +#endif /* HAVE_GETWD */ + + if (zScwd != NULL) + zScwd = (char *) xrealloc ((pointer) zScwd, + strlen (zScwd) + 1); + } + } + + if ((iflags & INIT_NOCHDIR) == 0) + { + /* Connect to the spool directory, and create it if it doesn't + exist. */ + if (chdir (zSspooldir) < 0) + { + if (errno == ENOENT + && mkdir ((char *) zSspooldir, IDIRECTORY_MODE) < 0) + ulog (LOG_FATAL, "mkdir (%s): %s", zSspooldir, + strerror (errno)); + if (chdir (zSspooldir) < 0) + ulog (LOG_FATAL, "chdir (%s): %s", zSspooldir, + strerror (errno)); + } + } +} + +/* Exit the program. */ + +void +usysdep_exit (fsuccess) + boolean fsuccess; +{ + exit (fsuccess ? EXIT_SUCCESS : EXIT_FAILURE); +} + +/* This is called when a non-standard configuration file is used, to + make sure the program doesn't hand out privileged file access. + This means that to test non-standard configuration files, you + should be logged in as uucp. This is called before + usysdep_initialize. It ensures that someone can't simply use an + alternate configuration file to steal UUCP transfers from other + systems. This will still permit people to set up their own + configuration file and pretend to be whatever system they choose. + The only real security is to use a high level of protection on the + modem ports. */ + +/*ARGSUSED*/ +boolean fsysdep_other_config (z) + const char *z; +{ + (void) setuid (getuid ()); + (void) setgid (getgid ()); + return TRUE; +} + +/* Get the node name to use if it was not specified in the configuration + file. */ + +const char * +zsysdep_localname () +{ + return zSlocalname; +} + +/* Get the login name. We actually get the login name in + usysdep_initialize, because after that we may switch away from the + real uid. */ + +const char * +zsysdep_login_name () +{ + if (zSlogin == NULL) + ulog (LOG_FATAL, "Can't get login name"); + return zSlogin; +} |
