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