1/* init.c 2 Initialize the system dependent routines. 3 4 Copyright (C) 1991, 1992, 1993, 1994, 2002 Ian Lance Taylor 5 6 This file is part of the Taylor UUCP package. 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of the 11 License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 22 The author of the program may be contacted at ian@airs.com. 23 */ 24 25#include "uucp.h" 26 27#include "uudefs.h" 28#include "uuconf.h" 29#include "system.h" 30#include "sysdep.h" 31 32#include <errno.h> 33#include <pwd.h> 34 35#if HAVE_FCNTL_H 36#include <fcntl.h> 37#else 38#if HAVE_SYS_FILE_H 39#include <sys/file.h> 40#endif 41#endif 42 43#ifndef O_RDONLY 44#define O_RDONLY 0 45#define O_WRONLY 1 46#define O_RDWR 2 47#endif 48 49#if ! HAVE_GETHOSTNAME && HAVE_UNAME 50#include <sys/utsname.h> 51#endif 52 53/* Use getcwd in preference to getwd; if we have neither, we will be 54 using a getcwd replacement. */ 55#if HAVE_GETCWD 56#undef HAVE_GETWD 57#define HAVE_GETWD 0 58#else /* ! HAVE_GETCWD */ 59#if ! HAVE_GETWD 60#undef HAVE_GETCWD 61#define HAVE_GETCWD 1 62#endif /* ! HAVE_GETWD */ 63#endif /* ! HAVE_GETCWD */ 64 65#if HAVE_GETWD 66/* Get a value for MAXPATHLEN. */ 67#if HAVE_SYS_PARAMS_H 68#include <sys/params.h> 69#endif 70 71#if HAVE_LIMITS_H 72#include <limits.h> 73#endif 74 75#ifndef MAXPATHLEN 76#ifdef PATH_MAX 77#define MAXPATHLEN PATH_MAX 78#else /* ! defined (PATH_MAX) */ 79#define MAXPATHLEN 1024 80#endif /* ! defined (PATH_MAX) */ 81#endif /* ! defined (MAXPATHLEN) */ 82#endif /* HAVE_GETWD */ 83 84/* External functions. */ 85#ifndef getlogin 86extern char *getlogin (); 87#endif 88#if GETPWNAM_DECLARATION_OK 89#ifndef getpwnam 90extern struct passwd *getpwnam (); 91#endif 92#endif 93#if GETPWUID_DECLARATION_OK 94#ifndef getpwuid 95extern struct passwd *getpwuid (); 96#endif 97#endif 98#if HAVE_GETCWD 99#ifndef getcwd 100extern char *getcwd (); 101#endif 102#endif 103#if HAVE_GETWD 104#ifndef getwd 105extern char *getwd (); 106#endif 107#endif 108#if HAVE_SYSCONF 109#ifndef sysconf 110extern long sysconf (); 111#endif 112#endif 113 114/* Initialize the system dependent routines. We will probably be running 115 suid to uucp, so we make sure that nothing is obviously wrong. We 116 save the login name since we will be losing the real uid. */ 117static char *zSlogin; 118 119/* The UUCP spool directory. */ 120const char *zSspooldir; 121 122/* The UUCP lock directory. */ 123const char *zSlockdir; 124 125/* The local UUCP name. */ 126const char *zSlocalname; 127 128/* We save the current directory since we will do a chdir to the 129 spool directory. */ 130char *zScwd; 131 132/* The maximum length of a system name is controlled by the type of spool 133 directory we use. */ 134#if SPOOLDIR_V2 || SPOOLDIR_BSD42 || SPOOLDIR_BSD43 || SPOOLDIR_ULTRIX 135size_t cSysdep_max_name_len = 7; 136#endif 137#if SPOOLDIR_HDB || SPOOLDIR_SVR4 138size_t cSysdep_max_name_len = 14; 139#endif 140#if SPOOLDIR_TAYLOR 141#if HAVE_LONG_FILE_NAMES 142size_t cSysdep_max_name_len = 255; 143#else /* ! HAVE_LONG_FILE_NAMES */ 144size_t cSysdep_max_name_len = 14; 145#endif /* ! HAVE_LONG_FILE_NAMES */ 146#endif /* SPOOLDIR_TAYLOR */ 147 148/* Initialize the system dependent routines. */ 149 150void 151usysdep_initialize (puuconf,iflags) 152 pointer puuconf; 153 int iflags; 154{ 155 int iuuconf; 156 char *z; 157 struct passwd *q; 158 159 ulog_id (getpid ()); 160 161 if ((iflags & INIT_NOCLOSE) == 0) 162 { 163 int cdescs; 164 int o; 165 166 /* Close everything but stdin, stdout and stderr. */ 167#if HAVE_GETDTABLESIZE 168 cdescs = getdtablesize (); 169#else 170#if HAVE_SYSCONF 171 cdescs = sysconf (_SC_OPEN_MAX); 172#else 173#ifdef OPEN_MAX 174 cdescs = OPEN_MAX; 175#else 176#ifdef NOFILE 177 cdescs = NOFILE; 178#else 179 cdescs = 20; 180#endif /* ! defined (NOFILE) */ 181#endif /* ! defined (OPEN_MAX) */ 182#endif /* ! HAVE_SYSCONF */ 183#endif /* ! HAVE_GETDTABLESIZE */ 184 185 for (o = 3; o < cdescs; o++) 186 (void) close (o); 187 } 188 189 /* Make sure stdin, stdout and stderr are open. */ 190 if (fcntl (0, F_GETFD, 0) < 0 191 && open ((char *) "/dev/null", O_RDONLY, 0) != 0) 192 exit (EXIT_FAILURE); 193 if (fcntl (1, F_GETFD, 0) < 0 194 && open ((char *) "/dev/null", O_WRONLY, 0) != 1) 195 exit (EXIT_FAILURE); 196 if (fcntl (2, F_GETFD, 0) < 0 197 && open ((char *) "/dev/null", O_WRONLY, 0) != 2) 198 exit (EXIT_FAILURE); 199 200 iuuconf = uuconf_spooldir (puuconf, &zSspooldir); 201 if (iuuconf != UUCONF_SUCCESS) 202 ulog_uuconf (LOG_FATAL, puuconf, iuuconf); 203 204 iuuconf = uuconf_lockdir (puuconf, &zSlockdir); 205 if (iuuconf != UUCONF_SUCCESS) 206 ulog_uuconf (LOG_FATAL, puuconf, iuuconf); 207 208 iuuconf = uuconf_localname (puuconf, &zSlocalname); 209 if (iuuconf == UUCONF_NOT_FOUND) 210 { 211#if HAVE_GETHOSTNAME 212 char ab[256]; 213 214 if (gethostname (ab, sizeof ab - 1) < 0) 215 ulog (LOG_FATAL, "gethostname: %s", strerror (errno)); 216 ab[sizeof ab - 1] = '\0'; 217 ab[strcspn (ab, ".")] = '\0'; 218 zSlocalname = zbufcpy (ab); 219#else /* ! HAVE_GETHOSTNAME */ 220#if HAVE_UNAME 221 struct utsname s; 222 223 if (uname (&s) < 0) 224 ulog (LOG_FATAL, "uname: %s", strerror (errno)); 225 zSlocalname = zbufcpy (s.nodename); 226#else /* ! HAVE_UNAME */ 227 ulog (LOG_FATAL, "Don't know how to get local node name"); 228#endif /* ! HAVE_UNAME */ 229#endif /* ! HAVE_GETHOSTNAME */ 230 } 231 else if (iuuconf != UUCONF_SUCCESS) 232 ulog_uuconf (LOG_FATAL, puuconf, iuuconf); 233 234 /* We always set our file modes to exactly what we want. */ 235 umask (0); 236 237 /* Get the login name, making sure that it matches the uid. Many 238 systems truncate the getlogin return value to 8 characters, but 239 keep the full name in the password file, so we prefer the name in 240 the password file. */ 241 z = getenv ("LOGNAME"); 242 if (z == NULL) 243 z = getenv ("USER"); 244 if (z == NULL) 245 z = getlogin (); 246 if (z == NULL) 247 q = NULL; 248 else 249 { 250 q = getpwnam (z); 251 if (q != NULL) 252 z = q->pw_name; 253 } 254 if (q == NULL || q->pw_uid != getuid ()) 255 { 256 q = getpwuid (getuid ()); 257 if (q == NULL) 258 z = NULL; 259 else 260 z = q->pw_name; 261 } 262 if (z != NULL) 263 zSlogin = zbufcpy (z); 264 265 266 { 267 char *zlf; 268 if (getuid() == 4 && UUCONF_SUCCESS == uuconf_logfile (puuconf, &zlf)) { 269 chmod(zlf, 0777); 270 } 271 } 272 273 /* On some old systems, an suid program run by root is started with 274 an euid of 0. If this happens, we look up the uid we should have 275 and set ourselves to it manually. This means that on such a 276 system root will not be able to uucp or uux files that are not 277 readable by uucp. */ 278 if ((iflags & INIT_SUID) != 0 279 && geteuid () == 0) 280 { 281 q = getpwnam (OWNER); 282 if (q != NULL) 283 setuid (q->pw_uid); 284 } 285 286 if ((iflags & INIT_GETCWD) != 0) 287 { 288 const char *zenv; 289 struct stat senv, sdot; 290 291 /* Get the current working directory. We have to get it now, 292 since we're about to do a chdir. We use PWD if it's defined 293 and if it really names the working directory, since if it's 294 not the same as whatever getcwd returns it's probably more 295 appropriate. */ 296 zenv = getenv ("PWD"); 297 if (zenv != NULL 298 && stat ((char *) zenv, &senv) == 0 299 && stat ((char *) ".", &sdot) == 0 300 && senv.st_ino == sdot.st_ino 301 && senv.st_dev == sdot.st_dev) 302 zScwd = zbufcpy (zenv); 303 else 304 { 305 306#if HAVE_GETCWD 307 { 308 size_t c; 309 310 c = 128; 311 while (TRUE) 312 { 313 zScwd = (char *) xmalloc (c); 314 if (getcwd (zScwd, c) != NULL) 315 break; 316 xfree ((pointer) zScwd); 317 zScwd = NULL; 318 if (errno != ERANGE) 319 break; 320 c <<= 1; 321 } 322 } 323#endif /* HAVE_GETCWD */ 324 325#if HAVE_GETWD 326 zScwd = (char *) xmalloc (MAXPATHLEN); 327 if (getwd (zScwd) == NULL) 328 { 329 xfree ((pointer) zScwd); 330 zScwd = NULL; 331 } 332#endif /* HAVE_GETWD */ 333 334 if (zScwd != NULL) 335 zScwd = (char *) xrealloc ((pointer) zScwd, 336 strlen (zScwd) + 1); 337 } 338 } 339 340 if ((iflags & INIT_NOCHDIR) == 0) 341 { 342 /* Connect to the spool directory, and create it if it doesn't 343 exist. */ 344 if (chdir (zSspooldir) < 0) 345 { 346 if (errno == ENOENT 347 && mkdir ((char *) zSspooldir, IDIRECTORY_MODE) < 0) 348 ulog (LOG_FATAL, "mkdir (%s): %s", zSspooldir, 349 strerror (errno)); 350 if (chdir (zSspooldir) < 0) 351 ulog (LOG_FATAL, "chdir (%s): %s", zSspooldir, 352 strerror (errno)); 353 } 354 } 355} 356 357/* Exit the program. */ 358 359void 360usysdep_exit (fsuccess) 361 boolean fsuccess; 362{ 363 exit (fsuccess ? EXIT_SUCCESS : EXIT_FAILURE); 364} 365 366/* This is called when a non-standard configuration file is used, to 367 make sure the program doesn't hand out privileged file access. 368 This means that to test non-standard configuration files, you 369 should be logged in as uucp. This is called before 370 usysdep_initialize. It ensures that someone can't simply use an 371 alternate configuration file to steal UUCP transfers from other 372 systems. This will still permit people to set up their own 373 configuration file and pretend to be whatever system they choose. 374 The only real security is to use a high level of protection on the 375 modem ports. */ 376 377/*ARGSUSED*/ 378boolean fsysdep_other_config (z) 379 const char *z ATTRIBUTE_UNUSED; 380{ 381 (void) setuid (getuid ()); 382 (void) setgid (getgid ()); 383 return TRUE; 384} 385 386/* Get the node name to use if it was not specified in the configuration 387 file. */ 388 389const char * 390zsysdep_localname () 391{ 392 return zSlocalname; 393} 394 395/* Get the login name. We actually get the login name in 396 usysdep_initialize, because after that we may switch away from the 397 real uid. */ 398 399const char * 400zsysdep_login_name () 401{ 402 if (zSlogin == NULL) 403 ulog (LOG_FATAL, "Can't get login name"); 404 return zSlogin; 405} 406