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