Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / rcvstore.c
1 /* rcvstore.c - incorporate new mail asynchronously
2                 originally from Julian Onions */
3 #ifndef lint
4 static char ident[] = "@(#)$Id: rcvstore.c,v 1.9 1992/12/15 00:20:22 jromine Exp $";
5 #endif  /* lint */
6
7 #include "../h/mh.h"
8 #include <errno.h>
9 #include <signal.h>
10 #include <stdio.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #ifdef LOCALE
14 #include        <locale.h>
15 #endif
16
17 /* \f */
18
19 static struct swit switches[] = {
20 #define CRETSW  0
21     "create",   0,
22 #define NCRETSW 1
23     "nocreate", 0,
24
25 #define PUBSW   2
26     "public",   0,
27 #define NPUBSW  3
28     "nopublic",  0,
29
30 #define SEQSW   4
31     "sequence name", 0,
32
33 #define ZEROSW  5
34     "zero",     0,
35 #define NZEROSW 6
36     "nozero",   0,
37
38 #define HELPSW  7
39     "help", 4,
40
41     NULL, 0
42 };
43
44 /* \f */
45
46 extern int  errno;
47
48 static char *tmpfilenam = NULLCP;
49 /* \f */
50
51 /* ARGSUSED */
52
53 main (argc, argv)
54 int     argc;
55 char   *argv[];
56 {
57     int     publicsw = -1,
58             zerosw = 0,
59             msgnum,
60             create = 1,
61             fd,
62             seqp = 0;
63     char   *cp,
64            *maildir,
65            *folder = NULL,
66             buf[100],
67           **ap,
68           **argp,
69            *arguments[MAXARGS],
70            *seqs[NATTRS+1];
71     struct msgs *mp;
72     struct stat st;
73
74 #ifdef LOCALE
75         setlocale(LC_ALL, "");
76 #endif
77     invo_name = r1bindex (argv[0], '/');
78     mts_init (invo_name);
79     if ((cp = m_find (invo_name)) != NULL) {
80         ap = brkstring (cp = getcpy (cp), " ", "\n");
81         ap = copyip (ap, arguments);
82     }
83     else
84         ap = arguments;
85     (void) copyip (argv + 1, ap);
86     argp = arguments;
87
88 /* \f */
89
90     while (cp = *argp++) {
91         if (*cp == '-')
92             switch (smatch (++cp, switches)) {
93                 case AMBIGSW: 
94                     ambigsw (cp, switches);
95                     done (1);
96                 case UNKWNSW: 
97                     adios (NULLCP, "-%s unknown", cp);
98                 case HELPSW: 
99                     (void) sprintf (buf, "%s [+folder] [switches]", invo_name);
100                     help (buf, switches);
101                     done (1);
102
103                 case SEQSW: 
104                     if (!(cp = *argp++) || *cp == '-')
105                         adios (NULLCP, "missing argument name to %s",
106                                 argp[-2]);
107                     if (seqp < NATTRS)
108                         seqs[seqp++] = cp;
109                     else
110                         adios (NULLCP, "only %d sequences allowed!", NATTRS);
111                     continue;
112                 case PUBSW: 
113                     publicsw = 1;
114                     continue;
115                 case NPUBSW: 
116                     publicsw = 0;
117                     continue;
118                 case ZEROSW: 
119                     zerosw++;
120                     continue;
121                 case NZEROSW: 
122                     zerosw = 0;
123                     continue;
124
125                 case CRETSW: 
126                     create++;
127                     continue;
128                 case NCRETSW: 
129                     create = 0;
130                     continue;
131             }
132         if (*cp == '+' || *cp == '@') {
133             if (folder)
134                 adios (NULLCP, "only one folder at a time!");
135             else
136                 folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
137         }
138         else
139             adios (NULLCP, "usage: %s [+folder] [switches]", invo_name);
140     }
141
142 /* \f */
143
144     if (!m_find ("path"))
145         free (path ("./", TFOLDER));
146     if (!folder && !(folder = m_find (inbox)))
147         folder = defalt;
148     maildir = m_maildir (folder);
149
150     if (stat (maildir, &st) == NOTOK) {
151         if (errno != ENOENT)
152             adios (maildir, "error on folder");
153         if (!create)
154             adios (NULLCP, "folder %s doesn't exist", maildir);
155         if (!makedir (maildir))
156             adios (NULLCP, "unable to create folder %s", maildir);
157     }
158
159     if (chdir (maildir) == NOTOK)
160         adios (maildir, "unable to change directory to");
161     if (!(mp = m_gmsg (folder)))
162         adios (NULLCP, "unable to read folder %s", folder);
163
164     (void) signal (SIGHUP, SIG_IGN);
165     (void) signal (SIGINT, SIG_IGN);
166     (void) signal (SIGQUIT, SIG_IGN);
167     (void) signal (SIGTERM, SIG_IGN);
168
169 /* \f */
170
171     if ((fd = creat (tmpfilenam = m_scratch ("", invo_name), m_gmprot ()))
172             == NOTOK)
173         adios (tmpfilenam, "unable to create");
174     (void) chmod (tmpfilenam, m_gmprot ());
175
176     cpydata (fileno (stdin), fd, "standard input", tmpfilenam);
177
178     if (fstat (fd, &st) == NOTOK) {
179         (void) unlink (tmpfilenam);
180         adios (tmpfilenam, "unable to fstat");
181     }
182     if (close (fd) == NOTOK)
183         adios (tmpfilenam, "error closing");
184     if (st.st_size == 0) {
185         (void) unlink (tmpfilenam);
186         advise (NULLCP, "empty file");
187         done (0);
188     }
189
190     msgnum = mp -> hghmsg;
191     do {
192         msgnum++, mp -> hghmsg++;
193         if (msgnum > mp -> hghoff)
194             if ((mp = m_remsg (mp, 0, mp -> hghoff + MAXFOLDER)) == NULL)
195                 adios (NULLCP, "unable to allocate folder storage");
196
197         mp -> msgstats[msgnum] |= EXISTS | UNSEEN;
198         errno = 0;
199     } while (link (tmpfilenam, m_name (msgnum)) == NOTOK && errno == EEXIST);
200
201     (void) unlink (tmpfilenam);
202     tmpfilenam = NULLCP;
203     if (errno != 0)
204         adios (NULLCP, "can't file message %d", msgnum);
205
206     if (mp -> lowmsg == 0)
207         mp -> lowmsg = msgnum;
208     mp -> msgflags |= SEQMOD;
209
210     seqs[seqp] = NULL;
211     for (seqp = 0; seqs[seqp]; seqp++) {
212         if (zerosw && !m_seqnew (mp, seqs[seqp], publicsw))
213             done (1);
214         if (!m_seqadd (mp, seqs[seqp], msgnum, publicsw))
215             done (1);
216     }
217
218     m_setvis (mp, 0);
219     m_sync (mp);
220     m_update ();
221
222     done (0);
223 }
224
225 void done (status)
226 register int     status;
227 {
228     if (tmpfilenam && *tmpfilenam)
229         (void) unlink (tmpfilenam);
230     exit (status);
231 }