mh-format.man5: Restored the warning placeholder.
[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 #define BADHDR  "please re-edit %s to remove the ``%s'' header!"
17 #define BADTXT  "please re-edit %s to consist of headers only!"
18 #define BADMSG  "please re-edit %s to include a ``Resent-To:''!"
19 #define BADRFT  "please re-edit %s and fix that header!"
20
21 /*
22 ** static prototypes
23 */
24 static void ready_msg(char *);
25
26 int
27 distout(char *drft, char *msgnam, char *backup)
28 {
29         int state;
30         register unsigned char *dp;
31         register char *resent;
32         char name[NAMESZ], buffer[BUFSIZ];
33         register FILE *ifp, *ofp;
34
35         if (rename(drft, strcpy(backup, m_backup(drft))) == NOTOK)
36                 adios(backup, "unable to rename %s to",drft);
37         if ((ifp = fopen(backup, "r")) == NULL)
38                 adios(backup, "unable to read");
39
40         if ((ofp = fopen(drft, "w")) == NULL)
41                 adios(drft, "unable to create temporary file");
42         chmod(drft, m_gmprot());
43
44         ready_msg(msgnam);
45         lseek(hdrfd, (off_t) 0, SEEK_SET); /* msgnam not accurate */
46         cpydata(hdrfd, fileno(ofp), msgnam, drft);
47
48         for (state = FLD, resent = NULL;;)
49                 switch (state = m_getfld (state, name, buffer,
50                                 sizeof buffer, ifp)) {
51                 case FLD:
52                 case FLDPLUS:
53                 case FLDEOF:
54                         if (uprf(name, "distribute-"))
55                                 snprintf(name, sizeof(name), "%s%s",
56                                                 "Resent", &name[10]);
57                         if (uprf(name, "distribution-"))
58                                 snprintf(name, sizeof(name), "%s%s",
59                                                 "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, buffer,
70                                                 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         char *cp = NULL;
135
136         if (hdrfd != NOTOK)
137                 close(hdrfd), hdrfd = NOTOK;
138         if (txtfd != NOTOK)
139                 close(txtfd), txtfd = NOTOK;
140
141         if ((ifp = fopen(msgnam, "r")) == NULL)
142                 adios(msgnam, "unable to open message");
143
144         cp = m_mktemp2(NULL, "dist", &hdrfd, NULL);
145         if (cp == NULL) {
146                 adios("distsbr", "unable to create temporary file");
147         }
148         fchmod(hdrfd, 0600);
149         strncpy(tmpfil, cp, sizeof(tmpfil));
150         if ((out = dup(hdrfd)) == NOTOK
151                         || (ofp = fdopen(out, "w")) == NULL)
152                 adios(NULL, "no file descriptors -- you lose big");
153         unlink(tmpfil);
154
155         for (state = FLD;;) {
156                 state = m_getfld(state, name, buffer, sizeof buffer, ifp);
157                 switch (state) {
158                 case FLD:
159                 case FLDPLUS:
160                 case FLDEOF:
161                         if (uprf(name, "resent"))
162                                 fprintf(ofp, "Prev-");
163                         fprintf(ofp, "%s: %s", name, buffer);
164                         while (state == FLDPLUS) {
165                                 state = m_getfld(state, name, buffer,
166                                                 sizeof buffer, ifp);
167                                 fputs(buffer, ofp);
168                         }
169                         if (state == FLDEOF)
170                                 goto process;
171                         break;
172
173                 case BODY:
174                 case BODYEOF:
175                         fclose(ofp);
176
177                         cp = m_mktemp2(NULL, "dist", &txtfd, NULL);
178                         if (cp == NULL) {
179                                 adios("distsbr", "unable to create temporary file");
180                         }
181                         fchmod(txtfd, 0600);
182                         strncpy(tmpfil, cp, sizeof(tmpfil));
183                         if ((out = dup(txtfd)) == NOTOK
184                                         || (ofp = fdopen(out, "w")) == NULL)
185                                 adios(NULL, "no file descriptors -- you lose big");
186                         unlink(tmpfil);
187                         fprintf(ofp, "\n%s", buffer);
188                         while (state == BODY) {
189                                 state = m_getfld(state, name, buffer,
190                                                 sizeof buffer, ifp);
191                                 fputs(buffer, ofp);
192                         }
193                 case FILEEOF:
194                         goto process;
195
196                 case LENERR:
197                 case FMTERR:
198                         adios(NULL, "format error in message %s", msgnam);
199
200                 default:
201                         adios(NULL, "getfld() returned %d", state);
202                 }
203         }
204 process: ;
205         fclose(ifp);
206         fclose(ofp);
207 }