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