Index: mail/cmd1.c =================================================================== --- mail/cmd1.c (revision 302903) +++ mail/cmd1.c (working copy) @@ -192,7 +192,7 @@ if (mp->m_flag & MBOX) dispc = 'M'; parse(headline, &hl, pbuf); - sprintf(wcount, "%3ld/%-5ld", mp->m_lines, mp->m_size); + sprintf(wcount, "%3ld/%-5ld", mp->m_blines, mp->m_size); subjlen = screenwidth - 50 - strlen(wcount); name = value("show-rcpt") != NULL ? skin(hfield("to", mp)) : nameof(mp, 0); @@ -304,7 +304,7 @@ nlines = 0; if (!page) { for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) - nlines += message[*ip - 1].m_lines; + nlines += message[*ip - 1].m_blines; } if (page || nlines > (*cp ? atoi(cp) : realscreenheight)) { cp = value("PAGER"); Index: mail/cmd2.c =================================================================== --- mail/cmd2.c (revision 302903) +++ mail/cmd2.c (working copy) @@ -133,12 +133,27 @@ int save(void *v) { - char *str = v; + char *str; + str = v; return (save1(str, 1, "save", saveignore)); } /* + * Save a message in a file. Mark the message as saved + * so we can discard when the user quits. Save all fields + * overriding saveignore and saveretain. + */ +int +Save(void *v) +{ + char *str; + + str = v; + return (save1(str, 1, "Save", NULL)); +} + +/* * Copy a message to a file without affected its saved-ness */ int Index: mail/cmd3.c =================================================================== --- mail/cmd3.c (revision 302903) +++ mail/cmd3.c (working copy) @@ -61,7 +61,7 @@ return (1); if ((sh = value("SHELL")) == NULL) sh = _PATH_CSHELL; - (void)run_command(sh, 0, -1, -1, "-c", cmd, NULL); + (void)run_command(sh, 0, 0, -1, "-c", cmd, NULL); (void)signal(SIGINT, sigint); printf("!\n"); return (0); @@ -79,7 +79,7 @@ if ((sh = value("SHELL")) == NULL) sh = _PATH_CSHELL; - (void)run_command(sh, 0, -1, -1, NULL); + (void)run_command(sh, 0, 0, -1, NULL); (void)signal(SIGINT, sigint); printf("\n"); return (0); @@ -497,7 +497,52 @@ } /* - * Sort the passed string vecotor into ascending dictionary + * The unalias command takes a list of aliases + * and discards the remembered groups of users. + */ +int +unalias(void *v) +{ + char **ap; + + for (ap = v; *ap != NULL; ap++) + (void)delgroup(*ap); + return (0); +} + +/* + * Delete the named group alias. Return zero if the group was + * successfully deleted, or -1 if there was no such group. + */ +int +delgroup(const char *name) +{ + struct grouphead *gh, *p; + struct group *g; + int h; + + h = hash(name); + for (gh = groups[h], p = NULL; gh != NULL; p = gh, gh = gh->g_link) + if (strcmp(gh->g_name, name) == 0) { + if (p == NULL) + groups[h] = gh->g_link; + else + p->g_link = gh->g_link; + while (gh->g_list != NULL) { + g = gh->g_list; + gh->g_list = g->ge_link; + free(g->ge_name); + free(g); + } + free(gh->g_name); + free(gh); + return (0); + } + return (-1); +} + +/* + * Sort the passed string vector into ascending dictionary * order. */ void Index: mail/cmdtab.c =================================================================== --- mail/cmdtab.c (revision 302903) +++ mail/cmdtab.c (working copy) @@ -69,6 +69,7 @@ { "page", more, MSGLIST, 0, MMNDEL }, { "More", More, MSGLIST, 0, MMNDEL }, { "Page", More, MSGLIST, 0, MMNDEL }, + { "unalias", unalias, M|RAWLIST, 1, 1000 }, { "unread", unread, MSGLIST, 0, MMNDEL }, { "!", shell, I|STRLIST, 0, 0 }, { "copy", copycmd, M|STRLIST, 0, 0 }, @@ -75,6 +76,7 @@ { "chdir", schdir, M|RAWLIST, 0, 1 }, { "cd", schdir, M|RAWLIST, 0, 1 }, { "save", save, STRLIST, 0, 0 }, + { "Save", Save, STRLIST, 0, 0 }, { "source", source, M|RAWLIST, 1, 1 }, { "set", set, M|RAWLIST, 0, 1000 }, { "shell", dosh, I|NOLIST, 0, 0 }, Index: mail/def.h =================================================================== --- mail/def.h (revision 302899) +++ mail/def.h (working copy) @@ -72,6 +72,7 @@ long m_block; /* block number of this message */ long m_size; /* Bytes in the message */ long m_lines; /* Lines in the message */ + long m_blines; /* Body (non-header) lines */ }; /* Index: mail/edit.c =================================================================== --- mail/edit.c (revision 302899) +++ mail/edit.c (working copy) @@ -109,11 +109,22 @@ mp->m_offset = boffsetof(size); mp->m_size = (long)fsize(fp); mp->m_lines = 0; + mp->m_blines = 0; mp->m_flag |= MODIFY; rewind(fp); while ((c = getc(fp)) != EOF) { - if (c == '\n') + // + // XXX. if you edit a message, we treat + // header lines as body lines in the recount. + // This is because the original message copy + // and the edit reread use different code to + // count the lines, and this one here is + // simple-minded. + // + if (c == '\n') { mp->m_lines++; + mp->m_blines++; + } if (putc(c, otf) == EOF) break; } @@ -180,7 +191,7 @@ nf = NULL; if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NULL) edit = type == 'e' ? _PATH_EX : _PATH_VI; - if (run_command(edit, 0, -1, -1, tempname, NULL) < 0) { + if (run_command(edit, 0, 0, -1, tempname, NULL) < 0) { (void)rm(tempname); goto out; } Index: mail/extern.h =================================================================== --- mail/extern.h (revision 302903) +++ mail/extern.h (working copy) @@ -50,9 +50,9 @@ char *expand(char *); char *getdeadletter(void); char *getname(uid_t); -char *hfield(const char *, struct message *); +char *hfield(const char *, const struct message *); FILE *infix(struct header *, FILE *); -char *ishfield(char *, char *, const char *); +char *ishfield(const char *, char *, const char *); char *name1(struct message *, int); char *nameof(struct message *, int); char *nextword(char *, char *); @@ -61,7 +61,7 @@ FILE *run_editor(FILE *, off_t, int, int); char *salloc(int); char *savestr(char *); -FILE *setinput(struct message *); +FILE *setinput(const struct message *); char *skin(char *); char *skip_comment(char *); char *snarf(char *, int *); @@ -99,6 +99,7 @@ int core(void); int count(struct name *); int deletecmd(void *); +int delgroup(const char *); int delm(int *); int deltype(void *); void demail(void); @@ -141,6 +142,7 @@ void holdsigs(void); int ifcmd(char **); int igcomp(const void *, const void *); +int unalias(void *); int igfield(void *); int ignore1(char **, struct ignoretab *, const char *); int igshow(struct ignoretab *, const char *); @@ -200,6 +202,7 @@ int rm(char *); int run_command(char *, sigset_t *, int, int, ...); int save(void *v); +int Save(void *v); int save1(char *, int, const char *, struct ignoretab *); void savedeadletter(FILE *); int saveigfield(void *); Index: mail/fio.c =================================================================== --- mail/fio.c (revision 302899) +++ mail/fio.c (working copy) @@ -92,6 +92,7 @@ this.m_flag = MUSED|MNEW; this.m_size = 0; this.m_lines = 0; + this.m_blines = 0; this.m_block = 0; this.m_offset = 0; for (;;) { @@ -124,6 +125,7 @@ this.m_flag = MUSED|MNEW; this.m_size = 0; this.m_lines = 0; + this.m_blines = 0; this.m_block = blockof(offset); this.m_offset = boffsetof(offset); inhead = 1; @@ -151,6 +153,17 @@ offset += count; this.m_size += count; this.m_lines++; + if (!inhead) { + int lines_plus_wraps = 1; + int linelen = strlen(linebuf); + + if (linelen > screenwidth) { + lines_plus_wraps = linelen / screenwidth; + if (linelen % screenwidth != 0) + ++lines_plus_wraps; + } + this.m_blines += lines_plus_wraps; + } maybe = linebuf[0] == 0; } } @@ -202,7 +215,7 @@ * passed message pointer. */ FILE * -setinput(struct message *mp) +setinput(const struct message *mp) { (void)fflush(otf); @@ -239,6 +252,7 @@ errx(1, "Message temporary file corrupted"); message[msgCount].m_size = 0; message[msgCount].m_lines = 0; + message[msgCount].m_blines = 0; (void)Fclose(f); } Index: mail/lex.c =================================================================== --- mail/lex.c (revision 302899) +++ mail/lex.c (working copy) @@ -67,7 +67,7 @@ FILE *ibuf; int checkmode, i, fd; struct stat stb; - char isedit = *name != '%' || getuserid(myname) != getuid(); + char isedit = *name != '%' || getuserid(myname) != (int)getuid(); char *who = name[1] ? name + 1 : myname; char tempname[PATHSIZE]; static int shudclob; Index: mail/send.c =================================================================== --- mail/send.c (revision 302899) +++ mail/send.c (working copy) @@ -566,8 +566,12 @@ char buf[BUFSIZ]; int i; time_t now; + mode_t m; - if ((fo = Fopen(name, "a")) == NULL) { + m = umask(077); + fo = Fopen(name, "a"); + (void)umask(m); + if (fo == NULL) { warn("%s", name); return (-1); } Index: mail/util.c =================================================================== --- mail/util.c (revision 302914) +++ mail/util.c (working copy) @@ -130,7 +130,7 @@ * pointer (or NULL if the desired header field is not available). */ char * -hfield(const char *field, struct message *mp) +hfield(const char *field, const struct message *mp) { FILE *ibuf; char linebuf[LINESIZE]; @@ -214,7 +214,7 @@ */ char* -ishfield(char *linebuf, char *colon, const char *field) +ishfield(const char *linebuf, char *colon, const char *field) { char *cp = colon; Index: mail/v7.local.c =================================================================== --- mail/v7.local.c (revision 302911) +++ mail/v7.local.c (working copy) @@ -70,7 +70,12 @@ { int fd; - if (value("keep") != NULL || rm(mailname) < 0) + /* + * Do not remove the spool file, just truncate it to zero + * bytes if possible, since we wouldn't preserve + * owner/permissions otherwise. + */ + if (value("keep") != NULL || truncate(mailname, 0) < 0) if ((fd = open(mailname, O_CREAT | O_TRUNC | O_WRONLY, 0600)) >= 0) (void)close(fd);