📄 mail.c
字号:
#ifndef lint#ifdef sccsstatic char sccsid[] = "@(#)mail.c 1.1 92/07/30 Copyr 1987 Sun Micro";#endif#endif/* * Copyright (c) 1985 by Sun Microsystems, Inc. *//* * Mailtool - Mail subprocess handling */#include <stdio.h>#include <sunwindow/window_hs.h>#include <sys/types.h>#include <sys/stat.h>#include <signal.h>#include <vfork.h>#include <suntool/window.h>#include <suntool/frame.h>#include <suntool/panel.h>#include <suntool/text.h>#include <suntool/scrollbar.h>#include <suntool/selection.h>#include <suntool/selection_svc.h>#include <suntool/selection_attributes.h>#include <suntool/walkmenu.h>#include <suntool/icon.h>/* performance: global cache of getdtablesize() */int dtablesize_cache;#define GETDTABLESIZE() \ (dtablesize_cache?dtablesize_cache:(dtablesize_cache=getdtablesize()))#include "glob.h"#include "tool.h"char *strcpy();static int mt_mailpid; /* pid of mail */static int mt_talking_to_Mail;static FILE *mt_mailin, *mt_mailout; /* input to mail, output from mail */int current_size; /* size of mt_message array allocated */int mt_curmsg; /* number of current message */int mt_maxmsg;int mt_scandir; /* scan direction, forward to start */char *mt_mailbox; /* name of user's mailbox [256] */char *mt_folder; /* name of current folder [256] */char *mt_info; /* info from save, file, etc. [256] */char *line; /* tmp line buffer, used everywhere * [LINE_SIZE] */static char **folder_list; /* pointers to folder names [MAXFOLDERS+2] */static enum mstate { S_NOMAIL, S_MAIL} mt_mstate;struct msg *mt_message; /* [MAXMSGS] */struct msg *mt_delp; /* pointer to linked list of deleted messages */int mt_del_count; /* number of deleted messages */static void mt_set_state(), mt_insert_msg();static Notify_value mt_Mail_died(), mt_broken_pipe();/* * Dynamically allocate all the large arrays for mailtool * so that when we are bound with suntools (using toolmerge) * we don't take up a lot of data space that will not be used * by the other tools merged into suntools. */voidmt_init_mail_storage(){ extern char *calloc(); current_size = 0; mt_message = (struct msg *)(LINT_CAST(calloc(INCR_SIZE, sizeof (struct msg)))); current_size += INCR_SIZE; mt_delp = NULL; mt_del_count = 0; line = calloc(LINE_SIZE, sizeof (char)); /* * (Bug# 1010094 fix) Increasing MAXFOLDERS by +2 allows * "av[ac] = av[ac + 1] = 0" to work in mt_folder_menu_build() * w/o trashing the next byte. */ folder_list = (char **)(LINT_CAST(calloc(MAXFOLDERS+2, sizeof (char *)))); mt_mailbox = calloc(256, sizeof (char)); mt_folder = calloc(256, sizeof (char)); mt_info = calloc(256, sizeof (char)); mt_scandir = 1; mt_talking_to_Mail = FALSE;}mt_release_mail_storage() {} /* No-op for now *//* * Start the Mail subprocess. */intmt_start_mail(){ int in[2], out[2]; int i; FILE *f; static char *args[6] = {"Mail", "-N", "-B", "-f", 0, 0}; if(!(f = mt_fopen(mt_dummybox, "w"))) return(FALSE); (void)chmod(mt_dummybox, 0600); args[4] = mt_dummybox; (void)fprintf(f, "From xxx Fri Jan 1 00:00:00 1970\n"); (void)fclose(f); (void)pipe(in); /* input to mail */ (void)pipe(out); /* output from mail */ if ((mt_mailpid = vfork()) == 0) { (void)dup2(in[0], 0); (void)dup2(out[1], 1); (void)dup2(out[1], 2); for (i = GETDTABLESIZE(); i > 2; i--) (void)close(i); execvp("Mail", args, 0); exit(-1); } (void)close(in[0]); (void)close(out[1]); mt_mailin = fdopen(in[1], "w"); mt_mailout = fdopen(out[0], "r"); (void)strcpy(mt_folder, "[None]"); (void)notify_set_wait3_func(&mt_mailclient, mt_Mail_died, mt_mailpid); (void)notify_set_signal_func(&mt_mailclient, mt_broken_pipe, SIGPIPE, NOTIFY_ASYNC); return(TRUE);}/* ARGSUSED */static Notify_valuemt_Mail_died(client, sig) Notify_client client; int sig;{ fprintf(stderr, "Mail process died! Aborting mailtool!\n"); (void)fclose(mt_mailin); (void)fclose(mt_mailout); (void)unlink(mt_dummybox); mt_done(1);}/* ARGSUSED */static Notify_valuemt_broken_pipe(client, sig) Notify_client client; int sig;{ if (!mt_talking_to_Mail) return; fprintf(stderr, "Mailtool not able to communicate with Mail!\n(Perhaps Mail is not an executable appropriate for this machine.)\n"); (void)fclose(mt_mailin); (void)fclose(mt_mailout); (void)unlink(mt_dummybox); fprintf(stderr, "Aborting mailtool!\n"); mt_done(1);}intmt_idle_mail(){ FILE *f; if(!(f = mt_fopen(mt_dummybox, "w"))) return(FALSE); (void)chmod(mt_dummybox, 0600); (void)fprintf(f, "From xxx Fri Jan 1 00:00:00 1970\n"); (void)fclose(f); (void)mt_set_folder(mt_dummybox); return(TRUE);}voidmt_stop_mail(doabort) int doabort;{ mt_mail_cmd(doabort ? "x" : "quit"); (void)fclose(mt_mailin); (void)fclose(mt_mailout); (void)unlink(mt_dummybox);}voidmt_tool_is_busy(busy, s) int busy; char *s;{ if (busy) { mt_waitcursor(); mt_set_namestripe_temp(s); } else { mt_restorecursor(); mt_check_mail_box(); }}/* * Flag new mail when it arrives and check to see if the mail has been seen * but not necessarily read or deleted. After mail is seen the flag goes * down. Returns TRUE if new mail, FALSE if not. */intmt_check_mail_box(){ struct stat stat_buf; static time_t mbox_time; /* time mailbox last changed state */ /* * Stat the mailbox, if it doesn't exist then we don't have any mail. */ if (stat(mt_mailbox, &stat_buf) < 0) { if (mt_debugging) printf("checking mailbox: stat = %d\nNo Mail\n\n", stat); mt_set_state(S_NOMAIL); return (FALSE); } if (mt_debugging) printf("checking mailbox:\nsize = %d,\nlast accessed = %d,\nlast modified = %d,\nlast checked = %d,\n", stat_buf.st_size, stat_buf.st_atime, stat_buf.st_mtime, mbox_time); /* * If the mailbox has been accessed (read) but not modified (written) * since the last time we have checked, or is empty, then there is * no new mail. Update mbox_time to the mailbox last accessed time. */ if ((stat_buf.st_atime > stat_buf.st_mtime && stat_buf.st_atime > mbox_time) || stat_buf.st_size == 0) { if (mt_debugging) printf("No Mail\n\n"); mbox_time = stat_buf.st_atime; mt_set_state(S_NOMAIL); } /* * If the mailbox size is non-zero (it has some mail in it) and * has been modified (written) since the last time we checked then * there is new mail. * Update mbox_time to the mailbox last modified time. */ else if (stat_buf.st_mtime > mbox_time) { if (mt_debugging) printf("New Mail\n\n"); mbox_time = stat_buf.st_mtime; mt_set_state(S_MAIL); mt_announce_mail(); } else if (mt_debugging) printf("No change\n\n"); /* * If none of the above, nothing has changed. */ return (mt_mstate == S_MAIL);}/* * Set the icon and window label to reflect the * internal state (mail or no mail). */static voidmt_set_state(s) enum mstate s;{ char *new; Pixrect *pr; pr = NULL; mt_mstate = s; switch (mt_mstate) { case S_NOMAIL: mt_icon_ptr = &mt_nomail_icon; new = ""; pr = mt_nomail_pr; break; case S_MAIL: mt_icon_ptr = &mt_mail_icon; new = "[New Mail]"; pr = mt_newmail_pr; break; } mt_set_icon(mt_icon_ptr); mt_set_namestripe_left(mt_folder, new, TRUE); if (mt_panel_style == mt_3DImages) panel_set(mt_state_item, PANEL_LABEL_IMAGE, pr, 0);}/* * Get the headers for all messages from the Mail subprocess. */intmt_get_headers(start) int start;{ extern char *realloc(); int n = 0, first = TRUE; register struct msg *mp; mt_mail_start_cmd("from %d-$", start); while (MT_MAIL_GET_LINE) { if (first) /* check for error msg from /bin/mail */ { extern char *index(); char *p; p = index(line, ':'); if (p != NULL && (strcmp(p, ": Invalid message number\n") == 0)) { while (MT_MAIL_GET_LINE) {}; /* ignore the rest */ return(FALSE); } first = FALSE; } n = atoi(&line[2]); if (n >= current_size) /* if too many lines read, get more space */ { if((current_size+INCR_SIZE) <= MAXMSGS) { struct msg *old_address; old_address = mt_message; /* save old address to calc offset*/ /* allocate more storage by moving array if needed */ if((mt_message=(struct msg *)realloc( (struct msg *)mt_message, (unsigned)(sizeof(struct msg)*(current_size+ INCR_SIZE)))) == NULL) { fprintf(stderr,"Realloc failed to increment storage\n"); exit(1); } else { int address_offset; /* * In this case, the msg list has possibly been moved * to another address. This means the reverse list * of deleted msgs, maintained with the m_next field, * will all point to the wrong addresses. By calculating * the address offset and incrementing the m_next field, * this will be corrected. */ current_size = current_size + INCR_SIZE; /* * realloc() does not guarentee "clean" memory, so * zero out the additional memory after the header msgs. */ bzero((char *)&mt_message[current_size - INCR_SIZE], sizeof(struct msg)*INCR_SIZE); /* * the compiler scales the result according to the size of * the objects pointed to. If not cast as chars (bytes), * it would return the size in terms of struct msg. */ address_offset = (char *)mt_message - (char *)old_address; if ((mt_delp != NULL) && (address_offset)) /* if array was actually moved */ { struct msg *mt_curr; /* set to last deleted msg in moved array */ (char *)mt_delp += address_offset; /* transverse delete list and fix the addresses */ for (mt_curr = mt_delp; mt_curr->m_next != NULL; mt_curr = mt_curr->m_next) (char *)mt_curr->m_next += address_offset; } } } else /* not enough space for messages */ { mt_warn(mt_frame, "Maximum number of messages exceeded.", "Split this folder.", 0); n--; while (MT_MAIL_GET_LINE) {}; break; } } /* * if this message is the 'current' message according to * Mail, remember it */ if (line[0] == '>') { mt_curmsg = n; line[0] = ' '; } mp = &mt_message[n]; if (mp->m_header) free(mp->m_header); mp->m_header = mt_savestr(line); mp->m_next = NULL; mp->m_deleted = FALSE; } mt_maxmsg = n; mt_message[mt_maxmsg+1].m_deleted = TRUE; return(TRUE);}char *mt_get_header(msg) int msg;{ mt_mail_cmd("from %d", msg); return (mt_info);}/* * Get the name of the current folder from Mail. */voidmt_get_folder(){ char *p; extern char *index(); mt_mail_cmd("folder"); if (mt_info[0] == '"' && (p = index(&mt_info[1], '"'))) { *p = '\0'; (void)strcpy(mt_folder, &mt_info[1]); }}/* * Get the names of all the user's folders. */char **mt_get_folder_list(path_string, fdir_name, strtab, acp) char *path_string, *fdir_name, *strtab; int *acp;{ char *s, *strtab_max; char **av; int ac, n = 0; /* reserve the first slot for use by the folder menu code */ av = &folder_list[1]; ac = 0; strtab_max = strtab + 15*MAXFOLDERS - 1; *strtab = '\0'; if (*fdir_name != '\0' && mt_value("foldermenupullrights")) /* * present subdirectories as * pullright menu items. * Note: executing this * command is somewhat slower * than simply executing * "folder". This is left in * for people who run new * mailtool without new mail */ mt_mail_start_cmd("!ls -F %s", fdir_name); else mt_mail_start_cmd("folders %s", ((*path_string == '+') ? path_string+1 : path_string)); /* * Newer version of mail lets you specify an argument to * folders command indicating a subdirectory in folders * hierarchy. Much more efficient than performing '!ls -F' */ while (MT_MAIL_GET_LINE) { n++; if (n > MAXFOLDERS) { while (MT_MAIL_GET_LINE) n++; sprintf(line, "%d folders exceeds maximum number (%d) allowed.", n, MAXFOLDERS); mt_warn(mt_frame, line, "Additional folders will be left off of folder menu.", "Suggest you combine several folders, or move some", "folders to other folder subdirectories.", 0); break; } if (strcmp(line, "!\n") == 0) continue; *av++ = strtab; ac++; if (*path_string == '\0' && strtab < strtab_max) *strtab++ = '+'; /* only put + when at top * level, i.e. in folders * directory. This is * backwards compatible * behavior. */ for (s = line; *s != '\n' && strtab < strtab_max;) *strtab++ = *s++; if (*(strtab - 1) == '@') { char buf[128]; struct stat stbuf; (void) strcpy(buf, fdir_name); line[strlen(line) - 2] = '\0'; /* remove the @ and newline */ (void)strcat((char *)buf,(char *)line); if (stat(buf, &stbuf) != -1 && ((stbuf.st_mode & S_IFMT) == S_IFDIR) ) { *(strtab - 1) = '/'; *strtab++ = '@'; } } if (strtab < strtab_max) *strtab++ = '\0'; else { sprintf(line, "Maximum number of characters (%d) in folder names exceeded.", 15*MAXFOLDERS - 1); mt_warn(mt_frame, line, "Suggest you delete or give some folders shorter names,", "or move some folders to other folder subdirectories.", 0); /* * Note that this warning will only go up for top * level folder. However, chances are that if * somebody is using the pullrights, rather than a * flat structure, then they probably have smaller * subdirectories. */ /* * If this really turns out to happen often, the * right solution is to change the code to reallocate * the table. This would require passing in to * mt_get_folder_list the address of strtab, along * with its current size, so that the new strtab * could be saved. */ *strtab_max = '\0'; while (MT_MAIL_GET_LINE) {}; break; } } *av = NULL; *acp = ac; return (&folder_list[1]);}/* * Get the variables (and their values) that Mail knows about. */voidmt_get_vars(forceset)int forceset;{ char *p, *s, *tmp_line; char mailrc_str[256]; FILE *mailrc_ptr; /* * Read the user's .mailrc file if possible */ /* mailrc_str = (char *)calloc(256,sizeof(char)); */ if (getenv("MAILRC")) strcpy(mailrc_str,getenv("MAILRC")); else sprintf(mailrc_str, "%s/.mailrc", getenv("HOME")); if ( (forceset != 0) ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -