1 /* nmcopy.c - copies netmails to homedirs */
2
3 // obvious
4 #define VERSION "1.0"
5 // group with all fido-users
6 #define GROUPNAME "fido"
7 // file/path of area, relative to homedir
8 #define NETMAILAREA ".fido/netmail"
9
10 #include <errno.h>
11 #include <smapi/msgapi.h>
12 #include <fidoconf/fidoconf.h>
13 #include <fidoconf/common.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <pwd.h>
17 #include <grp.h>
18 #include <sys/types.h>
19
20 #ifndef nfree
21 #define nfree(a) { if (a) { free(a); a = NULL; } }
22 #endif
23
24 char **users = NULL;
25 char **userNames = NULL;
26 char **homeDirs = NULL;
27 unsigned int numUsers = 0;
28 s_fidoconfig *config = NULL;
29
cvtAddr(const NETADDR aka1,hs_addr * aka2)30 void cvtAddr(const NETADDR aka1, hs_addr *aka2)
31 {
32 aka2->zone = aka1.zone;
33 aka2->net = aka1.net;
34 aka2->node = aka1.node;
35 aka2->point = aka1.point;
36 }
37
done()38 void done()
39 {
40 unsigned int i;
41
42 for (i = 0; i < numUsers; i++)
43 {
44 nfree(users[i]);
45 nfree(userNames[i]);
46 nfree(homeDirs[i]);
47 }
48 nfree(users);
49 nfree(userNames);
50 nfree(homeDirs);
51
52 if (config) disposeConfig(config);
53 }
54
getHomeDir(char * user)55 char *getHomeDir(char *user)
56 {
57 struct passwd *pw;
58
59 pw = getpwnam(user);
60 return strdup(pw->pw_dir);
61 }
62
getRealname(char * user)63 char *getRealname(char *user)
64 {
65 struct passwd *pw;
66 char *pos;
67 char *res;
68
69 pw = getpwnam(user);
70 if (!pw) return strdup(user);
71
72 if ((pw->pw_gecos != NULL) && (*pw->pw_gecos != 0))
73 {
74 pos = strchr(pw->pw_gecos, ',');
75 if (pos)
76 {
77 res = malloc(pos - pw->pw_gecos + 1);
78 strncpy(res, pw->pw_gecos, pos - pw->pw_gecos);
79 res[pos - pw->pw_gecos] = 0;
80
81 return res;
82 }
83 else return strdup(pw->pw_gecos);
84 }
85 else return strdup(user);
86 }
87
getUsers()88 void getUsers()
89 {
90 struct group *gr;
91 unsigned int i;
92
93 gr = getgrnam(GROUPNAME);
94 if (!gr)
95 {
96 printf("Could not get members of group '%s'!\n", GROUPNAME);
97 done();
98 exit(10);
99 }
100
101 for (i = 0; (gr->gr_mem[i]); i++)
102 {
103 numUsers++;
104 users = realloc(users, numUsers * sizeof(char *));
105 users[i] = strdup(gr->gr_mem[i]);
106 }
107 userNames = malloc(numUsers * sizeof(char *));
108 homeDirs = malloc(numUsers * sizeof(char *));
109 for (i = 0; i < numUsers; i++)
110 {
111 userNames[i] = strLower(getRealname(users[i]));
112 homeDirs[i] = getHomeDir(users[i]);
113 }
114 }
115
scanMsg(HAREA area,unsigned int msgNum)116 int scanMsg(HAREA area, unsigned int msgNum)
117 {
118 HMSG msg, newMsg;
119 XMSG xmsg;
120 long int addrMatch, nameMatch;
121 unsigned int i;
122 char *toLow;
123 hs_addr dest;
124 char *text, *ctrlText;
125 unsigned long int textLen, ctrlLen;
126 HAREA userArea;
127 char *userAreaName;
128
129 msg = MsgOpenMsg(area, MOPEN_READ, msgNum);
130 if (msg == NULL) return 0;
131
132 MsgReadMsg(msg, &xmsg, 0, 0, NULL, 0, NULL);
133
134 // check address
135 addrMatch = -1;
136 cvtAddr(xmsg.dest, &dest);
137 for (i = 0; i < config->addrCount; i++)
138 if (addrComp(dest, config->addr[i]) == 0)
139 {
140 addrMatch = i;
141 i = config->addrCount;
142 }
143
144 if (addrMatch == -1) return 0;
145
146 // check name
147 nameMatch = -1;
148 toLow = strLower(strdup(xmsg.to));
149 for (i = 0; i < numUsers; i++)
150 if (strstr(toLow, userNames[i]))
151 {
152 printf("Message #%d to '%s' matching user '%s'\n", msgNum, toLow,
153 users[i]);
154 nameMatch = i;
155 i = numUsers;
156 }
157 nfree(toLow);
158
159 if (nameMatch == -1) return 0;
160
161 // copy msg
162 userAreaName = malloc(strlen(homeDirs[nameMatch])+strlen(NETMAILAREA)+2);
163 sprintf(userAreaName, "%s/%s", homeDirs[nameMatch], NETMAILAREA);
164
165 userArea = MsgOpenArea(userAreaName, MSGAREA_NORMAL, MSGTYPE_SQUISH);
166 if (!userArea)
167 {
168 printf("Could not open area '%s' for user '%s'!\n", userAreaName,
169 users[nameMatch]);
170 nfree(userAreaName);
171
172 return 0;
173 }
174 nfree(userAreaName);
175
176 textLen = MsgGetTextLen(msg);
177 ctrlLen = MsgGetCtrlLen(msg);
178
179 text = (char *) malloc(textLen+1);
180 text[textLen] = '\0';
181
182 ctrlText = (char *) malloc(ctrlLen+1);
183 ctrlText[ctrlLen] = '\0';
184
185 MsgReadMsg(msg, NULL, 0, textLen, (byte*)text, ctrlLen, (byte*)ctrlText);
186 newMsg = MsgOpenMsg(userArea, MOPEN_CREATE, 0);
187
188 MsgWriteMsg(newMsg, 0, &xmsg, (byte*)text, textLen, textLen, ctrlLen, (byte*)ctrlText);
189 MsgCloseMsg(newMsg);
190
191 free(text);
192 free(ctrlText);
193
194 MsgCloseArea(userArea);
195
196 return 1;
197 }
198
scanArea(HAREA area)199 void scanArea(HAREA area)
200 {
201 unsigned int highMsg;
202 unsigned int i;
203
204 highMsg = MsgGetHighMsg(area);
205 for (i = 1; i <= highMsg; i++)
206 {
207 if (scanMsg(area, i))
208 {
209 // printf("deleting msg #%d\n", i);
210 MsgKillMsg(area, i);
211 }
212 }
213 }
214
main(int argc,char ** argv)215 int main(int argc, char **argv)
216 {
217 struct _minf m;
218 HAREA area;
219
220 printf("nmcopy %s\n", VERSION);
221
222 if (argc > 1)
223 {
224 printf("nmcopy - copy netmails to homedirs\n");
225 printf("Syntax: nmcopy\n");
226
227 return 1;
228 }
229
230 // get usernames
231 getUsers();
232
233 // read fidoconfig
234 config = readConfig(NULL);
235
236 if (config != NULL)
237 {
238 m.req_version = 0;
239 m.def_zone = config->addr[0].zone;
240
241 if (MsgOpenApi(&m) != 0)
242 {
243 printf("Cannot open smapi!\n");
244 done();
245 return 6;
246 }
247
248 area = MsgOpenArea(config->netMailAreas[0].fileName, MSGAREA_NORMAL,
249 config->netMailAreas[0].msgbType);
250 if (!area)
251 {
252 printf("Cannot open primary netmail area!\n");
253 done();
254 return 7;
255 }
256 else
257 {
258 scanArea(area);
259 MsgCloseArea(area);
260 }
261
262 done();
263 }
264 else
265 {
266 printf("Cannot read fidoconfig!\n");
267 done();
268
269 return 5;
270 }
271
272 return 0;
273 }
274
275