1/* ufopen.c
2   Open a file with the permissions of the invoking user.
3
4   Copyright (C) 1992, 1995, 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 "sysdep.h"
29#include "system.h"
30
31#include <errno.h>
32
33#if HAVE_FCNTL_H
34#include <fcntl.h>
35#else
36#if HAVE_SYS_FILE_H
37#include <sys/file.h>
38#endif
39#endif
40
41#ifndef O_RDONLY
42#define O_RDONLY 0
43#define O_WRONLY 1
44#define O_RDWR 2
45#endif
46
47#ifndef O_NOCTTY
48#define O_NOCTTY 0
49#endif
50
51#ifndef FD_CLOEXEC
52#define FD_CLOEXEC 1
53#endif
54
55/* Open a file with the permissions of the invoking user.  Ignore the
56   fbinary argument since Unix has no distinction between text and
57   binary files.  */
58
59/*ARGSUSED*/
60openfile_t
61esysdep_user_fopen (zfile, frd, fbinary)
62     const char *zfile;
63     boolean frd;
64     boolean fbinary ATTRIBUTE_UNUSED;
65{
66  uid_t ieuid;
67  gid_t iegid;
68  openfile_t e;
69  const char *zerr;
70  int o = 0;
71
72  if (! fsuser_perms (&ieuid, &iegid))
73    return EFILECLOSED;
74
75  zerr = NULL;
76
77#if USE_STDIO
78  e = fopen (zfile, frd ? "r" : "w");
79  if (e == NULL)
80    zerr = "fopen";
81  else
82    o = fileno (e);
83#else
84  if (frd)
85    {
86      e = open ((char *) zfile, O_RDONLY | O_NOCTTY, 0);
87      zerr = "open";
88    }
89  else
90    {
91      e = creat ((char *) zfile, IPUBLIC_FILE_MODE);
92      zerr = "creat";
93    }
94  if (e >= 0)
95    {
96      o = e;
97      zerr = NULL;
98    }
99#endif
100
101  if (! fsuucp_perms ((long) ieuid, (long) iegid))
102    {
103      if (ffileisopen (e))
104	(void) ffileclose (e);
105      return EFILECLOSED;
106    }
107
108  if (zerr != NULL)
109    {
110      ulog (LOG_ERROR, "%s (%s): %s", zerr, zfile, strerror (errno));
111#if ! HAVE_SETREUID
112      /* Are these error messages helpful or confusing?  */
113#if HAVE_SAVED_SETUID
114      if (errno == EACCES && getuid () == 0)
115	ulog (LOG_ERROR,
116	      "The superuser may only transfer files that are readable by %s",
117	      OWNER);
118#else
119      if (errno == EACCES)
120	ulog (LOG_ERROR,
121	      "You may only transfer files that are readable by %s", OWNER);
122#endif
123#endif /* ! HAVE_SETREUID */
124      return EFILECLOSED;
125    }
126
127  if (fcntl (o, F_SETFD, fcntl (o, F_GETFD, 0) | FD_CLOEXEC) < 0)
128    {
129      ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno));
130      (void) ffileclose (e);
131      return EFILECLOSED;
132    }
133
134  return e;
135}
136