Added support for optional Content_Disposition header in mhbuild directive.s
[mmh] / uip / distsbr.c
1
2 /*
3  * distsbr.c -- routines to do additional "dist-style" processing
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 <fcntl.h>
14 #include <h/utils.h>
15
16 static int  hdrfd = NOTOK;
17 static int  txtfd = NOTOK;
18
19 #define BADHDR  "please re-edit %s to remove the ``%s'' header!"
20 #define BADTXT  "please re-edit %s to consist of headers only!"
21 #define BADMSG  "please re-edit %s to include a ``Resent-To:''!"
22 #define BADRFT  "please re-edit %s and fix that header!"
23
24 /*
25  * static prototypes
26  */
27 static void ready_msg(char *);
28
29 int
30 distout (char *drft, char *msgnam, char *backup)
31 {
32     int state;
33     register char *dp, *resent;
34     char name[NAMESZ], buffer[BUFSIZ];
35     register FILE *ifp, *ofp;
36
37     if (rename (drft, strcpy (backup, m_backup (drft))) == NOTOK)
38         adios (backup, "unable to rename %s to",drft);
39     if ((ifp = fopen (backup, "r")) == NULL)
40         adios (backup, "unable to read");
41
42     if ((ofp = fopen (drft, "w")) == NULL)
43         adios (drft, "unable to create temporary file");
44     chmod (drft, m_gmprot ());
45
46     ready_msg (msgnam);
47     lseek (hdrfd, (off_t) 0, SEEK_SET); /* msgnam not accurate */
48     cpydata (hdrfd, fileno (ofp), msgnam, drft);
49
50     for (state = FLD, resent = NULL;;)
51         switch (state =
52                 m_getfld (state, name, buffer, sizeof buffer, ifp)) {
53             case FLD: 
54             case FLDPLUS: 
55             case FLDEOF: 
56                 if (uprf (name, "distribute-"))
57                     snprintf (name, sizeof(name), "%s%s", "Resent", &name[10]);
58                 if (uprf (name, "distribution-"))
59                     snprintf (name, sizeof(name), "%s%s", "Resent", &name[12]);
60                 if (!uprf (name, "resent")) {
61                     advise (NULL, BADHDR, "draft", name);
62                     goto leave_bad;
63                 }
64                 if (state == FLD)
65                     resent = add (":", add (name, resent));
66                 resent = add (buffer, resent);
67                 fprintf (ofp, "%s: %s", name, buffer);
68                 while (state == FLDPLUS) {
69                     state = m_getfld (state, name,
70                             buffer, sizeof buffer, ifp);
71                     resent = add (buffer, resent);
72                     fputs (buffer, ofp);
73                 }
74                 if (state == FLDEOF)
75                     goto process;
76                 break;
77
78             case BODY: 
79             case BODYEOF: 
80                 for (dp = buffer; *dp; dp++)
81                     if (!isspace (*dp)) {
82                         advise (NULL, BADTXT, "draft");
83                         goto leave_bad;
84                     }
85
86             case FILEEOF: 
87                 goto process;
88
89             case LENERR: 
90             case FMTERR: 
91                 advise (NULL, BADRFT, "draft");
92         leave_bad: ;
93                 fclose (ifp);
94                 fclose (ofp);
95                 unlink (drft);
96                 if (rename (backup, drft) == NOTOK)
97                     adios (drft, "unable to rename %s to", backup);
98                 return NOTOK;
99
100             default: 
101                 adios (NULL, "getfld() returned %d", state);
102         }
103 process: ;
104     fclose (ifp);
105     fflush (ofp);
106
107     if (!resent) {
108         advise (NULL, BADMSG, "draft");
109         fclose (ofp);
110         unlink (drft);
111         if (rename (backup, drft) == NOTOK)
112             adios (drft, "unable to rename %s to", backup);
113         return NOTOK;
114     }
115     free (resent);
116
117     if (txtfd != NOTOK) {
118         lseek (txtfd, (off_t) 0, SEEK_SET); /* msgnam not accurate */
119         cpydata (txtfd, fileno (ofp), msgnam, drft);
120     }
121
122     fclose (ofp);
123
124     return OK;
125 }
126
127
128 static void
129 ready_msg (char *msgnam)
130 {
131     int state, out;
132     char name[NAMESZ], buffer[BUFSIZ], tmpfil[BUFSIZ];
133     register FILE *ifp, *ofp;
134
135     if (hdrfd != NOTOK)
136         close (hdrfd), hdrfd = NOTOK;
137     if (txtfd != NOTOK)
138         close (txtfd), txtfd = NOTOK;
139
140     if ((ifp = fopen (msgnam, "r")) == NULL)
141         adios (msgnam, "unable to open message");
142
143     strncpy (tmpfil, m_tmpfil ("dist"), sizeof(tmpfil));
144     if ((hdrfd = open (tmpfil, O_RDWR | O_CREAT | O_TRUNC, 0600)) == NOTOK)
145         adios (tmpfil, "unable to re-open temporary file");
146     if ((out = dup (hdrfd)) == NOTOK
147             || (ofp = fdopen (out, "w")) == NULL)
148         adios (NULL, "no file descriptors -- you lose big");
149     unlink (tmpfil);
150
151     for (state = FLD;;)
152         switch (state =
153                 m_getfld (state, name, buffer, sizeof buffer, ifp)) {
154             case FLD: 
155             case FLDPLUS: 
156             case FLDEOF: 
157                 if (uprf (name, "resent"))
158                     fprintf (ofp, "Prev-");
159                 fprintf (ofp, "%s: %s", name, buffer);
160                 while (state == FLDPLUS) {
161                     state = m_getfld (state, name,
162                             buffer, sizeof buffer, ifp);
163                     fputs (buffer, ofp);
164                 }
165                 if (state == FLDEOF)
166                     goto process;
167                 break;
168
169             case BODY: 
170             case BODYEOF: 
171                 fclose (ofp);
172
173                 strncpy (tmpfil, m_tmpfil ("dist"), sizeof(tmpfil));
174                 if ((txtfd = open (tmpfil, O_RDWR | O_CREAT | O_TRUNC, 0600)) == NOTOK)
175                     adios (tmpfil, "unable to open temporary file");
176                 if ((out = dup (txtfd)) == NOTOK
177                         || (ofp = fdopen (out, "w")) == NULL)
178                     adios (NULL, "no file descriptors -- you lose big");
179                 unlink (tmpfil);
180                 fprintf (ofp, "\n%s", buffer);
181                 while (state == BODY) {
182                     state = m_getfld (state, name,
183                             buffer, sizeof buffer, ifp);
184                     fputs (buffer, ofp);
185                 }
186             case FILEEOF: 
187                 goto process;
188
189             case LENERR: 
190             case FMTERR: 
191                 adios (NULL, "format error in message %s", msgnam);
192
193             default: 
194                 adios (NULL, "getfld() returned %d", state);
195         }
196 process: ;
197     fclose (ifp);
198     fclose (ofp);
199 }