/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include "mail.h" /* * Print mail entries */ void printmail() { static char pn[] = "printmail"; int flg, curlet, showlet, k, print, aret, stret, rc; int nsmbox = 0; /* 1 ==> mailbox is in non-standard place */ int sav_j = -1; char *p, *getarg(); struct stat stbuf; struct stat *stbufp; int ttyf = isatty(1) ? TTY : ORDINARY; char readbuf[LSIZE]; /* holds user's response in interactive mode */ char *resp; gid_t savedegid; stbufp = &stbuf; /* * create working directory mbox name */ if ((hmbox = malloc(strlen(home) + strlen(mbox) + 1)) == NULL) { errmsg(E_MBOX, ""); return; } cat(hmbox, home, mbox); /* * If we are not using an alternate mailfile, then get * the $MAIL value and build the filename for the mailfile. * If $MAIL is set, but is NOT the 'standard' place, then * use it but set flgf to circumvent :saved processing. */ if (!flgf) { if ((p = malloc(strlen(maildir) + strlen(my_name) + 1)) == NULL) { errmsg(E_MEM, ""); return; } cat(p, maildir, my_name); if (((mailfile = getenv("MAIL")) == NULL) || (strlen(mailfile) == 0)) { /* $MAIL not set, use standard path to mailfile */ mailfile = p; } else { if (strcmp(mailfile, p) != 0) { flgf = 1; nsmbox = 1; Dout(pn, 0, "$MAIL ('%s') != standard path\n", mailfile); Dout("", 0, "\tSetting flgf to 1.\n"); } free(p); } } /* * Get ACCESS and MODIFICATION times of mailfile BEFORE we * use it. This allows us to put them back when we are * done. If we didn't, the shell would think NEW mail had * arrived since the file times would have changed. */ stret = CERROR; if (access(mailfile, A_EXIST) == A_OK) { if ((stret = stat(mailfile, stbufp)) != A_OK) { errmsg(E_FILE, "Cannot stat mailfile"); return; } mf_gid = stbufp->st_gid; mf_uid = stbufp->st_uid; utimep->actime = stbufp->st_atime; utimep->modtime = stbufp->st_mtime; file_size = stbufp->st_size; } /* Open the file as the real gid */ savedegid = getegid(); (void) setegid(getgid()); malf = fopen(mailfile, "r"); (void) setegid(savedegid); /* * stat succeeded, but we cannot access the mailfile */ if (stret == CSUCCESS && malf == NULL) { char buf[MAXFILENAME+50]; (void) snprintf(buf, sizeof (buf), "Invalid permissions on %s", mailfile); errmsg(E_PERM, buf); return; } else /* * using an alternate mailfile, but we failed on access */ if (!nsmbox && flgf && (malf == NULL)) { errmsg(E_FILE, "Cannot open mailfile"); return; } /* * we failed to access OR the file is empty */ else if ((malf == NULL) || (stbuf.st_size == 0)) { if (!flge && !flgE) { printf("No mail.\n"); } error = E_FLGE; Dout(pn, 0, "error set to %d\n", error); return; } if (flge) return; if (flgE) { if (utimep->modtime < utimep->actime) { error = E_FLGE_OM; Dout(pn, 0, "error set to %d\n", error); } return; } /* * Secure the mailfile to guarantee integrity */ lock(my_name); /* * copy mail to temp file and mark each letter in the * let array --- mailfile is still locked !!! */ mktmp(); copymt(malf, tmpf); onlet = nlet; fclose(malf); fclose(tmpf); unlock(); /* All done, OK to unlock now */ tmpf = doopen(lettmp, "r+", E_TMP); changed = 0; print = 1; curlet = 0; while (curlet < nlet) { /* * reverse order ? */ showlet = flgr ? curlet : nlet - curlet - 1; if (setjmp(sjbuf) == 0 && print != 0) { /* -h says to print the headers first */ if (flgh) { gethead(showlet, 0); flgh = 0; /* Only once */ /* set letter # to invalid # */ curlet--; showlet = flgr ? curlet : nlet - curlet - 1; } else { if (showlet != sav_j) { /* Looking at new message. */ /* Reset flag to override */ /* non-display of binary */ /* contents */ sav_j = showlet; pflg = 0; Pflg = flgP; } copylet(showlet, stdout, ttyf); } } /* * print only */ if (flgp) { curlet++; continue; } /* * Interactive */ interactive = 1; setjmp(sjbuf); stat(mailfile, stbufp); if (stbufp->st_size != file_size) { /* * New mail has arrived, load it */ k = nlet; lock(my_name); malf = doopen(mailfile, "r", E_FILE); fclose(tmpf); tmpf = doopen(lettmp, "a", E_TMP); fseek(malf, let[nlet].adr, 0); copymt(malf, tmpf); file_size = stbufp->st_size; fclose(malf); fclose(tmpf); unlock(); tmpf = doopen(lettmp, "r+", E_TMP); if (++k < nlet) printf("New mail loaded into letters %d - %d\n", k, nlet); else printf("New mail loaded into letter %d\n", nlet); } /* read the command */ printf("? "); fflush(stdout); fflush(stderr); if (fgets(readbuf, sizeof (readbuf), stdin) == NULL) break; resp = readbuf; while (*resp == ' ' || *resp == '\t') resp++; print = 1; Dout(pn, 0, "resp = '%s'\n", resp); if ((rc = atoi(resp)) != 0) { if (!validmsg(rc)) print = 0; else curlet = flgr ? rc - 1 : nlet - rc; } else switch (resp[0]) { default: printf("Usage:\n"); /* * help */ case '?': print = 0; for (rc = 0; help[rc]; rc++) printf("%s", help[rc]); break; /* * print message number of current message */ case '#': print = 0; if ((showlet == nlet) || (showlet < 0)) { printf("No message selected yet.\n"); } else { printf("Current message number is %d\n", showlet+1); } break; /* * headers */ case 'h': print = 0; if (resp[2] != 'd' && resp[2] != 'a' && (rc = getnumbr(resp+1)) > 0) { showlet = rc - 1; curlet = flgr ? rc - 1 : nlet - rc- 1; } if (rc == -1 && resp[2] != 'a' && resp[2] != 'd') break; if (resp[2] == 'a') rc = 1; else if (resp[2] == 'd') rc = 2; else rc = 0; /* * if (!validmsg(showlet)) break; */ gethead(showlet, rc); break; /* * skip entry */ case '+': case 'n': case '\n': curlet++; break; case 'P': Pflg++; break; case 'p': pflg++; break; case 'x': changed = 0; case 'q': goto donep; /* * Previous entry */ case '^': case '-': if (--curlet < 0) curlet = 0; break; /* * Save in file without header */ case 'y': case 'w': /* * Save mail with header */ case 's': print = 0; if (!validmsg(curlet)) break; if (resp[1] == '\n' || resp[1] == '\0') { cat(resp+1, hmbox, ""); } else if (resp[1] != ' ') { printf("Invalid command\n"); break; } umask(umsave); flg = 0; if (getarg(lfil, resp + 1) == NULL) { cat(resp + 1, hmbox, ""); } malf = (FILE *)NULL; p = resp + 1; while ((p = getarg(lfil, p)) != NULL) { if (flg) { fprintf(stderr, "%s: File '%s' skipped\n", program, lfil); continue; } malf = NULL; if ((aret = legal(lfil))) { malf = fopen(lfil, "a"); } if ((malf == NULL) || (aret == 0)) { fprintf(stderr, "%s: Cannot append to %s\n", program, lfil); flg++; } else if (aret == 2) { chown(lfil, my_euid, my_gid); } if (!flg && copylet(showlet, malf, resp[0] == 's'? ORDINARY: ZAP) == FALSE) { fprintf(stderr, "%s: Cannot save mail to '%s'\n", program, lfil); flg++; } else Dout(pn, 0, "!saved\n"); if (malf != (FILE *)NULL) { fclose(malf); } } umask(7); if (!flg) { setletr(showlet, resp[0]); print = 1; curlet++; } break; /* * Reply to a letter */ case 'r': print = 0; if (!validmsg(curlet)) break; replying = 1; for (k = 1; resp[k] == ' ' || resp[k] == '\t'; ++k); resp[strlen(resp)-1] = '\0'; (void) strlcpy(m_sendto, resp+k, sizeof (m_sendto)); goback(showlet); replying = 0; setletr(showlet, resp[0]); break; /* * Undelete */ case 'u': print = 0; if ((k = getnumbr(resp+1)) <= 0) k = showlet; else k--; if (!validmsg(k)) break; setletr(k, ' '); break; /* * Mail letter to someone else */ case 'm': { reciplist list; print = 0; if (!validmsg(curlet)) break; new_reciplist(&list); flg = 0; k = 0; if (substr(resp, " -") != -1 || substr(resp, "\t-") != -1) { printf("Only users may be specified\n"); break; } p = resp + 1; while ((p = getarg(lfil, p)) != NULL) { char *env; if (lfil[0] == '$') { if (!(env = getenv(&lfil[1]))) { fprintf(stderr, "%s: %s has no value or is not exported.\n", program, lfil); flg++; } else add_recip(&list, env, FALSE); k++; } else if (lfil[0] != '\0') { add_recip(&list, lfil, FALSE); k++; } } (void) strlcpy(Rpath, my_name, sizeof (Rpath)); sending = TRUE; flg += sendlist(&list, showlet, 0); sending = FALSE; if (k) { if (!flg) { setletr(showlet, 'm'); print = 1; curlet++; } } else printf("Invalid command\n"); del_reciplist(&list); break; } /* * Read new letters */ case 'a': if (onlet == nlet) { printf("No new mail\n"); print = 0; break; } curlet = 0; print = 1; break; /* * Escape to shell */ case '!': systm(resp + 1); printf("!\n"); print = 0; break; /* * Delete an entry */ case 'd': print = 0; k = 0; if (strncmp("dq", resp, 2) != SAME && strncmp("dp", resp, 2) != SAME) if ((k = getnumbr(resp+1)) == -1) break; if (k == 0) { k = showlet; if (!validmsg(curlet)) break; print = 1; curlet++; } else k--; setletr(k, 'd'); if (resp[1] == 'p') print = 1; else if (resp[1] == 'q') goto donep; break; } } /* * Copy updated mailfile back */ donep: if (changed) { copyback(); stamp(); } }