1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 #pragma ident "%Z%%M% %I% %E% SMI"
31
32 #include "mail.h"
33 #ifdef SVR4
34 #include <locale.h>
35 #endif
36 /*
37 * mail [ -ehpPqrtw ] [-x debuglevel] [ -f file ] [ -F user(s) ]
38 * mail -T file persons
39 * mail [ -tw ] [ -m messagetype ] persons
40 * rmail [ -tw ] persons
41 */
42 int
main(int argc,char ** argv)43 main(int argc, char **argv)
44 {
45 register int i;
46 char *cptr, *p;
47 struct stat statb;
48 static char pn[] = "main";
49 extern char **environ;
50 int env_var_idx, next_slot_idx;
51 int tmpfd = -1;
52
53 #ifdef SVR4
54 (void) setlocale(LC_ALL, "");
55 #endif
56 /* fix here for bug #1086130 - security hole */
57 /* skip over the LD_* env variable */
58 env_var_idx = 0; next_slot_idx = 0;
59 while (environ[env_var_idx] != NULL) {
60 environ[next_slot_idx] = environ[env_var_idx];
61 if (strncmp(environ[env_var_idx], "LD_", 3)) {
62 next_slot_idx++;
63 }
64 env_var_idx++;
65 }
66 environ[next_slot_idx] = NULL;
67
68 #ifdef SIGCONT
69 #ifdef SVR4
70 {
71 struct sigaction nsig;
72 nsig.sa_handler = SIG_DFL;
73 sigemptyset(&nsig.sa_mask);
74 nsig.sa_flags = SA_RESTART;
75 (void) sigaction(SIGCONT, &nsig, (struct sigaction *)0);
76 }
77 #else
78 sigset(SIGCONT, SIG_DFL);
79 #endif
80 #endif
81
82 /*
83 * Strip off path name of this command for use in messages
84 */
85 if ((program = strrchr(argv[0], '/')) != NULL) {
86 program++;
87 } else {
88 program = argv[0];
89 }
90
91 /* Close all file descriptors except stdin, stdout & stderr */
92 closefrom(STDERR_FILENO + 1);
93
94 /*
95 * Get group id for mail, exit if none exists
96 */
97 if ((grpptr = getgrnam("mail")) == NULL) {
98 errmsg(E_GROUP, "");
99 exit(1);
100 } else {
101 mailgrp = grpptr->gr_gid;
102 }
103
104 /*
105 * Save the *id for later use.
106 */
107 my_uid = getuid();
108 my_gid = getgid();
109 my_euid = geteuid();
110 my_egid = getegid();
111
112 /*
113 * What command (rmail or mail)?
114 */
115 if (strcmp(program, "rmail") == SAME) {
116 ismail = FALSE;
117 }
118
119 /*
120 * Parse the command line and adjust argc and argv
121 * to compensate for any options
122 */
123 i = parse(argc, argv);
124 argv += (i - 1);
125 argc -= (i - 1);
126
127 /* block a potential security hole */
128 if (flgT && (my_euid != 0)) {
129 setgid(my_gid);
130 Tout(pn, "Setgid unset\n");
131 }
132
133 if (debug == 0) {
134 /* If not set as an invocation option, check for system-wide */
135 /* global flag */
136 char *xp = xgetenv("DEBUG");
137 if (xp != (char *)NULL) {
138 debug = atoi(xp);
139 if (debug < 0) {
140 /* Keep trace file even if successful */
141 keepdbgfile = -1;
142 debug = -debug;
143 }
144 }
145 }
146 if (debug > 0) {
147 strcpy(dbgfname, "/tmp/MLDBGXXXXXX");
148 if ((tmpfd = mkstemp(dbgfname)) == -1) {
149 fprintf(stderr, "%s: can't open debugging file '%s'\n",
150 program, dbgfname);
151 exit(13);
152 }
153 if ((dbgfp = fdopen(tmpfd, "w")) == (FILE *)NULL) {
154 fprintf(stderr, "%s: can't open debugging file '%s'\n",
155 program, dbgfname);
156 (void) close(tmpfd);
157 exit(13);
158 }
159 setbuf(dbgfp, NULL);
160 fprintf(dbgfp, "main(): debugging level == %d\n", debug);
161 fprintf(dbgfp, "main(): trace file ='%s': kept %s\n", dbgfname,
162 ((keepdbgfile < 0) ?
163 "on success or failure." : "only on failure."));
164 }
165
166 if (!ismail && (goerr > 0 || !i)) {
167 Dout(pn, 11, "!ismail, goerr=%d, i=%d\n", goerr, i);
168 if (goerr > 0) {
169 errmsg(E_SYNTAX, "Usage: rmail [-wt] person(s)");
170 }
171 if (!i) {
172 errmsg(E_SYNTAX, "At least one user must be specified");
173 }
174 Dout(pn, 11, "exiting!\n");
175 done(0);
176 }
177
178 umsave = umask(7);
179 uname(&utsn);
180 if ((p = xgetenv("CLUSTER")) != (char *)NULL) {
181 /*
182 * We are not who we appear...
183 */
184 thissys = p;
185 } else {
186 thissys = utsn.nodename;
187 }
188 Dout(pn, 11, "thissys = '%s', uname = '%s'\n", thissys, utsn.nodename);
189
190 failsafe = xgetenv("FAILSAFE");
191 if (failsafe)
192 Dout(pn, 11, "failsafe processing enabled to %s\n", failsafe);
193
194 /*
195 * Use environment variables
196 */
197 home = getenv("HOME");
198 if (!home || !*home) {
199 home = ".";
200 }
201
202 my_name[0] = '\0';
203 pwd = getpwuid(my_uid);
204 if (pwd)
205 (void) strlcpy(my_name, pwd->pw_name, sizeof (my_name));
206
207 /* If root, use LOGNAME if set */
208 if (my_uid == 0) {
209 /* If root, use LOGNAME if set */
210 if (((cptr = getenv("LOGNAME")) != NULL) &&
211 (strlen(cptr) != 0)) {
212 (void) strlcpy(my_name, cptr, sizeof (my_name));
213 }
214 }
215 Dout(pn, 11, "my_name = '%s'\n", my_name);
216
217 /*
218 * Catch signals for cleanup
219 */
220 if (setjmp(sjbuf)) {
221 done(0);
222 }
223 for (i = SIGINT; i < SIGCLD; i++) {
224 setsig(i, delete);
225 }
226 setsig(SIGHUP, sig_done);
227 setsig(SIGTERM, sig_done);
228
229 cksaved(my_name);
230
231 /*
232 * Rmail is always invoked to send mail
233 */
234 Dout(pn, 11, "ismail=%d, argc=%d\n", ismail, argc);
235 if (ismail && (argc == 1)) {
236 sending = FALSE;
237 printmail();
238
239 } else {
240 sending = TRUE;
241 sendmail(argc, argv);
242 }
243 done(0);
244 }
245