Merge commit '00f1a4f432b3d8aad1aa270e91c44c57f03ef407'
[unleashed.git] / usr / src / cmd / mail / main.c
blob895debb75e0f85c6fff11c9b6ff4d7264fe434a3
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include "mail.h"
33 #ifdef SVR4
34 #include <locale.h>
35 #endif
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
42 int
43 main(int argc, char **argv)
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;
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++;
64 env_var_idx++;
66 environ[next_slot_idx] = NULL;
68 #ifdef SIGCONT
69 #ifdef SVR4
71 struct sigaction nsig;
72 nsig.sa_handler = SIG_IGN;
73 (void) sigaction(SIGPIPE, &nsig, NULL);
75 nsig.sa_handler = SIG_DFL;
76 sigemptyset(&nsig.sa_mask);
77 nsig.sa_flags = SA_RESTART;
78 (void) sigaction(SIGCONT, &nsig, NULL);
80 #else
81 sigset(SIGCONT, SIG_DFL);
82 #endif
83 #endif
86 * Strip off path name of this command for use in messages
88 if ((program = strrchr(argv[0], '/')) != NULL) {
89 program++;
90 } else {
91 program = argv[0];
94 /* Close all file descriptors except stdin, stdout & stderr */
95 closefrom(STDERR_FILENO + 1);
98 * Get group id for mail, exit if none exists
100 if ((grpptr = getgrnam("mail")) == NULL) {
101 errmsg(E_GROUP, "");
102 exit(1);
103 } else {
104 mailgrp = grpptr->gr_gid;
108 * Save the *id for later use.
110 my_uid = getuid();
111 my_gid = getgid();
112 my_euid = geteuid();
113 my_egid = getegid();
116 * What command (rmail or mail)?
118 if (strcmp(program, "rmail") == SAME) {
119 ismail = FALSE;
123 * Parse the command line and adjust argc and argv
124 * to compensate for any options
126 i = parse(argc, argv);
127 argv += (i - 1);
128 argc -= (i - 1);
130 /* block a potential security hole */
131 if (flgT && (my_euid != 0)) {
132 setgid(my_gid);
133 Tout(pn, "Setgid unset\n");
136 if (debug == 0) {
137 /* If not set as an invocation option, check for system-wide */
138 /* global flag */
139 char *xp = xgetenv("DEBUG");
140 if (xp != NULL) {
141 debug = atoi(xp);
142 if (debug < 0) {
143 /* Keep trace file even if successful */
144 keepdbgfile = -1;
145 debug = -debug;
149 if (debug > 0) {
150 strcpy(dbgfname, "/tmp/MLDBGXXXXXX");
151 if ((tmpfd = mkstemp(dbgfname)) == -1) {
152 fprintf(stderr, "%s: can't open debugging file '%s'\n",
153 program, dbgfname);
154 exit(13);
156 if ((dbgfp = fdopen(tmpfd, "w")) == NULL) {
157 fprintf(stderr, "%s: can't open debugging file '%s'\n",
158 program, dbgfname);
159 (void) close(tmpfd);
160 exit(13);
162 setbuf(dbgfp, NULL);
163 fprintf(dbgfp, "main(): debugging level == %d\n", debug);
164 fprintf(dbgfp, "main(): trace file ='%s': kept %s\n", dbgfname,
165 ((keepdbgfile < 0) ?
166 "on success or failure." : "only on failure."));
169 if (!ismail && (goerr > 0 || !i)) {
170 Dout(pn, 11, "!ismail, goerr=%d, i=%d\n", goerr, i);
171 if (goerr > 0) {
172 errmsg(E_SYNTAX, "Usage: rmail [-wt] person(s)");
174 if (!i) {
175 errmsg(E_SYNTAX, "At least one user must be specified");
177 Dout(pn, 11, "exiting!\n");
178 done(0);
181 umsave = umask(7);
182 uname(&utsn);
183 if ((p = xgetenv("CLUSTER")) != NULL) {
185 * We are not who we appear...
187 thissys = p;
188 } else {
189 thissys = utsn.nodename;
191 Dout(pn, 11, "thissys = '%s', uname = '%s'\n", thissys, utsn.nodename);
193 failsafe = xgetenv("FAILSAFE");
194 if (failsafe)
195 Dout(pn, 11, "failsafe processing enabled to %s\n", failsafe);
198 * Use environment variables
200 home = getenv("HOME");
201 if (!home || !*home) {
202 home = ".";
205 my_name[0] = '\0';
206 pwd = getpwuid(my_uid);
207 if (pwd)
208 (void) strlcpy(my_name, pwd->pw_name, sizeof (my_name));
210 /* If root, use LOGNAME if set */
211 if (my_uid == 0) {
212 /* If root, use LOGNAME if set */
213 if (((cptr = getenv("LOGNAME")) != NULL) &&
214 (strlen(cptr) != 0)) {
215 (void) strlcpy(my_name, cptr, sizeof (my_name));
218 Dout(pn, 11, "my_name = '%s'\n", my_name);
221 * Catch signals for cleanup
223 if (setjmp(sjbuf)) {
224 done(0);
226 for (i = SIGINT; i < SIGCLD; i++) {
227 setsig(i, delete);
229 setsig(SIGHUP, sig_done);
230 setsig(SIGTERM, sig_done);
232 cksaved(my_name);
235 * Rmail is always invoked to send mail
237 Dout(pn, 11, "ismail=%d, argc=%d\n", ismail, argc);
238 if (ismail && (argc == 1)) {
239 sending = FALSE;
240 printmail();
242 } else {
243 sending = TRUE;
244 sendmail(argc, argv);
246 done(0);