[bug #4302] errno is not always an extern int
[mmh] / uip / ap.c
1
2 /*
3  * ap.c -- parse addresses 822-style
4  *
5  * $Id$
6  *
7  * This code is Copyright (c) 2002, by the authors of nmh.  See the
8  * COPYRIGHT file in the root directory of the nmh distribution for
9  * complete copyright information.
10  */
11
12 #include <h/mh.h>
13 #include <h/addrsbr.h>
14 #include <h/fmt_scan.h>
15 #include <h/mts.h>
16
17 #define NADDRS  100
18
19 #define WIDTH   78
20 #define WBUFSIZ BUFSIZ
21
22 #define FORMAT  "%<{error}%{error}: %{text}%|%(putstr(proper{text}))%>"
23
24 static struct swit switches[] = {
25 #define FORMSW  0
26     { "form formatfile", 0 },
27 #define FMTSW   1
28     { "format string", 5 },
29 #define NORMSW  2
30     { "normalize", 0 },
31 #define NNORMSW 3
32     { "nonormalize", 0 },
33 #define WIDTHSW 4
34     { "width columns", 0 },
35 #define VERSIONSW 5
36     { "version", 0 },
37 #define HELPSW  6
38     { "help", 0 },
39     { NULL, 0 }
40 };
41
42 static struct format *fmt;
43
44 static int dat[5];
45
46 /*
47  * prototypes
48  */
49 int sc_width (void);  /* from termsbr.c */
50
51 /*
52  * static prototypes
53  */
54 static int process (char *, int, int);
55
56
57 int
58 main (int argc, char **argv)
59 {
60     int addrp = 0, normalize = AD_HOST;
61     int width = 0, status = 0;
62     char *cp, *form = NULL, *format = NULL, *nfs;
63     char buf[BUFSIZ], **argp;
64     char **arguments, *addrs[NADDRS];
65
66 #ifdef LOCALE
67     setlocale(LC_ALL, "");
68 #endif
69     invo_name = r1bindex (argv[0], '/');
70
71     /* read user profile/context */
72     context_read();
73
74     mts_init (invo_name);
75     arguments = getarguments (invo_name, argc, argv, 1);
76     argp = arguments;
77
78     while ((cp = *argp++)) {
79         if (*cp == '-') {
80             switch (smatch (++cp, switches)) {
81                 case AMBIGSW: 
82                     ambigsw (cp, switches);
83                     done (1);
84
85                 case UNKWNSW: 
86                     adios (NULL, "-%s unknown", cp);
87
88                 case HELPSW: 
89                     snprintf (buf, sizeof(buf), "%s [switches] addrs ...",
90                         invo_name);
91                     print_help (buf, switches, 1);
92                     done (1);
93                 case VERSIONSW:
94                     print_version (invo_name);
95                     done (1);
96
97                 case FORMSW: 
98                     if (!(form = *argp++) || *form == '-')
99                         adios (NULL, "missing argument to %s", argp[-2]);
100                     format = NULL;
101                     continue;
102                 case FMTSW: 
103                     if (!(format = *argp++) || *format == '-')
104                         adios (NULL, "missing argument to %s", argp[-2]);
105                     form = NULL;
106                     continue;
107
108                 case WIDTHSW: 
109                     if (!(cp = *argp++) || *cp == '-')
110                         adios (NULL, "missing argument to %s", argp[-2]);
111                     width = atoi (cp);
112                     continue;
113
114                 case NORMSW: 
115                     normalize = AD_HOST;
116                     continue;
117                 case NNORMSW: 
118                     normalize = AD_NHST;
119                     continue;
120             }
121         }
122         if (addrp > NADDRS)
123             adios (NULL, "more than %d addresses", NADDRS);
124         else
125             addrs[addrp++] = cp;
126     }
127     addrs[addrp] = NULL;
128
129     if (addrp == 0)
130         adios (NULL, "usage: %s [switches] addrs ...", invo_name);
131
132     /* get new format string */
133     nfs = new_fs (form, format, FORMAT);
134
135     if (width == 0) {
136         if ((width = sc_width ()) < WIDTH / 2)
137             width = WIDTH / 2;
138         width -= 2;
139     }
140     if (width > WBUFSIZ)
141         width = WBUFSIZ;
142     fmt_norm = normalize;
143     fmt_compile (nfs, &fmt);
144
145     dat[0] = 0;
146     dat[1] = 0;
147     dat[2] = 0;
148     dat[3] = width;
149     dat[4] = 0;
150
151     for (addrp = 0; addrs[addrp]; addrp++)
152         status += process (addrs[addrp], width, normalize);
153
154     return done (status);
155 }
156
157 struct pqpair {
158     char *pq_text;
159     char *pq_error;
160     struct pqpair *pq_next;
161 };
162
163
164 static int
165 process (char *arg, int length, int norm)
166 {
167     int status = 0;
168     register char *cp;
169     char buffer[WBUFSIZ + 1], error[BUFSIZ];
170     register struct comp *cptr;
171     register struct pqpair *p, *q;
172     struct pqpair pq;
173     register struct mailname *mp;
174
175     (q = &pq)->pq_next = NULL;
176     while ((cp = getname (arg))) {
177         if ((p = (struct pqpair *) calloc ((size_t) 1, sizeof(*p))) == NULL)
178             adios (NULL, "unable to allocate pqpair memory");
179         if ((mp = getm (cp, NULL, 0, norm, error)) == NULL) {
180             p->pq_text = getcpy (cp);
181             p->pq_error = getcpy (error);
182             status++;
183         }
184         else {
185             p->pq_text = getcpy (mp->m_text);
186             mnfree (mp);
187         }
188         q = (q->pq_next = p);
189     }
190
191     for (p = pq.pq_next; p; p = q) {
192         FINDCOMP (cptr, "text");
193         if (cptr)
194             cptr->c_text = p->pq_text;
195         FINDCOMP (cptr, "error");
196         if (cptr)
197             cptr->c_text = p->pq_error;
198
199         fmt_scan (fmt, buffer, length, dat);
200         fputs (buffer, stdout);
201
202         free (p->pq_text);
203         if (p->pq_error)
204             free (p->pq_error);
205         q = p->pq_next;
206         free ((char *) p);
207     }
208
209     return status;
210 }