main.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
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/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23/*	  All Rights Reserved  	*/
24
25/*
26 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
27 * Use is subject to license terms.
28 */
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 */
42main(argc, argv)
43char	**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); /*NOTREACHED*/
244}
245