Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtmail / dtmailpr / utils.C
1 /* $XConsortium: utils.C /main/4 1996/04/21 19:44:10 drk $ */
2
3 /*
4  *+SNOTICE
5  *
6  *      $:$
7  *
8  *      RESTRICTED CONFIDENTIAL INFORMATION:
9  *      
10  *      The information in this document is subject to special
11  *      restrictions in a confidential disclosure agreement between
12  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
13  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
14  *      Sun's specific written approval.  This document and all copies
15  *      and derivative works thereof must be returned or destroyed at
16  *      Sun's request.
17  *
18  *      Copyright 1994 Sun Microsystems, Inc.  All rights reserved.
19  *
20  *+ENOTICE
21  */
22
23 #include "dmx.hh"
24
25 // fn proto for mailx fn
26 static char * dispname(const char *hdr);
27
28 // error-handling: should do something with minor codes
29
30 boolean_t
31 handleError (DtMailEnv &dterror, char *msg)
32 {
33         if (dterror.isSet () == DTM_TRUE)
34         {
35                 fprintf (stderr, "dtmailpr: (%s) %s\n", 
36                         msg, (const char *)dterror);
37                 dterror.logError (DTM_FALSE, "dtmailpr: (%s) %s\n",
38                         msg, (const char *)dterror);
39
40                 dterror.clear ();
41                 return B_TRUE;
42         }
43
44         dterror.clear ();
45         return B_FALSE;
46 }
47         
48
49 char *
50 errorString (enum DmxHeaders hdr)
51 {
52         switch (hdr)
53         {
54                 case DMXFROM:
55                         return "(unknown)";
56                 case DMXSUBJ:
57                         return "(no subject)";
58                 case DMXCLENGTH:
59                         return "0";
60                 case DMXSTATUS:
61                         return "  ";
62                 case DMXDATE:
63                         return "(unknown date)";
64                 case DMXTO:
65                         return " ";
66                 case DMXNUMHDRS:
67                 default:
68                         return " ";
69         }
70 }
71
72 char *
73 formatHeader (DtMailHeaderLine &info, enum DmxHeaderType htype)
74 {
75         int     i = 0, length = 0;
76         int     buflength = 0;
77         char    *fbuf;
78
79         const char      *header [DMXNUMHDRS];
80
81         for (i = 0; i < DMXNUMHDRS; i++)
82         {
83                 length = info.header_values[i].length ();
84                 if (length == 0)
85                 {
86                         header [i] = errorString ((enum DmxHeaders)i);
87                 } else {
88                         header [i] = *((info.header_values[i])[0]);
89                 }
90         }
91
92         for (i = 0; i < DMXNUMHDRS; i++)
93         {
94                 buflength += strlen (header [i]);
95         }
96
97         fbuf = new char [buflength + 64];
98
99         switch (htype)
100         {
101                 case MSGLIST:
102                         sprintf (fbuf,
103                         "%-18.18s %-16.16s %4ld/%-5s %-.25s",
104                                 dispname (header [DMXFROM]),
105                                 header [DMXDATE],
106                                 atoi (header [DMXCLENGTH]) / 40,
107                                 header [DMXCLENGTH],
108                                 header [DMXSUBJ]
109                                 );
110                         break;
111                 case MSGHEADER:
112                         sprintf (fbuf,
113                         "From: %s\nDate: %s\nTo: %s\nSubject: %s\n",
114                                 dispname (header [DMXFROM]),
115                                 header [DMXDATE],
116                                 header [DMXTO],
117                                 header [DMXSUBJ]);
118                         break;
119                 case NUMHDRTYPES:
120                 default:
121                         return "";
122         }
123         return (fbuf); //need to free this after using it
124 }
125
126 // stuff grabbed from mailx...it's ugly, but it looks pretty
127
128 #define NOSTR ((char *) 0)    /* Nill string pointer */
129 #define LINESIZE 5120            /* max readable line width */
130 static char *phrase(char *, int , int );
131
132 /*
133  * Return a pointer to a dynamic copy of the argument.
134  */
135 // changed salloc to malloc
136 char *
137 savestr(char *str)
138 {
139         register char *cp, *cp2, *top;
140
141         for (cp = str; *cp; cp++)
142                 ;
143         top = (char *)malloc((unsigned)(cp-str + 1));
144         if (top == NOSTR)
145                 return(NOSTR);
146         for (cp = str, cp2 = top; *cp; cp++)
147                 *cp2++ = *cp;
148         *cp2 = 0;
149         return(top);
150 }
151
152
153 char *
154 skin(char *name)
155 {
156         return phrase(name, 0, 0);
157 }
158 /*
159  * Return the full name from an RFC-822 header line
160  * or the last two (or one) component of the address.
161  */
162
163 static char *
164 dispname(const char *hdr)
165 // made it a const char * instead of a char *
166 {
167         char *cp, *cp2;
168
169         if (hdr == 0)
170                 return 0;
171         if (((cp = strchr(hdr, '<')) != 0) && (cp > hdr)) {
172                 *cp = 0;
173                 if ((*hdr == '"') && ((cp = strrchr(++hdr, '"')) != 0))
174                         *cp = 0;
175                 return (char *)hdr;
176         } else if ((cp = strchr(hdr, '(')) != 0) {
177                 hdr = ++cp;
178                 if ((cp = strchr(hdr, '+')) != 0)
179                         *cp = 0;
180                 if ((cp = strrchr(hdr, ')')) != 0)
181                         *cp = 0;
182                 return (char *)hdr;
183         }
184         cp = skin((char *)hdr);
185         if ((cp2 = strrchr(cp, '!')) != 0) {
186                 while (cp2 >= cp && *--cp2 != '!');
187                 cp = ++cp2;
188         }
189         return cp;
190 }
191
192
193 #define equal(a, b)     (strcmp(a,b)==0)/* A nice function to string compare */
194
195 /*
196  * Skin an arpa net address according to the RFC 822 interpretation
197  * of "host-phrase."
198  */
199 // changed salloc to malloc
200 static char *
201 phrase(char *name, int token, int comma)
202 {
203         register char c;
204         register char *cp, *cp2;
205         char *bufend, *nbufp;
206         int gotlt, lastsp, didq;
207         char nbuf[LINESIZE];
208         int nesting;
209
210         if (name == NOSTR)
211                 return(NOSTR);
212         if (strlen(name) >= (unsigned)LINESIZE)
213                 nbufp = (char *)malloc(strlen(name));
214         else
215                 nbufp = nbuf;
216         gotlt = 0;
217         lastsp = 0;
218         bufend = nbufp;
219         for (cp = name, cp2 = bufend; (c = *cp++) != 0;) {
220                 switch (c) {
221                 case '(':
222                         /*
223                                 Start of a comment, ignore it.
224                         */
225                         nesting = 1;
226                         while ((c = *cp) != 0) {
227                                 cp++;
228                                 switch(c) {
229                                 case '\\':
230                                         if (*cp == 0) goto outcm;
231                                         cp++;
232                                         break;
233                                 case '(':
234                                         nesting++;
235                                         break;
236                                 case ')':
237                                         --nesting;
238                                         break;
239                                 }
240                                 if (nesting <= 0) break;
241                         }
242                 outcm:
243                         lastsp = 0;
244                         break;
245                 case '"':
246                         /*
247                                 Start a quoted string.
248                                 Copy it in its entirety.
249                         */
250                         didq = 0;
251                         while ((c = *cp) != 0) {
252                                 cp++;
253                                 switch (c) {
254                                 case '\\':
255                                         if ((c = *cp) == 0) goto outqs;
256                                         cp++;
257                                         break;
258                                 case '"':
259                                         goto outqs;
260                                 }
261                                 if (gotlt == 0 || gotlt == '<') {
262                                         if (lastsp) {
263                                                 lastsp = 0;
264                                                 *cp2++ = ' ';
265                                         }
266                                         if (!didq) {
267                                                 *cp2++ = '"';
268                                                 didq++;
269                                         }
270                                         *cp2++ = c;
271                                 }
272                         }
273                 outqs:
274                         if (didq)
275                                 *cp2++ = '"';
276                         lastsp = 0;
277                         break;
278
279                 case ' ':
280                 case '\t':
281                 case '\n':
282                         if (token && (!comma || c == '\n')) {
283                         done:
284                                 cp[-1] = 0;
285                                 return cp;
286                         }
287                         lastsp = 1;
288                         break;
289
290                 case ',':
291                         *cp2++ = c;
292                         if (gotlt != '<') {
293                                 if (token)
294                                         goto done;
295                                 bufend = cp2 + 1;
296                                 gotlt = 0;
297                         }
298                         break;
299
300                 case '<':
301                         cp2 = bufend;
302                         gotlt = c;
303                         lastsp = 0;
304                         break;
305
306                 case '>':
307                         if (gotlt == '<') {
308                                 gotlt = c;
309                                 break;
310                         }
311
312                         /* FALLTHROUGH . . . */
313
314                 default:
315                         if (gotlt == 0 || gotlt == '<') {
316                                 if (lastsp) {
317                                         lastsp = 0;
318                                         *cp2++ = ' ';
319                                 }
320                                 *cp2++ = c;
321                         }
322                         break;
323                 }
324         }
325         *cp2 = 0;
326         return (token ? --cp : equal(name, nbufp) ? name :
327             nbufp == nbuf ? savestr(nbuf) : nbufp);
328 }
329
330
331