]> diplodocus.org Git - nmh/blob - uip/ap.c
seq_setprev.c: Move interface to own file.
[nmh] / uip / ap.c
1 /* ap.c -- parse addresses 822-style
2 *
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include "h/mh.h"
9 #include "sbr/smatch.h"
10 #include "sbr/getcpy.h"
11 #include "sbr/ambigsw.h"
12 #include "sbr/print_version.h"
13 #include "sbr/print_help.h"
14 #include "sbr/error.h"
15 #include "h/addrsbr.h"
16 #include "h/fmt_scan.h"
17 #include "h/mts.h"
18 #include "h/done.h"
19 #include "h/utils.h"
20 #include "sbr/terminal.h"
21
22 #define NADDRS 100
23
24 #define WIDTH 78
25
26 #define FORMAT "%<{error}%{error}: %{text}%|%(putstr(proper{text}))%>"
27
28 #define AP_SWITCHES \
29 X("form formatfile", 0, FORMSW) \
30 X("format string", 5, FMTSW) \
31 X("width columns", 0, WIDTHSW) \
32 X("version", 0, VERSIONSW) \
33 X("help", 0, HELPSW) \
34
35 #define X(sw, minchars, id) id,
36 DEFINE_SWITCH_ENUM(AP);
37 #undef X
38
39 #define X(sw, minchars, id) { sw, minchars, id },
40 DEFINE_SWITCH_ARRAY(AP, switches);
41 #undef X
42
43 static struct format *fmt;
44
45 static int dat[5];
46
47 /*
48 * static prototypes
49 */
50 static int process (char *, int);
51
52
53 int
54 main (int argc, char **argv)
55 {
56 int addrp = 0;
57 int width = -1, status = 0;
58 char *cp, *form = NULL, *format = NULL, *nfs;
59 char buf[BUFSIZ], **argp;
60 char *addrs[NADDRS + 1]; /* Includes terminating NULL. */
61
62 if (nmh_init(argv[0], true, false)) { return 1; }
63
64 mts_init ();
65
66 argp = getarguments (invo_name, argc, argv, 1);
67 while ((cp = *argp++)) {
68 if (*cp == '-') {
69 switch (smatch (++cp, switches)) {
70 case AMBIGSW:
71 ambigsw (cp, switches);
72 done (1);
73
74 case UNKWNSW:
75 die("-%s unknown", cp);
76
77 case HELPSW:
78 snprintf (buf, sizeof(buf), "%s [switches] addrs ...",
79 invo_name);
80 print_help (buf, switches, 1);
81 done (0);
82 case VERSIONSW:
83 print_version (invo_name);
84 done (0);
85
86 case FORMSW:
87 if (!(form = *argp++) || *form == '-')
88 die("missing argument to %s", argp[-2]);
89 format = NULL;
90 continue;
91 case FMTSW:
92 if (!(format = *argp++) || *format == '-')
93 die("missing argument to %s", argp[-2]);
94 form = NULL;
95 continue;
96
97 case WIDTHSW:
98 if (!(cp = *argp++) || *cp == '-')
99 die("missing argument to %s", argp[-2]);
100 width = atoi (cp);
101 continue;
102 }
103 }
104 if (addrp == NADDRS)
105 die("more than %d addresses", NADDRS);
106 addrs[addrp++] = cp;
107 }
108 addrs[addrp] = NULL;
109
110 if (addrp == 0)
111 die("usage: %s [switches] addrs ...", invo_name);
112
113 /* get new format string */
114 nfs = new_fs (form, format, FORMAT);
115
116 if (width == -1) {
117 if ((width = sc_width ()) < WIDTH / 2) {
118 /* Default: width of the terminal, but at least WIDTH/2. */
119 width = WIDTH / 2;
120 }
121 width -= 2;
122 } else if (width == 0) {
123 /* Unlimited width. */
124 width = INT_MAX;
125 }
126 fmt_compile (nfs, &fmt, 1);
127
128 dat[0] = 0;
129 dat[1] = 0;
130 dat[2] = 0;
131 dat[3] = width;
132 dat[4] = 0;
133
134 for (addrp = 0; addrs[addrp]; addrp++)
135 status += process (addrs[addrp], width);
136
137 fmt_free (fmt, 1);
138 done(!!status);
139 return 1;
140 }
141
142 struct pqpair {
143 char *pq_text;
144 char *pq_error;
145 struct pqpair *pq_next;
146 };
147
148
149 static int
150 process (char *arg, int length)
151 {
152 int status = 0;
153 char *cp;
154 char error[BUFSIZ];
155 struct comp *cptr;
156 struct pqpair *p, *q;
157 struct pqpair pq;
158 struct mailname *mp;
159
160 (q = &pq)->pq_next = NULL;
161 while ((cp = getname (arg))) {
162 NEW0(p);
163 if ((mp = getm (cp, NULL, 0, error, sizeof(error))) == NULL) {
164 p->pq_text = mh_xstrdup(cp);
165 p->pq_error = mh_xstrdup(error);
166 status++;
167 }
168 else {
169 p->pq_text = getcpy (mp->m_text);
170 mnfree (mp);
171 }
172 q = (q->pq_next = p);
173 }
174
175 for (p = pq.pq_next; p; p = q) {
176 charstring_t scanl =
177 charstring_create (length < NMH_BUFSIZ ? length : NMH_BUFSIZ);
178
179 cptr = fmt_findcomp ("text");
180 if (cptr) {
181 free(cptr->c_text);
182 cptr->c_text = p->pq_text;
183 p->pq_text = NULL;
184 }
185 cptr = fmt_findcomp ("error");
186 if (cptr) {
187 free(cptr->c_text);
188 cptr->c_text = p->pq_error;
189 p->pq_error = NULL;
190 }
191
192 fmt_scan (fmt, scanl, length, dat, NULL);
193 fputs (charstring_buffer (scanl), stdout);
194 charstring_free (scanl);
195
196 free(p->pq_text);
197 free(p->pq_error);
198 q = p->pq_next;
199 free(p);
200 }
201
202 return status;
203 }