mh: improve mhn store mode.
* mh/mhn.c (options): Add --build as an alias to --compose. (options): Likewise. (store_destination): New enum. (mhn_store_command): Support all variants of mhn-store-* components. Return store_destination type. (store_handler): Rewrite accordingly. (main): Consistently use mh_expand_name to expand the value of input_file. * mh/tests/mhn.at: New file. * mh/tests/Makefile.am (TESTSUITE_AT): Add mhn.at. * mh/tests/testsuite.at: Include mhn.at.
Showing
4 changed files
with
320 additions
and
58 deletions
... | @@ -39,7 +39,11 @@ static struct argp_option options[] = { | ... | @@ -39,7 +39,11 @@ static struct argp_option options[] = { |
39 | {N_("MIME editing options"), 0, NULL, OPTION_DOC, NULL, GRID}, | 39 | {N_("MIME editing options"), 0, NULL, OPTION_DOC, NULL, GRID}, |
40 | {"compose", ARG_COMPOSE, N_("BOOL"), OPTION_ARG_OPTIONAL, | 40 | {"compose", ARG_COMPOSE, N_("BOOL"), OPTION_ARG_OPTIONAL, |
41 | N_("compose the MIME message (default)"), GRID+1}, | 41 | N_("compose the MIME message (default)"), GRID+1}, |
42 | {"nocompose", ARG_NOCOMPOSE, NULL, OPTION_HIDDEN, "", GRID+1}, | 42 | {"build", 0, NULL, OPTION_ALIAS, |
43 | NULL, GRID+1 }, | ||
44 | {"nocompose", ARG_NOCOMPOSE, NULL, OPTION_HIDDEN, NULL, GRID+1}, | ||
45 | {"nobuild", ARG_NOCOMPOSE, NULL, OPTION_HIDDEN|OPTION_ALIAS, | ||
46 | NULL, GRID+1}, | ||
43 | #undef GRID | 47 | #undef GRID |
44 | #define GRID 20 | 48 | #define GRID 20 |
45 | {N_("Listing options"), 0, NULL, OPTION_DOC, NULL, GRID}, | 49 | {N_("Listing options"), 0, NULL, OPTION_DOC, NULL, GRID}, |
... | @@ -97,6 +101,7 @@ static struct argp_option options[] = { | ... | @@ -97,6 +101,7 @@ static struct argp_option options[] = { |
97 | struct mh_option mh_option[] = { | 101 | struct mh_option mh_option[] = { |
98 | { "file", MH_OPT_ARG, "filename" }, | 102 | { "file", MH_OPT_ARG, "filename" }, |
99 | { "compose" }, | 103 | { "compose" }, |
104 | { "build" }, | ||
100 | { "list", MH_OPT_BOOL }, | 105 | { "list", MH_OPT_BOOL }, |
101 | { "headers", MH_OPT_BOOL }, | 106 | { "headers", MH_OPT_BOOL }, |
102 | { "realsize", MH_OPT_BOOL }, | 107 | { "realsize", MH_OPT_BOOL }, |
... | @@ -801,18 +806,71 @@ mhn_show_command (mu_message_t msg, msg_part_t part, int *flags, | ... | @@ -801,18 +806,71 @@ mhn_show_command (mu_message_t msg, msg_part_t part, int *flags, |
801 | return (char*) str; | 806 | return (char*) str; |
802 | } | 807 | } |
803 | 808 | ||
804 | char * | 809 | enum store_destination |
805 | mhn_store_command (mu_message_t msg, msg_part_t part, char *name) | 810 | { |
811 | store_to_folder, | ||
812 | store_to_folder_msg, | ||
813 | store_to_file, | ||
814 | store_to_command, | ||
815 | store_to_stdout | ||
816 | }; | ||
817 | |||
818 | enum store_destination | ||
819 | mhn_store_command (mu_message_t msg, msg_part_t part, const char *name, | ||
820 | char **return_string) | ||
806 | { | 821 | { |
807 | const char *p, *str, *tmp; | 822 | const char *p, *str, *tmp; |
808 | char *typestr, *type, *subtype, *typeargs; | 823 | char *typestr, *type, *subtype, *typeargs; |
809 | struct obstack stk; | 824 | struct obstack stk; |
810 | mu_header_t hdr; | 825 | mu_header_t hdr; |
826 | enum store_destination dest; | ||
811 | 827 | ||
812 | mu_message_get_header (msg, &hdr); | 828 | mu_message_get_header (msg, &hdr); |
813 | _get_content_type (hdr, &typestr, &typeargs); | 829 | _get_content_type (hdr, &typestr, &typeargs); |
814 | split_content (typestr, &type, &subtype); | 830 | split_content (typestr, &type, &subtype); |
815 | str = _mhn_profile_get ("store", type, subtype, "%m%P.%s"); | 831 | str = _mhn_profile_get ("store", type, subtype, NULL); |
832 | |||
833 | if (!str) | ||
834 | { | ||
835 | /* FIXME: | ||
836 | [If the mhn-store component] isn't found, mhn will check to see if | ||
837 | the content is application/octet-stream with parameter "type=tar". | ||
838 | If so, mhn will choose an appropriate filename. | ||
839 | */ | ||
840 | |||
841 | if (mu_c_strcasecmp (type, "message") == 0) | ||
842 | { | ||
843 | /* If the content is not application/octet-stream, then mhn | ||
844 | will check to see if the content is a message. If so, mhn | ||
845 | will use the value "+". */ | ||
846 | *return_string = xstrdup (mh_current_folder ()); | ||
847 | return store_to_folder_msg; | ||
848 | } | ||
849 | else | ||
850 | str = "%m%P.%s"; | ||
851 | } | ||
852 | |||
853 | switch (str[0]) | ||
854 | { | ||
855 | case '+': | ||
856 | if (str[1]) | ||
857 | *return_string = xstrdup (str); | ||
858 | else | ||
859 | *return_string = xstrdup (mh_current_folder ()); | ||
860 | return store_to_folder; | ||
861 | |||
862 | case '-': | ||
863 | *return_string = NULL; | ||
864 | return store_to_stdout; | ||
865 | |||
866 | case '|': | ||
867 | dest = store_to_command; | ||
868 | str = mu_str_skip_class (str + 1, MU_CTYPE_SPACE); | ||
869 | break; | ||
870 | |||
871 | default: | ||
872 | dest = store_to_file; | ||
873 | } | ||
816 | 874 | ||
817 | /* Expand macro-notations: | 875 | /* Expand macro-notations: |
818 | %m message number | 876 | %m message number |
... | @@ -880,12 +938,12 @@ mhn_store_command (mu_message_t msg, msg_part_t part, char *name) | ... | @@ -880,12 +938,12 @@ mhn_store_command (mu_message_t msg, msg_part_t part, char *name) |
880 | str = obstack_finish (&stk); | 938 | str = obstack_finish (&stk); |
881 | p = mu_str_skip_class (str, MU_CTYPE_SPACE); | 939 | p = mu_str_skip_class (str, MU_CTYPE_SPACE); |
882 | if (!*p) | 940 | if (!*p) |
883 | str = NULL; | 941 | *return_string = NULL; |
884 | else | 942 | else |
885 | str = xstrdup (p); | 943 | *return_string = xstrdup (p); |
886 | 944 | ||
887 | obstack_free (&stk, NULL); | 945 | obstack_free (&stk, NULL); |
888 | return (char*) str; | 946 | return dest; |
889 | } | 947 | } |
890 | 948 | ||
891 | 949 | ||
... | @@ -1539,13 +1597,14 @@ int | ... | @@ -1539,13 +1597,14 @@ int |
1539 | store_handler (mu_message_t msg, msg_part_t part, char *type, char *encoding, | 1597 | store_handler (mu_message_t msg, msg_part_t part, char *type, char *encoding, |
1540 | void *data) | 1598 | void *data) |
1541 | { | 1599 | { |
1542 | char *prefix = data; | 1600 | const char *prefix = data; |
1543 | char *name = NULL; | 1601 | char *name = NULL; |
1544 | char *tmp; | 1602 | char *partstr; |
1545 | int ismime; | 1603 | int ismime; |
1546 | int rc; | 1604 | int rc; |
1547 | mu_stream_t out; | 1605 | mu_stream_t out; |
1548 | const char *dir = mh_global_profile_get ("mhn-storage", NULL); | 1606 | const char *dir = mh_global_profile_get ("mhn-storage", NULL); |
1607 | enum store_destination dest = store_to_file; | ||
1549 | 1608 | ||
1550 | if (mu_message_is_multipart (msg, &ismime) == 0 && ismime) | 1609 | if (mu_message_is_multipart (msg, &ismime) == 0 && ismime) |
1551 | return 0; | 1610 | return 0; |
... | @@ -1559,6 +1618,7 @@ store_handler (mu_message_t msg, msg_part_t part, char *type, char *encoding, | ... | @@ -1559,6 +1618,7 @@ store_handler (mu_message_t msg, msg_part_t part, char *type, char *encoding, |
1559 | { | 1618 | { |
1560 | name = normalize_path (dir, val); | 1619 | name = normalize_path (dir, val); |
1561 | free (val); | 1620 | free (val); |
1621 | dest = store_to_file; | ||
1562 | } | 1622 | } |
1563 | else if (rc != MU_ERR_NOENT) | 1623 | else if (rc != MU_ERR_NOENT) |
1564 | { | 1624 | { |
... | @@ -1571,57 +1631,126 @@ store_handler (mu_message_t msg, msg_part_t part, char *type, char *encoding, | ... | @@ -1571,57 +1631,126 @@ store_handler (mu_message_t msg, msg_part_t part, char *type, char *encoding, |
1571 | } | 1631 | } |
1572 | 1632 | ||
1573 | if (!name) | 1633 | if (!name) |
1574 | { | 1634 | dest = mhn_store_command (msg, part, prefix, &name); |
1575 | char *fname = mhn_store_command (msg, part, prefix); | 1635 | |
1576 | if (dir) | 1636 | partstr = msg_part_format (part); |
1577 | name = mh_safe_make_file_name (dir, fname); | 1637 | /* Set prefix for diagnostic purposes */ |
1578 | else | 1638 | if (!prefix) |
1579 | name = fname; | 1639 | prefix = mu_umaxtostr (0, msg_part_subpart (part, 0)); |
1580 | } | 1640 | out = NULL; |
1581 | 1641 | rc = 0; | |
1582 | tmp = msg_part_format (part); | 1642 | switch (dest) |
1583 | if (prefix) | 1643 | { |
1584 | printf (_("storing message %s part %s as file %s\n"), | 1644 | case store_to_folder_msg: |
1585 | prefix, | 1645 | case store_to_folder: |
1586 | tmp, | 1646 | { |
1587 | name); | 1647 | mu_mailbox_t mbox = mh_open_folder (name, 1); |
1588 | else | 1648 | size_t uid; |
1589 | printf (_("storing message %s part %s as file %s\n"), | 1649 | |
1590 | mu_umaxtostr (0, msg_part_subpart (part, 0)), | 1650 | mu_mailbox_uidnext (mbox, &uid); |
1591 | tmp, | 1651 | printf (_("storing message %s part %s to folder %s as message %lu\n"), |
1592 | name); | 1652 | prefix, partstr, name, (unsigned long) uid); |
1593 | free (tmp); | 1653 | if (dest == store_to_folder_msg) |
1594 | 1654 | { | |
1595 | if (!(mode_options & OPT_QUIET) && access (name, R_OK) == 0) | 1655 | mu_body_t body; |
1596 | { | 1656 | mu_stream_t str; |
1597 | char *p; | 1657 | mu_message_t tmpmsg; |
1598 | int rc; | 1658 | |
1659 | rc = mu_message_get_body (msg, &body); | ||
1660 | if (rc) | ||
1661 | { | ||
1662 | mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_body", | ||
1663 | NULL, rc); | ||
1664 | break; | ||
1665 | } | ||
1666 | rc = mu_body_get_streamref (body, &str); | ||
1667 | if (rc) | ||
1668 | { | ||
1669 | mu_diag_funcall (MU_DIAG_ERROR, "mu_body_get_stream", | ||
1670 | NULL, rc); | ||
1671 | break; | ||
1672 | } | ||
1673 | rc = mu_stream_to_message (str, &tmpmsg); | ||
1674 | mu_stream_unref (str); | ||
1675 | if (rc) | ||
1676 | { | ||
1677 | mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_to_message", | ||
1678 | NULL, rc); | ||
1679 | break; | ||
1680 | } | ||
1681 | |||
1682 | rc = mu_mailbox_append_message (mbox, tmpmsg); | ||
1683 | mu_message_destroy (&tmpmsg, mu_message_get_owner (tmpmsg)); | ||
1684 | } | ||
1685 | else | ||
1686 | rc = mu_mailbox_append_message (mbox, msg); | ||
1599 | 1687 | ||
1600 | mu_asprintf (&p, _("File %s already exists. Rewrite"), name); | 1688 | if (rc) |
1601 | rc = mh_getyn (p); | 1689 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_append_message", NULL, |
1602 | free (p); | 1690 | rc); |
1603 | if (!rc) | 1691 | mu_mailbox_close (mbox); |
1692 | mu_mailbox_destroy (&mbox); | ||
1693 | } | ||
1694 | break; | ||
1695 | |||
1696 | case store_to_file: | ||
1697 | printf (_("storing message %s part %s as file %s\n"), | ||
1698 | prefix, partstr, name); | ||
1699 | |||
1700 | if (!(mode_options & OPT_QUIET) && access (name, R_OK) == 0) | ||
1604 | { | 1701 | { |
1605 | free (name); | 1702 | char *p; |
1606 | return 0; | 1703 | int ok; |
1704 | |||
1705 | mu_asprintf (&p, _("File %s already exists. Rewrite"), name); | ||
1706 | ok = mh_getyn (p); | ||
1707 | free (p); | ||
1708 | if (!ok) | ||
1709 | { | ||
1710 | free (name); | ||
1711 | return 0; | ||
1712 | } | ||
1713 | unlink (name); | ||
1607 | } | 1714 | } |
1608 | unlink (name); | ||
1609 | } | ||
1610 | 1715 | ||
1611 | rc = mu_file_stream_create (&out, name, MU_STREAM_WRITE|MU_STREAM_CREAT); | 1716 | rc = mu_file_stream_create (&out, name, MU_STREAM_WRITE|MU_STREAM_CREAT); |
1612 | if (rc) | 1717 | if (rc) |
1718 | mu_error (_("cannot create output stream (file %s): %s"), | ||
1719 | name, mu_strerror (rc)); | ||
1720 | break; | ||
1721 | |||
1722 | case store_to_command: | ||
1723 | /* FIXME: Change to homedir, reflect this in the message below. | ||
1724 | Chdir should better be implemented within mu_prog_stream_create | ||
1725 | Example message: | ||
1726 | storing msg 4 part 1 using command (cd /home/gray; less) | ||
1727 | */ | ||
1728 | printf (_("storing msg %s part %s using command %s\n"), | ||
1729 | prefix, partstr, name); | ||
1730 | rc = mu_prog_stream_create (&out, name, MU_STREAM_WRITE); | ||
1731 | if (rc) | ||
1732 | mu_diag_funcall (MU_DIAG_ERROR, "mu_prog_stream_create", NULL, rc); | ||
1733 | break; | ||
1734 | |||
1735 | case store_to_stdout: | ||
1736 | printf (_("storing msg %s part %s to stdout\n"), | ||
1737 | prefix, partstr); | ||
1738 | rc = mu_stdio_stream_create (&out, MU_STDOUT_FD, 0); | ||
1739 | if (rc) | ||
1740 | mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", NULL, rc); | ||
1741 | break; | ||
1742 | } | ||
1743 | |||
1744 | if (out) | ||
1613 | { | 1745 | { |
1614 | mu_error (_("cannot create output stream (file %s): %s"), | 1746 | show_internal (msg, part, encoding, out); |
1615 | name, mu_strerror (rc)); | 1747 | mu_stream_destroy (&out); |
1616 | free (name); | ||
1617 | return rc; | ||
1618 | } | 1748 | } |
1619 | show_internal (msg, part, encoding, out); | 1749 | |
1620 | |||
1621 | mu_stream_destroy (&out); | ||
1622 | free (name); | 1750 | free (name); |
1751 | free (partstr); | ||
1623 | 1752 | ||
1624 | return 0; | 1753 | return rc; |
1625 | } | 1754 | } |
1626 | 1755 | ||
1627 | void | 1756 | void |
... | @@ -2663,7 +2792,9 @@ main (int argc, char **argv) | ... | @@ -2663,7 +2792,9 @@ main (int argc, char **argv) |
2663 | mu_error (_("extra arguments")); | 2792 | mu_error (_("extra arguments")); |
2664 | return 1; | 2793 | return 1; |
2665 | } | 2794 | } |
2666 | message = mh_file_to_message (mu_folder_directory (), input_file); | 2795 | input_file = mh_expand_name (mu_folder_directory (), |
2796 | argc == 1 ? argv[0] : "draft", 0); | ||
2797 | message = mh_file_to_message (NULL, input_file); | ||
2667 | if (!message) | 2798 | if (!message) |
2668 | return 1; | 2799 | return 1; |
2669 | } | 2800 | } |
... | @@ -2674,8 +2805,9 @@ main (int argc, char **argv) | ... | @@ -2674,8 +2805,9 @@ main (int argc, char **argv) |
2674 | mu_error (_("extra arguments")); | 2805 | mu_error (_("extra arguments")); |
2675 | return 1; | 2806 | return 1; |
2676 | } | 2807 | } |
2677 | input_file = argc == 1 ? argv[0] : "draft"; | 2808 | input_file = mh_expand_name (mu_folder_directory (), |
2678 | message = mh_file_to_message (mu_folder_directory (), input_file); | 2809 | argc == 1 ? argv[0] : "draft", 0); |
2810 | message = mh_file_to_message (NULL, input_file); | ||
2679 | if (!message) | 2811 | if (!message) |
2680 | return 1; | 2812 | return 1; |
2681 | } | 2813 | } |
... | @@ -2688,9 +2820,6 @@ main (int argc, char **argv) | ... | @@ -2688,9 +2820,6 @@ main (int argc, char **argv) |
2688 | switch (mode) | 2820 | switch (mode) |
2689 | { | 2821 | { |
2690 | case mode_compose: | 2822 | case mode_compose: |
2691 | /* Prepare filename for diagnostic purposes */ | ||
2692 | if (input_file[0] != '/') | ||
2693 | input_file = mh_safe_make_file_name (mu_folder_directory (), input_file); | ||
2694 | rc = mhn_compose (); | 2823 | rc = mhn_compose (); |
2695 | break; | 2824 | break; |
2696 | 2825 | ... | ... |
mh/tests/mhn.at
0 → 100644
1 | # This file is part of GNU Mailutils. -*- Autotest -*- | ||
2 | # Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # GNU Mailutils is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU General Public License as | ||
6 | # published by the Free Software Foundation; either version 3, or (at | ||
7 | # your option) any later version. | ||
8 | # | ||
9 | # GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | m4_pushdef([MH_KEYWORDS],[mhn]) | ||
18 | |||
19 | dnl ------------------------------------------------------------------- | ||
20 | dnl 1. List mode | ||
21 | dnl ------------------------------------------------------------------- | ||
22 | |||
23 | MH_CHECK([mhn -list],[mhn00 mhn-list],[ | ||
24 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
25 | mhn +inbox -list all | ||
26 | ], | ||
27 | [0], | ||
28 | [ msg part type/subtype size description | ||
29 | 1 text/plain 937 | ||
30 | 2 text/plain 215 | ||
31 | 3 multipart/mixed 2K | ||
32 | 1 text/plain 230 How doth | ||
33 | 2 application/octet-stream 462 Father William Part I | ||
34 | 4 multipart/mixed 3K | ||
35 | 1 text/plain 341 Father William Part I | ||
36 | 2 multipart/mixed 3K | ||
37 | 2.1 application/octet-stream 479 Father William Part II | ||
38 | 2.2 multipart/mixed 2K | ||
39 | 2.2.1 application/octet-stream 483 Father William Part III | ||
40 | 2.2.2 application/octet-stream 495 Father William Part IV | ||
41 | 5 multipart/mixed 355 | ||
42 | 1 text/plain 0 Empty part | ||
43 | 2 text/plain 1 Single line part | ||
44 | ]) | ||
45 | |||
46 | MH_CHECK([mhn -list -realsize],[mhn01 mhn-list-realsize],[ | ||
47 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
48 | mhn +inbox -list -realsize all | ||
49 | ], | ||
50 | [0], | ||
51 | [ msg part type/subtype size description | ||
52 | 1 text/plain 937 | ||
53 | 2 text/plain 215 | ||
54 | 3 multipart/mixed 2K | ||
55 | 1 text/plain 230 How doth | ||
56 | 2 application/octet-stream 341 Father William Part I | ||
57 | 4 multipart/mixed 3K | ||
58 | 1 text/plain 341 Father William Part I | ||
59 | 2 multipart/mixed 3K | ||
60 | 2.1 application/octet-stream 352 Father William Part II | ||
61 | 2.2 multipart/mixed 2K | ||
62 | 2.2.1 application/octet-stream 357 Father William Part III | ||
63 | 2.2.2 application/octet-stream 366 Father William Part IV | ||
64 | 5 multipart/mixed 355 | ||
65 | 1 text/plain 0 Empty part | ||
66 | 2 text/plain 1 Single line part | ||
67 | ]) | ||
68 | |||
69 | dnl ------------------------------------------------------------------- | ||
70 | dnl 2. Store mode | ||
71 | dnl ------------------------------------------------------------------- | ||
72 | |||
73 | MH_CHECK([mhn -store],[mhn02 mhn-store],[ | ||
74 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
75 | mhn +inbox -store 4 || exit $? | ||
76 | for file in 4.1.plain 4.2.1.octet-stream 4.2.2.1.octet-stream 4.2.2.2.octet-stream | ||
77 | do | ||
78 | echo == $file == | ||
79 | cat $file | ||
80 | done | ||
81 | ], | ||
82 | [0], | ||
83 | [storing message 4 part 1 as file 4.1.plain | ||
84 | storing message 4 part 2.1 as file 4.2.1.octet-stream | ||
85 | storing message 4 part 2.2.1 as file 4.2.2.1.octet-stream | ||
86 | storing message 4 part 2.2.2 as file 4.2.2.2.octet-stream | ||
87 | == 4.1.plain == | ||
88 | `You are old, Father William,' the young man said, | ||
89 | `And your hair has become very white; | ||
90 | And yet you incessantly stand on your head-- | ||
91 | Do you think, at your age, it is right?' | ||
92 | |||
93 | `In my youth,' Father William replied to his son, | ||
94 | `I feared it might injure the brain; | ||
95 | But, now that I'm perfectly sure I have none, | ||
96 | Why, I do it again and again.' | ||
97 | |||
98 | == 4.2.1.octet-stream == | ||
99 | `You are old,' said the youth, `as I mentioned before, | ||
100 | And have grown most uncommonly fat; | ||
101 | Yet you turned a back-somersault in at the door-- | ||
102 | Pray, what is the reason of that?' | ||
103 | |||
104 | `In my youth,' said the sage, as he shook his grey locks, | ||
105 | `I kept all my limbs very supple | ||
106 | By the use of this ointment--one shilling the box-- | ||
107 | Allow me to sell you a couple?' | ||
108 | == 4.2.2.1.octet-stream == | ||
109 | `You are old,' said the youth, `and your jaws are too weak | ||
110 | For anything tougher than suet; | ||
111 | Yet you finished the goose, with the bones and the beak-- | ||
112 | Pray how did you manage to do it?' | ||
113 | |||
114 | `In my youth,' said his father, `I took to the law, | ||
115 | And argued each case with my wife; | ||
116 | And the muscular strength, which it gave to my jaw, | ||
117 | Has lasted the rest of my life.' | ||
118 | == 4.2.2.2.octet-stream == | ||
119 | `You are old,' said the youth, `one would hardly suppose | ||
120 | That your eye was as steady as ever; | ||
121 | Yet you balanced an eel on the end of your nose-- | ||
122 | What made you so awfully clever?' | ||
123 | |||
124 | `I have answered three questions, and that is enough,' | ||
125 | Said his father; `don't give yourself airs! | ||
126 | Do you think I can listen all day to such stuff? | ||
127 | Be off, or I'll kick you down stairs!' | ||
128 | ]) | ||
129 | |||
130 | m4_popdef[MH_KEYWORDS]) | ||
131 | # End of mhn.at |
-
Please register or sign in to post a comment