* Bug #15213, #18635: The use of the insecure m_scratch() and
[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 unsigned char *dp;
34     register char *resent;
35     char name[NAMESZ], buffer[BUFSIZ];
36     register FILE *ifp, *ofp;
37
38     if (rename (drft, strcpy (backup, m_backup (drft))) == NOTOK)
39         adios (backup, "unable to rename %s to",drft);
40     if ((ifp = fopen (backup, "r")) == NULL)
41         adios (backup, "unable to read");
42
43     if ((ofp = fopen (drft, "w")) == NULL)
44         adios (drft, "unable to create temporary file");
45     chmod (drft, m_gmprot ());
46
47     ready_msg (msgnam);
48     lseek (hdrfd, (off_t) 0, SEEK_SET); /* msgnam not accurate */
49     cpydata (hdrfd, fileno (ofp), msgnam, drft);
50
51     for (state = FLD, resent = NULL;;)
52         switch (state =
53                 m_getfld (state, name, buffer, sizeof buffer, ifp)) {
54             case FLD: 
55             case FLDPLUS: 
56             case FLDEOF: 
57                 if (uprf (name, "distribute-"))
58                     snprintf (name, sizeof(name), "%s%s", "Resent", &name[10]);
59                 if (uprf (name, "distribution-"))
60                     snprintf (name, sizeof(name), "%s%s", "Resent", &name[12]);
61                 if (!uprf (name, "resent")) {
62                     advise (NULL, BADHDR, "draft", name);
63                     goto leave_bad;
64                 }
65                 if (state == FLD)
66                     resent = add (":", add (name, resent));
67                 resent = add (buffer, resent);
68                 fprintf (ofp, "%s: %s", name, buffer);
69                 while (state == FLDPLUS) {
70                     state = m_getfld (state, name,
71                             buffer, sizeof buffer, ifp);
72                     resent = add (buffer, resent);
73                     fputs (buffer, ofp);
74                 }
75                 if (state == FLDEOF)
76                     goto process;
77                 break;
78
79             case BODY: 
80             case BODYEOF: 
81                 for (dp = buffer; *dp; dp++)
82                     if (!isspace (*dp)) {
83                         advise (NULL, BADTXT, "draft");
84                         goto leave_bad;
85                     }
86
87             case FILEEOF: 
88                 goto process;
89
90             case LENERR: 
91             case FMTERR: 
92                 advise (NULL, BADRFT, "draft");
93         leave_bad: ;
94                 fclose (ifp);
95                 fclose (ofp);
96                 unlink (drft);
97                 if (rename (backup, drft) == NOTOK)
98                     adios (drft, "unable to rename %s to", backup);
99                 return NOTOK;
100
101             default: 
102                 adios (NULL, "getfld() returned %d", state);
103         }
104 process: ;
105     fclose (ifp);
106     fflush (ofp);
107
108     if (!resent) {
109         advise (NULL, BADMSG, "draft");
110         fclose (ofp);
111         unlink (drft);
112         if (rename (backup, drft) == NOTOK)
113             adios (drft, "unable to rename %s to", backup);
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), hdrfd = NOTOK;
139     if (txtfd != NOTOK)
140         close (txtfd), txtfd = NOTOK;
141
142     if ((ifp = fopen (msgnam, "r")) == NULL)
143         adios (msgnam, "unable to open message");
144
145     cp = m_mktemp2(NULL, "dist", &hdrfd, NULL);
146     if (cp == NULL) {
147         adios("distsbr", "unable to create temporary file");
148     }
149     fchmod(hdrfd, 0600);
150     strncpy(tmpfil, cp, sizeof(tmpfil));
151     if ((out = dup (hdrfd)) == NOTOK
152             || (ofp = fdopen (out, "w")) == NULL)
153         adios (NULL, "no file descriptors -- you lose big");
154     unlink (tmpfil);
155
156     for (state = FLD;;)
157         switch (state =
158                 m_getfld (state, name, buffer, sizeof buffer, ifp)) {
159             case FLD: 
160             case FLDPLUS: 
161             case FLDEOF: 
162                 if (uprf (name, "resent"))
163                     fprintf (ofp, "Prev-");
164                 fprintf (ofp, "%s: %s", name, buffer);
165                 while (state == FLDPLUS) {
166                     state = m_getfld (state, name,
167                             buffer, sizeof buffer, ifp);
168                     fputs (buffer, ofp);
169                 }
170                 if (state == FLDEOF)
171                     goto process;
172                 break;
173
174             case BODY: 
175             case BODYEOF: 
176                 fclose (ofp);
177
178                 cp = m_mktemp2(NULL, "dist", &txtfd, NULL);
179                 if (cp == NULL) {
180                     adios("distsbr", "unable to create temporary file");
181                 }
182                 fchmod(txtfd, 0600);
183                 strncpy (tmpfil, cp, sizeof(tmpfil));
184                 if ((out = dup (txtfd)) == NOTOK
185                         || (ofp = fdopen (out, "w")) == NULL)
186                     adios (NULL, "no file descriptors -- you lose big");
187                 unlink (tmpfil);
188                 fprintf (ofp, "\n%s", buffer);
189                 while (state == BODY) {
190                     state = m_getfld (state, name,
191                             buffer, sizeof buffer, ifp);
192                     fputs (buffer, ofp);
193                 }
194             case FILEEOF: 
195                 goto process;
196
197             case LENERR: 
198             case FMTERR: 
199                 adios (NULL, "format error in message %s", msgnam);
200
201             default: 
202                 adios (NULL, "getfld() returned %d", state);
203         }
204 process: ;
205     fclose (ifp);
206     fclose (ofp);
207 }