Initial commit of files for the project, started from scratch.
[infodrom/newmail] / folder.c
1 /*
2     Copyright (c) 2004  Joey Schulze <joey@infodrom.org>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <strings.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <sys/types.h>
26 #include <pwd.h>
27 #include <errno.h>
28 #include <paths.h>
29 #include "mbox.h"
30
31 #define FOLDERS_DELTA   5
32
33 struct folder {
34   char *path;
35   char *prefix;
36   off_t size;
37 };
38
39 struct folder **folders = NULL;
40 unsigned int numfolders = 0;
41 unsigned int maxfolders = 0;
42
43 void add_folder(char *path)
44 {
45   struct folder *thisfolder;
46   struct stat st;
47   char *cp;
48   int sh;
49
50   if (numfolders == maxfolders) {
51     if ((folders = (struct folder **)
52          realloc(folders,
53                  (maxfolders + FOLDERS_DELTA) * sizeof(struct folder *))) == NULL) {
54       perror("realloc");
55       exit(1);
56     }
57     maxfolders += FOLDERS_DELTA;
58   }
59
60   if ((thisfolder = (struct folder *)malloc(sizeof(struct folder))) == NULL) {
61     perror("malloc");
62     exit(1);
63   }
64
65   if ((cp = index(path, '=')) != NULL) {
66     *cp++ = '\0';
67     if ((thisfolder->prefix = (char *)strdup(cp)) == NULL) {
68       perror("strdup");
69       exit(1);
70     }
71     strcpy(thisfolder->prefix, cp);
72   } else {
73     if (numfolders > 0) {
74       /* More than one mailbox to monitor --> need prefix anyway */
75       if ((cp = rindex(path, '/')) != NULL) {
76         cp++;
77         if ((thisfolder->prefix = (char *)strdup(cp)) == NULL) {
78           perror("strdup");
79           exit(1);
80         }
81       } else {
82         if ((thisfolder->prefix = (char *)strdup(path)) == NULL) {
83           perror("strdup");
84           exit(1);
85         }
86       }
87     } else
88       thisfolder->prefix = NULL;
89   }
90
91   if ((thisfolder->path = (char *)strdup(path)) == NULL) {
92     perror("strdup");
93     exit(1);
94   }
95
96   sh = stat(path, &st);
97
98   if (sh == 0) {
99     thisfolder->size = st.st_size;
100   } else if (sh == -1 && errno == ENOENT) {
101     thisfolder->size = 0;
102   } else {
103     free (thisfolder->path);
104     free (thisfolder);
105     return;
106   }
107
108   folders[numfolders++] = thisfolder;
109 }
110
111 void add_default_folder()
112 {
113   char path[128];
114   char *env;
115   uid_t uid;
116   struct passwd *pw;
117
118   if ((env = getenv("MAIL")) == NULL) {
119     uid = getuid();
120     if ((pw = getpwuid(uid)) == NULL) {
121       perror("getpwuid");
122       exit(1);
123     }
124
125     snprintf(path, sizeof(path), "%s/%s", _PATH_MAILDIR, pw->pw_name);
126   } else {
127     snprintf(path, sizeof(path), env);
128   }
129
130   add_folder(path);
131 }
132
133 void fix_prefix()
134 {
135   char *cp;
136
137   if (numfolders < 2)
138     return;
139
140   if (folders[0]->prefix != NULL)
141     return;
142
143   if ((cp = rindex(folders[0]->path, '/')) != NULL) {
144     cp++;
145     if ((folders[0]->prefix = (char *)strdup(cp)) == NULL) {
146       perror("strdup");
147       exit(1);
148     }
149   } else {
150     if ((folders[0]->prefix = (char *)strdup(folders[0]->path)) == NULL) {
151       perror("strdup");
152       exit(1);
153     }
154   }
155 }
156
157 void watch_folders(int opt_bell)
158 {
159   unsigned int i;
160   int newmail = 0;
161
162   for (i=0; i < numfolders; i++)
163     newmail |= watch_mbox(folders[i]->path, folders[i]->prefix, &folders[i]->size);
164
165   if (newmail && opt_bell) {
166     putchar('\007');
167     fflush(stdout);
168   }
169 }