Move #include from h/mh.h to source files
[mmh] / uip / distsbr.c
1 /*
2 ** distsbr.c -- routines to do additional "dist-style" processing
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <fcntl.h>
11 #include <h/utils.h>
12 #include <unistd.h>
13 #include <ctype.h>
14 #include <sys/stat.h>
15
16 static int  hdrfd = NOTOK;
17 static int  txtfd = NOTOK;
18
19 /*
20 ** static prototypes
21 */
22 static int ready_msg(char *);
23
24 int
25 distout(char *drft, char *msgnam, char *backup)
26 {
27         int state;
28         register unsigned char *dp;
29         register char *resent;
30         char name[NAMESZ], buffer[BUFSIZ];
31         register FILE *ifp, *ofp;
32
33         strcpy(backup, m_mktemp(toabsdir(invo_name), NULL, NULL));
34         if (rename(drft, backup) == NOTOK) {
35                 advise(backup, "unable to rename %s to",drft);
36                 return NOTOK;
37         }
38         if (!(ifp = fopen(backup, "r"))) {
39                 advise(backup, "unable to read");
40                 return NOTOK;
41         }
42
43         if (!(ofp = fopen(drft, "w"))) {
44                 advise(drft, "unable to create temporary file");
45                 return NOTOK;
46         }
47         chmod(drft, m_gmprot());
48
49         if (ready_msg(msgnam) != OK) {
50                 return NOTOK;
51         }
52         lseek(hdrfd, (off_t) 0, SEEK_SET); /* msgnam not accurate */
53         cpydata(hdrfd, fileno(ofp), msgnam, drft);
54
55         state = FLD;
56         resent = NULL;
57         while (1) {
58                 switch (state = m_getfld(state, name, buffer, sizeof buffer,
59                                 ifp)) {
60                 case FLD:
61                 case FLDPLUS:
62                 case FLDEOF:
63                         if (!uprf(name, "resent")) {
64                                 advise(NULL, "Please re-edit draft to remove the ``%s'' header.", name);
65                                 goto leave_bad;
66                         }
67                         if (state == FLD) {
68                                 resent = add(":", add(name, resent));
69                         }
70                         resent = add(buffer, resent);
71                         fprintf(ofp, "%s: %s", name, buffer);
72                         while (state == FLDPLUS) {
73                                 state = m_getfld(state, name, buffer,
74                                                 sizeof buffer, ifp);
75                                 resent = add(buffer, resent);
76                                 fputs(buffer, ofp);
77                         }
78                         if (state == FLDEOF) {
79                                 goto process;
80                         }
81                         break;
82
83                 case BODY:
84                 case BODYEOF:
85                         for (dp = buffer; *dp; dp++) {
86                                 if (!isspace(*dp)) {
87                                         advise(NULL, "Please re-edit draft to consist of headers only.");
88                                         goto leave_bad;
89                                 }
90                         }
91
92                 case FILEEOF:
93                         goto process;
94
95                 case LENERR:
96                 case FMTERR:
97                         advise(NULL, "Please re-edit draft and fix that header.");
98 leave_bad: ;
99                         fclose(ifp);
100                         fclose(ofp);
101                         unlink(drft);
102                         if (rename(backup, drft) == NOTOK) {
103                                 advise(drft, "unable to rename %s to", backup);
104                         }
105                         return NOTOK;
106
107                 default:
108                         advise(NULL, "getfld() returned %d", state);
109                         return NOTOK;
110                 }
111         }
112
113 process: ;
114         fclose(ifp);
115         fflush(ofp);
116
117         if (!resent) {
118                 advise(NULL, "Please re-edit draft to include a ``Resent-To:'' header.");
119                 fclose(ofp);
120                 unlink(drft);
121                 if (rename(backup, drft) == NOTOK) {
122                         advise(drft, "unable to rename %s to", backup);
123                 }
124                 return NOTOK;
125         }
126         free(resent);
127
128         if (txtfd != NOTOK) {
129                 lseek(txtfd, (off_t) 0, SEEK_SET);  /* msgnam not accurate */
130                 cpydata(txtfd, fileno(ofp), msgnam, drft);
131         }
132
133         fclose(ofp);
134
135         return OK;
136 }
137
138
139 static int
140 ready_msg(char *msgnam)
141 {
142         int state, out;
143         char name[NAMESZ], buffer[BUFSIZ], tmpfil[BUFSIZ];
144         register FILE *ifp, *ofp;
145         char *cp = NULL;
146
147         if (hdrfd != NOTOK) {
148                 close(hdrfd);
149                 hdrfd = NOTOK;
150         }
151         if (txtfd != NOTOK) {
152                 close(txtfd);
153                 txtfd = NOTOK;
154         }
155         if (!(ifp = fopen(msgnam, "r"))) {
156                 advise(msgnam, "unable to open message");
157                 return NOTOK;
158         }
159
160         cp = m_mktemp2(NULL, "dist", &hdrfd, NULL);
161         if (!cp) {
162                 advise("distsbr", "unable to create temporary file");
163                 return NOTOK;
164         }
165         fchmod(hdrfd, 0600);
166         strncpy(tmpfil, cp, sizeof(tmpfil));
167         if ((out = dup(hdrfd)) == NOTOK || !(ofp = fdopen(out, "w"))) {
168                 advise(NULL, "no file descriptors -- you lose big");
169                 return NOTOK;
170         }
171         unlink(tmpfil);
172
173         state = FLD;
174         while (1) {
175                 state = m_getfld(state, name, buffer, sizeof buffer, ifp);
176                 switch (state) {
177                 case FLD:
178                 case FLDPLUS:
179                 case FLDEOF:
180                         if (uprf(name, "resent")) {
181                                 fprintf(ofp, "Prev-");
182                         }
183                         fprintf(ofp, "%s: %s", name, buffer);
184                         while (state == FLDPLUS) {
185                                 state = m_getfld(state, name, buffer,
186                                                 sizeof buffer, ifp);
187                                 fputs(buffer, ofp);
188                         }
189                         if (state == FLDEOF) {
190                                 goto process;
191                         }
192                         break;
193
194                 case BODY:
195                 case BODYEOF:
196                         fclose(ofp);
197
198                         cp = m_mktemp2(NULL, "dist", &txtfd, NULL);
199                         if (!cp) {
200                                 advise("distsbr", "unable to create temp file");
201                                 return NOTOK;
202                         }
203                         fchmod(txtfd, 0600);
204                         strncpy(tmpfil, cp, sizeof(tmpfil));
205                         if ((out = dup(txtfd)) == NOTOK ||
206                                         !(ofp = fdopen(out, "w"))) {
207                                 advise(NULL, "no file descriptors -- you lose");
208                                 return NOTOK;
209                         }
210                         unlink(tmpfil);
211                         fprintf(ofp, "\n%s", buffer);
212                         while (state == BODY) {
213                                 state = m_getfld(state, name, buffer,
214                                                 sizeof buffer, ifp);
215                                 fputs(buffer, ofp);
216                         }
217                 case FILEEOF:
218                         goto process;
219
220                 case LENERR:
221                 case FMTERR:
222                         advise(NULL, "format error in message %s", msgnam);
223                         return NOTOK;
224
225                 default:
226                         advise(NULL, "getfld() returned %d", state);
227                         return NOTOK;
228                 }
229         }
230 process: ;
231         fclose(ifp);
232         fclose(ofp);
233         return OK;
234 }