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