|
|
1.1 root 1: ; This is "mhe", the Emacs-based front end to "mh", which is the Rand Mail
2: ; Handler. MH is a set of programs designed to be called as commands from the
3: ; shell. This system uses single-keystroke commands and maintains a visual
4: ; display of the contents of the message file. I initially wrote it because I
5: ; was drowning in mail and I needed some way to pare out the junk, and it has
6: ; just sort of mushroomed into a real system.
7: ;
8: ; Brian K. Reid, Stanford University
9: ; Version 1: April 1982
10: ; Version 2: May 1982: new commands added
11: ; Version 3: August 1982: rewrote send-to-shell for increased speed
12: ; Version 4: Added extensive header caching mechanism for increased speed
13: ; Version 5: documentation updated slightly. November 1982
14: ;
15: ; ------------------------------------------------------------------------
16: ; GETTING IT INSTALLED AT YOUR SITE:
17: ;
18: ; Mhe consists of about a dozen mlisp files. The primary file is mh-e.ml,
19: ; which in turn loads the others as needed. All of them must be in the
20: ; directory where your Emacs will look for its library files.
21: ;
22: ; The file mh-e.ml must be edited to reflect the filename paths on your
23: ; system:
24: ; mh-progs must be set to the name of the directory
25: ; in which the MH programs are stored, i.e.
26: ; "/usr/local/lib/mh" if the "scan" command
27: ; is /usr/local/lib/mh/scan.
28: ; bboard-path must be set to the name of the directory
29: ; that is the root of your "readnews" tree.
30: ; If your "fa.human-nets" newsgroup is stored
31: ; in /usr/spool/news/fa.human-nets/*, then
32: ; you should set this variable to
33: ; "/usr/spool/news". If you don't use
34: ; readnews, then set it to "/dev/null".
35: ;
36: ; The MH programs "repl", and "forw" have to be modified to include
37: ; the option "-build", which causes them not to ask the "What now?"
38: ; question at the end, but instead just exit (having built the file). Mhe will
39: ; also be a lot more tolerable if you remove a lot of the warning messages
40: ; from adrparse.c; there's no point making them fatal errors. If you aren't up
41: ; to hacking directly on the MH programs, contact me as Reid@SU-SCORE or
42: ; ucbvax!Shasta!reid, and I will provide you with my version of the code.
43: ; If I weren't so lazy I would propagate these changes back to Rand, but I've
44: ; forgotten the name of the contact there and I can't find our licensing
45: ; agreement to look his name up. Besides, they have probably changed their
46: ; sources out from under me anyhow. I have included a summary of the important
47: ; changes at the end of this documentation.
48: ;
49: ; Mhe requires Emacs #45 of Fri May 21 1982 or later, because it uses
50: ; buffer-local variables.
51: ; ----------------------------------------------------------------------------
52: ; SETTING UP A NEW MHE USER.
53: ;
54: ; If you are an mh user, then you can just run mhe with no further ado.
55: ; However, you can speed things up substantially by putting an alias into your
56: ; .cshrc file so that you won't need to spawn a new subshell when you run it:
57: ;
58: ; alias mhe /usr/local/bin/emacs -lmh-e.ml -estartup $*
59: ;
60: ; The shell syntax for mhe is
61: ; mhe
62: ; or
63: ; mhe +inbox first argument is folder name
64: ; or
65: ; mhe +inbox 200:300 second argument is message range
66: ;
67: ; The folder name defaults to current-folder, and the message range defaults
68: ; to "all".
69: ; ------------------------------------------------------------------------
70: ; HOW MHE WORKS
71: ;
72: ; Mhe uses the Emacs subprocess facility to run mh commands in a subshell.
73: ; Normally when you use mh, it runs the editor in a subshell; this inverted
74: ; scheme of the editor running mh in the subshell is actually much much
75: ; faster, because editors are slow in starting up but the mh programs are
76: ; pretty fast. When you start mhe, it builds a buffer whose name equals the
77: ; name of the current folder (e.g. "+inbox"), and places a "scan" listing into
78: ; that buffer. Then as you edit your mail, deleting and moving messages, mhe
79: ; builds up a set of shell commands in a buffer called "cmd-buffer". When you
80: ; exit from mhe, it passes the contents of cmd-buffer off to the shell, and
81: ; the deletes and moves are actually processed. If you open another mail file,
82: ; its header is given its own buffer ("+carbons", "+bugs", etc.), and you can
83: ; switch back and forth to them as needed. The Emacs buffer-local context
84: ; mechanism makes everything happen almost perfectly.
85: ;
86: ; To avoid the overhead of doing a "scan" everytime you run mhe or switch
87: ; folders, mhe maintains a cache of header lines in a file with the same name
88: ; as the buffer; e.g. a file named ~/Mail/inbox/+inbox will hold the header
89: ; cache for folder +inbox. The extended command "scavenge" will regenerate
90: ; this header listing.
91: ;
92: ; To avoid the overhead of loading the entire 50000-character mhe system on
93: ; startup, most of the command-driven functions are off in autoloaded files,
94: ; so that the first time you use a command you will have to wait for its
95: ; definition to be loaded. This scheme seems to be perfectly acceptable to
96: ; users. However, most people use mhe by running it once in the morning and
97: ; sitting in it all day, so this feature doesn't buy much in the grand scheme.
98: ; ------------------------------------------------------------------------
99: ;
100: ; MODIFICATIONS TO MH
101: ;
102: ; Here is a summary of the relevant changes to MH that I have made. Some of
103: ; them are just optimizations.
104: ;
105: ; (from repl.c; nearly identical changes go into forw.c.)
106: ;
107: ; short buildflag = 0; /* just building a reply file? */
108: ; ...
109: ; "build", 0, /*12 */
110: ; ...
111: ; case 12:buildflag++; continue; /* -build */
112: ; if (buildflag)
113: ; drft = m_maildir("reply");
114: ; else
115: ; drft = m_maildir(draft);
116: ; ...
117: ; if((!buildflag) & (stat(drft, &stbuf) != -1)) {
118: ; cp = concat("\"", drft, "\" exists; delete (y,n,l) ? ", 0);
119: ; ...
120: ; if (!buildflag) {
121: ; if(m_edit(&ed, drft, NOUSE, msg) < 0)
122: ; return;
123: ; }
124: ; ...
125: ; if(!buildflag) {
126: ; if(!(argp = getans("\nWhat now? ", aleqs))) {
127: ; VOID unlink("@");
128: ; return;
129: ; }
130: ; ...
131: ; switch(buildflag ? 4 : smatch(*argp, aleqs)) {
132: ; case 0: VOID showfile(drft); /* list */
133: ; ...
134: ;
135: ; In inc.c: (this code makes it possible for you to use an "inc" command
136: ; outside of mhe, like in your .login file, and still have mhe pick up
137: ; the headers of the new messages the next time you run it)
138: ;
139: ; FILE *in, *aud, *mhe_aud;
140: ; ...
141: ; char ..., *mhe_audfile;
142: ; ...
143: ; mhe_audfile = m_find("mhe");
144: ; if(!m_find("path")) free(path("./", TFOLDER));
145: ; ...
146: ; if(mhe_audfile) {
147: ; cp = concat(maildir, "/++", NULLCP);
148: ; i = stat(cp, &stbuf);
149: ; if((mhe_aud = fopen(cp, "a")) == NULL) {
150: ; fprintf(stderr, "Can't append to ");
151: ; perror(cp);
152: ; } else if(i < 0)
153: ; VOID chmod(cp, 0600);
154: ; }
155: ; ...
156: ; if(aud)
157: ; fputs(scanl, aud);
158: ; if(mhe_aud)
159: ; fputs(scanl, mhe_aud);
160: ; ...
161: ; if(mhe_aud)
162: ; VOID fclose(mhe_aud);
163: ;
164: ; In adrparse.c:
165: ; Remove all instances of "goto line", replacing it with "break" if it is in
166: ; the "switch" statement, otherwise just taking it out. This makes it so syntax
167: ; errors will be non-fatal. Remove the
168: ; if(isalnum(*cp))||*cp=="-" || etc.
169: ; statement about 40% of the way through, so that all characters not given
170: ; specific meanings in the switch statement above it will be legal in mail
171: ; names.
172: ;
173: ;
174: ; ------------------------------------------------------------------------
175: ; these functions let me edit the above documentation without the semicolons.
176: (defun
177: (add-semicolons
178: (beginning-of-file)
179: (while (! (| (eobp) (looking-at "^(defun")))
180: (insert-string "; ")
181: (next-line) (beginning-of-line)
182: )
183: )
184:
185: (remove-semicolons
186: (beginning-of-file)
187: (while (! (| (eobp) (looking-at "^(defun")))
188: (while (| (looking-at "^; ") (looking-at "^;$"))
189: (delete-next-character)
190: (if (! (eolp))
191: (delete-next-character))
192: )
193: (next-line)
194: )
195: )
196: )
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.