/* * 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 */ /* NAME Dout - Print debug output SYNOPSIS void Dout(char *subname, int level, char *msg, ...) DESCRIPTION Dout prints debugging output if debugging is turned on (-x specified) and the level of this message is lower than the value of the global variable debug. The subroutine name is printed if it is not a null string. */ #include "mail.h" #ifdef __STDC__ # include #else # include #endif /* VARARGS3 PRINTFLIKE3 */ void #ifdef __STDC__ Dout(char *subname, int level, char *fmt, ...) #else # ifdef lint Dout(Xsubname, Xlevel, Xfmt, va_alist) char *Xsubname, *Xfmt; int Xlevel; va_dcl # else Dout(va_alist) va_dcl # endif #endif { #ifndef __STDC__ char *subname; int level; char *fmt; #endif va_list args; #ifndef __STDC__ #ifdef lint subname = Xsubname; level = Xlevel; fmt = Xfmt; # endif #endif #ifdef __STDC__ va_start(args, fmt); #else va_start(args); subname = va_arg(args, char *); level = va_arg(args, int); fmt = va_arg(args, char *); #endif if (debug > level) { if (subname && *subname) { fprintf(dbgfp,"%s(): ", subname); } vfprintf(dbgfp, fmt, args); } va_end(args); } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (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 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright (c) 2018, Joyent, Inc. # BINPROG= mail PROG= $(BINPROG) include ../Makefile.cmd CLOBBERFILES= $(PROG) CLEANFILES= $(MAILOBJS) MAILOBJS= add_recip.o cat.o ckdlivopts.o \ cksaved.o clr_hinfo.o copyback.o copylet.o \ copymt.o createmf.o del_recipl.o Dout.o delete.o \ done.o doopen.o dumpaff.o dumprcv.o \ errmsg.o gendeliv.o getarg.o getcomment.o \ gethead.o goback.o init.o \ isheader.o isit.o islocal.o istext.o legal.o \ lock.o main.o mkdead.o mta_ercode.o \ new_recipl.o parse.o pckaffspot.o pckrcvspot.o \ pickFrom.o pipletr.o poplist.o printhdr.o printmail.o \ pushlist.o savehdrs.o sel_disp.o sendlist.o \ sendmail.o setsig.o \ stamp.o Tout.o MAILSRC= $(MAILOBJS:%.o=%.c) CPROG= mail CPROGSRC= $(CPROG:%=_%.c) # ROOT directories ROOTMAILD= $(ROOTLIB)/mail ROOTINC= $(ROOT)/usr/include # installed modules ROOTBINPROG= $(BINPROG:%=$(ROOTBIN)/%) ROOTSYMLINKS= $(ROOTBIN)/rmail EDITPATH= \ $(SED) -e 's!REAL_PATH!/usr/bin!g' \ -e 's!USR_SHARE_LIB!/usr/share/lib!g' \ -e 's!VAR_MAIL!/var/mail!g' < $? > $@ CPPFLAGS = -DSVR4 -I. $(CPPFLAGS.master) CERRWARN += -Wno-implicit-function-declaration CERRWARN += -Wno-unused-variable CERRWARN += $(CNOWARN_UNINIT) CERRWARN += -Wno-clobbered CERRWARN += -Wno-extra # missing type declarations for old-style functions SMATCH = off LDLIBS += -lmail -lsocket # mail defines its own delete() - reduce symbols to locals to remove name clash. LDFLAGS += $(MAPFILE.NGB:%=-Wl,-M%) # conditional assignments # all: TARGET= all install: TARGET= install clean: TARGET= clean clobber: TARGET= clobber # file modes, owners and groups for the install target # $(ROOTBIN)/mail : FILEMODE = 02511 # install rules $(ROOTINC)/% : % $(INS.file) .KEEP_STATE: .PARALLEL: $(MAILOBJS) $(OBJS) all: $(PROG) mail: $(MAILOBJS) $(LINK.c) -o $@ $(MAILOBJS) $(LDLIBS) $(POST_PROCESS) install: all .WAIT $(ROOTBINPROG) $(ROOTSYMLINKS) # ROOTSYMLINKS # $(ROOTBIN)/rmail: $(RM) $@; $(SYMLINK) mail $@ clean: $(RM) $(OBJS) $(MAILOBJS) clobber: $(RM) $(OBJS) $(MAILOBJS) mail Subject: AUTOANSWERED!!! I am on vacation. I will read (and answer if necessary) your e-mail message when I return. This message was generated automatically and you will receive it only once, although all the messages you send me while I am away WILL be saved. /* * 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 */ /* NAME Tout - Print surrogate debug output SYNOPSIS void Tout(char *subname, char *msg, ...) DESCRIPTION Tout prints debugging output if surrogate tracing has been turned on (-T specified). The message will also go to the debug output if debugging is turned on (-x specified). The subroutine name is printed if it is not a null string. */ #include "mail.h" #ifdef __STDC__ # include #else # include #endif /* VARARGS2 PRINTFLIKE2 */ void #ifdef __STDC__ Tout(char *subname, char *fmt, ...) #else # ifdef lint Tout(Xsubname, Xfmt, va_alist) char *Xsubname, *Xfmt; va_dcl # else Tout(va_alist) va_dcl # endif #endif { #ifndef __STDC__ char *subname; char *fmt; #endif va_list args; #if !defined(__STDC__) && defined(lint) subname = Xsubname; fmt = Xfmt; #endif if (debug > 0) { #ifdef __STDC__ va_start(args, fmt); #else va_start(args); subname = va_arg(args, char *); fmt = va_arg(args, char *); #endif if (subname && *subname) { fprintf(dbgfp,"%s(): ", subname); } vfprintf(dbgfp, fmt, args); va_end(args); } if (flgT) { #ifdef __STDC__ va_start(args, fmt); #else va_start(args); subname = va_arg(args, char *); fmt = va_arg(args, char *); #endif vfprintf(stdout, fmt, args); va_end(args); } } /* * 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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* NAME add_recip, madd_recip - add recipients to recipient list SYNOPSIS int add_recip(reciplist *plist, char *name, int checkdups) void madd_recip(reciplist *plist, char *name, int checkdups) DESCRIPTION add_recip() adds the name to the recipient linked list. If checkdups is set, it first checks to make certain that the name is not in the list. madd_recips() is given a list of names separated by white space. Each name is split off and passed to add_recips. */ #include "mail.h" int add_recip(reciplist *plist, char *name, int checkdups) { char *p; static char pn[] = "add_recip"; recip *r = &plist->recip_list; if ((name == (char *)NULL) || (*name == '\0')) { Tout(pn, "translation to NULL name ignored\n"); return(0); } p = name; while (*p && !isspace(*p)) { p++; } if (*p != '\0') { Tout(pn, "'%s' not added due to imbedded spaces\n", name); return(0); } if (checkdups == TRUE) { while (r->next != (struct recip *)NULL) { r = r->next; if (strcmp(r->name, name) == 0) { Tout(pn, "duplicate recipient '%s' not added to list\n", name); return(0); } } } if ((p = malloc (sizeof(struct recip))) == (char *)NULL) { errmsg(E_MEM,"first malloc failed in add_recip()"); done(1); } plist->last_recip->next = (struct recip *)p; r = plist->last_recip = plist->last_recip->next; if ((r->name = malloc (strlen(name)+1)) == (char *)NULL) { errmsg(E_MEM,"second malloc failed in add_recip()"); done(1); } strcpy (r->name, name); r->next = (struct recip *)NULL; Tout(pn, "'%s' added to recipient list\n", name); return(1); } void madd_recip(reciplist *plist, char *namelist, int checkdups) { char *name; for (name = strtok(namelist, " \t"); name; name = strtok((char*)0, " \t")) add_recip(plist, name, checkdups); } # # Copyright 1989 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.3 */ # @(#)binarsys 2.1 Default=y /* * 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 */ /* NAME cat - concatenate two strings SYNOPSIS void cat(char *to, char *from1, char *from2) DESCRIPTION cat() concatenates "from1" and "from2" to "to" to -> destination string from1 -> source string from2 -> source string */ #include "mail.h" void cat(to, from1, from2) register char *to, *from1, *from2; { for (; *from1;) *to++ = *from1++; for (; *from2;) *to++ = *from2++; *to = '\0'; } /* * 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 */ /* NAME ckdlivopts - check delivery notification options SYNOPSIS int ckdlivopts(int tcopy_hdr, int *svopts) DESCRIPTION Check if delivery notification requested for message being processed. Returns specified options as combined from H_DEFOPTS, H_TROPTS, & H_TCOPY lines. (Positive notification options) 001 ==> /delivery requested 002 ==> /nodelivery requested (Negative notification options) 010 ==> /report requested 020 ==> /return requested 040 ==> /ignore requested Combinations are expected, i.e. - 011 ==> /delivery/report If not specified, the assumed defaults are /nodelivery/return (rc=022) The options discovered in the header are stored into svopts. */ #include "mail.h" static void getopts(); static void mergeopts(); struct dlvopts { int deliv; int nodeliv; int rept; int rtrn; int ign; }; int ckdlivopts(tcopy_hdr, svopts) int tcopy_hdr; int *svopts; { static char pn[] = "ckdlivopts"; struct hdrs *hp; struct dlvopts toopts, tropts, defopts; int rc; /* already done this once. no need to repeat..... */ if (svopts && *svopts != 0) { Dout(pn, 0, "*svopts = o%o\n", *svopts); return (*svopts); } memset((char *)&defopts, 0, sizeof(struct dlvopts)); if ((hp = hdrlines[H_DEFOPTS].head) != (struct hdrs *)NULL) { Dout(pn, 3, "H_DEFOPTS line = '%s'\n", hp->value); getopts(hp->value, &defopts); } memset((char *)&tropts, 0, sizeof(struct dlvopts)); if ((hp = hdrlines[H_TROPTS].head) != (struct hdrs *)NULL) { Dout(pn, 3, "H_TROPTS line = '%s'\n", hp->value); getopts(hp->value, &tropts); } memset((char *)&toopts, 0, sizeof(struct dlvopts)); if ((hp = hdrlines[tcopy_hdr].head) != (struct hdrs *)NULL) { Dout(pn, 3,"H_TCOPY line = '%s'\n", hp->value); getopts(hp->value, &toopts); } /* Combine options from different header lines. Precedence is */ /* toopts --> tropts --> defopts. Results left in defopts */ mergeopts(&tropts,&defopts); mergeopts(&toopts,&defopts); if (defopts.deliv) rc = DELIVERY; else rc = NODELIVERY; if (defopts.rtrn) rc += RETURN; else if (defopts.rept) rc += REPORT; else if (defopts.ign) rc += IGNORE; else rc += RETURN; Dout(pn, 0,"returning = o%o\n", rc); if (svopts) *svopts = rc; return (rc); } /* * Pick transport options off of header line. * If conflicting options found, use MOST demanding; i.e. - /delivery/return. */ static void getopts(s, optr) register char *s; register struct dlvopts *optr; { register char *op; for (op = strchr (s, '/'); op++; op = strchr(op, '/')) { if (casncmp(op, "delivery", 7) == 0) { optr->deliv = 1; optr->nodeliv = 0; } else if (casncmp(op, "nodelivery", 10) == 0) { if (optr->deliv == 0) { optr->nodeliv = 1; } } else if (casncmp(op, "report", 6) == 0) { optr->ign = 0; if (optr->rtrn == 0) { optr->rept = 1; } } else if (casncmp(op, "return", 6) == 0) { optr->rtrn = 1; optr->rept = optr->ign = 0; } else if (casncmp(op, "ignore", 6) == 0) { optr->rept = 0; if (optr->rtrn == 0) { optr->ign = 1; } } } } /* * Merge options between 2 sets. Higher set has precedence. * Results left in lower set. */ static void mergeopts(higher, lower) register struct dlvopts *higher, *lower; { if (higher->deliv == 1) { lower->deliv = 1; lower->nodeliv = 0; } if (higher->nodeliv == 1) { lower->nodeliv = 1; lower->deliv = 0; } if (higher->rept == 1) { lower->rept = 1; lower->rtrn = lower->ign = 0; } if (higher->rtrn == 1) { lower->rtrn = 1; lower->rept = lower->ign = 0; } if (higher->ign == 1) { lower->ign = 1; lower->rept = lower->rtrn = 0; } } /* * 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 */ /* * NAME * cksaved - check for an orphaned save file * * SYNOPSIS * void cksaved(char *user) * * DESCRIPTION * cksaved() looks to see if there is a saved-mail file sitting * around which should be reinstated. These files should be sitting * around only in the case of a crash during rewriting a mail message. * * The strategy is simple: if the file exists it is appended to * the end of $MAIL. It is better that a user potentially sees the * mail twice than to lose it. * * If $MAIL doesn't exist, then a simple rename() will suffice. */ #include "mail.h" void cksaved(user) char *user; { struct stat stbuf; char command[512]; char save[MAXFILENAME], mail[MAXFILENAME]; cat(mail, maildir, user); cat(save, mailsave, user); /* * If no save file, or size is 0, return. */ if ((stat(save, &stbuf) != 0) || (stbuf.st_size == 0)) return; /* * Ok, we have a savefile. If no mailfile exists, * then we want to restore to the mailfile, * else we append to the mailfile. */ lock(user); if (stat(mail, &stbuf) != 0) { /* * Restore from the save file by linking * it to $MAIL then unlinking save file */ chmod(save, MFMODE); #ifdef SVR3 if (link(save, mail) != 0) { unlock(); perror("Restore failed to link to mailfile"); return; } if (unlink(save) != 0) { unlock(); perror("Cannot unlink saved file"); return; } #else if (rename(save, mail) != 0) { unlock(); perror("Cannot rename saved file"); return; } #endif (void) snprintf(command, sizeof (command), "echo \"Your mailfile was just restored by the mail " "program.\nPermissions of your mailfile are set " "to 0660.\"| mail %s", user); } else { FILE *Istream, *Ostream; if ((Ostream = fopen(mail, "a")) == NULL) { (void) fprintf(stderr, "%s: Cannot open file '%s' for output\n", program, mail); unlock(); return; } if ((Istream = fopen(save, "r")) == NULL) { (void) fprintf(stderr, "%s: Cannot open saved " "file '%s' for reading\n", program, save); fclose(Ostream); unlock(); return; } copystream(Istream, Ostream); fclose(Istream); fclose(Ostream); if (unlink(save) != 0) { perror("Unlink of save file failed"); return; } (void) snprintf(command, sizeof (command), "echo \"Your mail save file has just been appended " "to your mail box by the mail program.\" | mail %s", user); } /* * Try to send mail to the user whose file * is being restored. */ unlock(); systm(command); } /* * 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 */ /* NAME clr_hinfo, clrhdr - clean out mail header information SYNOPSIS void clr_hinfo() void clrhdr(int hdrtype) DESCRIPTION Clr_hinfo() cleans out hdrlines[] and other associated data in preparation for the next message. Clrhdr() does a single hdrlines[]. */ #include "mail.h" void clr_hinfo() { register int i; static int firsttime = 1; static char pn[] = "clr_hinfo"; Dout(pn, 0, "\n"); if (firsttime) { firsttime = 0; return; } fnuhdrtype = 0; orig_aff = orig_rcv = 0; for (i = 0; i < H_CONT; i++) { clrhdr(i); } return; } void clrhdr(hdrtype) int hdrtype; { while (hdrlines[hdrtype].head != (struct hdrs *)NULL) { poplist (hdrtype, HEAD); } } /* * 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 */ /* * NAME * copyback - copy temp or whatever back to /var/mail * * SYNOPSIS * void copyback() * * DESCRIPTION * Copy the reduced contents of lettmp back to * the mail file. First copy any new mail from * the mail file to the end of lettmp. */ #include "mail.h" void copyback() { register int i, n; int new = 0; mode_t mailmode, omask; struct stat stbuf; void (*hstat)(), (*istat)(), (*qstat)(); istat = signal(SIGINT, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); hstat = signal(SIGHUP, SIG_IGN); lock(my_name); stat(mailfile, &stbuf); mailmode = stbuf.st_mode; /* * Has new mail arrived? */ if (stbuf.st_size != let[nlet].adr) { malf = doopen(mailfile, "r", E_FILE); fseek(malf, let[nlet].adr, 0); fclose(tmpf); tmpf = doopen(lettmp, "a", E_TMP); /* * Append new mail assume only one new letter */ if (!copystream(malf, tmpf)) { fclose(malf); tmperr(); done(0); } fclose(malf); fclose(tmpf); tmpf = doopen(lettmp, "r+", E_TMP); if (nlet == (MAXLET-2)) { errmsg(E_SPACE, ""); done(0); } let[++nlet].adr = stbuf.st_size; new = 1; } /* * Copy mail back to mail file */ omask = umask(0117); /* * The invoker must own the mailfile being copied to */ if ((stbuf.st_uid != my_euid) && (stbuf.st_uid != my_uid)) { errmsg(E_OWNR, ""); done(0); } /* * If user specified the '-f' option we dont do * the routines to handle :saved files. * As we would(incorrectly) restore to the user's * mailfile upon next execution! */ if (flgf) { (void) strlcpy(savefile, mailfile, sizeof (savefile)); } else { cat(savefile, mailsave, my_name); } if ((malf = fopen(savefile, "w")) == NULL) { if (!flgf) { errmsg(E_FILE, "Cannot open savefile"); } else { errmsg(E_FILE, "Cannot re-write the alternate file"); } done(0); } if (chown(savefile, mf_uid, mf_gid) == -1) { errmsg(E_FILE, "Cannot chown savefile"); done(0); } umask(omask); n = 0; for (i = 0; i < nlet; i++) { /* * Note: any action other than an undelete, or a * plain read causes the letter acted upon to be * deleted */ if (let[i].change == ' ') { if (copylet(i, malf, ORDINARY) == FALSE) { errmsg(E_FILE, "Cannot copy mail to savefile"); (void) fprintf(stderr, "%s: A copy of your " "mailfile is in '%s'\n", program, lettmp); done(1); /* keep temp file */ } n++; } } fclose(malf); if (!flgf) { if (unlink(mailfile) != 0) { errmsg(E_FILE, "Cannot unlink mailfile"); done(0); } chmod(savefile, mailmode); #ifdef SVR4 if (rename(savefile, mailfile) != 0) { errmsg(E_FILE, "Cannot rename savefile to mailfile"); done(0); } #else if (link(savefile, mailfile) != 0) { errmsg(E_FILE, "Cannot link savefile to mailfile"); done(0); } if (unlink(savefile) != 0) { errmsg(E_FILE, "Cannot unlink save file"); done(0); } #endif } /* * Empty mailbox? */ if (n == 0) { delempty(stbuf.st_mode, mailfile); } if (new && !flgf) { printf("New mail arrived\n"); } unlock(); (void) signal(SIGINT, istat); (void) signal(SIGQUIT, qstat); (void) signal(SIGHUP, hstat); } /* * 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 2017 Gary Mills * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" /* NAME copylet - copy a given letter to a file pointer SYNOPSIS int copylet(int letnum, FILE *f, int type) DESCRIPTION Copylet() will copy the letter "letnum" to the given file pointer. letnum -> index into: letter table f -> file pointer to copy file to type -> copy type Returns TRUE on a completely successful copy. */ int copylet(int letnum, FILE *f, int type) { int pos = ftell(f); int rc = xxxcopylet(letnum, f, type); if (fflush(f) != 0) rc = FALSE; /* * On error, truncate the file to its original position so that a * partial message is not left in the mailbox. */ if (rc == FALSE) ftruncate(fileno(f), pos); return(rc); } int xxxcopylet(int letnum, FILE *f, int type) { static char pn[] = "copylet"; char buf[LSIZE], lastc; char wbuf[LSIZE]; int n; long i, k; int num; int rtrncont = 1; /* True: nondelivery&content included, or regular mail */ int suppress = FALSE; int sav_suppress = FALSE; /* Did we suppress previous hdr line? */ int print_from_struct = FALSE; /* print from hdrlines struct */ /* rather than fgets() buffer */ int pushrest = FALSE; int ctf = FALSE; int didafflines = FALSE; /* Did we already put out any */ /* H_AFWDFROM lines? */ int didrcvlines = FALSE; /* Did we already put out any */ /* H_RECEIVED lines? */ long clen = -1L; int htype; /* header type */ struct hdrs *hptr; if (!sending) { /* Clear out any saved header info from previous message */ clr_hinfo(); } fseek(tmpf, let[letnum].adr, 0); /* Get size of message as stored into tempfile by copymt() */ k = let[letnum+1].adr - let[letnum].adr; Dout(pn, 1, "(letnum = %d, type = %d), k = %ld\n", letnum, type, k); while (k>0) { /* process header */ num = ((k < sizeof(buf)) ? k+1 : sizeof(buf)); if (fgets (buf, num, tmpf) == NULL) { return (FALSE); } if ((n = strlen (buf)) == 0) { k = 0; break; } k -= n; lastc = buf[n-1]; if (pushrest) { pushrest = (lastc != '\n'); continue; } htype = isheader (buf, &ctf); Dout(pn, 5, "loop 1: buf = %s, htype= %d/%s\n", buf, htype, header[htype].tag); if (htype == H_CLEN) { if (!sending) { savehdrs(buf,htype); } if ((hptr = hdrlines[H_CLEN].head) != (struct hdrs *)NULL) { clen = atol (hptr->value); } } if (type == ZAP) { if (htype != FALSE) { pushrest = (lastc != '\n'); continue; } /* end of header. Print non-blank line and bail. */ Dout(pn, 5, "ZAP end header; n=%d, buf[0] = %d\n", n, buf[0]); if (buf[0] != '\n') { if (fwrite(buf,1,n,f) != n) { sav_errno = errno; return(FALSE); } } else { n = 0; } break; } /* Copy From line appropriately */ if (fwrite(buf,1,n-1,f) != n-1) { sav_errno = errno; return(FALSE); } if (lastc != '\n') { if (fwrite(&lastc,1,1,f) != 1) { sav_errno = errno; return(FALSE); } continue; } switch(type) { case REMOTE: if (fprintf(f, rmtmsg, thissys) < 0) { sav_errno = errno; return(FALSE); } break; case TTY: case ORDINARY: default: if (fprintf(f, "\n") < 0) { sav_errno = errno; return(FALSE); } break; } if ((error > 0) && (dflag == 1)) { Dout(pn, 3, "before gendeliv(), uval = '%s'\n", uval); gendeliv(f, dflag, uval); if (!(ckdlivopts(H_TCOPY, (int*)0) & RETURN)) { rtrncont = 0; } else { /* Account for content-type info */ /* of returned msg */ if (fprintf(f, "%s %s\n", header[H_CTYPE].tag, (let[letnum].text == TRUE ? "text/plain" : "application/octet-stream")) < 0) { sav_errno = errno; return(FALSE); } /* Compute Content-Length of what's being */ /* returned... */ i = k; /* Account for H_AFWDFROM, H_AFWDCNT, */ /* H_TCOPY, or H_RECEIVED lines which may */ /* be added later */ if (affcnt > 0) { sprintf(wbuf, "%d", affcnt); i += (affbytecnt + strlen(header[H_AFWDCNT].tag) + strlen(wbuf) + 2); } if (orig_tcopy) { if ((hptr = hdrlines[H_TCOPY].head) != (struct hdrs *)NULL) { i += strlen(hdrlines[H_TCOPY].head->value); } } if ((hptr = hdrlines[H_RECEIVED].head) != (struct hdrs *)NULL) { i += rcvbytecnt; } /* Add in strlen of MIME-Version:, */ /* Content-Length: and Content-Type: */ /* values for msg being returned... */ if ((hptr = hdrlines[H_MIMEVERS].head) != (struct hdrs *)NULL) { i += strlen(hdrlines[H_MIMEVERS].head->value); } if ((hptr = hdrlines[H_CTYPE].head) != (struct hdrs *)NULL) { i += strlen(hdrlines[H_CTYPE].head->value); } if ((hptr = hdrlines[H_CLEN].head) != (struct hdrs *)NULL) { i += strlen(hdrlines[H_CLEN].head->value); } if (fprintf(f, "%s %ld\n", header[H_CLEN].tag, i) < 0) { sav_errno = errno; return(FALSE); } } if (fprintf(f, "\n") < 0) { sav_errno = errno; return(FALSE); } } if (fflush(f)) { sav_errno = errno; return(FALSE); } break; } /* if not ZAP, copy balance of header */ n = 0; if ((type != ZAP) && rtrncont) while (k>0 || n>0) { if ((n > 0) && !suppress) { if (print_from_struct == TRUE) { if (printhdr (type, htype, hptr, f) < 0) { return (FALSE); } } else { if (sel_disp(type, htype, buf) >= 0) { if (fwrite(buf,1,n,f) != n) { sav_errno = errno; return(FALSE); } } } if (htype == H_DATE) { dumprcv(type, htype,&didrcvlines,&suppress,f); dumpaff(type, htype,&didafflines,&suppress,f); } } if (k <= 0) { /* Can only get here if k=0 && n>0, which occurs */ /* in a message with header lines but no content. */ /* If we haven't already done it, force out any */ /* H_AFWDFROM or H_RECEIVED lines */ dumprcv(type, -1,&didrcvlines,&suppress,f); dumpaff(type, -1,&didafflines,&suppress,f); break; } num = ((k < sizeof(buf)) ? k+1 : sizeof(buf)); if (fgets (buf, num, tmpf) == NULL) { return (FALSE); } n = strlen (buf); k -= n; lastc = buf[n-1]; if (pushrest) { pushrest = (lastc != '\n'); continue; } sav_suppress = suppress; suppress = FALSE; print_from_struct = FALSE; htype = isheader (buf, &ctf); Dout(pn, 5, "loop 2: buf = %s, htype= %d/%s\n", buf, htype, header[htype].tag); /* The following order is defined in the MTA documents. */ switch (htype) { case H_CONT: if (sending) { suppress = sav_suppress; } continue; case H_TCOPY: case H_MIMEVERS: case H_CTYPE: case H_CLEN: if (!sending) { savehdrs(buf,htype); } hptr = hdrlines[htype].head; if (htype == H_CLEN) { clen = atol (hptr->value); } /* * Use values saved in hdrlines[] structure * rather than what was read from tmp file. */ print_from_struct = TRUE; /* FALLTHROUGH */ case H_EOH: case H_AFWDFROM: case H_AFWDCNT: case H_RECEIVED: dumprcv(type, htype,&didrcvlines,&suppress,f); dumpaff(type, htype,&didafflines,&suppress,f); continue; /* next header line */ default: pushrest = (lastc != '\n'); continue; /* next header line */ case FALSE: /* end of header */ break; } /* Found the blank line after the headers. */ if (n > 0) { if (fwrite(buf,1,n,f) != n) { sav_errno = errno; return(FALSE); } } Dout(pn, 3,", let[%d].text = %s\n", letnum, (let[letnum].text ? "TRUE" : "FALSE")); if ((type == TTY) && (let[letnum].text == FALSE) && !pflg) { if (fprintf (f, "\n%s\n", binmsg) < 0) { sav_errno = errno; return(FALSE); } return (TRUE); } if (n == 1 && buf[0] == '\n') { n = 0; } break; } Dout(pn, 1, "header processed, clen/k/n = %ld/%ld/%d\n", clen, k, n); if (clen >= 0) { if (((clen - n) == k) || ((clen - n) == (k - 1))) { k = clen - n; } else { /* probable content-length mismatch. show it ALL! */ Dout(pn, 1, "clen conflict. using k = %ld\n", k); } } /* copy balance of message */ if (rtrncont) while (k > 0) { num = ((k < sizeof(buf)) ? k : sizeof(buf)); if ((n = fread (buf, 1, num, tmpf)) <= 0) { Dout(pn, 1, "content-length mismatch. return(FALSE)\n"); return(FALSE); } k -= n; if (fwrite(buf,1,n,f) != n) { sav_errno = errno; return(FALSE); } } Dout(pn, 3, "body processed, k=%ld\n", k); if (rtrncont && type != ZAP && type != REMOTE) { if (fwrite("\n",1,1,f) != 1) { sav_errno = errno; return(FALSE); } } return(TRUE); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (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) 1989, 2010, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* NAME copymt - copy mail (f1) to temp (f2) SYNOPSIS void copymt(FILE *f1, FILE *f2) DESCRIPTION The mail messages in /var/mail are copied into the temp file. The file pointers f1 and f2 point to the files, respectively. */ #include "mail.h" void copymt(f1, f2) register FILE *f1, *f2; { static char pn[] = "copymt"; long nextadr; int n, newline = 1; int StartNewMsg = TRUE; int ToldUser = FALSE; int mesg = 0; int ctf = FALSE; /* header continuation flag */ long clen = (long)0; int hdr = 0; int cflg = 0; /* found Content-length in header */ Dout(pn, 0,"entered\n"); if (!let[1].adr) { nlet = nextadr = 0; let[0].adr = 0; let[0].text = TRUE; /* until proven otherwise.... */ let[0].change = ' '; } else { nextadr = let[nlet].adr; } while ((n = getaline(line, sizeof line, f1)) > 0) { if (!newline) { goto putout; } else if ((hdr = isheader (line, &ctf)) == FALSE) { ctf = FALSE; /* next line can't be cont. */ } if (!hdr && cflg) { /* nonheader, Content-length seen */ if (clen < n) { /* read too much */ /* NB: this only can happen if the content-length * says a smaller number than what's seen on the * first non-header line. */ if (let[nlet-1].text == TRUE) { let[nlet-1].text = istext((unsigned char*)line,clen); Dout(pn, 0, "1, let[%d].text = %s\n", nlet-1, (let[nlet-1].text ? "TRUE":"FALSE")); } if (fwrite(line,1,(int)clen,f2) != clen) { fclose(f1); fclose(f2); errmsg(E_FILE, "Write error in copymt()"); done(0); } nextadr += clen; n -= clen; strmove (line, line+clen); cflg = 0; ctf = FALSE; hdr = isheader(line, &ctf); goto dohdr; } /* here, clen >= n */ if (n == 1 && line[0] == '\n'){ /* leading empty line */ clen++; /* cheat */ } nextadr += clen; for (;;) { if (let[nlet-1].text == TRUE) { let[nlet-1].text = istext((unsigned char*)line,n); Dout(pn, 0, "2, let[%d].text = %s\n", nlet-1, (let[nlet-1].text ? "TRUE" : "FALSE")); } if (fwrite(line,1,n,f2) != n) { fclose(f1); fclose(f2); errmsg(E_FILE, "Write error in copymt()"); done(0); } clen -= n; if (clen <= 0) { break; } n = clen < sizeof line ? clen : sizeof line; if ((n = fread (line, 1, n, f1)) <= 0) { fprintf(stderr, "%c%s:\tYour mailfile was found to be corrupted.\n", BELL, program); fprintf(stderr, "\t(Unexpected end-of-file).\n"); fprintf(stderr, "\tMessage #%d may be truncated.%c\n\n", nlet, BELL); nextadr -= clen; clen = 0; /* stop the loop */ } } /* All done, go to top for next message */ cflg = 0; StartNewMsg = TRUE; continue; } dohdr: switch (hdr) { case H_FROM: if(nlet >= (MAXLET-2)) { if (!mesg) { fprintf(stderr,"%s: Too many letters, overflowing letters concatenated\n\n",program); mesg++; } } else { let[nlet++].adr = nextadr; let[nlet].text = TRUE; let[nlet].change = ' '; } Dout(pn, 5, "setting StartNewMsg to FALSE\n"); StartNewMsg = FALSE; ToldUser = FALSE; break; case H_CLEN: if (cflg) { break; } cflg = TRUE; /* mark for clen processing */ clen = atol (strpbrk (line, ":")+1); break; default: break; } putout: if (nlet == 0) { fclose(f1); fclose(f2); errmsg(E_FILE,"mailfile does not begin with a 'From' line"); done(0); } nextadr += n; if (let[nlet-1].text == TRUE) { let[nlet-1].text = istext((unsigned char*)line,n); Dout(pn, 5,"3, let[%d].text = %s\n", nlet-1, (let[nlet-1].text ? "TRUE" : "FALSE")); } if (fwrite(line,1,n,f2) != n) { fclose(f1); fclose(f2); errmsg(E_FILE,"Write error in copymt()"); done(0); } if (line[n-1] == '\n') { newline = 1; if (n == 1) { /* Blank line. Skip StartNewMsg */ /* check below */ continue; } } else { newline = 0; } if (StartNewMsg == TRUE && ToldUser == FALSE) { fprintf(stderr, "%c%s:\tYour mailfile was found to be corrupted\n", BELL, program); fprintf(stderr, "\t(Content-length mismatch).\n"); fprintf(stderr,"\tMessage #%d may be truncated,\n", nlet); fprintf(stderr, "\twith another message concatenated to it.%c\n\n", BELL); ToldUser = TRUE; } } /* last plus 1 */ let[nlet].adr = nextadr; let[nlet].change = ' '; let[nlet].text = TRUE; } /* * 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 1995 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" /* If mail file does not exist create it */ #ifdef OLD void createmf(uid, file) uid_t uid; char *file; { int fd; void (*istat)(), (*qstat)(), (*hstat)(); if (access(file, A_EXIST) == CERROR) { istat = signal(SIGINT, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); hstat = signal(SIGHUP, SIG_IGN); umask(0); if ((fd = creat(file, MFMODE)) == -1) sav_errno = errno; else close(fd); umask(7); (void) signal(SIGINT, istat); (void) signal(SIGQUIT, qstat); (void) signal(SIGHUP, hstat); } } #else #include #include #include int accessmf(path) char *path; { struct stat fsb,sb; int mbfd; tryagain: if (lstat(path, &sb)) { /* file/symlink does not exist, so create one */ mbfd = open(path, O_APPEND|O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); chmod(path, 0660); /* if someone create a symlink/file just ahead */ /* of us, the create will failed with EEXIST */ /* This is what we want, because we do not */ /* want someone to re-direct our "create" */ /* request to a another location. */ if (mbfd == -1) { if (errno == EEXIST) goto tryagain; } /* file/symlink exist, make sure it is not linked */ } else if (sb.st_nlink != 1 || S_ISLNK(sb.st_mode)) { fprintf(stderr, "%s: security violation, '%s' should not be linked to other file\n", program, path); sav_errno = errno; return -1; } else { /* if we get here, there is a pre-existing file, */ /* and it is not a symlink... */ /* open it, and make sure it is the same file */ /* we lstat() before... */ /* this is to guard against someone deleting the */ /* old file and creat a new symlink in its place */ /* We are not createing a new file here, but we */ /* do not want append to the worng file either */ mbfd = open(path, O_APPEND|O_WRONLY, 0); if (mbfd != -1 && (fstat(mbfd, &fsb) || fsb.st_nlink != 1 || S_ISLNK(fsb.st_mode) || sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino)) { /* file changed after open */ fprintf(stderr, "%s: security violation, '%s' inode changed after open\n", program, path); (void)close(mbfd); return -1; } } if (mbfd == -1) { sav_errno = errno; return -1; } return mbfd; } #endif /* * 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 */ #include "mail.h" /* NAME del_reciplist - delete a recipient list SYNOPSIS del_reciplist (reciplist *list) DESCRIPTION Free the space used by a recipient list. */ void del_reciplist (plist) reciplist *plist; { static char pn[] = "del_reciplist"; recip *r = &plist->recip_list; Dout(pn, 0, "entered\n"); if (r->next != (struct recip *)NULL) { for (r = r->next; r != (struct recip *)NULL; ) { recip *old = r; r = old->next; free(old->name); free((char*)old); } } } /* * 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 */ #include "mail.h" /* signal catching routine --- reset signals on quits and interupts exit on other signals i -> signal # */ void delete(i) register int i; { static char pn[] = "delete"; setsig(i, delete); if (i > SIGQUIT) { fprintf(stderr, "%s: ERROR signal %d\n",program,i); Dout(pn, 0, "caught signal %d\n", i); } else { fprintf(stderr, "\n"); } if (delflg && (i==SIGINT || i==SIGQUIT)) { longjmp(sjbuf, 1); } done(0); } /* * 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 1995 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" #include /* * remap the bin/mail exit code to sendmail recognizable * exit code when in deliver mode. */ static int maperrno(err) int err; { int rc; switch (sav_errno) { case 0: rc = EX_OK; break; case EPERM: case EACCES: case ENOSPC: case EDQUOT: rc = EX_CANTCREAT; break; case EAGAIN: rc = EX_TEMPFAIL; break; case ENOENT: case EISDIR: case ENOTDIR: rc = EX_OSFILE; break; default: rc = EX_IOERR; break; } return(rc); } /* Fix for bug 1207994 */ void sig_done(needtmp) int needtmp; { static char pn[] = "sig_done"; Dout(pn, 0, "got signal %d\n", needtmp); done(0); } void done(needtmp) int needtmp; { static char pn[] = "done"; unlock(); if (!maxerr) { maxerr = error; Dout(pn, 0, "maxerr set to %d\n", maxerr); if ((debug > 0) && (keepdbgfile == 0)) { unlink (dbgfname); } } if (maxerr && sending) mkdead(); if (tmpf) fclose(tmpf); if (!needtmp && lettmp) { Dout(pn, 0, "temp file removed\n"); unlink(lettmp); } if (deliverflag) { /* bug fix for 1104684 */ exit(maperrno(sav_errno)); } exit(maxerr); /* NOTREACHED */ } /* * 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 */ #include "mail.h" /* Generic open routine. Exits on error with passed error value. Returns file pointer on success. Note: This should be used only for critical files as it will terminate mail(1) on failure. */ FILE * doopen(char *file, char *type, int errnum) { static char pn[] = "doopen"; FILE *fptr; struct stat st; if ((stat(file, &st) < 0 && errno == EOVERFLOW) || (fptr = fopen(file, type)) == NULL) { fprintf(stderr, "%s: Can't open '%s' type: %s\n",program,file,type); error = errnum; sav_errno = errno; Dout(pn, 0, "can't open '%s' type: %s\n",program,file,type); Dout(pn, 0, "error set to %d\n", error); done(0); } return(fptr); } /* * 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 */ #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.6 */ #include "mail.h" /* * Put out H_AFWDFROM and H_AFWDCNT lines if necessary, or * suppress their printing from the calling routine. */ void dumpaff (type, htype, didafflines, suppress, f) register int type; register int htype; register int *didafflines; register int *suppress; register FILE *f; { int affspot; /* Place to put H_AFWDFROM lines */ struct hdrs *hptr; char *pn = "dumpaff"; Dout(pn, 15, "type=%d, htype=%d/%s, *didafflines=%d, *suppress=%d\n", type, htype, htype >= 0 ? header[htype].tag : "None", *didafflines, *suppress); affspot = pckaffspot(); if (affspot == -1) { Dout(pn, 15, "\taffspot==-1\n"); return; } switch (htype) { case H_AFWDCNT: *suppress = TRUE; Dout(pn, 15, "\tAuto-Forward-Count found\n"); return; case H_AFWDFROM: *suppress = TRUE; break; } if (*didafflines == TRUE) { Dout(pn, 15, "\tdidafflines == TRUE\n"); return; } if ((htype >= 0) && (affspot != htype)) { Dout(pn, 15, "\thtype < 0 || affspot != htype, *suppress=%d\n", *suppress); return; } *didafflines = TRUE; for (hptr = hdrlines[H_AFWDFROM].head; hptr != (struct hdrs *)NULL; hptr = hptr->next) { printhdr(type, H_AFWDFROM, hptr, f); } fprintf(f,"%s %d\n", header[H_AFWDCNT].tag, affcnt); Dout(pn, 15, "\t*didafflines=%d, *suppress=%d\n", *didafflines, *suppress); } /* * 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 */ #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.6 */ #include "mail.h" /* * Put out H_RECEIVED lines if necessary, or * suppress their printing from the calling routine. */ void dumprcv (type, htype, didrcvlines, suppress, f) register int type; register int htype; register int *didrcvlines; register int *suppress; register FILE *f; { int rcvspot; /* Place to put H_RECEIVED lines */ struct hdrs *hptr; char *pn = "dumprcv"; Dout(pn, 15, "type=%d, htype=%d/%s, *didrcvlines=%d, *suppress=%d\n", type, htype, htype >= 0 ? header[htype].tag : "None", *didrcvlines, *suppress); rcvspot = pckrcvspot(); if (rcvspot == -1) { Dout(pn, 15, "\trcvspot==-1\n"); return; } if (htype == H_RECEIVED) { *suppress = TRUE; } if (*didrcvlines == TRUE) { Dout(pn, 15, "\tdidrcvlines == TRUE\n"); return; } if ((htype >= 0) && (rcvspot != htype)) { Dout(pn, 15, "\thtype < 0 || rcvspot != htype, *suppress=%d\n", *suppress); return; } *didrcvlines = TRUE; for (hptr = hdrlines[H_RECEIVED].head; hptr != (struct hdrs *)NULL; hptr = hptr->next) { printhdr(type, H_RECEIVED, hptr, f); } Dout(pn, 15, "\t*didrcvlines=%d, *suppress=%d\n", *didrcvlines, *suppress); } /* * 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 */ #include "mail.h" /* NAME errmsg - print error message SYNOPSIS void errmsg(int error_value, char *error_message) DESCRIPTION Errmsg() prints error messages. If error_message is supplied, that is taken as the text for the message, otherwise the text for the err_val message is gotten from the errlist[] array. */ void errmsg(int err_val, char *err_txt) { static char pn[] = "errmsg"; error = err_val; if (err_txt && *err_txt) { fprintf(stderr,"%s: %s\n",program,err_txt); Dout(pn, 0, "%s\n",err_txt); } else { fprintf(stderr,"%s: %s\n",program,errlist[err_val]); Dout(pn, 0,"%s\n",errlist[err_val]); } Dout(pn, 0,"error set to %d\n", error); } /* * 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 */ #include "mail.h" /* * generate delivery notification if required. */ void gendeliv(fp, rc, name) FILE *fp; int rc; char *name; { static char pn[] = "gendeliv"; register char *p; char buf[1024], cbuf[256], ybuf[10]; register int i; int didafflines = 0, didrcvlines = 0, suppress = 0, svopts = 0; time_t ltmp; register struct hdrs *hptr; FILE *outfile; Dout(pn, 0, "at entry, fp = o%lo, rc = %d,name = '%s'\n", (long)fp, rc, name); if (fp == (FILE *)NULL) { /* Want to send Positive delivery notification. Need to */ /* put selected header info from orig. msg aside to */ /* avoid confusion with header info in Delivery Rpt. */ Daffbytecnt = affbytecnt; affbytecnt = 0; Daffcnt = affcnt; affcnt = 0; Drcvbytecnt = rcvbytecnt; rcvbytecnt = 0; hdrlines[H_DAFWDFROM].head = hdrlines[H_AFWDFROM].head; hdrlines[H_DAFWDFROM].tail = hdrlines[H_AFWDFROM].tail; hdrlines[H_AFWDFROM].head = (struct hdrs *)NULL; hdrlines[H_AFWDFROM].tail = (struct hdrs *)NULL; hdrlines[H_DRECEIVED].head = hdrlines[H_RECEIVED].head; hdrlines[H_DRECEIVED].tail = hdrlines[H_RECEIVED].tail; hdrlines[H_RECEIVED].head = (struct hdrs *)NULL; hdrlines[H_RECEIVED].tail = (struct hdrs *)NULL; hdrlines[H_DTCOPY].head = hdrlines[H_TCOPY].head; hdrlines[H_DTCOPY].tail = hdrlines[H_TCOPY].tail; hdrlines[H_TCOPY].head = (struct hdrs *)NULL; hdrlines[H_TCOPY].tail = (struct hdrs *)NULL; pushlist (H_TCOPY, HEAD, Rpath, FALSE); } if (rc == 0) { /* Verify that positive delivery notification requested */ if (ckdlivopts(H_DTCOPY, &svopts) & NODELIVERY) { Dout(pn, 0, "pos. notif. not requested\n"); goto rtrn; } } else { /* Verify that negative delivery notification requested */ if (ckdlivopts(H_DTCOPY, &svopts) & IGNORE) { Dout(pn, 0, "neg. notif. not requested\n"); goto rtrn; } } if (fp == (FILE *)NULL) { char *pargs[3]; pargs[0] = "mail"; pargs[1] = Rpath; pargs[2] = 0; if ((outfile = popenvp(pargs[0], pargs, "w", 1)) == (FILE *)NULL) { /* Can't get pipe to mail. Just forget it..... */ Dout(pn, 0,"popenvp() failed\n"); goto rtrn; } } else { outfile = fp; } /* get date string into buf for later...*/ ltmp = time((time_t)0); strcpy(buf, asctime(gmtime(<mp))); /* strip year out of date string, insert 'GMT', and put year back... */ p = strrchr(buf,' '); strcpy(ybuf,++p); *p = '\0'; strcat(buf,"GMT "); strcat(buf, ybuf); trimnl(buf); fprintf(outfile,"%s 2\n", header[H_RVERS].tag); fprintf(outfile,"%s %s\n", header[H_TCOPY].tag, hdrlines[H_TCOPY].head->value); fprintf(outfile,"%s %s\n", header[H_DATE].tag, buf); dumprcv(ORDINARY, -1,&didrcvlines,&suppress,outfile); dumpaff(ORDINARY, -1,&didafflines,&suppress,outfile); fprintf(outfile,"Original-%s ", header[H_DATE].tag); if ((hptr = hdrlines[H_DATE].head) != (struct hdrs *)NULL) { Dout(pn, 0,"date from H_DATE = '%s'\n", hptr->value); fprintf(outfile,"%s\n", hptr->value); } else { /* If no H_DATE line in original message, use date */ /* in last UNIX H_FROM1 or H_FROM line */ if ((hptr = hdrlines[H_FROM1].tail) == (struct hdrs *)NULL) { hptr = hdrlines[H_FROM].tail; } Dout(pn, 0,"date from H_FROM = '%s'\n", hptr->value); (void) strlcpy(buf, hptr->value, sizeof (buf)); /* Find date portion of line. */ /* Assumes line is of form - */ /* 'name_date_[remote_from_sys|forwarded_by_name]' */ if ((p = strchr(buf,' ')) == (char *)NULL) { strcpy(buf, "No valid datestamp in original."); } else { (void) strlcpy(buf, p++, sizeof (buf)); /* Walk backwards from end of string to 3rd blank, */ /* and then check for 'remote from' or 'forwarded by' */ /* If either found, truncate there, else use entire */ /* string. */ p = buf + strlen(buf) - 1; i = 0; while (p > buf) { if (*p == ' ') { if (++i == 3) { break; } } p--; } if ((i != 3) || (p <= buf)) { strcpy(buf, "No valid datestamp in original."); } else { if ((strncmp((p+1),"remote from", 11) == 0) || (strncmp((p+1),"forwarded by", 12) == 0)) { *p = '\0'; } } } fprintf(outfile,"%s\n", buf); } if ((hptr = hdrlines[H_SUBJ].head) != (struct hdrs *)NULL) { fprintf(outfile,"Original-%s %s\n", header[H_SUBJ].tag, hptr->value); } if ((hptr = hdrlines[H_MSVC].head) != (struct hdrs *)NULL) { if ((strlen(hptr->value) != 4) || (casncmp("mail", hptr->value, 4) != 0)) { fprintf(outfile,"Original-%s %s\n", header[H_MSVC].tag, hptr->value); } } if ((hptr = hdrlines[H_MTSID].head) != (struct hdrs *)NULL) { fprintf(outfile,"Confirming-%s <%s>\n", header[H_MTSID].tag, hptr->value); } if ((hptr = hdrlines[H_UAID].head) != (struct hdrs *)NULL) { fprintf(outfile,"Confirming-%s <%s>\n", header[H_UAID].tag, hptr->value); } cbuf[0] = '\0'; if ((hptr = hdrlines[H_DTCOPY].head) != (struct hdrs *)NULL) { /* Pick comment field off of ">To:" line and put into cbuf */ getcomment(hptr->value, cbuf); } if (rc == 0) { fprintf(outfile,"Delivered-To: %s!%s %s on %s\n", thissys, name, cbuf, buf); } else { (void) strlcpy (buf, name, sizeof (buf)); if ((p = strchr(buf,'!')) != (char *)NULL) { *p = '\0'; } fprintf(outfile,"Not-Delivered-To: %s!%s %s due to ", thissys, buf, /* if en-route-to, put comment there, else put it here*/ ((p == (char *)NULL) ? cbuf : "")); mta_ercode(outfile); if (ckdlivopts(H_DTCOPY, &svopts) & RETURN) { fprintf(outfile," ORIGINAL MESSAGE ATTACHED\n"); } if (error == E_FRWL) { fprintf(outfile, frwlmsg, program, uval); } else { fprintf(outfile, " (%s: Error # %d '%s'", program,error,errlist[error]); if (error == E_SURG) { fprintf(outfile,", rc = %d)\n",surg_rc); fprintf(outfile, " ======= Surrogate command =======\n"); fprintf(outfile," %s\n", ((SURRcmdstr == (char *)NULL) ? "" : SURRcmdstr)); /* Include stderr from surrogate, if any */ if (SURRerrfile) { fprintf(outfile, " ==== Start of stdout & stderr ===\n"); rewind (SURRerrfile); while (fgets(buf, sizeof(buf), SURRerrfile) != (char *)NULL) { fprintf(outfile," %s", buf); } if (buf[strlen(buf)-1] != '\n') { fprintf(outfile,"\n"); } fprintf(outfile, " ==== End of stdout & stderr ===\n"); } else fprintf(outfile, " ==== stdout & stderr unavailable ===\n"); } else { fprintf(outfile,")\n"); } } if (p != (char *)NULL) { fprintf(outfile, "En-Route-To: %s %s\n", name, cbuf); } } if ((hptr = hdrlines[H_DAFWDFROM].head) != (struct hdrs *)NULL) { while (hptr != (struct hdrs *)NULL) { fprintf(outfile,"Original-%s %s\n", header[H_DAFWDFROM].tag, hptr->value); hptr = hptr->next; } } fprintf(outfile,"%s\n", header[H_EOH].tag); if (fp == (FILE *)NULL) { pclosevp(outfile); } Dout(pn, 5, "notification sent.\n"); rtrn: /* Restore header info from original message. (see above and also */ /* goback()). */ clrhdr(H_TCOPY); clrhdr(H_AFWDFROM); clrhdr(H_RECEIVED); affbytecnt = Daffbytecnt; Daffbytecnt = 0; affcnt = Daffcnt; Daffcnt = 0; rcvbytecnt = Drcvbytecnt; Drcvbytecnt = 0; hdrlines[H_AFWDFROM].head = hdrlines[H_DAFWDFROM].head; hdrlines[H_AFWDFROM].tail = hdrlines[H_DAFWDFROM].tail; hdrlines[H_DAFWDFROM].head = (struct hdrs *)NULL; hdrlines[H_DAFWDFROM].tail = (struct hdrs *)NULL; hdrlines[H_RECEIVED].head = hdrlines[H_DRECEIVED].head; hdrlines[H_RECEIVED].tail = hdrlines[H_DRECEIVED].tail; hdrlines[H_DRECEIVED].head = (struct hdrs *)NULL; hdrlines[H_DRECEIVED].tail = (struct hdrs *)NULL; hdrlines[H_TCOPY].head = hdrlines[H_DTCOPY].head; hdrlines[H_TCOPY].tail = hdrlines[H_DTCOPY].tail; hdrlines[H_DTCOPY].head = (struct hdrs *)NULL; hdrlines[H_DTCOPY].tail = (struct hdrs *)NULL; return; } /* * 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 */ #include "mail.h" /* get next token p -> string to be searched s -> area to return token returns: p -> updated string pointer s -> token NULL -> no token */ char * getarg(s, p) register char *s, *p; { while (*p == ' ' || *p == '\t') p++; if (*p == '\n' || *p == '\0') return(NULL); while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') *s++ = *p++; *s = '\0'; return(p); } /* * 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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" /* * Get comment field, if any, from line. * 1 ==> found comment. * 0 ==> no comment found. * -1 ==> no closing (terminating) paren found for comment. */ int getcomment(char *s, char *q) /* Copy comment, if found, to q */ { char *p, *sav_q; int depth = 0; if ((p = strchr(s, '(')) == (char *)NULL) { /* no comment found */ return (0); } sav_q = q; while (*p) { *q++ = *p; if (*p == ')') { /* account for nested parens within comment */ depth--; if (depth == 0) { break; } } else if (*p == '(') { depth++; } p++; } *q = '\0'; if (*p != ')') { /* closing paren not found */ *sav_q = '\0'; return (-1); } /* found comment */ return (1); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (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) 1989, 2010, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" #define MAXHDRSIZE 100 /* Maximum length of header line */ #define MAXUNAME 20 /* Maximum length of user name */ /* * display headers, indicating current and status * * current is the displacement into the mailfile of the * current letter * * all indicates how many headers should be shown. * 0 -> show window +/-6 around current * 1 -> show all messages * 2 -> show deleted messages * * Only 100 characters of the From (first) header line will * be read in. This line is assumed to be in the following * format: * From * where * is either a UUCP-style (sysa!sysb!user) * or domain-style address (user@host). * * If the sender address contains a UUCP-style address, then * the user name displayed is made up of the characters following * the final '!' in the sender address, otherwise the sender * address is considered to be the user name. * * The maximum number of characters of a user name displayed * is 19. * */ int gethead(int current, int all) { int displayed = 0; FILE *file; char *hold; char holdval[MAXHDRSIZE]; char *wline; char wlineval[MAXHDRSIZE]; int ln; char mark; int rc, size, start, stop, ix; char userval[MAXUNAME]; char *uucpptr; int uucpstart; int unamechars = MAXUNAME - 1; int sender_size; hold = holdval; wline = wlineval; printf("%d letters found in %s, %d scheduled for deletion, " "%d newly arrived\n", nlet, mailfile, changed, nlet - onlet); if (all == 2 && !changed) return (0); file = doopen(lettmp, "r", E_TMP); if (!flgr) { stop = current - 6; if (stop < -1) stop = -1; start = current + 5; if (start > nlet - 1) start = nlet - 1; if (all) { start = nlet -1; stop = -1; } } else { stop = current + 6; if (stop > nlet) stop = nlet; start = current - 5; if (start < 0) start = 0; if (all) { start = 0; stop = nlet; } } for (ln = start; ln != stop; ln = flgr ? ln + 1 : ln - 1) { size = let[ln+1].adr - let[ln].adr; if ((rc = fseek(file, let[ln].adr, 0)) != 0) { errmsg(E_FILE, "Cannot seek header"); fclose(file); return (1); } if (fgets(wline, MAXHDRSIZE, file) == NULL) { errmsg(E_FILE, "Cannot read header"); fclose(file); return (1); } if ((rc = strncmp(wline, header[H_FROM].tag, 5)) != SAME) { errmsg(E_FILE, "Invalid header encountered"); fclose(file); return (1); } /* skip past trailing white space after header tag */ for (rc = 5; wline[rc] == ' ' || wline[rc] == '\t'; ++rc) ; (void) strlcpy(hold, wline + rc, MAXHDRSIZE); fgets(wline, MAXHDRSIZE, file); while (((rc = strncmp(wline, header[H_FROM1].tag, 6)) == SAME) && (substr(wline, "remote from ") != -1)) { (void) strlcpy(hold, wline + 6, MAXHDRSIZE); fgets(wline, MAXHDRSIZE, file); } /* * If UUCP-style sender address, then read past * last "!" to get the start of the user name. */ sender_size = strcspn(hold, " \t"); uucpstart = 0; if ((uucpptr = strrchr(hold, '!')) != NULL) { uucpstart = uucpptr - hold + 1; if (uucpstart > sender_size) { uucpstart = 0; } } /* Get the user name out of the sender address. */ for (ix = 0, rc = uucpstart; ix < unamechars && hold[rc] != ' ' && hold[rc] != '\t' && rc < sender_size; ++rc) { userval[ix++] = hold[rc]; } if ((ix > 0) && (userval[ix - 1] == '\n')) { userval[ix - 1] = '\0'; } else { userval[ix] = '\0'; } /* * Skip past the rest of the sender address, and * delimiting white space. */ for (; hold[rc] != '\0' && hold[rc] != ' ' && hold[rc] != '\t'; ++rc) ; for (; hold[rc] == ' ' || hold[rc] == '\t'; ++rc) ; /* Get the date information. */ (void) strlcpy(wline, hold + rc, MAXHDRSIZE); for (rc = 0; wline[rc] != '\0' && wline[rc] != '\n'; ++rc) ; wline[rc] = '\0'; if (!flgh && current == ln) mark = '>'; else mark = ' '; if (all == 2) { if (displayed >= changed) { fclose(file); return (0); } if (let[ln].change == ' ') continue; } printf("%c %3d %c %-5d %-10s %s\n", mark, ln + 1, let[ln].change, size, userval, wline); displayed++; } fclose(file); return (0); } void tmperr(void) { fclose(tmpf); errmsg(E_TMP, ""); } /* * Write a string out to tmp file, with error checking. * Return 1 on success, else 0 */ int wtmpf(char *str, int length) { if (fwrite(str, 1, length, tmpf) != length) { tmperr(); return (0); } return (1); } /* * Read a line from stdin, assign it to line and * return number of bytes in length */ int getaline(char *ptr2line, int max, FILE *f) { int i, ch; for (i = 0; i < max-1 && (ch = getc(f)) != EOF; ) if ((ptr2line[i++] = ch) == '\n') break; ptr2line[i] = '\0'; return (i); } /* * Make temporary file for letter */ void mktmp(void) { static char tmpl[] = "/var/tmp/mailXXXXXX"; int fd = mkstemp(lettmp = tmpl); if (fd < 0 || (tmpf = fdopen(fd, "w+")) == NULL) { fprintf(stderr, "%s: Can't open '%s', type: w+\n", program, lettmp); done(0); } } /* * Get a number from user's reply, * return its value or zero if none present, -1 on error */ int getnumbr(char *s) { int k = 0; while (*s == ' ' || *s == '\t') s++; if (*s != '\0') { if ((k = atoi(s)) != 0) if (!validmsg(k)) return (-1); for (; *s >= '0' && *s <= '9'; ) s++; if (*s != '\0' && *s != '\n') { printf("Illegal numeric\n"); return (-1); } return (k); } return (0); } /* * If valid msgnum return 1, * else print message and return 0 */ int validmsg(int i) { if ((i < 0) || (i > nlet)) { printf("No such message\n"); return (0); } return (1); } /* * Set letter to passed status, and adjust changed as necessary */ void setletr(int letter, int status) { if (status == ' ') { if (let[letter].change != ' ') if (changed) changed--; } else { if (let[letter].change == ' ') changed++; } let[letter].change = status; } /* * 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 2002 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "mail.h" /* This routine returns undeliverable mail as well as handles replying to letters */ void goback(letnum) int letnum; { static char pn[] = "goback"; int i, w; char buf[1024], *cp, work[1024], wuser[1024]; /* * If dflag already == 1, then been here already and * having a problem delivering failure notification. * Reset dflag to 9 to avoid endless loop..... */ if (dflag == 1) { dflag = 9; Dout(pn, 0, "dflag = %d\n", dflag); if (!error) { error = E_REMOTE; Dout(pn, 0, "error = %d\n", error); } } if (dflag < 2) { work[0] = '\0'; wuser[0] = '\0'; fclose(tmpf); if (!replying) { dflag = 1; Dout(pn, 0, "dflag = 1\n"); if ((debug > 0) && (keepdbgfile == 0)) { keepdbgfile++; } if (ckdlivopts(H_TCOPY, (int *)0) & IGNORE) { goto skipsend; } } tmpf = doopen(lettmp, "r+", E_TMP); if (replying) { fseek(tmpf, let[letnum].adr, 0); } for (fgets(line, LSIZE, tmpf); strncmp(line, header[H_FROM].tag, strlen(header[H_FROM].tag)) == SAME || strncmp(line, header[H_FROM1].tag, strlen(header[H_FROM1].tag)) == SAME; ) { if ((i = substr(line, "remote from")) != -1) { for (i = 0, cp = strrchr(line, ' ') + 1; *cp != '\n'; cp++) { buf[i++] = *cp; } buf[i++] = '!'; buf[i] = '\0'; strcat(work, buf); if (line[0] == '>') { i = 6; } else { i = 5; } for (w = i; line[w] != ' '; w++) { wuser[w-i] = line[w]; } wuser[w-i] = '\0'; } else if ((i = substr(line, "forwarded by")) == -1) { if (line[0] == '>') { break; } else { i = 5; } for (w = i; line[w] != ' '; w++) { wuser[w-i] = line[w]; } wuser[w-i] = '\0'; } else if ((i = substr(line, "forwarded by")) > -1) { break; } fgets(line, LSIZE, tmpf); } strcat(work, wuser); fclose(tmpf); tmpf = doopen(lettmp, "r+", E_TMP); if (work[0] != '\0') { reciplist list; if (replying) { (void) snprintf(buf, sizeof (buf), "mail %s %s", m_sendto, work); printf("%s\n", buf); systm(buf); return; } if (interactive) { (void) strlcpy(work, my_name, sizeof (work)); } fprintf(stderr, "%s: Return to %s\n", program, work); /* Put header info from message aside so it won't */ /* get confused with the Delivery Notification info */ Daffbytecnt = affbytecnt; affbytecnt = 0; Daffcnt = affcnt; affcnt = 0; Drcvbytecnt = rcvbytecnt; rcvbytecnt = 0; hdrlines[H_DAFWDFROM].head = hdrlines[H_AFWDFROM].head; hdrlines[H_DAFWDFROM].tail = hdrlines[H_AFWDFROM].tail; hdrlines[H_AFWDFROM].head = (struct hdrs *)NULL; hdrlines[H_AFWDFROM].tail = (struct hdrs *)NULL; hdrlines[H_DRECEIVED].head = hdrlines[H_RECEIVED].head; hdrlines[H_DRECEIVED].tail = hdrlines[H_RECEIVED].tail; hdrlines[H_RECEIVED].head = (struct hdrs *)NULL; hdrlines[H_RECEIVED].tail = (struct hdrs *)NULL; hdrlines[H_DTCOPY].head = hdrlines[H_TCOPY].head; hdrlines[H_DTCOPY].tail = hdrlines[H_TCOPY].tail; hdrlines[H_TCOPY].head = (struct hdrs *)NULL; hdrlines[H_TCOPY].tail = (struct hdrs *)NULL; pushlist(H_TCOPY, HEAD, work, FALSE); new_reciplist(&list); add_recip(&list, work, FALSE); sendlist(&list, 0, 0); del_reciplist(&list); } } skipsend: if (dflag == 9) { fprintf(stderr, "%s: Cannot return mail.\n", program); mkdead(); } else if (dflag < 2) { if (!maxerr && (dflag != 1)) { maxerr = error; Dout(pn, 0, "maxerr = %d\n", maxerr); } dflag = 0; error = 0; Dout(pn, 0, "before return, dflag = %d, error = %d\n", dflag, error); } } /* * 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 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * All global externs defined in mail.h. All variables are initialized * here! * * !!!!!IF YOU CHANGE (OR ADD) IT HERE, DO IT THERE ALSO !!!!!!!! * */ #include "mail.h" int ac; /* argument list count */ char **av; /* argument list */ int affbytecnt; /* Total bytes of Auto-Fwd. info in msg. */ int affcnt; /* Number of Auto-Fwd.-From: lines in msg. */ int Daffbytecnt; /* Hold affbytecnt when sending Delivery Notification */ int Daffcnt; /* Hold affcnt when sending Delivery Notification */ char binmsg[] = "*** Message content is not printable: delete, write or save it to a file ***"; int changed; /* > 0 says mailfile has changed */ char datestring[60]; /* Today's date and time */ char dbgfname[20]; FILE *dbgfp; char dead[] = "/dead.letter"; /* name of dead.letter */ int debug; /* Controls debugging level. 0 ==> no debugging */ int delflg = 1; int dflag = 0; /* 1 says returning unsendable mail */ char *errlist[]= { "", "Unknown system", "Problem with mailfile", "Space problem", "Unable to forward mail, check permissions and group", "Syntax error", "Forwarding loop", "Invalid sender", "Invalid recipient", "Too many From lines", "Invalid permissions", "Cannot open mbox", "Temporary file problem", "Cannot create dead.letter", "Unbounded forwarding", "Cannot create lock file", "No group id of 'mail'", "Problem allocating memory", "Could not fork", "Cannot pipe", "Must be owner to modify mailfile", "Permission denied by /etc/mail/mailsurr file", "Surrogate command failed" }; int error = 0; /* Local value for error */ char *failsafe; /* $FAILSAFE */ int file_size; int flge = 0; /* 1 ==> 'e' option specified */ int flgE = 0; /* 1 ==> 'E' option specified */ int flgF = 0; /* 1 ==> Installing/Removing Forwarding */ int flgf = 0; /* 1 ==> 'f' option specified */ int flgh = 0; /* 1 ==> 'h' option specified */ int flgm; int flgp = 0; /* 1 ==> 'p' option specified */ int flgP = 0; /* 1 ==> 'P' option specified */ int flgr = 0; /* 1 ==> 'r' option -- print in fifo order */ int flgt = 0; /* 1 ==> 't' option -- add To: line to letter */ int flgT = 0; /* 1 ==> 'T' option specified */ int flgw = 0; /* 1 ==> 'w' option specified */ int fnuhdrtype = 0; /* type of first non-UNIX header line */ char forwmsg[] = " forwarded by %s\n"; char fromS[1024]; /* stored here by sendmail for sendsurg */ char fromU[1024]; /* stored here by sendmail for sendsurg */ char frwlmsg[] = " %s: Forwarding loop detected in %s's mailfile.\n"; char frwrd[] = "Forward to "; /* forwarding sentinel */ char fwdFrom[1024]; int goerr = 0; /* counts parsing errors */ struct group *grpptr; /* pointer to struct group */ struct hdrlines hdrlines[H_CONT]; /* Default_display indicates whether to display this header line to the TTY */ /* when in default mode. Can be overridden via 'P' command at ? prompt */ struct hdr header[] = { "", FALSE, "Auto-Forward-Count:", FALSE, "Auto-Forwarded-From:", FALSE, "Content-Length:", TRUE, "Content-Type:", FALSE, "Date:", TRUE, "Default-Options:", FALSE, "End-of-Header:", FALSE, "From ", TRUE, ">From ", TRUE, "From:", TRUE, "MIME-Version:", FALSE, "MTS-Message-ID:", FALSE, "Message-Type:", FALSE, "Message-Version:", FALSE, "Message-Service:", TRUE, "Received:", FALSE, "Report-Version:", FALSE, "Subject:", TRUE, "To:", TRUE, ">To:", FALSE, "Transport-Options:", FALSE, "UA-Content-ID:", FALSE, /*Dummy place holders for H_DAFWDFROM,*/ /*H_DTCOPY and H_RECEIVED. Should */ /* match above first...*/ "Hold-Auto-Forwarded-From:", FALSE, "Hold->To:", FALSE, "Hold-Received:", FALSE, "Continue:", FALSE, "Name-Value:", FALSE, }; char *help[] = { "?\t\tprint this help message\n", "#\t\tdisplay message number #\n", "-\t\tprint previous\n", "+\t\tnext (no delete)\n", "! cmd\t\texecute cmd\n", "\t\tnext (no delete)\n", "a\t\tposition at and read newly arrived mail\n", "d [#]\t\tdelete message # (default current message)\n", "dp\t\tdelete current message and print the next\n", "dq\t\tdelete current message and exit\n", "h a\t\tdisplay all headers\n", "h d\t\tdisplay headers of letters scheduled for deletion\n", "h [#]\t\tdisplay headers around # (default current message)\n", "m user \tmail (and delete) current message to user\n", "n\t\tnext (no delete)\n", "p\t\tprint (override any warnings of binary content)\n", "P\t\toverride default 'brief' mode and display ALL header lines\n", "q, ^D\t\tquit\n", "r [args]\treply to (and delete) current letter via mail [args]\n", "s [files]\tsave (and delete) current message (default mbox)\n", "u [#]\t\tundelete message # (default current message)\n", "w [files]\tsave (and delete) current message without header\n", "x\t\texit without changing mail\n", "y [files]\tsave (and delete) current message (default mbox)\n", 0 }; char *hmbox; /* pointer to $HOME/mbox */ char *hmdead; /* pointer to $HOME/dead.letter */ char *home; /* pointer to $HOME */ time_t iop; int interactive = 0; /* 1 says user is interactive */ int ismail = TRUE; /* default to program=mail */ int deliverflag = FALSE; /* -d flag, skip sendmail * deliver directly to mailbox */ int fromflag = FALSE; /* -f from_user, set a user * when going into a mailbox */ int keepdbgfile; struct let let[MAXLET]; char *lettmp; /* pointer to tmp filename */ char lfil[MAXFILENAME]; char line[LSIZE]; /* holds a line of a letter in many places */ char *mailfile; /* pointer to mailfile */ char mailcnfg[] = MAILCNFG; /* configuration file */ char maildir[] = MAILDIR; /* directory for mail files */ gid_t mailgrp; /* numeric id of group 'mail' */ char mailsave[] = SAVEDIR; /* dir for save files */ char *mailsurr = MAILSURR; /* surrogate file name */ FILE *malf; /* File pointer for mailfile */ int maxerr = 0; /* largest value of error */ char mbox[] = "/mbox"; /* name for mbox */ uid_t mf_uid; /* uid of users mailfile */ gid_t mf_gid; /* gid of users mailfile */ char *msgtype; char my_name[1024]; /* user's name who invoked this command */ char from_user[1024]; /* user's name specified w/ -f when sending */ uid_t my_euid; /* user's euid */ gid_t my_egid; /* user's egid */ uid_t my_uid; /* user's uid */ gid_t my_gid; /* user's gid */ int nlet = 0; /* current number of letters in mailfile */ int onlet = 0; /* number of letters in mailfile at startup*/ int optcnt = 0; /* Number of options specified */ int orig_aff = 0; /* orig. msg. contained H_AFWDFROM lines */ int orig_dbglvl; /* argument to -x invocation option */ int orig_rcv = 0; /* orig. msg. contained H_RECEIVED lines */ int orig_tcopy = 0; /* orig. msg. contained H_TCOPY lines */ struct passwd *pwd; /* holds passwd entry for this user */ int pflg = 0; /* binary message display override flag */ int Pflg = 0; /* Selective display flag; 1 ==> display all */ char *program; /* program name */ int rcvbytecnt; /* Total bytes of Received: info in msg. */ int Drcvbytecnt; /* Hold rcvbytecnt when sending Delivery Notification */ char *recipname; /* full recipient name/address */ int replying = 0; /* 1 says we are replying to a letter */ char RFC822datestring[60];/* Date in RFC822 date format */ char Rpath[1024]; /* return path to sender of message */ char rmtmsg[] = " remote from %s\n"; char rtrnmsg[] = "***** UNDELIVERABLE MAIL sent to %s, being returned by %s *****\n"; int sav_errno; char savefile[MAXFILENAME]; /* holds filename of save file */ void (*saveint)(); /* Any header line prefixes listed here WILL be displayed in default mode */ /* If it's not here, it won't be shown. Can be overridden via 'P' command */ /* at ? prompt */ char *seldisp[] = { "Cc:", "Bcc:", "Paper-", "Phone:", "Message-", "Original-", "Confirming-", "Delivered-", "Deliverable-", "Not-", "En-Route-To:", 0 }; int sending; /* TRUE==>sending mail; FALSE==>printing mail */ char m_sendto[1024]; jmp_buf sjbuf; int surg_rc = 0; /* exit code of surrogate command */ int surr_len = 0; char *SURRcmdstr = (char *)NULL; /* save in case of FAILURE */ FILE *SURRerrfile; /* stderr from surrogate in case of FAILURE */ char *thissys; /* Holds name of the system we are on */ FILE *tmpf; /* file pointer for temporary files */ mode_t umsave; struct utsname utsn; static struct utimbuf utims; struct utimbuf *utimep = &utims; char uval[1024]; int init() { utims.actime = utims.modtime = -1; return (xsetenv(mailcnfg)); } /* * 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 */ #include "mail.h" /* * isheader(lp, ctf) - check if lp is header line and return type * lp -> pointer to line * ctfp -> continuation flag (should be FALSE the first time * isheader() is called on a message. isheader() sets * it for the remaining calls to that message) * returns * FALSE -> not header line * H_* -> type of header line found. */ int isheader(char *lp, int *ctfp) { char *p, *q; int i; p = lp; while ((*p) && (*p != '\n') && (isspace(*p))) { p++; } if ((*p == '\0') || (*p == '\n')) { /* blank line */ return (FALSE); } if ((*ctfp) && ((*lp == ' ') || (*lp == '\t'))) { return (H_CONT); } *ctfp = FALSE; for (i = 1; i < H_CONT; i++) { if (!isit(lp, i)) { continue; } if ((i == H_FROM) || (i == H_FROM1)) { /* * Should NEVER get 'From ' or '>From ' line on stdin * if invoked as mail (rather than rmail) since * 'From ' and/or '>From ' lines are generated by * program itself. Therefore, if it DOES match and * ismail == TRUE, it must be part of the content. */ if (sending && ismail && !deliverflag) { return (FALSE); } } *ctfp = TRUE; return (i); } /* * Check if name: value pair */ if ((p = strpbrk(lp, ":")) != NULL) { for (q = lp; q < p; q++) { if ((*q == ' ') || (!isprint(*q))) { return (FALSE); } } *ctfp = TRUE; return (H_NAMEVALUE); } return (FALSE); } /* * 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 1995 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" /* * isit(lp, type) -- match "name" portion of * "name: value" pair * lp -> pointer to line to check * type -> type of header line to match * returns * TRUE -> lp matches header type (case independent) * FALSE -> no match * * Execpt for H_FORM type, matching is case insensitive (bug 1173101) */ int isit(char *lp, int type) { char *p; switch (type) { case H_FROM: for (p = header[type].tag; *lp && *p; lp++, p++) { if (*p != *lp) { return (FALSE); } } break; default: for (p = header[type].tag; *lp && *p; lp++, p++) { if (toupper(*p) != toupper(*lp)) { return (FALSE); } } break; } if (*p == '\0') { return (TRUE); } return (FALSE); } /* * 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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include #include "mail.h" /* * islocal (char *user, uid_t *puid) - see if user exists on this system */ int islocal(char *user, uid_t *puid) { char fname[MAXPATHLEN]; struct stat statb; struct passwd *pwd_ptr; /* Check for existing mailfile first */ (void) snprintf(fname, sizeof (fname), "%s%s", maildir, user); if (stat(fname, &statb) == 0) { *puid = statb.st_uid; return (TRUE); } /* If no existing mailfile, check passwd file */ setpwent(); if ((pwd_ptr = getpwnam(user)) == NULL) { return (FALSE); } *puid = pwd_ptr->pw_uid; return (TRUE); } /* * 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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" /* * istext(line, size) - check for text characters */ int istext(unsigned char *s, int size) { unsigned char *ep; int c; for (ep = s+size; --ep >= s; ) { c = *ep; if ((!isprint(c)) && (!isspace(c)) && /* Since backspace is not included in either of the */ /* above, must do separately */ /* Bell character is allowable control char in the text */ (c != 010) && (c != 007)) { return(FALSE); } } return(TRUE); } /* * 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 (c) 2001 by Sun Microsystems, Inc. * All rights reserved. */ /* * NAME * legal - check existence of file * * SYNOPSIS * int legal(char *file) * * DESCRIPTION * legal() checks to see if "file" is a writable file name. * * Returns: * 0 -> file or directory exists, but is unwriteable * 1 -> file exists writeable * 2 -> file does not exist, but can be created */ #include "mail.h" int legal(file) register char *file; { register char *sp; char dfile[MAXFILENAME]; /* * If file does not exist then try "." if file name has * no "/". For file names that have a "/", try check * for existence of previous directory. */ if (access(file, A_EXIST) == A_OK) { if (access(file, A_WRITE) == A_OK) return (1); else return (0); } else { if ((sp = strrchr(file, '/')) == NULL) { strcpy(dfile, "."); } else if (sp == file) { strcpy(dfile, "/"); } else { if ((sp - file + 1) > MAXFILENAME) return (0); strncpy(dfile, file, sp - file); dfile[sp - file] = '\0'; } if (access(dfile, A_WRITE) == CERROR) return (0); return (2); } } /* * 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 2002 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "mail.h" void lock(char *user) { char tbuf[80]; switch (maillock(user, 10)) { case L_SUCCESS: return; case L_NAMELEN: (void) snprintf(tbuf, sizeof (tbuf), "%s: Cannot create lock file. Username '%s' is > 13 chars\n", program, user); break; case L_TMPLOCK: strcpy(tbuf, "Cannot create temp lock file\n"); break; case L_TMPWRITE: strcpy(tbuf, "Error writing pid to lock file\n"); break; case L_MAXTRYS: strcpy(tbuf, "Creation of lockfile failed after 10 tries"); break; case L_ERROR: strcpy(tbuf, "Cannot link temp lockfile to lockfile\n"); break; case L_MANLOCK: strcpy(tbuf, "Cannot set mandatory file lock on temp lockfile\n"); break; } errmsg(E_LOCK, tbuf); if (sending) { goback(0); } done(0); } void unlock() { mailunlock(); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (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) 1989, 2010, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #ifndef _MAIL_H #define _MAIL_H /* * All global externs defined here. All variables are initialized * in init.c * * !!!!!IF YOU CHANGE (OR ADD) IT HERE, DO IT THERE ALSO !!!!!!!! * */ #include #include #include #include #include #include #include #include #include #include /* The following is a kludge to allow for inconsistent header files in SVR4 */ #define _CLOCK_T #include #include #include #include #include #ifdef SVR3 struct utimbuf { time_t actime; time_t modtime; }; #else # include #endif #include "libmail.h" /* The following typedefs must be used in SVR4 */ #ifdef SVR3 # ifndef sun typedef int gid_t; typedef int uid_t; # endif typedef int pid_t; #endif #define CHILD 0 #define SAME 0 #define BELL 07 # define PIPER "/usr/lib/mail/mail_pipe" #define SENDMAIL "/usr/lib/sendmail" #define CERROR -1 #define CSUCCESS 0 #define TRUE 1 #define FALSE 0 #define HEAD 1 #define TAIL 0 #define REAL 1 #define DEFAULT 0 /* findSurg() return values */ #define NOMATCH -1 #define DELIVER 0 #define POSTDELIVER 1 #define DENY 2 #define TRANSLATE 3 /* sendsurg() return values */ #define FAILURE 0 #define CONTINUE 1 #define SUCCESS 2 /* TRANSLATE 3 */ #define HDRSIZ 1024 /* maximum length of header line */ #define E_FLGE 1 /* flge error */ #define E_FLGE_OM 2 /* flgE error, mail present but already accessed */ #define E_REMOTE 1 /* unknown remote */ #define E_FILE 2 /* file error */ #define E_SPACE 3 /* no space */ #define E_FRWD 4 /* cannot forward */ #define E_SYNTAX 5 /* syntax error */ #define E_FRWL 6 /* forwarding loop */ #define E_SNDR 7 /* invalid sender */ #define E_USER 8 /* invalid user */ #define E_FROM 9 /* too many From lines */ #define E_PERM 10 /* bad permissions */ #define E_MBOX 11 /* mbox problem */ #define E_TMP 12 /* temporary file problem */ #define E_DEAD 13 /* Cannot create dead.letter */ #define E_UNBND 14 /* Unbounded forwarding */ #define E_LOCK 15 /* cannot create lock file */ #define E_GROUP 16 /* no group id of 'mail' */ #define E_MEM 17 /* malloc failure */ #define E_FORK 18 /* could not fork */ #define E_PIPE 19 /* could not pipe */ #define E_OWNR 20 /* invoker does not own mailfile */ #define E_DENY 21 /* permission denied by mailsurr file */ #define E_SURG 22 /* surrogate command failed - rc != 0 || 99 */ #define H_AFWDCNT 1 /* "Auto-Forward-Count:" */ #define H_AFWDFROM 2 /* "Auto-Forwarded-From:" */ #define H_CLEN 3 /* "Content-Length:" */ #define H_CTYPE 4 /* "Content-Type:" */ #define H_DATE 5 /* "Date:" */ #define H_DEFOPTS 6 /* "Default-Options:" */ #define H_EOH 7 /* "End-of-Header:" */ #define H_FROM 8 /* "From " */ #define H_FROM1 9 /* ">From " */ #define H_FROM2 10 /* "From: " */ #define H_MIMEVERS 11 /* "MIME-Version:" */ #define H_MTSID 12 /* "MTS-Message-ID:" */ #define H_MTYPE 13 /* "Message-Type:" */ #define H_MVERS 14 /* "Message-Version:" */ #define H_MSVC 15 /* "Message-Service:" */ #define H_RECEIVED 16 /* "Received:" */ #define H_RVERS 17 /* "Report-Version:" */ #define H_SUBJ 18 /* "Subject:" */ #define H_TO 19 /* "To:" */ #define H_TCOPY 20 /* ">To:" */ #define H_TROPTS 21 /* "Transport-Options:" */ #define H_UAID 22 /* "UA-Content-ID:" */ #define H_DAFWDFROM 23 /* Hold A-F-F when sending Del. Notf. */ #define H_DTCOPY 24 /* Hold ">To:" when sending Del. Notf.*/ #define H_DRECEIVED 25 /* Hold Rcvd: when sending Del. Notf.*/ #define H_CONT 26 /* Continuation of previous line */ #define H_NAMEVALUE 27 /* unrecognized "name: value" hdr line*/ /* MTA Transport Options */ #define DELIVERY 001 #define NODELIVERY 002 #define REPORT 010 #define RETURN 020 #define IGNORE 040 /* copylet flags */ #define REMOTE 1 /* remote mail, add rmtmsg */ #define ORDINARY 2 #define ZAP 3 /* zap header and trailing empty line */ #define FORWARD 4 #define TTY 5 /* suppress binary to tty */ #define LSIZE (2*BUFSIZ) /* maximum size of a line */ #define MAXLET 1000 /* maximum number of letters */ #define FROMLEVELS 20 /* maxium number of forwards */ #ifdef FILENAME_MAX # define MAXFILENAME FILENAME_MAX /* max length of a filename */ #else # define MAXFILENAME 512 /* max length of a filename */ #endif #define DEADPERM 0600 /* permissions of dead.letter */ #ifndef MFMODE #define MFMODE 0660 /* create mode for `/var/mail' files */ #endif #define A_OK 0 /* return value for access */ #define A_EXECUTE 1 #define A_EXIST 0 /* access check for existence */ #define A_WRITE 2 /* access check for write permission */ #define A_READ 4 /* access check for read permission */ # define MAILSURR "/etc/mail/mailsurr" # define MAILCNFG "/etc/mail/mailcnfg" struct hdr { char *tag; int default_display; }; struct hdrs { struct hdrs *next; struct hdrs *prev; struct hdrs *cont; /* Continuation lines */ char value[HDRSIZ+1]; }; struct hdrlines { struct hdrs *head; struct hdrs *tail; }; typedef struct recip { struct recip *next; char *name; } recip; typedef struct reciplist { recip *last_recip; recip recip_list; } reciplist; struct let { long adr; /* offset in mailfile of letter n */ char change; /* disposition status of letter n */ char text; /* 1 ==> text content, 0 ==> binary content. * This is determined INDEPENDENTLY of what * the Content-type, if present, says... */ }; typedef enum t_surrtype { t_eof, t_transport = '<', t_accept = 'a', t_deny = 'd', t_translate = 't', t_postprocess = '>' } t_surrtype; typedef struct t_surrfile { /* originator's regular expression */ string *orig_pattern; char *orig_regex; int orig_reglen; int orig_nbra; /* recipient's regular expression */ string *recip_pattern; char *recip_regex; int recip_reglen; int recip_nbra; /* the type of the command string */ t_surrtype surr_type; int batchsize; /* transport translate postprocess */ char *statlist; /* transport */ string *cmd_left; /* transport translate postprocess */ string *cmd_right; /* transport translate postprocess */ int fullyresolved; /* translate */ } t_surrfile; #include #include extern void Dout(char *subname, int level, char *fmt, ...); extern void Tout(char *subname, char *msg, ...); extern int add_recip(reciplist *plist, char *name, int checkdups); extern char *altcompile(const char *instring, char *expbuf, char *endbuf); extern int areforwarding(char *mailfile); extern void cat(char*, char*, char*); extern int ckdlivopts(int tcopy_hdr, int *svopts); extern void cksaved(char *user); extern int cksurg_rc(int surr_num, int rc); extern void clr_hinfo(void); extern void clrhdr(int hdrtype); extern void cmdexpand(int letnum, string *instr, string *outstr, char **lbraslist, char **lbraelist); extern void copyback(void); extern int copylet(int letnum, FILE *f, int type); extern void copymt(FILE *f1, FILE *f2); extern void createmf(uid_t uid, char *file); extern void del_reciplist (reciplist *list); extern void delete(int); extern void doFopt(void); extern void done(int) __NORETURN; extern void sig_done(int); extern FILE *doopen(char *file, char *type, int errnum); extern int dowait(pid_t pidval); extern void dumpaff(int type, int htype, int *didafflines, int *suppress, FILE *f); extern void dumprcv(int type, int htype, int *didrcvlines, int *suppress, FILE *f); extern void errmsg(int error_value, char *error_message); extern int findSurg(int letnum, string *execbuf, int flag, int *psurr_num, int *paccept, string *lorig, string *lrecipname); extern void gendeliv(FILE *fp, int rc, char *name); extern int getcomment(char *s, char *q); extern int gethead(int current, int all); extern int getaline(char *ptr2line, int max, FILE *f); extern int getnumbr(char *s); extern int getsurr(FILE *fp, string *buf, int firstfield); extern void goback(int letnum); extern int init(void); extern void initsurrfile(void); extern int isheader(char *lp, int *ctfp); extern int isit(char *lp, int type); extern int islocal(char *user, uid_t *puid); extern int istext(unsigned char *s, int size); extern int legal(char *file); extern void lock(char *user); extern void madd_recip(reciplist *plist, char *name, int checkdups); extern char *mailcompile(string *pattern, int *retlen, int *retnbra); extern void mkdead(void); extern void mktmp(void); extern void mta_ercode(FILE *outfile); extern void new_reciplist (reciplist *list); extern int notme(char *fto, char *myname); extern int parse(int argc, char **argv); extern int pckaffspot(void); extern int pckrcvspot(void); extern void pickFrom(char *lineptr); extern int pipletr(int letter, char *command, int cltype); extern void poplist (int hdrtype, int where); extern int printhdr (int type, int hdrtype, struct hdrs *hptr, FILE *fp); extern void printmail(void); extern void pushlist(int hdrtype, int where, char *s, int contflg); extern void savdead(void); extern void savehdrs(char *s, int hdrtype); extern int sel_disp (int type, int hdrtype, char *s); extern int sendlist(reciplist *list, int letnum, int level); extern void sendmail(int argc, char **argv); extern int sendsurg(reciplist *plist, int letnum, int flag, int local); extern void setletr(int letter, int status); extern void (*setsig(int i, void(*f)()))(); extern void setsurg_bt(string *st, int *pbatchsize, int *presolved); extern char *setsurg_rc(string *st, int defreal, int *pbatchsize); extern char **setup_exec(char*); extern void stamp(void); extern int systm(char *s); extern void tmperr(void); extern string *tokdef(string *fld, string *tok, char *name); extern int translate(reciplist *plist, char *cmdstr, char *origname); extern void unlock(void); extern int validmsg(int); extern int wtmpf(char *str, int length); extern int ac; /* argument list count */ extern char **av; /* argument list */ extern int affbytecnt; /* Total bytes of Auto-Fwd. info in msg. */ extern int affcnt; /* Number of Auto-Fwd.-From: lines in msg. */ extern int Daffbytecnt; /* Hold affbytecnt when sending Deliv. Notif. */ extern int Daffcnt; /* Hold affcnt when sending Deliv. Notif. */ extern char binmsg[]; extern int changed; /* > 0 says mailfile has changed */ extern char datestring[60]; extern char dbgfname[20]; /* name of file for debugging output */ extern FILE *dbgfp; /* FILE* for debugging output */ extern char dead[]; /* name of dead.letter */ extern int debug; /* Controls debugging level. 0 ==> no debugging */ extern int delflg; extern int dflag; /* 1 says returning unsendable mail */ extern char *errlist[]; extern int error; /* Local value for error */ extern char *failsafe; /* $FAILSAFE */ extern int file_size; extern int flge; /* 1 ==> 'e' option specified */ extern int flgE; /* 1 ==> 'E' option specified */ extern int flgF; /* 1 ==> Installing/Removing Forwarding */ extern int flgf; /* 1 ==> 'f' option specified */ extern int flgh; /* 1 ==> 'h' option specified */ extern int flgm; extern int flgp; /* 1 ==> 'p' option specified */ extern int flgP; /* 1 ==> 'P' option specified */ extern int flgr; /* 1 ==> 'r' option -- print in fifo order */ extern int flgt; /* 1 ==> 't' option -- add To: line to letter */ extern int flgT; /* 1 ==> 'T' option specified */ extern int flgw; /* 1 ==> 'w' option specified */ extern int fnuhdrtype; /* type of first non-UNIX header line */ extern char forwmsg[]; /* " forwarded by %s" */ extern char frwlmsg[]; /* "Forwarding loop detected in mailfile" */ extern char fromS[1024]; /* stored here by sendmail for sendsurg */ extern char fromU[1024]; /* stored here by sendmail for sendsurg */ extern char frwrd[]; /* forwarding sentinel */ extern char fwdFrom[1024]; extern int goerr; /* counts parsing errors */ extern struct group *grpptr; /* pointer to struct group */ extern struct hdrlines hdrlines[H_CONT]; extern struct hdr header[]; /* H_* #define's used to index into array */ extern char *help[]; extern char *hmbox; /* pointer to $HOME/mbox */ extern char *hmdead; /* pointer to $HOME/dead.letter */ extern char *home; /* pointer to $HOME */ extern time_t iop; extern int interactive; /* 1 says user is interactive */ extern int ismail; /* default to program=mail */ extern int deliverflag; /* -d flag, bypass sendmail and go to mbox */ extern int fromflag; /* -f from_user while sending */ extern int keepdbgfile; /* does debug file get deleted at end? */ extern struct let let[MAXLET]; extern char *lettmp; /* pointer to tmp filename */ extern char lfil[MAXFILENAME]; extern char line[LSIZE]; /* holds a line of a letter in many places */ extern char *mailfile; /* pointer to mailfile */ extern char mailcnfg[]; /* /etc/mail/mailcnfg */ extern char maildir[]; /* directory for mail files */ extern gid_t mailgrp; /* numeric id of group 'mail' */ extern char mailsave[]; /* dir for save files */ extern char *mailsurr; /* surrogate file name */ extern FILE *malf; /* File pointer for mailfile */ extern int maxerr; /* largest value of error */ extern char mbox[]; /* name for mbox */ extern uid_t mf_uid; /* uid of user's mailfile */ extern gid_t mf_gid; /* gid of user's mailfile */ extern char *msgtype; extern char my_name[1024]; /* user's name who invoked this command */ extern char from_user[1024];/* name of user mail's from, used w/ -f */ extern uid_t my_euid; /* user's euid */ extern gid_t my_egid; /* user's egid */ extern uid_t my_uid; /* user's uid */ extern gid_t my_gid; /* user's gid */ extern int nlet; /* current number of letters in mailfile */ extern int onlet; /* number of letters in mailfile at startup*/ extern int optcnt; /* Number of options specified */ extern int orig_aff; /* orig. msg. contained H_AFWDFROM lines */ extern int orig_dbglvl; /* argument to -x invocation option */ extern int orig_rcv; /* orig. msg. contained H_RECEIVED lines */ extern int orig_tcopy; /* orig. msg. contained H_TCOPY lines */ extern struct passwd *pwd; /* holds passwd entry for this user */ extern int pflg; /* binary message display override flag */ extern int Pflg; /* Selective display flag; 1 ==> display all */ extern char *program; /* program name */ extern int rcvbytecnt; /* Total bytes of Received: info in msg. */ extern int Drcvbytecnt; /* Hold rcvbytecnt when sending Del. Notif. */ extern char *recipname; /* full recipient name/address */ extern int replying; /* 1 says we are replying to a letter */ extern char RFC822datestring[60];/* Date in RFC822 date format */ extern char rmtmsg[]; /* "remote from %s" */ extern char Rpath[1024]; /* return path to sender of message */ extern char rtrnmsg[]; /* "UNDELIVERABLE MAIL being returned by %s" */ extern int sav_errno; extern char savefile[MAXFILENAME]; /* holds filename of save file */ extern void (*saveint)(int); extern char *seldisp[]; extern int sending; /* TRUE==>sending mail; FALSE==>printing mail */ extern char m_sendto[1024]; extern jmp_buf sjbuf; extern int surg_rc; /* exit code of surrogate command */ extern t_surrfile *surrfile; /* the compiled surrogate file */ extern int surr_len; /* # entries in surrogate file */ extern char *SURRcmdstr; /* save in case of FAILURE */ extern FILE *SURRerrfile; /* stderr from surrogate in case of failure */ extern char *thissys; /* Holds name of the system we are on */ extern FILE *tmpf; /* file pointer for temporary files */ extern mode_t umsave; extern struct utsname utsn; extern struct utimbuf *utimep; extern char uval[1024]; #ifdef NOTDEF #ifdef sun #define _NFILE getdtablesize() #endif #endif /* NOTDEF */ #endif /* _MAIL_H */ /* * 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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" #ifdef SVR4 #include #endif /* * mail [ -ehpPqrtw ] [-x debuglevel] [ -f file ] [ -F user(s) ] * mail -T file persons * mail [ -tw ] [ -m messagetype ] persons * rmail [ -tw ] persons */ int main(int argc, char **argv) { register int i; char *cptr, *p; struct stat statb; static char pn[] = "main"; extern char **environ; int env_var_idx, next_slot_idx; int tmpfd = -1; #ifdef SVR4 (void) setlocale(LC_ALL, ""); #endif /* fix here for bug #1086130 - security hole */ /* skip over the LD_* env variable */ env_var_idx = 0; next_slot_idx = 0; while (environ[env_var_idx] != NULL) { environ[next_slot_idx] = environ[env_var_idx]; if (strncmp(environ[env_var_idx], "LD_", 3)) { next_slot_idx++; } env_var_idx++; } environ[next_slot_idx] = NULL; #ifdef SIGCONT #ifdef SVR4 { struct sigaction nsig; nsig.sa_handler = SIG_DFL; sigemptyset(&nsig.sa_mask); nsig.sa_flags = SA_RESTART; (void) sigaction(SIGCONT, &nsig, (struct sigaction *)0); } #else sigset(SIGCONT, SIG_DFL); #endif #endif /* * Strip off path name of this command for use in messages */ if ((program = strrchr(argv[0], '/')) != NULL) { program++; } else { program = argv[0]; } /* Close all file descriptors except stdin, stdout & stderr */ closefrom(STDERR_FILENO + 1); /* * Get group id for mail, exit if none exists */ if ((grpptr = getgrnam("mail")) == NULL) { errmsg(E_GROUP, ""); exit(1); } else { mailgrp = grpptr->gr_gid; } /* * Save the *id for later use. */ my_uid = getuid(); my_gid = getgid(); my_euid = geteuid(); my_egid = getegid(); /* * What command (rmail or mail)? */ if (strcmp(program, "rmail") == SAME) { ismail = FALSE; } /* * Parse the command line and adjust argc and argv * to compensate for any options */ i = parse(argc, argv); argv += (i - 1); argc -= (i - 1); /* block a potential security hole */ if (flgT && (my_euid != 0)) { setgid(my_gid); Tout(pn, "Setgid unset\n"); } if (debug == 0) { /* If not set as an invocation option, check for system-wide */ /* global flag */ char *xp = xgetenv("DEBUG"); if (xp != (char *)NULL) { debug = atoi(xp); if (debug < 0) { /* Keep trace file even if successful */ keepdbgfile = -1; debug = -debug; } } } if (debug > 0) { strcpy(dbgfname, "/tmp/MLDBGXXXXXX"); if ((tmpfd = mkstemp(dbgfname)) == -1) { fprintf(stderr, "%s: can't open debugging file '%s'\n", program, dbgfname); exit(13); } if ((dbgfp = fdopen(tmpfd, "w")) == (FILE *)NULL) { fprintf(stderr, "%s: can't open debugging file '%s'\n", program, dbgfname); (void) close(tmpfd); exit(13); } setbuf(dbgfp, NULL); fprintf(dbgfp, "main(): debugging level == %d\n", debug); fprintf(dbgfp, "main(): trace file ='%s': kept %s\n", dbgfname, ((keepdbgfile < 0) ? "on success or failure." : "only on failure.")); } if (!ismail && (goerr > 0 || !i)) { Dout(pn, 11, "!ismail, goerr=%d, i=%d\n", goerr, i); if (goerr > 0) { errmsg(E_SYNTAX, "Usage: rmail [-wt] person(s)"); } if (!i) { errmsg(E_SYNTAX, "At least one user must be specified"); } Dout(pn, 11, "exiting!\n"); done(0); } umsave = umask(7); uname(&utsn); if ((p = xgetenv("CLUSTER")) != (char *)NULL) { /* * We are not who we appear... */ thissys = p; } else { thissys = utsn.nodename; } Dout(pn, 11, "thissys = '%s', uname = '%s'\n", thissys, utsn.nodename); failsafe = xgetenv("FAILSAFE"); if (failsafe) Dout(pn, 11, "failsafe processing enabled to %s\n", failsafe); /* * Use environment variables */ home = getenv("HOME"); if (!home || !*home) { home = "."; } my_name[0] = '\0'; pwd = getpwuid(my_uid); if (pwd) (void) strlcpy(my_name, pwd->pw_name, sizeof (my_name)); /* If root, use LOGNAME if set */ if (my_uid == 0) { /* If root, use LOGNAME if set */ if (((cptr = getenv("LOGNAME")) != NULL) && (strlen(cptr) != 0)) { (void) strlcpy(my_name, cptr, sizeof (my_name)); } } Dout(pn, 11, "my_name = '%s'\n", my_name); /* * Catch signals for cleanup */ if (setjmp(sjbuf)) { done(0); } for (i = SIGINT; i < SIGCLD; i++) { setsig(i, delete); } setsig(SIGHUP, sig_done); setsig(SIGTERM, sig_done); cksaved(my_name); /* * Rmail is always invoked to send mail */ Dout(pn, 11, "ismail=%d, argc=%d\n", ismail, argc); if (ismail && (argc == 1)) { sending = FALSE; printmail(); } else { sending = TRUE; sendmail(argc, argv); } done(0); } /* * 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 */ #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.6 */ #include "mail.h" /* Routine creates dead.letter */ void mkdead() { static char pn[] = "mkdead"; int aret; char *dotdead = &dead[1]; gid_t egid = getegid(); struct stat st; malf = (FILE *)NULL; /* Make certain that there's something to copy. */ if (!tmpf) return; /* Try to create dead letter in current directory or in home directory */ umask(umsave); setgid(getgid()); if ((aret = legal(dotdead)) && stat(dotdead, &st) == 0) malf = fopen(dotdead, "a"); if ((malf == NULL) || (aret == 0)) { /* try to create in $HOME */ if((hmdead = malloc(strlen(home) + strlen(dead) + 1)) == NULL) { fprintf(stderr, "%s: Can't malloc\n",program); Dout(pn, 0, "Cannot malloc.\n"); goto out; } cat(hmdead, home, dead); if ((aret=legal(hmdead)) && !(stat(hmdead, &st) < 0 && errno == EOVERFLOW)) malf = fopen(hmdead, "a"); if ((malf == NULL) || (aret == 0)) { fprintf(stderr, "%s: Cannot create %s\n", program,dotdead); Dout(pn, 0, "Cannot create %s\n", dotdead); out: fclose(tmpf); error = E_FILE; Dout(pn, 0, "error set to %d\n", error); umask(7); setegid(egid); return; } else { chmod(hmdead, DEADPERM); fprintf(stderr,"%s: Mail saved in %s\n",program,hmdead); } } else { chmod(dotdead, DEADPERM); fprintf(stderr,"%s: Mail saved in %s\n",program,dotdead); } /* Copy letter into dead letter box */ umask(7); aret = fseek(tmpf,0L,0); if (aret) errmsg(E_DEAD,""); if (!copystream(tmpf, malf)) errmsg(E_DEAD,""); fclose(malf); setegid(egid); } void savdead() { static char pn[] = "savdead"; setsig(SIGINT, saveint); dflag = 2; /* do not send back letter on interrupt */ Dout(pn, 0, "dflag set to 2\n"); if (!error) { error = E_REMOTE; Dout(pn, 0, "error set to %d\n", error); } maxerr = error; Dout(pn, 0, "maxerr set to %d\n", maxerr); } /* * 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 */ #include "mail.h" /* * Map mail(1) error into MTA reason-codes for negative delivery notification. */ static char *MTAerrors[] = { "", /* 1 */ "Invalid Address Specification", /* 2 */ "Ambiguous Originator/Recipient Name", /* 3 */ "Message Transfer Agent Congestion", /* 4 */ "Loop Detection", /* 5 */ "Unavailable User Agent", /* 6 */ "Expired Maximum Time", /* 7 */ "Unsupported Encoded Information Types", /* 8 */ "Prohibited Conversion", /* 9 */ "Impractical Conversion", /* 10 */ "Invalid Parameters", /* 11 */ "Transfer Failure", /* 12 */ "Inability To Transfer", /* 13 */ "Conversion Not Performed", /* 14 */ "Deferred Delivery Not Available", /* 15 */ "Too many Recipients", /* 16 */ "Mail Too Large For Destination To Receive" }; void mta_ercode(outfile) FILE *outfile; { register int mtacode; switch (error) { case E_FROM: /* too many From lines */ mtacode = 1; break; case E_SNDR: /* invalid sender */ case E_USER: /* invalid user */ mtacode = 2; break; case E_FRWL: /* forwarding loop */ case E_UNBND: /* Unbounded forwarding */ mtacode = 4; break; case 23: /* disallowed from sending binary to remote */ mtacode = 7; break; case E_SYNTAX: /* syntax error */ default: mtacode = 10; break; case E_SURG: /* surrogate command failed - rc != 0 || 99 */ mtacode = 11; break; case E_REMOTE: /* unknown remote */ case E_FILE: /* file error */ case E_FRWD: /* cannot forward */ case E_PERM: /* bad permissions */ case E_TMP: /* temporary file problem */ case E_DEAD: /* Cannot create dead.letter */ case E_LOCK: /* cannot create lock file */ case E_GROUP: /* no group id of 'mail' */ case E_MEM: /* malloc failure */ case E_FORK: /* could not fork */ case E_PIPE: /* could not pipe */ case E_OWNR: /* invoker does not own mailfile */ case E_DENY: /* permission denied by mailsurr file */ mtacode = 12; break; case E_MBOX: /* mbox problem */ mtacode = 12; if (sav_errno != EFBIG) { break; } /* Note drop-thru... */ case E_SPACE: /* no space */ mtacode = 16; break; } fprintf(outfile, "%.2d %s\n", mtacode, MTAerrors[mtacode]); } /* * 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 */ #include "mail.h" /* NAME new_reciplist - initialize a recipient list SYNOPSIS new_reciplist (reciplist *list) DESCRIPTION Initialize a recipient list to have no recipients. */ void new_reciplist (plist) reciplist *plist; { static char pn[] = "new_reciplist"; Dout(pn, 0, "entered\n"); plist->recip_list.next = 0; plist->recip_list.name = 0; plist->last_recip = &plist->recip_list; } /* * 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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" /* Parse the command line. Return index of first non-option field (i.e. user) */ int parse(int argc, char **argv) { int c; char *tmailsurr; static char pn[] = "parse"; /* "mail +" means to print in reverse order and is equivalent to "mail -r" */ if ((argc > 1) && (argv[1][0] == '+')) { if (ismail) { argv[1] = "-r"; } else { goerr++; } } while ((c = getopt(argc, argv, "m:f:x:shrpPqeEdtT:w")) != EOF) { switch(c) { /* Set debugging level... */ case 'x': debug = atoi(optarg); orig_dbglvl = debug; if (debug < 0) { /* Keep trace file even if successful */ keepdbgfile = -1; debug = -debug; } break; /* for backwards compatability with mailx... */ case 's': /* ignore this option */ break; /* * Deliver directly to a mailbox. Do Not go to sendmail */ case 'd': deliverflag = TRUE; break; /* do not print mail */ case 'e': if (ismail) { flge = 1; } else { goerr++; } optcnt++; break; /* do not print mail */ case 'E': if (ismail) { flgE = 1; } else { goerr++; } optcnt++; break; /* * use alternate file as mailfile, when reading mail * use this from user when sending mail. */ case 'f': flgf = 1; fromflag = TRUE; mailfile = optarg; strncpy(from_user, optarg, sizeof (from_user)); from_user[sizeof (from_user) - 1] = '\0'; optcnt++; break; /* Print headers first */ case 'h': if (ismail) { flgh = 1; } else { goerr++; } optcnt++; break; /* print without prompting */ case 'p': if (ismail) { flgp++; } else { goerr++; } optcnt++; break; /* override selective display default setting when reading mail... */ case 'P': if (ismail) { flgP++; } optcnt++; break; /* terminate on deletes */ case 'q': if (ismail) { delflg = 0; } else { goerr++; } optcnt++; break; /* print by first in, first out order */ case 'r': if (ismail) { flgr = 1; } else { goerr++; } optcnt++; break; /* add To: line to letters */ case 't': flgt = 1; optcnt++; break; /* don't wait on sends */ case 'w': flgw = 1; break; /* set message-type: */ case 'm': msgtype = optarg; if (msgtype[0] == '\0' || msgtype[0] == '-') { goerr++; } else { flgm = 1; } break; /* bad option */ case '?': goerr++; break; } } if (argc == optind) { if (flgm) { errmsg(E_SYNTAX, "-m option used but no recipient(s) specified."); goerr++; } if (flgt) { errmsg(E_SYNTAX, "-t option used but no recipient(s) specified."); goerr++; } if (flgw) { errmsg(E_SYNTAX, "-w option used but no recipient(s) specified."); goerr++; } if (flgf) { if (mailfile[0] == '-') { errmsg(E_SYNTAX, "Files names must not begin with '-'"); done(0); } if (!ismail) goerr++; } } if (ismail && (goerr > 0)) { errmsg(E_SYNTAX,"Usage: [-ehpPqr] [-f file] [-x debuglevel]"); (void) fprintf (stderr, "or\t[-tw] [-m message_type] [-T file] [-x debuglevel] persons\n"); (void) fprintf (stderr, "or\t[-x debuglevel]\n"); done(0); } return (optind); } /* * 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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" /* * If any H_AFWDFROM lines in msg, decide where to put them. * Returns : * -1 ==> No H_AFWDFROM lines to be printed. * > 0 ==> Header line type after (before) which to place H_AFWDFROM * lines and H_AFWDCNT */ int pckaffspot(void) { static char pn[] = "pckaffspot"; int rc; if (hdrlines[H_AFWDFROM].head == (struct hdrs *)NULL) { rc = -1; } else if (orig_aff) { rc = H_AFWDFROM; } else if (fnuhdrtype == H_RVERS) { if (hdrlines[H_EOH].head != (struct hdrs *)NULL) { if (hdrlines[H_DATE].head != (struct hdrs *)NULL) { rc = H_DATE; } else { rc = H_EOH; } } } else if ((fnuhdrtype == H_MVERS) && (hdrlines[H_EOH].head != (struct hdrs *)NULL)) { rc = H_EOH; } else { rc = H_CTYPE; } Dout(pn, 3, "'%s'\n", (rc == -1 ? "No Auto-Forward-From lines" : header[rc].tag)); return (rc); } /* * 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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" /* * If any H_RECEIVED lines in msg, decide where to put them. * Returns : * -1 ==> No H_RECEIVED lines to be printed. * > 0 ==> Header line type after (before) which to place H_RECEIVED lines */ int pckrcvspot(void) { static char pn[] = "pckrcvspot"; int rc; if (hdrlines[H_RECEIVED].head == (struct hdrs *)NULL) { rc = -1; } else if (orig_rcv) { rc = H_RECEIVED; } else if (orig_aff) { rc = H_AFWDFROM; } else if (fnuhdrtype == H_RVERS) { if (hdrlines[H_EOH].head != (struct hdrs *)NULL) { if (hdrlines[H_DATE].head != (struct hdrs *)NULL) { rc = H_DATE; } else { rc = H_EOH; } } } else if ((fnuhdrtype == H_MVERS) && (hdrlines[H_EOH].head != (struct hdrs *)NULL)) { rc = H_EOH; } else { rc = H_CTYPE; } Dout(pn, 3, "'%s'\n", (rc == -1 ? "No Received: lines": header[rc].tag)); return (rc); } /* * 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 */ #include "mail.h" /* * pickFrom (line) - scans line, ASSUMED TO BE of the form * [>]From [remote from ] * and fills fromU and fromS global strings appropriately. */ void pickFrom (lineptr) register char *lineptr; { register char *p; static char rf[] = "remote from "; int rfl; if (*lineptr == '>') lineptr++; lineptr += 5; for (p = fromU; *lineptr; lineptr++) { if (isspace (*lineptr)) break; *p++ = *lineptr; } *p = '\0'; rfl = strlen (rf); while (*lineptr && strncmp (lineptr, rf, rfl)) lineptr++; if (*lineptr == '\0') { fromS[0] = 0; } else { lineptr += rfl; for (p = fromS; *lineptr; lineptr++) { if (isspace (*lineptr)) break; *p++ = *lineptr; } *p = '\0'; } } /* * 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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" int dowait(pid_t pidval) { pid_t w; int status; void (*istat)(), (*qstat)(); /* Parent temporarily ignores signals so it will remain around for command to finish */ istat = signal(SIGINT, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); while ((w = wait(&status)) != pidval && w != CERROR); if (w == CERROR) { status = -errno; signal(SIGINT, istat); signal(SIGQUIT, qstat); return (status); } signal(SIGINT, istat); signal(SIGQUIT, qstat); status = ((status>>8)&0xFF); /* extract 8 high order bits */ return (status); } /* invoke shell to execute command waiting for command to terminate s -> command string return: status -> command exit status */ int systm(char *s) { pid_t pid; /* Spawn the shell to execute command, however, since the mail command runs setgid mode reset the effective group id to the real group id so that the command does not acquire any special privileges */ if ((pid = fork()) == CHILD) { setuid(my_uid); setgid(my_gid); #ifdef SVR3 execl("/bin/sh", "sh", "-c", s, (char*)NULL); #else execl("/usr/bin/sh", "sh", "-c", s, (char*)NULL); #endif exit(127); } return (dowait(pid)); } /* * 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 */ #include "mail.h" /* * Remove an entry from its linked list and free any malloc'd memory.. */ void poplist (hdrtype, where) register int hdrtype; register int where; { struct hdrs *hdr2rm, *cont2rm, *nextcont; /* Remove first/last entry from list */ hdr2rm = (where == HEAD ? hdrlines[hdrtype].head : hdrlines[hdrtype].tail); if (hdr2rm == (struct hdrs *)NULL) { return; } if (where == HEAD) { if (hdr2rm->next == (struct hdrs *)NULL) { /* Only 1 entry in list */ hdrlines[hdrtype].head = hdrlines[hdrtype].tail = (struct hdrs *)NULL; } else { hdrlines[hdrtype].head = hdr2rm->next; hdr2rm->next->prev = (struct hdrs *)NULL; } } else { if (hdr2rm->prev == (struct hdrs *)NULL) { /* Only 1 entry in list */ hdrlines[hdrtype].head = hdrlines[hdrtype].tail = (struct hdrs *)NULL; } else { hdrlines[hdrtype].tail = hdr2rm->prev; hdr2rm->prev->next = (struct hdrs *)NULL; } } /* Keep track of total bytes added to message due to */ /* selected lines in case non-delivery */ /* notification needs to be sent. (See also copylet()) */ if (hdrtype == H_AFWDFROM) { affbytecnt -= (strlen(header[H_AFWDFROM].tag) + strlen(hdr2rm->value) + 2); affcnt--; } if (hdrtype == H_RECEIVED) { rcvbytecnt -= (strlen(header[H_RECEIVED].tag) + strlen(hdr2rm->value) + 2); } cont2rm = hdr2rm->cont; while (cont2rm != (struct hdrs *)NULL) { nextcont = cont2rm->next; if (hdrtype == H_AFWDFROM) { affbytecnt -= (strlen(cont2rm->value) + 1); affcnt--; } if (hdrtype == H_RECEIVED) { rcvbytecnt -= (strlen(cont2rm->value) + 1); } free ((char *)cont2rm); cont2rm = nextcont; } free ((char *)hdr2rm); } /* * 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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" int printhdr(int type, int hdrtype, struct hdrs *hptr, FILE *fp) { char buf[1024]; int n; struct hdrs *contptr; if (hptr == NULL) return (0); if (sel_disp(type, hdrtype, header[hdrtype].tag) < 0) { return (0); } (void) snprintf(buf, sizeof (buf), "%s %s\n", header[hdrtype].tag, hptr->value); n = strlen(buf); if (fwrite(buf, 1, n, fp) != n) { sav_errno = errno; return (-1); } /* Print continuation lines, if any... */ contptr = hptr; while (contptr->cont != (struct hdrs *)NULL) { contptr = contptr->cont; (void) snprintf(buf, sizeof (buf), "%s\n", contptr->value); n = strlen(buf); if (fwrite(buf, 1, n, fp) != n) { sav_errno = errno; return (-1); } } return (0); } /* * 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. */ #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(); } } /* * 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 */ #include "mail.h" /* * link new entry into list of headerlines encountered of this type. * If contflg == TRUE, link this line to the end of the continuation lines * for the headerline specified (head or tail of type hdrtype). */ void pushlist(int hdrtype, int where, char *s, int contflg) { static char pn[] = "pushlist"; char *p; struct hdrs *nhp, *ohp, *nextcont; /* Keep track of total bytes added to message due to */ /* certain lines in case non-delivery */ /* notification needs to be sent. (See also copylet()) */ if (hdrtype == H_AFWDFROM) { affbytecnt += (strlen(s) + ((contflg == TRUE) ? 1 : (strlen(header[H_AFWDFROM].tag) + 2)) ); if (contflg == FALSE) { affcnt++; } } if (hdrtype == H_RECEIVED) { rcvbytecnt += (strlen(s) + ((contflg == TRUE) ? 1 : (strlen(header[H_RECEIVED].tag) + 2)) ); } if ((p = malloc(sizeof(struct hdrs))) == (char *)NULL) { errmsg(E_MEM,"malloc failed in pushlist()"); done(1); } memset(p, 0, sizeof(struct hdrs)); ohp = (where == HEAD ? hdrlines[hdrtype].head : hdrlines[hdrtype].tail); nhp = (struct hdrs *)p; (void) strlcpy(nhp->value, s, sizeof (nhp->value)); Dout(pn, 0, "hdrtype = %d/%s, contflg = %d, saved value = '%s'\n", hdrtype, header[hdrtype].tag, contflg, s); if (contflg) { if (ohp == (struct hdrs *)NULL) { /* This shouldn't happen.....? */ /* No headline of this type found so far. How */ /* did we think this is a continuation of something? */ if (debug > 0) { Dout(pn, 0, "H_CONT with no hdr yet\n"); abort(); } /* Throw it on the floor... (!) */ /**/ /* Subtract anything that might have been added above */ if (hdrtype == H_AFWDFROM) { affbytecnt -= (strlen(s) + ((contflg == TRUE) ? 1 : (strlen(header[H_AFWDFROM].tag) + 2)) ); } if (hdrtype == H_RECEIVED) { rcvbytecnt -= (strlen(s) + ((contflg == TRUE) ? 1 : (strlen(header[H_RECEIVED].tag) + 2)) ); } free ((char *)nhp); return; } /* Since we ONLY walk down 'cont' chains, */ /* we only need forward links */ nextcont = ohp; while (nextcont->cont != (struct hdrs *)NULL) { nextcont = nextcont->cont; } /* Add this one to end of list... */ nextcont->cont = nhp; return; } /* link value from this header line to end of list for */ /* all header lines of the same type */ if (ohp == (struct hdrs *)NULL) { /* Empty list so far. New element goes first */ hdrlines[hdrtype].head = hdrlines[hdrtype].tail = nhp; } else { if (where == HEAD) { /* Add new element to head of list */ nhp->next = ohp; hdrlines[hdrtype].head = ohp->prev = nhp; } else { /* Add new element to tail of list */ nhp->prev = ohp; hdrlines[hdrtype].tail = ohp->next = nhp; } } } /* * 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 */ #include "mail.h" /* * Save info on each header line for possible generation * of MTA positive or negative delivery notification */ void savehdrs(s, hdrtype) char *s; int hdrtype; { char *q; int rf; char delim = ':'; char tbuf[HDRSIZ]; static int last_hdrtype = -1; if (hdrtype > H_CONT) { return; } if (hdrtype == H_CONT) { trimnl(s); pushlist(last_hdrtype, TAIL, s, TRUE); return; } last_hdrtype = hdrtype; if ((hdrtype == H_FROM) || (hdrtype == H_FROM1)) { delim = ' '; } else { if (fnuhdrtype == 0) { /* Save type of first non-UNIX header line */ fnuhdrtype = hdrtype; } } switch (hdrtype) { case H_FROM1: /* If first ">From " line, check for '...remote from...' */ if (hdrlines[H_FROM1].head == (struct hdrs *)NULL) { if ((rf = substr(s, " remote from ")) >= 0) { trimnl(s + rf); (void) snprintf(tbuf, sizeof (tbuf), "from %s by %s%s; %s", s+rf+13, thissys, maildomain(), RFC822datestring); pushlist(H_RECEIVED, HEAD, tbuf, FALSE); } } break; /* Remember that these header line type were in orig. msg. */ case H_AFWDFROM: orig_aff++; break; case H_RECEIVED: orig_rcv++; break; case H_TCOPY: orig_tcopy++; break; } q = strchr(s, delim) + 1; q = skipspace(q); trimnl(q); if ((hdrtype == H_UAID) || (hdrtype == H_MTSID)) { /* Check for enclosing '<' & '>', and remove if found */ /* gendeliv() will replace them if necessary */ if ((*q == '<') && (*(q+strlen(q)-1) == '>')) { q++; *(q+strlen(q)-1) = '\0'; } } pushlist(hdrtype, TAIL, q, FALSE); } /* * 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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" /* * If in default display mode from printmail(), selectively output * header lines. Any recognized header lines will have flag stored in * header[] structure. Other header lines which should be displayed in * the default output mode will be listed in the seldisp[] array. * This can all be overridden via the 'P' command at the ? prompt. */ int sel_disp(int type, int hdrtype, char *s) { static char pn[] = "sel_disp"; char *p; static int sav_lastrc = 0; int i, rc = 0; if (sending || Pflg || (type != TTY)) { return (0); } switch (hdrtype) { case H_CONT: rc = sav_lastrc; break; case H_NAMEVALUE: for (i=0,p=seldisp[i]; p; p=seldisp[++i]) { if (casncmp(s, p, strlen(p)) == 0) { break; } } if (p == (char *)NULL) { rc = -1; } break; default: if (header[hdrtype].default_display == FALSE) { rc = -1; break; } } Dout(pn, 2, "type = %d, hdrtype = %d/'%s', rc = %d\n", type, hdrtype, header[hdrtype].tag, rc); sav_lastrc = rc; /* In case next one is H_CONT... */ return (rc); } /* * 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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ #include "mail.h" /* * NAME * sendlist - send copy to specified users * * SYNOPSIS * int sendlist(reciplist *list, int letnum, int level) * * DESCRIPTION * sendlist() will traverse the current recipient list and * send a copy of the given letter to each user specified, * invoking send() to do the sending. It returns * 1 if the sending fails, 0 otherwise. */ /* * mailx and mailtool read the SENDMAIL from an environment, since few * people use /bin/mail as their user agent and since /bin/mail is often * called as root or made setuid it's safer to leave this hardwired. */ static char *sendmail_prog = SENDMAIL; static void notifybiff(char *); int sendlist(reciplist *list, int letnum, int level) { recip *to; int rc = 0; FILE *fp; int nargs = 4; /* "sendmail", "-oi", "--", .. NULL */ char **argv; char **p; /* Deliver mail directly to a mailbox */ if (deliverflag) { /* * Note failure to deliver to any one of the recipients * should be considered a failure, so that the user * get's an indication of that failure. */ for (to = &(list->recip_list); to; to = to->next) { if (to->name) if (!send_mbox(to->name, letnum)) rc = 1; } return (rc); } /* * build argv list, allowing for arbitrarily long deliver lists * and then hand the message off to sendmail */ if (!ismail) nargs += 2; /* for "-f", "Rpath" */ for (to = &(list->recip_list); to; to = to->next) if (to->name) nargs++; argv = malloc(nargs * sizeof (char *)); if (argv == NULL) return (1); p = argv; *p++ = sendmail_prog; /* If we're rmail add "-f", "Rpath" to the the command line */ if (!ismail) { *p++ = "-f"; *p++ = Rpath; } *p++ = "-oi"; *p++ = "--"; /* extra protection: end of argument list */ for (to = &(list->recip_list); to; to = to->next) if (to->name) *p++ = to->name; *p = NULL; fp = popenvp(sendmail_prog, argv, "w", 0); free(argv); if (fp == NULL) return (1); copylet(letnum, fp, ORDINARY); rc = pclosevp(fp); if (!rc) return (0); else return (1); } /* * send_mbox(user, letnum) Sends the letter specified by letnum to the * "user"'s mailbox. It returns 1 if the sending fails; * 0 on success. */ int send_mbox(char *mbox, int letnum) { char file[PATH_MAX]; char biffmsg[PATH_MAX]; int mbfd; FILE *malf; int rc; uid_t useruid, saved_uid; void (*istat)(), (*qstat)(), (*hstat)(); if (!islocal(mbox, &useruid)) return (1); (void) strlcpy(file, maildir, sizeof (file)); if (strlcat(file, mbox, sizeof (file)) >= sizeof (file)) { rc = FALSE; goto done; } /* * We need to setgid and seteuid here since the users's mail box * might be NFS mounted and since root can't write across NFS. * Note this won't work with Secure NFS/RPC's. Since delivering to * NFS mounted directories isn't really supported that's OK for now. */ setgid(mailgrp); saved_uid = geteuid(); seteuid(useruid); lock(mbox); /* ignore signals */ istat = signal(SIGINT, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); hstat = signal(SIGHUP, SIG_IGN); /* now access mail box */ mbfd = accessmf(file); if (mbfd == -1) { /* mail box access failed, bail out */ unlock(); rc = FALSE; sav_errno = EACCES; goto done; } else { /* mail box is ok, now do append */ if ((malf = fdopen(mbfd, "a")) != NULL) { (void) snprintf(biffmsg, sizeof (biffmsg), "%s@%d\n", mbox, ftell(malf)); rc = copylet(letnum, malf, ORDINARY); fclose(malf); } } if (rc == FALSE) fprintf(stderr, "%s: Cannot append to %s\n", program, file); else notifybiff(biffmsg); done: /* restore signal */ (void) signal(SIGINT, istat); (void) signal(SIGQUIT, qstat); (void) signal(SIGHUP, hstat); unlock(); seteuid(saved_uid); return (rc); } #include #include static void notifybiff(char *msg) { static struct sockaddr_in addr; static int f = -1; if (addr.sin_family == 0) { addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_LOOPBACK; addr.sin_port = htons(IPPORT_BIFFUDP); } if (f < 0) f = socket(AF_INET, SOCK_DGRAM, 0); sendto(f, msg, strlen(msg)+1, 0, (struct sockaddr *)&addr, sizeof (addr)); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (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) 1989, 2010, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "mail.h" #include /* * Send mail - High level sending routine */ void sendmail(int argc, char **argv) { char **args; char *tp, *zp; char buf[2048], last1c; FILE *input; struct stat64 sbuf; int aret; int i, n; int oldn = 1; int ttyf = 0; int pushrest = 0; int hdrtyp = 0; int ctf = FALSE; int binflg = 0; long count = 0L; struct tm *bp; struct hdrs *hptr; static char pn[] = "sendmail"; reciplist list; Dout(pn, 0, "entered\n"); new_reciplist(&list); for (i = 1; i < argc; ++i) { if (argv[i][0] == '-') { if (argv[i][1] == '\0') { errmsg(E_SYNTAX, "Hyphens MAY NOT be followed by spaces"); } if (i > 1) { errmsg(E_SYNTAX, "Options MUST PRECEDE persons"); } done(0); } /* * Ensure no NULL names in list */ if (argv[i][0] == '\0' || argv[i][strlen(argv[i])-1] == '!') { errmsg(E_SYNTAX, "Null names are not allowed"); done(0); } /* Don't check for duplication */ add_recip(&list, argv[i], FALSE); } mktmp(); /* * Format time */ time(&iop); bp = localtime(&iop); tp = asctime(bp); zp = tzname[bp->tm_isdst]; sprintf(datestring, "%.16s %.3s %.5s", tp, zp, tp+20); trimnl(datestring); /* asctime: Fri Sep 30 00:00:00 1986\n */ /* 0123456789012345678901234 */ /* RFCtime: Fri, 28 Jul 89 10:30 EDT */ sprintf(RFC822datestring, "%.3s, %.2s %.3s %.4s %.5s %.3s", tp, tp+8, tp+4, tp+20, tp+11, zp); /* * Write out the from line header for the letter */ if (fromflag && deliverflag && from_user[0] != '\0') { (void) snprintf(buf, sizeof (buf), "%s%s %s\n", header[H_FROM].tag, from_user, datestring); } else { (void) snprintf(buf, sizeof (buf), "%s%s %s\n", header[H_FROM].tag, my_name, datestring); } if (!wtmpf(buf, strlen(buf))) { done(0); } savehdrs(buf, H_FROM); /* * Copy to list in mail entry? */ if (flgt == 1 && argc > 1) { aret = argc; args = argv; while (--aret > 0) { (void) snprintf(buf, sizeof (buf), "%s %s\n", header[H_TO].tag, *++args); if (!wtmpf(buf, strlen(buf))) { done(0); } savehdrs(buf, H_TO); } } flgf = 1; /* reset when first read of message body succeeds */ /* * Read mail message, allowing for lines of infinite * length. This is tricky, have to watch for newlines. */ saveint = setsig(SIGINT, savdead); last1c = ' '; /* anything other than newline */ ttyf = isatty(fileno(stdin)); pushrest = 0; /* * scan header & save relevant info. */ (void) strlcpy(fromU, my_name, sizeof (fromU)); fromS[0] = 0; /* set up for >From scan */ input = stdin; /* * Fifofs cannot handle if the inode number crosses * 32-bit limit. This results in overflow, if the * input steam is a pipe. Using 64-bit interface to * take care of that. */ if (fstat64(fileno(input), &sbuf) == 0) { /* Also care if we could not handle large mail. */ if ((sbuf.st_size > MAXOFF_T) || (sbuf.st_blocks > LONG_MAX)) { fprintf(stderr, "%s: stdin: %s\n", program, strerror(EOVERFLOW)); exit(1); } } while ((n = getaline(line, sizeof (line), stdin)) > 0) { last1c = line[n-1]; if (pushrest) { if (!wtmpf(line, n)) { done(0); } pushrest = (last1c != '\n'); continue; } pushrest = (last1c != '\n'); if ((hdrtyp = isheader(line, &ctf)) == FALSE) { break; } flgf = 0; switch (hdrtyp) { case H_RVERS: /* Are we dealing with a delivery report? */ /* dflag = 9 ==> do not return on failure */ dflag = 9; Dout(pn, 0, "dflag = 9\n"); break; case H_FROM: if (!wtmpf(">", 1)) { done(0); } /* note dropthru */ hdrtyp = H_FROM1; case H_FROM1: if (substr(line, "forwarded by") > -1) { break; } pickFrom(line); if (Rpath[0] != '\0') { strcat(Rpath, "!"); } (void) strlcat(Rpath, fromS, sizeof (Rpath)); n = 0; /* don't copy remote from's into mesg. */ break; case H_MIMEVERS: case H_CLEN: case H_CTYPE: /* suppress it: only generated if needed */ n = 0; /* suppress */ break; case H_TCOPY: /* Write out placeholder for later */ (void) snprintf(buf, sizeof (buf), "%s \n", header[H_TCOPY].tag); if (!wtmpf(buf, strlen(buf))) { done(0); } n = 0; /* suppress */ break; case H_MTYPE: if (flgm) { /* suppress if message-type argument */ n = 0; } break; case H_CONT: if (oldn == 0) { /* suppress continuation line also */ n = 0; } break; } oldn = n; /* remember if this line was suppressed */ if (n && !wtmpf(line, n)) { done(0); } if (!n) savehdrs(line, hdrtyp); } if (Rpath[0] != '\0') { strcat(Rpath, "!"); } (void) strlcat(Rpath, fromU, sizeof (Rpath)); /* push out message type if so requested */ if (flgm) { /* message-type */ snprintf(buf, sizeof (buf), "%s%s\n", header[H_MTYPE].tag, msgtype); if (!wtmpf(buf, strlen(buf))) { done(0); } } memcpy(buf, line, n); if (n == 0 || (ttyf && !strncmp(buf, ".\n", 2))) { if (flgf) { /* no input */ return; } else { /* * no content: put mime-version, content-type * and -length only if explicitly present. * Write out 'place-holders' only. (see below....) */ if ((hptr = hdrlines[H_MIMEVERS].head) != (struct hdrs *)NULL) { (void) snprintf(line, sizeof (line), "%s \n", header[H_MIMEVERS].tag); if (!wtmpf(line, strlen(line))) { done(0); } } if ((hptr = hdrlines[H_CTYPE].head) != (struct hdrs *)NULL) { (void) snprintf(line, sizeof (line), "%s \n", header[H_CTYPE].tag); if (!wtmpf(line, strlen(line))) { done(0); } } if ((hptr = hdrlines[H_CLEN].head) != (struct hdrs *)NULL) { (void) snprintf(line, sizeof (line), "%s \n", header[H_CLEN].tag); if (!wtmpf(line, strlen(line))) { done(0); } } goto wrapsend; } } if (n == 1 && last1c == '\n') { /* blank line -- suppress */ n = getaline(buf, sizeof (buf), stdin); if (n == 0 || (ttyf && !strncmp(buf, ".\n", 2))) { /* * no content: put mime-version, content-type * and -length only if explicitly present. * Write out 'place-holders' only. (see below....) */ if ((hptr = hdrlines[H_MIMEVERS].head) != (struct hdrs *)NULL) { (void) snprintf(line, sizeof (line), "%s \n", header[H_MIMEVERS].tag); if (!wtmpf(line, strlen(line))) { done(0); } } if ((hptr = hdrlines[H_CTYPE].head) != (struct hdrs *)NULL) { (void) snprintf(line, sizeof (line), "%s \n", header[H_CTYPE].tag); if (!wtmpf(line, strlen(line))) { done(0); } } if ((hptr = hdrlines[H_CLEN].head) != (struct hdrs *)NULL) { (void) snprintf(line, sizeof (line), "%s \n", header[H_CLEN].tag); if (!wtmpf(line, strlen(line))) { done(0); } } goto wrapsend; } } if (debug > 0) { buf[n] = '\0'; Dout(pn, 0, "header scan complete, readahead %d = \"%s\"\n", n, buf); } /* * Write out H_MIMEVERS, H_CTYPE & H_CLEN lines. These are used only as * placeholders in the tmp file. When the 'real' message is sent, * the proper values will be put out by copylet(). */ (void) snprintf(line, sizeof (line), "%s \n", header[H_MIMEVERS].tag); if (!wtmpf(line, strlen(line))) { done(0); } if (hdrlines[H_MIMEVERS].head == (struct hdrs *)NULL) { savehdrs(line, H_MIMEVERS); } (void) snprintf(line, sizeof (line), "%s \n", header[H_CTYPE].tag); if (!wtmpf(line, strlen(line))) { done(0); } if (hdrlines[H_CTYPE].head == (struct hdrs *)NULL) { savehdrs(line, H_CTYPE); } (void) snprintf(line, sizeof (line), "%s \n", header[H_CLEN].tag); if (!wtmpf(line, strlen(line))) { done(0); } if (hdrlines[H_CLEN].head == (struct hdrs *)NULL) { savehdrs(line, H_CLEN); } /* and a blank line */ if (!wtmpf("\n", 1)) { done(0); } Dout(pn, 0, "header out completed\n"); pushrest = 0; count = 0L; /* * Are we returning mail from a delivery failure of an old-style * (SVR3.1 or SVR3.0) rmail? If so, we won't return THIS on failure * [This line should occur as the FIRST non-blank non-header line] */ if (!strncmp("***** UNDELIVERABLE MAIL sent to", buf, 32)) { dflag = 9; /* 9 says do not return on failure */ Dout(pn, 0, "found old-style UNDELIVERABLE line. dflag = 9\n"); } /* scan body of message */ while (n > 0) { if (ttyf && !strcmp(buf, ".\n")) break; if (!binflg) { binflg = !istext((unsigned char *)buf, n); } if (!wtmpf(buf, n)) { done(0); } count += n; n = ttyf ? getaline(buf, sizeof (buf), stdin) : fread(buf, 1, sizeof (buf), stdin); } setsig(SIGINT, saveint); wrapsend: /* * In order to use some of the subroutines that are used to * read mail, the let array must be set up */ nlet = 1; let[0].adr = 0; let[1].adr = ftell(tmpf); let[0].text = (binflg == 1 ? FALSE : TRUE); Dout(pn, 0, "body copy complete, count %ld\n", count); /* * Modify value of H_MIMEVERS if necessary. */ if ((hptr = hdrlines[H_MIMEVERS].head) != (struct hdrs *)NULL) { if (strlen(hptr->value) == 0) { (void) strlcpy(hptr->value, "1.0", sizeof (hptr->value)); } } /* * Modify value of H_CTYPE if necessary. */ if ((hptr = hdrlines[H_CTYPE].head) != (struct hdrs *)NULL) { if (strlen(hptr->value) == 0) { (void) strlcpy(hptr->value, "text/plain", sizeof (hptr->value)); } } /* * Set 'place-holder' value of content length to true value */ if ((hptr = hdrlines[H_CLEN].head) != (struct hdrs *)NULL) { (void) snprintf(hptr->value, sizeof (hptr->value), "%ld", count); } if (fclose(tmpf) == EOF) { tmperr(); done(0); } tmpf = doopen(lettmp, "r+", E_TMP); /* Do not send mail on SIGINT */ if (dflag == 2) { done(0); } sendlist(&list, 0, 0); done(0); } /* * 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 */ #include "mail.h" /* Signal reset signals that are not being ignored will be caught by function f i -> signal number f -> signal routine return rc -> former signal */ void (*setsig(i, f))() int i; void (*f)(); { register void (*rc)(); if ((rc = signal(i, SIG_IGN)) != (void (*)()) SIG_IGN) signal(i, f); return(rc); } /* * 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 */ #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.5 */ #include "mail.h" /* If the mailfile still exists (it may have been deleted), time-stamp it; so that our re-writing of mail back to the mailfile does not make shell think that NEW mail has arrived (by having the file times change). */ void stamp() { if ((access(mailfile, A_EXIST) == A_OK) && (utimep->modtime != -1)) if (utime(mailfile, utimep) != A_OK) errmsg(E_FILE,"Cannot time-stamp mailfile"); }