Merge branch 'pick' into master
authorPhilipp Takacs <philipp@bureaucracy.de>
Sun, 30 Dec 2018 01:37:25 +0000 (02:37 +0100)
committerPhilipp Takacs <philipp@bureaucracy.de>
Sun, 30 Dec 2018 01:37:25 +0000 (02:37 +0100)
scan and pick is merged and pick matching is streamlined

32 files changed:
README
h/mh.h
h/prototypes.h
man/mh-alias.man5
man/mhl.man1
man/pick.man1
sbr/context_read.c
sbr/fmt_scan.c
sbr/m_getfld2.c
sbr/trim.c
test/common.sh
test/runtest
test/tests/config/test-inbox [new file with mode: 0644]
test/tests/inc/cksums [deleted file]
test/tests/inc/filler.txt [deleted file]
test/tests/inc/fromline.txt [deleted file]
test/tests/inc/msgheader.txt [deleted file]
test/tests/inc/test-eom-align [deleted file]
test/tests/mhl/test-mhl-flags
test/tests/mhsign/test-mhsign
test/tests/mhstore/test-filenames
test/tests/new/test-empty-seq [new file with mode: 0644]
test/tests/scan/test-scan-multibyte
test/tests/send/test-mimeify
test/tests/show/test-longlines [new file with mode: 0644]
uip/Makefile.in
uip/aliasbr.c
uip/mhl.c
uip/mhsign.sh
uip/new.c
uip/spost.c
uip/whatnow2.sh

diff --git a/README b/README
index 63037c2..8400d5e 100644 (file)
--- a/README
+++ b/README
@@ -5,8 +5,9 @@ Mmh is a modified version of the electronic mail handling system nmh.
 Nmh (new MH) itself was originally based on the package MH-6.8.3, and
 was intended to be a (mostly) compatible drop-in replacement for MH.
 In contrast, mmh is not intended to be a drop-in replacement for nmh,
-rather mmh breaks compatibility to nmh in order to modernize and
-simplify it.
+but rather aims for the modernization and simplification of nmh,
+accepting reduced compatiblity if it, at the same time, allows to
+achieve greater goals from mmh's point of view.
 
 Mmh is small and simple; nmh is established and matured; MH is ancient.
 
diff --git a/h/mh.h b/h/mh.h
index 53b301e..20346b6 100644 (file)
--- a/h/mh.h
+++ b/h/mh.h
@@ -210,6 +210,7 @@ struct field {
        char *value;
        size_t valuelen;
        size_t alloclen;
+       boolean crlf;
 };
 
 /* m_getfld2() states */
index 50d8a8b..fad1af4 100644 (file)
@@ -107,6 +107,7 @@ char *snprintb(char *, size_t, unsigned, char *);
 int stringdex(char *, char *);
 char *toabsdir(char *);
 char *trim(unsigned char *);
+char *rtrim(char *);
 char *trimcpy(unsigned char *);
 int unputenv(char *);
 void unquote_string(const char *input, char *output);
index 1d0508f..3769141 100644 (file)
@@ -135,7 +135,7 @@ Example Alias File:
 .nf
 <%etcdir%/MoreAliases
 sgroup: fred, fear, freida
-b-people: Blind List: bill, betty;
+b-people: Blind List: bill, betty
 fred: frated@UCI
 UNIX\-committee: <unix.aliases
 staff: =staff
@@ -218,6 +218,13 @@ Start adding aliases to your
 .RI ` aliases '
 file as appropriate.
 .RE
+.PP
+Earlier versions of this man page showed a semicolon at the end of the
+blind list example.  That caused the preceeding alias to not be
+expanded.  There must not be a semicolon at the end of, or within, the
+address group of a blind list.
+.B post
+will append the semicolon to the blind list name.
 
 .SH FILES
 None
@@ -249,5 +256,3 @@ command may defeat this.
 Since the number of file descriptors is finite (and very limited), such
 infinite recursion will terminate with a meaningless diagnostic when
 all the fds are used up.
-.PP
-Forward references do not work correctly inside blind lists.
index a80d6bf..b6af953 100644 (file)
@@ -136,6 +136,8 @@ leftadjust  flag    strip off leading whitespace on each
 noleftadjust   flag    don't leftadjust
 compress       flag    change newlines in text to spaces
 nocompress     flag    don't compress
+rtrim  flag    trim whitespace at end of text lines
+nortrim        flag    retain whitespace at end of text lines (default)
 split  flag    don't combine multiple fields into
                a single field
 nosplit        flag    combine multiple fields into
@@ -166,6 +168,11 @@ ignores=component,...
 .RE
 .PP
 specifies a list of components which are never output.
+This option supports some simple globbing,
+so a '*' at the end of a component will match
+for all components which start wich the string.
+When you want to match a component which ends with
+a '*', you can escape the '*' with a '\\'.
 .PP
 The component `MessageName' (case\-insensitive) will output the
 message file name as a one-line header, similar to
index ea63a75..5e20903 100644 (file)
@@ -222,7 +222,7 @@ switches are provided, which act just like opening and closing
 parentheses in logical expressions.
 .PP
 If no search criteria are given, all the messages specified on the
-command line are selected (this defaults to `all').
+command line are selected (this defaults to `a').
 .PP
 Once the search has been performed, if the
 .B \-list
@@ -446,7 +446,7 @@ mark(1)
 .SH DEFAULTS
 .nf
 .RB ` +folder "' defaults to the current folder"
-.RB ` msgs "' defaults to all"
+.RB ` msgs "' defaults to all messages"
 .RB ` "\-datefield date" '
 .RB ` \-zero '
 .RB ` \-list "' is the default if no `\-sequence', `\-nolist' otherwise"
@@ -573,5 +573,16 @@ was given, and if its standard output is not a tty, then
 outputs the illegal message number `0'
 when it fails.  This lets the outer command fail gracefully as well.
 .PP
+To account for this case when combining
+.B pick
+with regular shell tools, filter out the message number `0'.
+For example, do
+.PP
+.RS 5
+pick\0...\0|\0fgrep\0-vx\0\&0\0|\0wc\0-l
+.RE
+.PP
+to count the number of messages picked.
+.PP
 The pattern syntax `[l-r]' is not supported; each letter to be
 matched must be included within the square brackets.
index cfdcff2..51592a9 100644 (file)
@@ -137,7 +137,7 @@ context_read(void)
        /*
        ** Create the default folder (inbox)
        */
-       cp = toabsdir(defaultfolder);
+       cp = toabsdir(getdeffol());
        if (stat(cp, &st) == -1) {
                if (!makedir(cp)) {
                        adios(EX_CANTCREAT, cp, "Unable to create the default folder");
index 2485e6c..4d4d633 100644 (file)
@@ -188,26 +188,59 @@ cptrimmed(char **dest, char *str, unsigned int wid, char fill, size_t n) {
 static void
 cpstripped(char **start, char *end, char *str)
 {
+#ifdef MULTIBYTE_SUPPORT
+       int char_len;  /* bytes in current character */
+       int nbytes;
+       wchar_t wide_char;
+#else
        int c;
+#endif
        char *s = str;
 
        if (!s)
                return;
 
        /* skip any initial control characters or spaces */
+#ifdef MULTIBYTE_SUPPORT
+       nbytes = end - *start + 1;
+       mbtowc(NULL, NULL, 0); /* reset shift state */
+       while ((char_len = mbtowc(&wide_char, s, nbytes)) > 0 && (iswcntrl(wide_char) || iswspace(wide_char))) {
+               s += char_len;
+               nbytes -= char_len;
+       }
+#else
        while ((c = (unsigned char) *s) && (iscntrl(c) || isspace(c)))
                s++;
+#endif
 
        /* compact repeated control characters and spaces into a single space */
-       while((c = (unsigned char) *s++) && *start < end)
-               if (!iscntrl(c) && !isspace(c))
+#ifdef MULTIBYTE_SUPPORT
+       while ((char_len = mbtowc(&wide_char, s, nbytes)) > 0 && *start < end) {
+               if (!iswcntrl(wide_char) && !iswspace(wide_char)) {
+                       strncpy(*start, s, char_len);
+                       s += char_len;
+                       *start += char_len;
+                       nbytes -= char_len;
+               } else {
+                       while ((char_len = mbtowc(&wide_char, s, nbytes)) > 0 && (iswcntrl(wide_char) || iswspace(wide_char))) {
+                               s += char_len;
+                               nbytes -= char_len;
+                       }
+                       *(*start)++ = ' ';
+               }
+       }
+#else
+       while((c = (unsigned char) *s++) && *start < end) {
+               if (!iscntrl(c) && !isspace(c)) {
                        *(*start)++ = c;
-               else {
+               } else {
                        while ((c = (unsigned char) *s) &&
                                        (iscntrl(c) || isspace(c)))
                                s++;
                        *(*start)++ = ' ';
                }
+       }
+#endif
 }
 
 static char *lmonth[] = {
@@ -266,12 +299,13 @@ fmt_trim(char *str, int width)
        char *xp;
        int ljust, i;
        char buffer[BUFSIZ];
+       char *dst;
 
        strncpy(buffer, str, sizeof(buffer));
-       buffer[sizeof(buffer)-1] = '\0';
-       str = buffer;
-       while (isspace(*str)) {
-               str++;
+       dst = buffer;
+       dst[sizeof(buffer)-1] = '\0';
+       while (isspace(*dst)) {
+               dst++;
        }
        ljust = 0;
        if ((i = width) < 0) {
@@ -279,17 +313,18 @@ fmt_trim(char *str, int width)
                ljust++;
        }
 
-       if (!ljust && i > 0 && (int)strlen(str) > i) {
-               str[i] = '\0';
+       if (!ljust && i > 0 && (int)strlen(dst) > i) {
+               dst[i] = '\0';
        }
-       xp = str;
-       xp += strlen(str) - 1;
-       while (xp > str && isspace(*xp)) {
+       xp = dst;
+       xp += strlen(dst) - 1;
+       while (xp > dst && isspace(*xp)) {
                *xp-- = '\0';
        }
-       if (ljust && i > 0 && (int)strlen(str) > i) {
-               str += strlen(str) - i;
+       if (ljust && i > 0 && (int)strlen(dst) > i) {
+               dst += strlen(dst) - i;
        }
+       strncpy(str, dst, strlen(str) + 1);
        return str;
 }
 
index 956a556..b9a618d 100644 (file)
@@ -62,7 +62,8 @@ m_getfld2(enum state s, struct field *f, FILE *msg)
                        }
                }
 
-               if (nchars >= NAMESZ) {
+               f->crlf = (nchars > 2 && tmpline[nchars-2] == '\r');
+               if (nchars > NAMESZ+1 || (!f->crlf && nchars > NAMESZ)) {
                        ret = LENERR2;
                }
 
@@ -103,7 +104,7 @@ m_getfld2(enum state s, struct field *f, FILE *msg)
                                return IOERR2;
                        }
 
-                       if (nchars >= NAMESZ) {
+                       if (nchars > NAMESZ+1 || (!f->crlf && nchars > NAMESZ)) {
                                ret = LENERR2;
                        }
 
@@ -145,6 +146,7 @@ m_getfld2(enum state s, struct field *f, FILE *msg)
                        }
                }
 
+               f->crlf = (nchars > 2 && tmpline[nchars-2] == '\r');
                free(f->value);
                f->value = tmpline;
                f->valuelen = nchars;
index 249faf9..cbf9098 100644 (file)
@@ -31,3 +31,15 @@ trim(unsigned char *cp)
 
        return cp;
 }
+
+char *
+rtrim(char *cp)
+{
+       char *sp = cp + strlen(cp) - 1;
+
+       while (sp >= cp && isspace(*sp)) {
+               sp--;
+       }
+       *++sp = '\0';
+       return cp;
+}
index 805afea..b869d56 100644 (file)
@@ -52,6 +52,12 @@ require_locale()
        test_skip "no suitable locale available"
 }
 
+# Do a best guess at FQDN
+mh_hostname()
+{
+       hostname -f 2>/dev/null || uname -n
+}
+
 # Some stuff for doing silly progress indicators
 progress_update()
 {
@@ -74,6 +80,12 @@ progress_done()
 }
 
 
+#### Replace generated Content-ID headers with static value
+replace_contentid()
+{
+       sed "/^Content-ID/s/:.*/: <TESTID>/" "$@"
+}
+
 
 #### Filter that squeezes blank lines, partially emulating GNU cat -s,
 #### but sufficient for our purpose.
index 9f35ade..32c82f5 100755 (executable)
@@ -36,7 +36,7 @@ folder -create `mhparam trashfolder` >/dev/null
 folder -create `mhparam draftfolder` >/dev/null
 
 # create 10 basic messages
-for i in `seq 1 10`;
+for i in 1 2 3 4 5 6 7 8 9 10;
 do
        cat >"$MAILDIR/inbox/$i" <<-!
                From: Test$i <test$i@example.com>
diff --git a/test/tests/config/test-inbox b/test/tests/config/test-inbox
new file mode 100644 (file)
index 0000000..997e52e
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+######################################################
+#
+# Test the creation of the inbox
+#
+######################################################
+
+export MMHP="$MH_TEST_DIR/profile2"
+rm -rf "$MH_TEST_DIR/Mail2"
+printf "Path: %s\n" "$MH_TEST_DIR/Mail2" > "$MMHP"
+
+< /dev/null | folder > /dev/null
+if [ ! -d "$MH_TEST_DIR/Mail2" ]; then
+       exit 1
+fi
+
+if [ ! -d "$MH_TEST_DIR/Mail2/inbox" ]; then
+       exit 1
+fi
+
+folder -create +test > /dev/null
+rmdir "$MH_TEST_DIR/Mail2/inbox"
+
+printf "inbox: testinbox\n" >> $MMHP
+< /dev/null | folder > /dev/null
+if [ ! -d "$MH_TEST_DIR/Mail2/testinbox" ]; then
+       exit 1
+fi
+
+if [ -d "$MH_TEST_DIR/Mail2/inbox" ]; then
+       exit 1
+fi
diff --git a/test/tests/inc/cksums b/test/tests/inc/cksums
deleted file mode 100644 (file)
index a8667a7..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-4195362473 17161 filler.txt
-3020538295 51 fromline.txt
-525303352 121 msgheader.txt
diff --git a/test/tests/inc/filler.txt b/test/tests/inc/filler.txt
deleted file mode 100644 (file)
index 7be957f..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-CHAPTER I. MR. SHERLOCK HOLMES.
-
-
-IN the year 1878 I took my degree of Doctor of Medicine of the
-University of London, and proceeded to Netley to go through the course
-prescribed for surgeons in the army. Having completed my studies there,
-I was duly attached to the Fifth Northumberland Fusiliers as Assistant
-Surgeon. The regiment was stationed in India at the time, and before
-I could join it, the second Afghan war had broken out. On landing at
-Bombay, I learned that my corps had advanced through the passes, and
-was already deep in the enemy's country. I followed, however, with many
-other officers who were in the same situation as myself, and succeeded
-in reaching Candahar in safety, where I found my regiment, and at once
-entered upon my new duties.
-
-The campaign brought honours and promotion to many, but for me it had
-nothing but misfortune and disaster. I was removed from my brigade and
-attached to the Berkshires, with whom I served at the fatal battle of
-Maiwand. There I was struck on the shoulder by a Jezail bullet, which
-shattered the bone and grazed the subclavian artery. I should have
-fallen into the hands of the murderous Ghazis had it not been for the
-devotion and courage shown by Murray, my orderly, who threw me across a
-pack-horse, and succeeded in bringing me safely to the British lines.
-
-Worn with pain, and weak from the prolonged hardships which I had
-undergone, I was removed, with a great train of wounded sufferers, to
-the base hospital at Peshawar. Here I rallied, and had already improved
-so far as to be able to walk about the wards, and even to bask a little
-upon the verandah, when I was struck down by enteric fever, that curse
-of our Indian possessions. For months my life was despaired of, and
-when at last I came to myself and became convalescent, I was so weak and
-emaciated that a medical board determined that not a day should be lost
-in sending me back to England. I was dispatched, accordingly, in the
-troopship "Orontes," and landed a month later on Portsmouth jetty, with
-my health irretrievably ruined, but with permission from a paternal
-government to spend the next nine months in attempting to improve it.
-
-I had neither kith nor kin in England, and was therefore as free as
-air--or as free as an income of eleven shillings and sixpence a day will
-permit a man to be. Under such circumstances, I naturally gravitated to
-London, that great cesspool into which all the loungers and idlers of
-the Empire are irresistibly drained. There I stayed for some time at
-a private hotel in the Strand, leading a comfortless, meaningless
-existence, and spending such money as I had, considerably more freely
-than I ought. So alarming did the state of my finances become, that
-I soon realized that I must either leave the metropolis and rusticate
-somewhere in the country, or that I must make a complete alteration in
-my style of living. Choosing the latter alternative, I began by making
-up my mind to leave the hotel, and to take up my quarters in some less
-pretentious and less expensive domicile.
-
-On the very day that I had come to this conclusion, I was standing at
-the Criterion Bar, when some one tapped me on the shoulder, and turning
-round I recognized young Stamford, who had been a dresser under me at
-Barts. The sight of a friendly face in the great wilderness of London is
-a pleasant thing indeed to a lonely man. In old days Stamford had never
-been a particular crony of mine, but now I hailed him with enthusiasm,
-and he, in his turn, appeared to be delighted to see me. In the
-exuberance of my joy, I asked him to lunch with me at the Holborn, and
-we started off together in a hansom.
-
-"Whatever have you been doing with yourself, Watson?" he asked in
-undisguised wonder, as we rattled through the crowded London streets.
-"You are as thin as a lath and as brown as a nut."
-
-I gave him a short sketch of my adventures, and had hardly concluded it
-by the time that we reached our destination.
-
-"Poor devil!" he said, commiseratingly, after he had listened to my
-misfortunes. "What are you up to now?"
-
-"Looking for lodgings." [3] I answered. "Trying to solve the problem
-as to whether it is possible to get comfortable rooms at a reasonable
-price."
-
-"That's a strange thing," remarked my companion; "you are the second man
-to-day that has used that expression to me."
-
-"And who was the first?" I asked.
-
-"A fellow who is working at the chemical laboratory up at the hospital.
-He was bemoaning himself this morning because he could not get someone
-to go halves with him in some nice rooms which he had found, and which
-were too much for his purse."
-
-"By Jove!" I cried, "if he really wants someone to share the rooms and
-the expense, I am the very man for him. I should prefer having a partner
-to being alone."
-
-Young Stamford looked rather strangely at me over his wine-glass. "You
-don't know Sherlock Holmes yet," he said; "perhaps you would not care
-for him as a constant companion."
-
-"Why, what is there against him?"
-
-"Oh, I didn't say there was anything against him. He is a little queer
-in his ideas--an enthusiast in some branches of science. As far as I
-know he is a decent fellow enough."
-
-"A medical student, I suppose?" said I.
-
-"No--I have no idea what he intends to go in for. I believe he is well
-up in anatomy, and he is a first-class chemist; but, as far as I know,
-he has never taken out any systematic medical classes. His studies are
-very desultory and eccentric, but he has amassed a lot of out-of-the way
-knowledge which would astonish his professors."
-
-"Did you never ask him what he was going in for?" I asked.
-
-"No; he is not a man that it is easy to draw out, though he can be
-communicative enough when the fancy seizes him."
-
-"I should like to meet him," I said. "If I am to lodge with anyone, I
-should prefer a man of studious and quiet habits. I am not strong
-enough yet to stand much noise or excitement. I had enough of both in
-Afghanistan to last me for the remainder of my natural existence. How
-could I meet this friend of yours?"
-
-"He is sure to be at the laboratory," returned my companion. "He either
-avoids the place for weeks, or else he works there from morning to
-night. If you like, we shall drive round together after luncheon."
-
-"Certainly," I answered, and the conversation drifted away into other
-channels.
-
-As we made our way to the hospital after leaving the Holborn, Stamford
-gave me a few more particulars about the gentleman whom I proposed to
-take as a fellow-lodger.
-
-"You mustn't blame me if you don't get on with him," he said; "I know
-nothing more of him than I have learned from meeting him occasionally in
-the laboratory. You proposed this arrangement, so you must not hold me
-responsible."
-
-"If we don't get on it will be easy to part company," I answered. "It
-seems to me, Stamford," I added, looking hard at my companion, "that you
-have some reason for washing your hands of the matter. Is this fellow's
-temper so formidable, or what is it? Don't be mealy-mouthed about it."
-
-"It is not easy to express the inexpressible," he answered with a laugh.
-"Holmes is a little too scientific for my tastes--it approaches to
-cold-bloodedness. I could imagine his giving a friend a little pinch of
-the latest vegetable alkaloid, not out of malevolence, you understand,
-but simply out of a spirit of inquiry in order to have an accurate idea
-of the effects. To do him justice, I think that he would take it himself
-with the same readiness. He appears to have a passion for definite and
-exact knowledge."
-
-"Very right too."
-
-"Yes, but it may be pushed to excess. When it comes to beating the
-subjects in the dissecting-rooms with a stick, it is certainly taking
-rather a bizarre shape."
-
-"Beating the subjects!"
-
-"Yes, to verify how far bruises may be produced after death. I saw him
-at it with my own eyes."
-
-"And yet you say he is not a medical student?"
-
-"No. Heaven knows what the objects of his studies are. But here we
-are, and you must form your own impressions about him." As he spoke, we
-turned down a narrow lane and passed through a small side-door, which
-opened into a wing of the great hospital. It was familiar ground to me,
-and I needed no guiding as we ascended the bleak stone staircase and
-made our way down the long corridor with its vista of whitewashed
-wall and dun-coloured doors. Near the further end a low arched passage
-branched away from it and led to the chemical laboratory.
-
-This was a lofty chamber, lined and littered with countless bottles.
-Broad, low tables were scattered about, which bristled with retorts,
-test-tubes, and little Bunsen lamps, with their blue flickering flames.
-There was only one student in the room, who was bending over a distant
-table absorbed in his work. At the sound of our steps he glanced round
-and sprang to his feet with a cry of pleasure. "I've found it! I've
-found it," he shouted to my companion, running towards us with a
-test-tube in his hand. "I have found a re-agent which is precipitated
-by hoemoglobin, [4] and by nothing else." Had he discovered a gold mine,
-greater delight could not have shone upon his features.
-
-"Dr. Watson, Mr. Sherlock Holmes," said Stamford, introducing us.
-
-"How are you?" he said cordially, gripping my hand with a strength
-for which I should hardly have given him credit. "You have been in
-Afghanistan, I perceive."
-
-"How on earth did you know that?" I asked in astonishment.
-
-"Never mind," said he, chuckling to himself. "The question now is about
-hoemoglobin. No doubt you see the significance of this discovery of
-mine?"
-
-"It is interesting, chemically, no doubt," I answered, "but
-practically----"
-
-"Why, man, it is the most practical medico-legal discovery for years.
-Don't you see that it gives us an infallible test for blood stains. Come
-over here now!" He seized me by the coat-sleeve in his eagerness, and
-drew me over to the table at which he had been working. "Let us have
-some fresh blood," he said, digging a long bodkin into his finger, and
-drawing off the resulting drop of blood in a chemical pipette. "Now, I
-add this small quantity of blood to a litre of water. You perceive that
-the resulting mixture has the appearance of pure water. The proportion
-of blood cannot be more than one in a million. I have no doubt, however,
-that we shall be able to obtain the characteristic reaction." As he
-spoke, he threw into the vessel a few white crystals, and then added
-some drops of a transparent fluid. In an instant the contents assumed a
-dull mahogany colour, and a brownish dust was precipitated to the bottom
-of the glass jar.
-
-"Ha! ha!" he cried, clapping his hands, and looking as delighted as a
-child with a new toy. "What do you think of that?"
-
-"It seems to be a very delicate test," I remarked.
-
-"Beautiful! beautiful! The old Guiacum test was very clumsy and
-uncertain. So is the microscopic examination for blood corpuscles. The
-latter is valueless if the stains are a few hours old. Now, this appears
-to act as well whether the blood is old or new. Had this test been
-invented, there are hundreds of men now walking the earth who would long
-ago have paid the penalty of their crimes."
-
-"Indeed!" I murmured.
-
-"Criminal cases are continually hinging upon that one point. A man is
-suspected of a crime months perhaps after it has been committed. His
-linen or clothes are examined, and brownish stains discovered upon them.
-Are they blood stains, or mud stains, or rust stains, or fruit stains,
-or what are they? That is a question which has puzzled many an expert,
-and why? Because there was no reliable test. Now we have the Sherlock
-Holmes' test, and there will no longer be any difficulty."
-
-His eyes fairly glittered as he spoke, and he put his hand over his
-heart and bowed as if to some applauding crowd conjured up by his
-imagination.
-
-"You are to be congratulated," I remarked, considerably surprised at his
-enthusiasm.
-
-"There was the case of Von Bischoff at Frankfort last year. He would
-certainly have been hung had this test been in existence. Then there was
-Mason of Bradford, and the notorious Muller, and Lefevre of Montpellier,
-and Samson of new Orleans. I could name a score of cases in which it
-would have been decisive."
-
-"You seem to be a walking calendar of crime," said Stamford with a
-laugh. "You might start a paper on those lines. Call it the 'Police News
-of the Past.'"
-
-"Very interesting reading it might be made, too," remarked Sherlock
-Holmes, sticking a small piece of plaster over the prick on his finger.
-"I have to be careful," he continued, turning to me with a smile, "for I
-dabble with poisons a good deal." He held out his hand as he spoke, and
-I noticed that it was all mottled over with similar pieces of plaster,
-and discoloured with strong acids.
-
-"We came here on business," said Stamford, sitting down on a high
-three-legged stool, and pushing another one in my direction with
-his foot. "My friend here wants to take diggings, and as you were
-complaining that you could get no one to go halves with you, I thought
-that I had better bring you together."
-
-Sherlock Holmes seemed delighted at the idea of sharing his rooms with
-me. "I have my eye on a suite in Baker Street," he said, "which would
-suit us down to the ground. You don't mind the smell of strong tobacco,
-I hope?"
-
-"I always smoke 'ship's' myself," I answered.
-
-"That's good enough. I generally have chemicals about, and occasionally
-do experiments. Would that annoy you?"
-
-"By no means."
-
-"Let me see--what are my other shortcomings. I get in the dumps at
-times, and don't open my mouth for days on end. You must not think I am
-sulky when I do that. Just let me alone, and I'll soon be right. What
-have you to confess now? It's just as well for two fellows to know the
-worst of one another before they begin to live together."
-
-I laughed at this cross-examination. "I keep a bull pup," I said, "and
-I object to rows because my nerves are shaken, and I get up at all sorts
-of ungodly hours, and I am extremely lazy. I have another set of vices
-when I'm well, but those are the principal ones at present."
-
-"Do you include violin-playing in your category of rows?" he asked,
-anxiously.
-
-"It depends on the player," I answered. "A well-played violin is a treat
-for the gods--a badly-played one----"
-
-"Oh, that's all right," he cried, with a merry laugh. "I think we may
-consider the thing as settled--that is, if the rooms are agreeable to
-you."
-
-"When shall we see them?"
-
-"Call for me here at noon to-morrow, and we'll go together and settle
-everything," he answered.
-
-"All right--noon exactly," said I, shaking his hand.
-
-We left him working among his chemicals, and we walked together towards
-my hotel.
-
-"By the way," I asked suddenly, stopping and turning upon Stamford, "how
-the deuce did he know that I had come from Afghanistan?"
-
-My companion smiled an enigmatical smile. "That's just his little
-peculiarity," he said. "A good many people have wanted to know how he
-finds things out."
-
-"Oh! a mystery is it?" I cried, rubbing my hands. "This is very piquant.
-I am much obliged to you for bringing us together. 'The proper study of
-mankind is man,' you know."
-
-"You must study him, then," Stamford said, as he bade me good-bye.
-"You'll find him a knotty problem, though. I'll wager he learns more
-about you than you about him. Good-bye."
-
-"Good-bye," I answered, and strolled on to my hotel, considerably
-interested in my new acquaintance.
-
-
-CHAPTER II. THE SCIENCE OF DEDUCTION.
-
-
-WE met next day as he had arranged, and inspected the rooms at No. 221B,
-Baker Street, of which he had spoken at our meeting. They
-consisted of a couple of comfortable bed-rooms and a single large
-airy sitting-room, cheerfully furnished, and illuminated by two broad
-windows. So desirable in every way were the apartments, and so moderate
-did the terms seem when divided between us, that the bargain was
-concluded upon the spot, and we at once entered into possession.
-That very evening I moved my things round from the hotel, and on the
-following morning Sherlock Holmes followed me with several boxes and
-portmanteaus. For a day or two we were busily employed in unpacking and
-laying out our property to the best advantage. That done, we
-gradually began to settle down and to accommodate ourselves to our new
-surroundings.
-
-Holmes was certainly not a difficult man to live with. He was quiet
-in his ways, and his habits were regular. It was rare for him to be
-up after ten at night, and he had invariably breakfasted and gone out
-before I rose in the morning. Sometimes he spent his day at the chemical
-laboratory, sometimes in the dissecting-rooms, and occasionally in long
-walks, which appeared to take him into the lowest portions of the City.
-Nothing could exceed his energy when the working fit was upon him; but
-now and again a reaction would seize him, and for days on end he would
-lie upon the sofa in the sitting-room, hardly uttering a word or moving
-a muscle from morning to night. On these occasions I have noticed such
-a dreamy, vacant expression in his eyes, that I might have suspected him
-of being addicted to the use of some narcotic, had not the temperance
-and cleanliness of his whole life forbidden such a notion.
-
diff --git a/test/tests/inc/fromline.txt b/test/tests/inc/fromline.txt
deleted file mode 100644 (file)
index 8bc4790..0000000
+++ /dev/null
@@ -1 +0,0 @@
-From pm215@archaic.org.uk Fri Dec 26 15:03:52 2008
diff --git a/test/tests/inc/msgheader.txt b/test/tests/inc/msgheader.txt
deleted file mode 100644 (file)
index f6faad4..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-From: Test <test@example.com>
-To: Some User <user@example.com>
-Date: Fri, 29 Sep 2006 00:00:00
-Subject: Testing message
-
diff --git a/test/tests/inc/test-eom-align b/test/tests/inc/test-eom-align
deleted file mode 100644 (file)
index 2b6afb4..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/bin/sh
-# Test all combinations of alignment of the end-of-message delimiter
-# with the end of a stdio buffer
-
-set -e
-
-. $MH_TEST_COMMON
-
-THISDIR="tests/inc"
-
-if [ "$VALGRIND_ME" ]; then
-    require_prog valgrind
-    # Lack of quotes here is important
-    VALGRIND="valgrind --quiet --error-exitcode=1"
-    echo "Running tests under valgrind: takes ages!"
-else
-    VALGRIND=
-fi
-
-# First check that all our various pieces of text are
-# intact. (Since we're dealing in exact byte alignment
-# minor corruptions such as line ending changes could
-# render the tests useless.)
-(cd "$THISDIR" && cksum *.txt > "$MH_TEST_DIR/inctest.cksums")
-diff -u "$THISDIR/cksums" "$MH_TEST_DIR/inctest.cksums"
-
-FILLER="$THISDIR/filler.txt"
-FROMLINE="$THISDIR/fromline.txt"
-HDR="$THISDIR/msgheader.txt"
-
-if grep -q From "$FILLER"; then
-   echo "Somebody's messed with $FILLER -- it must not contain"
-   echo "anything that might look like a message delimiter!"
-   exit 1
-fi
-
-# a sort of worst-case guess for the buffer size;
-# obviously a buffer boundary for this will be a boundary
-# for any smaller power of two size.
-# If you need to increase this you'll need to make filler.txt
-# bigger as well.
-STDIO_BUFSZ=16384
-
-FROMLINESZ="$(wc -c "$FROMLINE" | cut -d ' ' -f 1)"
-HDRSZ="$(wc -c "$HDR" | cut -d ' ' -f 1)"
-
-# makembox_A mboxname sz
-# Assemble a mailbox into file mboxname, with two messages, such
-# that the first is exactly sz bytes long (including its header
-# and its initial 'From' line and the newline which terminates it
-# but not the newline which mbox format demands after each message)
-# We also leave the body of message one in mboxname.body
-# (the body of message two is always $FILLER in its entirety)
-makembox_A () {
-  MBOX="$1"
-  SZ=$2
-
-  WANTSZ="$(($SZ - $HDRSZ - $FROMLINESZ - 1))"
-  dd if="$FILLER" of="$MBOX.body" bs="$WANTSZ" count=1 2>/dev/null
-  echo >> "$MBOX.body"
-  cat "$FROMLINE" "$HDR" "$MBOX.body" > "$MBOX"
-  echo >> "$MBOX"
-  cat "$FROMLINE" "$HDR" "$FILLER" >> "$MBOX"
-  echo >> "$MBOX"
-}
-
-# make_mbox_B mboxname sz
-# Test B makes a mailbox with one message of sz bytes long,
-# which ends in a partial mbox delimiter (ie part of the string
-# \n\nFrom '). To both do this and be a valid mbox this means
-# it has to end with two newlines (one of which is in the message
-# body and one of which is the mbox format mandated one)
-makembox_B () {
-  MBOX="$1"
-  SZ=$2
-
-  WANTSZ="$(($SZ - $HDRSZ - $FROMLINESZ - 1))"
-  dd if="$FILLER" of="$MBOX.body" bs="$WANTSZ" count=1 2>/dev/null
-  echo >> "$MBOX.body"
-  cat "$FROMLINE" "$HDR" "$MBOX.body" > "$MBOX"
-  echo >> "$MBOX"
-}
-
-# do_one_test_A sz
-# Do a single test with message one's body of size sz.
-do_one_test_A () {
-  SZ=$1
-  makembox_A "$MH_TEST_DIR/eom-align.mbox" $STDIO_BUFSZ
-  $VALGRIND inc -silent -file "$MH_TEST_DIR/eom-align.mbox"
-  # We know the messages should be 11 and 12 in inbox
-  # Now get the bodies back out.
-  sed -e '1,/^$/d' "$MH_TEST_DIR/Mail/inbox/11" > "$MH_TEST_DIR/eom-align.inbox.body1"
-  sed -e '1,/^$/d' "$MH_TEST_DIR/Mail/inbox/12" > "$MH_TEST_DIR/eom-align.inbox.body2"
-  diff -u "$MH_TEST_DIR/eom-align.mbox.body" "$MH_TEST_DIR/eom-align.inbox.body1"
-  diff -u "$FILLER" "$MH_TEST_DIR/eom-align.inbox.body2"
-  rmm 11 12
-}
-
-# do_one_test_B sz
-# Do a test type B
-do_one_test_B () {
-  SZ=$1
-  makembox_B "$MH_TEST_DIR/eom-align.mbox" $STDIO_BUFSZ
-  $VALGRIND inc -silent -file "$MH_TEST_DIR/eom-align.mbox"
-  # We know the message should be 11 in the inbox
-  sed -e '1,/^$/d' "$MH_TEST_DIR/Mail/inbox/11" > "$MH_TEST_DIR/eom-align.inbox.body1"
-  diff -u "$MH_TEST_DIR/eom-align.mbox.body" "$MH_TEST_DIR/eom-align.inbox.body1"
-  rmm 11
-}
-
-
-# Cover a decent range around the stdio buffer size to make sure we catch
-# any corner cases whether they relate to total message size equal to
-# buffer size or to body size equal to buffer size.
-START=$(($STDIO_BUFSZ - 16))
-FINISH=$(($STDIO_BUFSZ + $HDRSZ + $FROMLINESZ + 32))
-echo "Testing inc of files with various alignments of eom marker with buffer size..."
-for sz in $(seq $START $FINISH); do
-  progress_update $sz $START $FINISH
-  do_one_test_A $sz
-  do_one_test_B $sz
-done
-progress_done
index 7220e6c..578fd37 100755 (executable)
@@ -4,7 +4,6 @@
 
 . "$MH_TEST_COMMON"
 
-test_skip "not implemented yet"
 
 
 cat >`mhpath b` <<EOF
index 3c2bb97..44e0997 100755 (executable)
@@ -7,7 +7,6 @@
 
 . "$MH_TEST_COMMON"
 
-
 # setup some aliases
 
 cat >"$MH_TEST_DIR/.mmh/aliases" <<!
@@ -66,9 +65,9 @@ unknownperson@example.org
 !
 
 runandcheck "mhsign -enc $draft" <<!
-Could not find key for <unknownperson@`hostname -f`>
+Could not find key for <unknownperson@`mh_hostname`>
 Could not find key for <unknownperson@example.org>
-Could not find key for <unknownperson@`hostname -f`>
+Could not find key for <unknownperson@`mh_hostname`>
 Could not find key for <unknownperson@example.org>
 Could not find key for <unknownperson@example.org>
 Could not find key for <unknownperson@example.org>
index a1d3c3d..31946ee 100755 (executable)
@@ -11,7 +11,7 @@ require_locale en_US.utf-8 en_US.utf8
 LC_ALL=en_US.UTF-8
 export LC_ALL
 
-tempdir=`TMPDIR=$MH_TEST_DIR mktemp -d -t "XXXXX"`
+tempdir=`TMPDIR=$MH_TEST_DIR mktemp -d`
 cd $tempdir
 
 msgfile=`mhpath b`
diff --git a/test/tests/new/test-empty-seq b/test/tests/new/test-empty-seq
new file mode 100644 (file)
index 0000000..f134f27
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+# TODO: Move to a common file tests can source; need more framework...
+failed=0
+check() {
+    diff -u $expected $actual
+    if [ $? -ne 0 ]; then
+        failed=$((failed + 1))
+    fi
+}
+
+folders=$MH_TEST_DIR/Mail/.folders
+
+expected=$MH_TEST_DIR/$$.expected
+actual=$MH_TEST_DIR/$$.actual
+
+# make second folder
+cp -r $MH_TEST_DIR/Mail/inbox $MH_TEST_DIR/Mail/foo1
+cp -r $MH_TEST_DIR/Mail/inbox $MH_TEST_DIR/Mail/foo2
+# but only list inbox and foo2 in .folders, and sorted differently
+cat > $folders <<EOF
+inbox
+foo2
+EOF
+
+# Add a sequence, which has no messages in it
+echo empty: >>"$MH_TEST_DIR/Mail/foo2/.mh_sequences"
+
+# test with the empty sequence
+cat > $expected <<EOF
+ total      0.
+EOF
+new empty > $actual 2>&1
+check
+new -folders $folders empty > $actual 2>&1
+check
+
+# test fnext/fprev with the empty sequence
+> $expected
+fnext empty > $actual 2>&1
+check
+fprev empty > $actual 2>&1
+check
+
index 0d843c3..a7a6356 100644 (file)
@@ -10,6 +10,22 @@ export LC_ALL
 
 
 cat >"$MH_TEST_DIR/Mail/inbox/11" <<!
+Mime-Version: 1.0
+From: Bar <bar@example.org>
+To: Baz <baz@example.org>
+Subject: Subject Test Header
+ =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88?=
+ =?UTF-8?q?=E3=83=98=E3=83=BC=E3=83=87=E3=83=BC?=
+Date: Mon, 15 May 2017 15:55:01 +0900
+Content-Transfer-Encoding: quoted-printable
+Content-Type: text/plain; charset=UTF-8
+Message-Id: <20170515065506.03959103B49@example.org>
+
+This is a test email
+
+!
+
+cat >"$MH_TEST_DIR/Mail/inbox/12" <<!
 Subject: =?iso-8859-1?Q?Schl=FCssel?=
 Mime-Version: 1.0
 From: Bob <bob@example.org>
@@ -30,13 +46,22 @@ Bob
 
 !
 
-runandcheck "scan 11 +inbox" <<!
-  11  2014-09-22 01:17  Bob                Schlüssel
+runandcheck "scan 12 +inbox" <<!
+  12  2014-09-22 01:17  Bob                Schlüssel
+!
+
+runandcheck "scan 11-12 +inbox -width 80" <<!
+  11  2017-05-15 15:55  Bar                Subject Test Header ãƒ†ã‚¹ãƒˆãƒ˜ãƒ¼
+  12  2014-09-22 01:17  Bob                Schlüssel
 !
 
+runandcheck "scan 11-12 +inbox -width 49" <<!
+  11  2017-05-15 15:55  Bar                Subje
+  12  2014-09-22 01:17  Bob                Schlü
+!
 
 LC_ALL=C
 unset MM_CHARSET
-runandcheck "scan 11 +inbox" <<!
-  11  2014-09-22 01:17  Bob                Schl?ssel
+runandcheck "scan 12 +inbox" <<!
+  12  2014-09-22 01:17  Bob                Schl?ssel
 !
index 3de45d7..f5a18aa 100644 (file)
@@ -21,7 +21,7 @@ Subject: Test MIME
 foo
 !
 
-runandcheck 'send -debug "$draft" | sed "/^Content-ID/s/:.*/: <TESTID>/"' <<!
+runandcheck 'send -debug "$draft" | replace_contentid' <<!
 From: Bob <bob@example.org>
 To: alice
 Date: Sun, 25 Oct 2015 18:59:56 +0100
@@ -70,7 +70,7 @@ Date: Fri, 05 Aug 2016 21:38:40 +0200
 --------
 foo
 !
-runandcheck 'send -debug "$draft" | sed "/^Content-ID/s/:.*/: <TESTID>/"' <<!
+runandcheck 'send -debug "$draft" | replace_contentid' <<!
 To: meillo
 Subject: mime test 1
 Date: Fri, 05 Aug 2016 21:38:40 +0200
@@ -93,7 +93,7 @@ Date: Fri, 05 Aug 2016 21:38:56 +0200
 foo
 füße
 !
-runandcheck 'send -debug "$draft" | sed "/^Content-ID/s/:.*/: <TESTID>/"' <<!
+runandcheck 'send -debug "$draft" | replace_contentid' <<!
 To: meillo
 Subject: mime test 2
 Date: Fri, 05 Aug 2016 21:38:56 +0200
@@ -119,7 +119,7 @@ Date: Fri, 05 Aug 2016 21:42:16 +0200
 --------
 foo
 !
-runandcheck 'send -debug "$draft" | sed "/^Content-ID/s/:.*/: <TESTID>/"' <<!
+runandcheck 'send -debug "$draft" | replace_contentid' <<!
 To: meillo
 Subject: mime test 3
 MIME-Version: 1.0
@@ -201,9 +201,13 @@ end
 !
 runandcheck 'mhbuild "$draft"' <<!
 !
+
+# Use static Content-ID headers values for reproducible results
+replace_contentid "$draft" >"$draft.temp" && mv "$draft.temp" "$draft"
+
 runandcheck 'mhlist -v -file "$draft"' <<!
  msg part  type/subtype              size description                         
-   0       multipart/mixed           2623
+   0       multipart/mixed           2343
                boundary="----- =_aaaaaaaaaa0"
      1     text/plain                   4
                charset="us-ascii"
@@ -213,7 +217,7 @@ runandcheck 'mhlist -v -file "$draft"' <<!
                charset="us-ascii"
      4     text/plain                   6
                charset="UTF-8"
-     5     multipart/alternative     1663 Picture of an Amphioctopus marginatu
+     5     multipart/alternative     1593 Picture of an Amphioctopus marginatu
                boundary="----- =_aaaaaaaaaa1"
      5.1   text/plain                  87
                charset="us-ascii"
@@ -221,7 +225,7 @@ runandcheck 'mhlist -v -file "$draft"' <<!
      6     text/plain                   4
                charset="us-ascii"
 !
-runandcheck 'send -debug "$draft" | sed "/^Content-ID/s/:.*/: <TESTID>/"' <<!
+runandcheck 'send -debug "$draft"' <<!
 To: meillo
 Subject: mime test 6
 Date: Fri, 05 Aug 2016 21:46:20 +0200
diff --git a/test/tests/show/test-longlines b/test/tests/show/test-longlines
new file mode 100644 (file)
index 0000000..f6ae126
--- /dev/null
@@ -0,0 +1,173 @@
+#!/bin/sh
+######################################################
+#
+# Test long header line handling (998 chars)
+#
+######################################################
+
+set -e
+
+expected=$MH_TEST_DIR/$$.expected
+actual=$MH_TEST_DIR/$$.actual
+
+genlongsubject() {
+       len="${1:-998}"
+       awk -v len="$len" 'BEGIN {
+               prefix = "Subject: " len " "
+               while (i++<len) {
+                       s = s "x"
+               }
+               print prefix substr(s, length(prefix) + 1)
+       }'
+}
+
+addcr() {
+       awk '{printf($0 "\r\n")}'
+}
+
+
+# Ensure lines won't get folded
+echo "mhl: -width 2000" >> "$MMH/profile"
+trap 'printf "/^mhl:/d\nw\nq\n" | ed - "$MMH/profile"' 0 1 2 15
+
+
+len=997
+
+# Write message with long header line
+msgfile=$(mhpath b)
+msgnum=$(basename $msgfile)
+cat > $msgfile <<-EOF
+From: foo@example.edu
+To: bar@example.edu
+`genlongsubject $len`
+Date: Sun, 15 Jul 2018 12:26:59 +0200
+
+foo
+EOF
+
+# check it
+cat > $expected <<-EOF
+Date:    Sun, 15 Jul 2018 12:26:59 +0200
+From:    foo@example.edu
+To:      bar@example.edu
+`genlongsubject $len`
+
+part       text/plain                   4
+foo
+EOF
+
+COLUMNS=2000 show $msgnum > $actual 2>&1
+diff -u $expected $actual
+
+
+len=998
+
+# Write message with long header line
+msgfile=$(mhpath b)
+msgnum=$(basename $msgfile)
+cat > $msgfile <<-EOF
+From: foo@example.edu
+To: bar@example.edu
+`genlongsubject $len`
+Date: Sun, 15 Jul 2018 12:26:59 +0200
+
+foo
+EOF
+
+# check it
+cat > $expected <<-EOF
+Date:    Sun, 15 Jul 2018 12:26:59 +0200
+From:    foo@example.edu
+To:      bar@example.edu
+`genlongsubject $len`
+
+part       text/plain                   4
+foo
+EOF
+
+COLUMNS=2000 show $msgnum > $actual 2>&1
+diff -u $expected $actual
+
+
+len=999
+
+# Write message with long header line
+msgfile=$(mhpath b)
+msgnum=$(basename $msgfile)
+cat > $msgfile <<-EOF
+From: foo@example.edu
+To: bar@example.edu
+`genlongsubject $len`
+Date: Sun, 15 Jul 2018 12:26:59 +0200
+
+foo
+EOF
+
+# check it
+cat > $expected <<-EOF
+mhl: format error in message 13
+part       text/plain                   4
+foo
+EOF
+
+COLUMNS=2000 show $msgnum > $actual 2>&1
+diff -u $expected $actual
+
+
+
+# now with CRLF
+
+
+len=998
+
+# Write message with long header line
+msgfile=$(mhpath b)
+msgnum=$(basename $msgfile)
+cat > $msgfile <<-EOF
+From: foo@example.edu
+To: bar@example.edu
+`genlongsubject $len | addcr`
+Date: Sun, 15 Jul 2018 12:26:59 +0200
+
+foo
+EOF
+
+# check it
+cat > $expected <<-EOF
+Date:    Sun, 15 Jul 2018 12:26:59 +0200
+From:    foo@example.edu
+To:      bar@example.edu
+`genlongsubject $len`
+
+part       text/plain                   4
+foo
+EOF
+
+COLUMNS=2000 show $msgnum > $actual 2>&1
+diff -u $expected $actual
+
+
+len=999
+
+# Write message with long header line
+msgfile=$(mhpath b)
+msgnum=$(basename $msgfile)
+cat > $msgfile <<-EOF
+From: foo@example.edu
+To: bar@example.edu
+`genlongsubject $len | addcr`
+Date: Sun, 15 Jul 2018 12:26:59 +0200
+
+foo
+EOF
+
+# check it
+cat > $expected <<-EOF
+mhl: format error in message 15
+part       text/plain                   4
+foo
+EOF
+
+COLUMNS=2000 show $msgnum > $actual 2>&1
+diff -u $expected $actual
+
index a758fe0..f037ec1 100644 (file)
@@ -241,7 +241,7 @@ install-cmds:
        done
 
 # install links
-install-lcmds:
+install-lcmds: install-cmds
        rm -f $(DESTDIR)$(bindir)/flists
        rm -f $(DESTDIR)$(bindir)/folders
        rm -f $(DESTDIR)$(bindir)/fnext
index b00f51b..3faa373 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <h/mh.h>
 #include <h/aliasbr.h>
+#include <h/addrsbr.h>
 #include <h/utils.h>
 #include <grp.h>
 #include <pwd.h>
@@ -99,9 +100,47 @@ akval(struct aka *ak, char *s)
        if (!s)
                return s;  /* XXX */
 
-       for (; ak; ak = ak->ak_next)
-               if (aleq(s, ak->ak_name))
-                       return akresult(ak);
+       for (; ak; ak = ak->ak_next) {
+               if (aleq (s, ak->ak_name)) {
+                       return akresult (ak);
+               } else if (strchr (s, ':')) {
+                       /*
+                       ** The first address in a blind list will contain the
+                       ** alias name, so try to match, but just with just the
+                       ** address (not including the list name).  If there's a
+                       ** match, then replace the alias part with its
+                       ** expansion.
+                       */
+
+                       char *name = getname(s);
+                       char *cp = NULL;
+
+                       if (name) {
+                               /*
+                               ** s is of the form "Blind list: address".  If address
+                               ** is an alias, expand it.
+                               */
+                               struct mailname *mp = getm(name, NULL, 0, AD_NAME, NULL);
+
+                               if (mp  &&  mp->m_ingrp) {
+                                       char *gname = add (mp->m_gname, NULL);
+
+                                       if (gname  &&  aleq(name, ak->ak_name)) {
+                                               /* Will leak cp. */
+                                               cp = concat (gname, akresult (ak), NULL);
+                                               free(gname);
+                                       }
+                               }
+                       mnfree(mp);
+                       }
+                       /* Need to flush getname after use. */
+                       while (getname("")) continue;
+
+                       if (cp) {
+                               return cp;
+                       }
+               }
+       }
 
        return mh_xstrdup(s);
 }
index a84703b..fa83602 100644 (file)
--- a/uip/mhl.c
+++ b/uip/mhl.c
@@ -77,7 +77,9 @@ char *version=VERSION;
 #define INIT        0x000800  /* initialize component        */
 #define SPLIT       0x001000  /* split headers (don't concatenate) */
 #define NONEWLINE   0x002000  /* don't write trailing newline */
-#define LBITS       "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07LEFTADJUST\010COMPRESS\011ADDRFMT\012DATEFMT\013FORMAT\014INIT\015SPLIT\016NONEWLINE"
+#define RTRIM       0x004000  /* trim trailing whitespace    */
+#define RAW         0x008000  /* print the raw input         */
+#define LBITS       "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07LEFTADJUST\010COMPRESS\011ADDRFMT\012DATEFMT\013FORMAT\014INIT\015SPLIT\016NONEWLINE\017RTRIM\020RAW"
 #define GFLAGS      (NOCOMPONENT | UPPERCASE | CENTER | LEFTADJUST | COMPRESS | SPLIT)
 
 struct mcomp {
@@ -138,19 +140,22 @@ struct triple {
 
 static struct triple triples[] = {
        { "nocomponent",  NOCOMPONENT, 0 },
-       { "uppercase", UPPERCASE, 0 },
+       { "uppercase", UPPERCASE, RAW },
        { "nouppercase", 0, UPPERCASE },
-       { "center", CENTER, 0 },
+       { "center", CENTER, RAW },
        { "nocenter", 0, CENTER },
-       { "leftadjust", LEFTADJUST, 0 },
+       { "leftadjust", LEFTADJUST, RAW },
        { "noleftadjust", 0, LEFTADJUST },
-       { "compress", COMPRESS, 0 },
+       { "compress", COMPRESS, RAW },
        { "nocompress", 0, COMPRESS },
        { "split", SPLIT, 0 },
        { "nosplit", 0, SPLIT },
-       { "addrfield", ADDRFMT, DATEFMT },
-       { "datefield", DATEFMT, ADDRFMT },
-       { "newline", 0, NONEWLINE },
+       { "rtrim", RTRIM, RAW },
+       { "nortrim", 0, RTRIM },
+       { "raw", RAW|SPLIT|NOCOMPONENT|NONEWLINE, UPPERCASE|CENTER|LEFTADJUST|COMPRESS|DATEFMT|ADDRFMT },
+       { "addrfield", ADDRFMT, DATEFMT|RAW },
+       { "datefield", DATEFMT, ADDRFMT|RAW },
+       { "newline", 0, NONEWLINE|RAW },
        { "nonewline", NONEWLINE, 0 },
        { NULL, 0, 0 }
 };
@@ -595,6 +600,34 @@ process(char *fname, int ofilen, int ofilec)
                c1->c_flags &= ~HDROUTPUT;
 }
 
+static boolean
+simplematch(char *pattern, char *b)
+{
+       char *match = strrchr(pattern, '*');
+       char repl;
+       boolean ret;
+
+       /* check if pattern ends with a * and is not escaped witch a \ */
+       if (!match || match[1] || (match > pattern && match[-1] == '\\')) {
+               if (!match || match[1]) {
+                       return mh_strcasecmp(pattern, b) == 0;
+               }
+               match[0] = '\0';
+               match[-1] = '*';
+               ret = mh_strcasecmp(pattern, b)==0;
+               match[-1] = '\\';
+               match[0] = '*';
+               return ret;
+       }
+
+       repl = b[match-pattern];
+       b[match-pattern] = '\0';
+       *match = '\0';
+       ret = (mh_strcasecmp(pattern, b) == 0);
+       b[match-pattern] = repl;
+       *match = '*';
+       return ret;
+}
 
 static void
 mhlfile(FILE *fp, char *mname, int ofilen, int ofilec)
@@ -623,7 +656,7 @@ mhlfile(FILE *fp, char *mname, int ofilen, int ofilec)
                switch (state = m_getfld2(state, &f, fp)) {
                case FLD2:
                        for (ip = ignores; *ip; ip++)
-                               if (mh_strcasecmp(f.name, *ip)==0) {
+                               if (simplematch(*ip, f.name)) {
                                        break;
                                }
                        if (*ip) {
@@ -878,13 +911,15 @@ free_queue(struct mcomp **head, struct mcomp **tail)
        *head = *tail = NULL;
 }
 
-
 static void
 putcomp(struct mcomp *c1, struct mcomp *c2, int flag)
 {
        int count, cchdr;
        unsigned char *cp;
+       char trimmed_prefix[BUFSIZ];
 
+       strncpy(trimmed_prefix, c1->c_text ? c1->c_text : c1->c_name, sizeof(trimmed_prefix) - 1);
+       rtrim(trimmed_prefix);
        cchdr = 0;
        lm = 0;
        wid = c1->c_width ? c1->c_width : global.c_width;
@@ -897,11 +932,28 @@ putcomp(struct mcomp *c1, struct mcomp *c2, int flag)
        onelp = NULL;
 
        if (c1->c_flags & CLEARTEXT) {
-               putstr(c1->c_text);
+               putstr((c1->c_flags & RTRIM) ? rtrim(c1->c_text) : c1->c_text);
                putstr("\n");
                return;
        }
 
+       if (c1->c_flags & RAW) {
+               switch (flag) {
+               case ONECOMP:
+                       printf("%s:%s", c1->c_name, c1->c_text);
+                       break;
+               case TWOCOMP:
+                       printf("%s:%s", c2->c_name, c2->c_text);
+                       break;
+               case BODYCOMP:
+                       fputs(c2->c_text, stdout);
+                       break;
+               default:
+                       adios(EX_SOFTWARE, NULL, "BUG: putcomp() is called with a unknown flag");
+               }
+               return;
+       }
+
        if (c1->c_fstr && (c1->c_flags & (ADDRFMT | DATEFMT | FORMAT)))
                mcomp_format(c1, c2);
 
@@ -922,7 +974,11 @@ putcomp(struct mcomp *c1, struct mcomp *c2, int flag)
                        for (cp = (c1->c_text ? c1->c_text : c1->c_name); *cp; cp++)
                                if (islower(*cp))
                                        *cp = toupper(*cp);
-               putstr(c1->c_text ? c1->c_text : c1->c_name);
+               if (*c2->c_text && *c2->c_text != '\n' && *c2->c_text != '\r') {
+                       putstr(c1->c_text ? c1->c_text : c1->c_name);
+               } else {
+                       putstr(trimmed_prefix);
+               }
                if (flag != BODYCOMP) {
                        putstr(": ");
                        if (!(c1->c_flags & SPLIT))
@@ -970,16 +1026,23 @@ putcomp(struct mcomp *c1, struct mcomp *c2, int flag)
        }
        count += c1->c_offset;
 
-       if ((cp = oneline(c2->c_text, c1->c_flags)))
-          putstr(cp);
+       if ((cp = oneline(c2->c_text, c1->c_flags))) {
+               putstr((c1->c_flags & RTRIM) ? rtrim(cp) : cp);
+       }
        if (term == '\n')
                putstr("\n");
        while ((cp = oneline(c2->c_text, c1->c_flags))) {
                lm = count;
-               if (flag == BODYCOMP && !(c1->c_flags & NOCOMPONENT))
-                       putstr(c1->c_text ? c1->c_text : c1->c_name);
+               if (flag == BODYCOMP && !(c1->c_flags & NOCOMPONENT)) {
+                       if (*cp) {
+                               putstr(c1->c_text ? c1->c_text : c1->c_name);
+                       } else {
+                               putstr(trimmed_prefix);
+                       }
+               }
                if (*cp)
-                       putstr(cp);
+                       putstr((c1->c_flags & RTRIM) ? rtrim(cp) : cp);
+
                if (term == '\n')
                        putstr("\n");
        }
@@ -987,7 +1050,6 @@ putcomp(struct mcomp *c1, struct mcomp *c2, int flag)
                c1->c_flags &= ~HDROUTPUT;  /* Buffer ended on a newline */
 }
 
-
 static char *
 oneline(char *stuff, long flags)
 {
@@ -1037,7 +1099,6 @@ oneline(char *stuff, long flags)
        return ret;
 }
 
-
 static void
 putstr(char *string)
 {
index 39a3f69..894ca5e 100755 (executable)
@@ -101,6 +101,12 @@ lookupkeyring() {
        return 0
 }
 
+### Do a best guess at FQDN
+mh_hostname()
+{
+       hostname -f 2>/dev/null || uname -n
+}
+
 ### lookupkeys file -- set $KL to list of recipient keys
 lookupkeys() {
        KL=
@@ -120,7 +126,7 @@ lookupkeys() {
                '|'*)   echo "Ignoring pipe address" >&2
                        continue ;;
                *@*)    ;;
-               *)      i="$i@`hostname -f`" ;;
+               *)      i="$i@`mh_hostname`" ;;
                esac
                if k=`lookupkeyfile "$i"` ; then
                        KL="$KL $k"
index 9763376..21435b3 100644 (file)
--- a/uip/new.c
+++ b/uip/new.c
@@ -121,7 +121,10 @@ get_msgnums(char *folder, char *sequences[])
                        */
                        if (seq_in_list(f.name, sequences)) {
                                this_msgnums = trimcpy(f.value);
-                               if (msgnums == NULL) {
+                               if (strlen(this_msgnums) == 0) {
+                                       free(this_msgnums);
+                                       continue;
+                               } else if (msgnums == NULL) {
                                        msgnums = this_msgnums;
                                } else {
                                        old_msgnums = msgnums;
index 39d8ada..fd0cbcc 100644 (file)
@@ -245,7 +245,7 @@ main(int argc, char **argv)
                        finish_headers(out);
                        fprintf(out, "\n%s", f.value);
                        while ((state = m_getfld2(state, &f, in)) == BODY2) {
-                               if (f.valuelen >= NAMESZ) {
+                               if (f.valuelen > NAMESZ+1 || (!f.crlf && f.valuelen > NAMESZ)) {
                                        adios(EX_DATAERR, NULL, "Body contains a to long line");
                                }
                                fputs(f.value, out);
index 59e91b7..91ff5a5 100755 (executable)
@@ -92,10 +92,14 @@ create()
        fi
        mhmetafile=$mhdraft.meta
        touch $mhmetafile
-       if [ -z $mheditor ]
+       if [ -z "$mheditor" ]
        then
                get_editor
        fi
+       if [ "$mhuse" -eq 1 ]
+       then
+               return
+       fi
        if [ -n "$mhaltmsg" ]
        then
                anno -nodate -component 'mhaltmsg' -text "$mhaltmsg" $mhmetafile
@@ -104,10 +108,6 @@ create()
        then
                anno -nodate -component 'mhdist' -text "$mhdist" $mhmetafile
        fi
-       if [ -n "$mhdist" ]
-       then
-               anno -nodate -component 'mhuse' -text "$mhuse" $mhmetafile
-       fi
        if [ -n "$mhfolder" ]
        then
                anno -nodate -component 'mhfolder' -text "$mhfolder" $mhmetafile
@@ -145,23 +145,22 @@ list()
 
 sendfunktion()
 {
-       export mhaltmsg=`anno -list -component 'mhaltmsg' $mhmetafile`
-       export mhdist=`anno -list -component 'mhdist' $mhmetafile`
-       export mhuse=`anno -list -component 'mhuse' $mhmetafile`
-       export mhfolder=`anno -list -component 'mhfolder' $mhmetafile`
-       export mhmessages=`anno -list -component 'mhmessages' $mhmetafile`
-       export mhannotate=`anno -list -component 'mhannotate' $mhmetafile`
-       send "$@" $mhdraft || exit $?
-       rm -f $mhmetafile
+       export mhaltmsg=`anno -list -component 'mhaltmsg' "$mhmetafile"`
+       export mhdist=`anno -list -component 'mhdist' "$mhmetafile"`
+       export mhfolder=`anno -list -component 'mhfolder' "$mhmetafile"`
+       export mhmessages=`anno -list -component 'mhmessages' "$mhmetafile"`
+       export mhannotate=`anno -list -component 'mhannotate' "$mhmetafile"`
+       send "$@" "$mhdraft" || exit $?
+       rm -f "$mhmetafile"
        exit 0
 }
 
 delete()
 {
-       folder -push $draftfolder >/dev/null 2>&1
-       rmm $draftfolder c
+       folder -push "$draftfolder" >/dev/null 2>&1
+       rmm "$draftfolder" c
        folder -pop >/dev/null 2>&1
-       rm $mhmetafile
+       rm "$mhmetafile"
 }
 
 attach()
@@ -179,7 +178,7 @@ attach()
                        exit 1
                fi
                file=`get_realpath "$1"`
-               anno -nodate -append -component $header -text "$file" $mhdraft
+               anno -nodate -append -component "$header" -text "$file" "$mhdraft"
                shift
        done
 }
@@ -187,7 +186,7 @@ attach()
 alist()
 {
        header=`mhparam 'Attachment-Header'`
-       anno -list -number -component $header $mhdraft
+       anno -list -number -component "$header" "$mhdraft"
 }
 
 detach()
@@ -195,7 +194,7 @@ detach()
        header=`mhparam 'Attachment-Header'`
        while [ -n "$1" ]
        do
-               anno -delete -component $header -number "$1" $mhdraft
+               anno -delete -component "$header" -number "$1" "$mhdraft"
                if [ $? -ne 0 ]
                then
                        echo "can't delet attachment $1" 1>&2
@@ -207,14 +206,14 @@ detach()
 
 display()
 {
-       mhaltmsg=`anno -list -component 'mhaltmsg' $mhmetafile`
+       mhaltmsg=`anno -list -component 'mhaltmsg' "$mhmetafile"`
        get_showproc
        if [ -z "$mhaltmsg" ]
        then
                echo "no altmsg" 1>&2
                exit 1
        fi
-       exec $mhshowproc -file $mhaltmsg
+       exec $mhshowproc -file "$mhaltmsg"
 }
 
 if [ $# -eq 0 ]
@@ -223,19 +222,19 @@ then
        exit
 fi
 
-command=$1
+command="$1"
 shift
 
 draftfolder=`mhparam draftfolder`
 
-mhdraft=`mhpath $draftfolder c 2>/dev/null`
+mhdraft=`mhpath "$draftfolder" c 2>/dev/null`
 if [ -z "$mhdraft" ]
 then
-       case $command in
-       -h*)
+       case "$command" in
+       -h|-he|-hel|-help)
                usage $#
                ;;
-       -V*)
+       -V|-Ve|-Ver|-Vers|-Versi|-Versio|-Version)
                version $#
                ;;
        *)
@@ -244,11 +243,11 @@ then
                ;;
        esac
 fi
-mhmetafile=$mhdraft.meta
-touch $mhmetafile
+mhmetafile="$mhdraft".meta
+touch "$mhmetafile"
 
 
-case $command in
+case "$command" in
 e|ed|edi|edit)
        edit "$@"
        ;;
@@ -278,10 +277,10 @@ det|deta|detac|detach)
        detach "$@"
        ;;
 r|re|ref|refi|refil|refile)
-       refile -file $mhdraft "$@"
+       refile -file "$mhdraft" "$@"
        ;;
 w|wh|who|whom)
-       whom "$@" $mhdraft
+       whom "$@" "$mhdraft"
        ;;
 -h|-he|-hel|-help)
        usage $#