1 /*
2 * ----------------------------------------------------------------
3 * ircproxy - Connection Logging Functions
4 * ----------------------------------------------------------------
5 * Copyright (C) 1997-2009 Jonas Kvinge
6 *
7 * This file is part of ircproxy.
8 *
9 * ircproxy is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * ircproxy is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ircproxy. If not, see <http://www.gnu.org/licenses/>.
21 *
22 * Additional permission under GNU GPL version 3 section 7
23 *
24 * If you modify ircproxy, or any covered work, by linking or
25 * combining it with openssl (or a modified version of that library),
26 * containing parts covered by the terms of the OpenSSL License and the
27 * SSLeay License, the licensors of ircproxy grant you additional
28 * permission to convey the resulting work.
29 *
30 * $Id: conn_log.c 54 2009-03-18 18:23:29Z jonasio $
31 *
32 */
33
34 #define CONN_LOG_C
35
36 #define NEED_SYS_TYPES_H 1 /* Extra types */
37 #define NEED_SYS_PARAM_H 1 /* Some systems need this */
38 #define NEED_LIMITS_H 0 /* Kernel limits */
39 #define NEED_STDARG_H 1 /* va_list, etc */
40 #define NEED_ERRNO_H 1 /* errno */
41 #define NEED_CTYPE_H 1 /* isdigit(), etc */
42 #define NEED_NETINET_IN_H 1 /* in_addr, sockaddr_in, etc */
43 #define NEED_ARPA_INET_H 0 /* inet_ntoa(), inet_aton(), etc */
44 #define NEED_STDIO_H 1 /* Standard C UNIX functions */
45 #define NEED_STDLIB_H 1 /* malloc(), exit(), atoi(), etc */
46 #define NEED_TIME_H 1 /* time(), etc */
47 #define NEED_SYSCTL_H 0 /* sysctl(), etc */
48 #define NEED_SYS_STAT_H 1 /* chmod(), mkdir(), etc */
49 #define NEED_SYS_UIO_H 0 /* iovec, etc */
50 #define NEED_FCNTL_H 1 /* open(), creat(), fcntl(), etc */
51 #define NEED_SYS_IOCTL_H 0 /* ioctl(), etc */
52 #define NEED_SYS_FILIO_H 0 /* Solaris need this for ioctl(), etc */
53 #define NEED_UNISTD_H 1 /* Unix standard functions */
54 #define NEED_STRING_H 1 /* C string functions */
55 #define NEED_SIGNAL_H 0 /* Signal functions */
56 #define NEED_SYS_SOCKET_H 0 /* Socket functions */
57 #define NEED_NETDB_H 0 /* Network database functions */
58 #define NEED_ARPA_NAMESER_H 0 /* Nameserver definitions */
59 #define NEED_GETUSERPW_HEADERS 0 /* Functions to retrive system passwords */
60 #define NEED_ARES 0 /* Functions needed for ares */
61 #define NEED_SSL 1 /* Needed for SSL support */
62
63 #include "includes.h"
64 #include "irc.h"
65
66 #include "conf.h"
67
68 #include "conn.h"
69 #include "conn_log.h"
70
71 #include "chan.h"
72
73 extern struct Conf_Struct ConfS;
74 extern unsigned short int Root;
75
76 /* CONN_ADDLOG - JONAS (20.01.2008) */
77
conn_addlog(struct Conn_Struct * ConnS,unsigned short int LogType,const char * const NamePT,const char * const LogFilePT,const char * const LogFileFullPathPT)78 struct ConnLog_Struct *conn_addlog(struct Conn_Struct *ConnS, unsigned short int LogType, const char *const NamePT, const char *const LogFilePT, const char *const LogFileFullPathPT) {
79
80 struct ConnLog_Struct *ConnLog = NULL;
81 struct ConnLog_Struct *ConnLog_NEW = NULL;
82
83 assert(ConnS != NULL);
84 assert(NamePT != NULL);
85 assert(LogFilePT != NULL);
86 assert(LogFileFullPathPT != NULL);
87
88 ConnLog = conn_getlog(ConnS, LogFilePT);
89 if (ConnLog != NULL) {
90 aerrno = AEEXISTS;
91 return(ConnLog);
92 }
93
94 ConnLog_NEW = malloc(sizeof(struct ConnLog_Struct));
95 if (ConnLog_NEW == NULL) {
96 aerrno = AEMALLOC;
97 return(NULL);
98 }
99 memset(ConnLog_NEW, 0, sizeof(struct ConnLog_Struct));
100
101 ConnLog_NEW->LogType = LogType;
102 ConnLog_NEW->Name = strdup(NamePT);
103 ConnLog_NEW->LogFile = strdup(LogFilePT);
104 ConnLog_NEW->LogFileFullPath = strdup(LogFileFullPathPT);
105
106 if ((ConnLog_NEW->Name == NULL) || (ConnLog_NEW->LogFile == NULL) || (ConnLog_NEW->LogFileFullPath == NULL)) {
107 free(ConnLog_NEW->Name);
108 free(ConnLog_NEW->LogFile);
109 free(ConnLog_NEW->LogFileFullPath);
110 free(ConnLog_NEW);
111 aerrno = AEMALLOC;
112 return(NULL);
113 }
114
115 if (ConnS->Log_Head == NULL) {
116 ConnS->Log_Head = ConnLog_NEW;
117 ConnS->Log_Tail = ConnLog_NEW;
118 }
119 else {
120 ConnLog = ConnS->Log_Tail;
121 ConnLog->Next = ConnLog_NEW;
122 ConnLog_NEW->Prev = ConnLog;
123 ConnS->Log_Tail = ConnLog_NEW;
124 }
125
126 ConnS->NumLogs++;
127
128 aerrno = AESUCCESS;
129 return(ConnLog_NEW);
130
131 }
132
133 /* CONN_REMLOG FUNCTION - JONAS (20.01.2008) */
134
conn_remlog(struct Conn_Struct * ConnS,struct ConnLog_Struct * ConnLog)135 void conn_remlog(struct Conn_Struct *ConnS, struct ConnLog_Struct *ConnLog) {
136
137 assert(ConnS != NULL);
138 assert(ConnLog != NULL);
139
140 if (ConnLog->Prev == NULL) { ConnS->Log_Head = ConnLog->Next; }
141 else { ConnLog->Prev->Next = ConnLog->Next; }
142
143 if (ConnLog->Next == NULL) { ConnS->Log_Tail = ConnLog->Prev; }
144 else { ConnLog->Next->Prev = ConnLog->Prev; }
145
146 free(ConnLog->Name);
147 free(ConnLog->LogFile);
148 free(ConnLog->LogFileFullPath);
149 free(ConnLog);
150
151 ConnS->NumLogs--;
152
153 }
154
155 /* CONN_GETLOG FUNCTION - JONAS (20.01.2008) */
156
conn_getlog(struct Conn_Struct * ConnS,const char * const LogFilePT)157 struct ConnLog_Struct *conn_getlog(struct Conn_Struct *ConnS, const char *const LogFilePT) {
158
159 struct ConnLog_Struct *ConnLog = NULL;
160
161 assert(ConnS != NULL);
162 assert(LogFilePT != NULL);
163
164 for (ConnLog = ConnS->Log_Head ; ConnLog != NULL ; ConnLog = ConnLog->Next) {
165 if (strcasecmp(ConnLog->LogFile, LogFilePT) == FALSE) {
166 aerrno = AESUCCESS;
167 return(ConnLog);
168 }
169 }
170 aerrno = AENOMATCH;
171 return(NULL);
172
173 }
174
175 /* CONN_REMLOGS FUNCTION - JONAS (20.01.2008) */
176
conn_destroylogs(struct Conn_Struct * ConnS)177 void conn_destroylogs(struct Conn_Struct *ConnS) {
178
179 while (ConnS->Log_Head != NULL) { conn_remlog(ConnS, ConnS->Log_Head); }
180
181 }
182
183 /* CONN_LOG FUNCTION - JONAS (18.07.2001) */
184
conn_log(struct Conn_Struct * ConnS,struct Chan_Struct * ChanS,const char * const ChanPT,const char * const NickPT,const char * const UserPT,const char * const HostPT,const char * const NUHPT,const char * const CommandPT,const char * const ParamPT,const char * const MessagePT)185 unsigned short int conn_log(struct Conn_Struct *ConnS, struct Chan_Struct *ChanS, const char *const ChanPT, const char *const NickPT, const char *const UserPT, const char *const HostPT, const char *const NUHPT, const char *const CommandPT, const char *const ParamPT, const char *const MessagePT) {
186
187 signed long int Result = 0;
188 char *HomeDirPT = NULL;
189 char LogFileName[FILELEN+1] = "";
190 char LogPath[FILELEN+1] = "";
191 char LogFileNamePath[FILELEN+1] = "";
192 char **FilePTT = NULL;
193 FILE *FileFP = NULL;
194 FILE **FileFPP = &FileFP;
195 #if 0
196 struct tm *TMPT = NULL;
197 char Date[LINELEN+1] = "";
198 #endif
199 unsigned short int LogErrors = 0;
200 char *LogFileNamePT = NULL;
201
202 assert(ConnS != NULL);
203
204 Conn_ClearLogHomeDir(ConnS);
205
206 if ((ConfS.UnixPasswd == TRUE) && (Root == TRUE)) {
207 HomeDirPT = sysgethomedirfromuser(ConnS->User);
208 if (HomeDirPT == NULL) {
209 ConnLogError("Unable to log messages for connection %s: Unable to retrive home directory for user \"%s\"", ConnS->Name, ConnS->User);
210 return(ERROR);
211 }
212 if (sysseteuidbyuser(ConnS->User) != SUCCESS) {
213 ConnLogError("Unable to log messages for connection %s: Unable to set effective user ID to \"%s\"", ConnS->Name, ConnS->User);
214 return(ERROR);
215 }
216 if (access(HomeDirPT, X_OK) != SUCCESS) {
217 ConnLogError("Unable to log messages for connection %s: Unable to access home directory for user \"%s\"", ConnS->Name, ConnS->User);
218 sysseteuidnormal();
219 return(ERROR);
220 }
221 Conn_SetLogHomeDir(ConnS);
222 snprintf(LogPath, FILELEN+1, "%s/ircproxy-logs", HomeDirPT);
223 }
224 else { snprintf(LogPath, FILELEN+1, "%s", ConfS.LogPath); }
225
226 if (access(LogPath, X_OK) == ERROR) {
227 Result = mkdir(LogPath, (S_IRWXU|S_IXGRP|S_IXOTH));
228 if ((Result <= ERROR) && (errno != EEXIST)) {
229 sysprint(BITMASK_ERROR, "Unable to create directory %s: [%d] %s", LogPath, errno, strerror(errno));
230 if (Conn_IsLogHomeDir(ConnS)) { sysseteuidnormal(); }
231 return(ERROR);
232 }
233 }
234
235 #if 0
236 TMPT = localtime(&NOW);
237 strftime(Date, LINELEN, "%Y%m%d", TMPT);
238 #endif
239
240 VariableDataS.ConnS = ConnS;
241 VariableDataS.ChanS = ChanS;
242 VariableDataS.Chan = ChanPT;
243 VariableDataS.Nick = NickPT;
244 VariableDataS.User = UserPT;
245 VariableDataS.Host = HostPT;
246 VariableDataS.NUH = NUHPT;
247 VariableDataS.Command = CommandPT;
248 VariableDataS.Param = ParamPT;
249 VariableDataS.Message = MessagePT;
250
251 if (CommandPT == NULL) {
252 LogFileNamePT = conn_log_variable(ConfS.RawLogFileFormat, NULL);
253 #if 0
254 snprintf(LogFileName, FILELEN+1, "%s-%s-%s.log", ConnS->Name, ConnS->ServerHostName, Date);
255 #endif
256 FilePTT = &ConnS->RawLogFile;
257 FileFPP = &ConnS->RawLogFileFP;
258 }
259 else {
260 if (ChanPT == NULL) {
261 LogFileNamePT = conn_log_variable(ConfS.PrivLogFileFormat, NULL);
262 #if 0
263 snprintf(LogFileName, FILELEN+1, "%s-%s.log", ConnS->Name, Date);
264 #endif
265 FilePTT = &ConnS->PrivLogFile;
266 FileFPP = &ConnS->PrivLogFileFP;
267 }
268 else {
269 LogFileNamePT = conn_log_variable(ConfS.ChanLogFileFormat, NULL);
270 #if 0
271 snprintf(LogFileName, FILELEN+1, "%s-%s-%s.log", ConnS->Name, ChanPT, Date);
272 #endif
273 if (ChanS == NULL) {
274 FileFPP = &FileFP;
275 }
276 else {
277 FilePTT = &ChanS->LogFile;
278 FileFPP = &ChanS->LogFileFP;
279 }
280 }
281 }
282 strcpy(LogFileName, LogFileNamePT);
283 FREE(LogFileNamePT);
284 strfilefix(LogFileName);
285 snprintf(LogFileNamePath, FILELEN+1, "%s/%s", LogPath, LogFileName);
286
287 if ((*FilePTT != NULL) && (strcmp(*FilePTT, LogFileName) != FALSE)) {
288 FREE(*FilePTT);
289 if (*FileFPP != NULL) {
290 fclose(*FileFPP);
291 *FileFPP = NULL;
292 }
293 }
294
295 do {
296
297 if (*FileFPP == NULL) {
298 *FileFPP = fopen(LogFileNamePath, "a");
299 if (*FileFPP == NULL) {
300 ConnLogError("Unable to open %s for writing: [%d] %s", LogFileNamePath, errno, strerror(errno));
301 if (Conn_IsLogHomeDir(ConnS)) { sysseteuidnormal(); }
302 return(ERROR);
303 }
304 if (FilePTT != NULL) *FilePTT = strrealloc(*FilePTT, LogFileName);
305 Result = chmod(LogFileNamePath, S_IRUSR|S_IWUSR);
306 if (Result <= ERROR) {
307 ConnLogError("Unable to set file permission for %s: [%d] %s", LogFileNamePath, errno, strerror(errno));
308 #if 0
309 fclose(*FileFPP);
310 if (FilePTT != NULL) FREE(*FilePTT);
311 if (Conn_IsLogHomeDir(ConnS)) { sysseteuidnormal(); }
312 return(ERROR);
313 #endif
314 }
315 Result = fprintf(*FileFPP, "%s *** Logging started.%s", dtstamp(), LINEFEED);
316 }
317
318 if (CommandPT == NULL) { Result = fprintf(*FileFPP, "%s *** %s%s", dtstamp(), MessagePT, LINEFEED); }
319 else {
320 assert(CommandPT != NULL);
321 assert(NUHPT != NULL);
322 assert(NickPT != NULL);
323 assert(UserPT != NULL);
324 assert(HostPT != NULL);
325 if (strcasecmp(CommandPT, "PRIVMSG") == FALSE) { Result = fprintf(*FileFPP, "%s <%s> %s%s", dtstamp(), NUHPT, MessagePT, LINEFEED); }
326 else if (strcasecmp(CommandPT, "NOTICE") == FALSE) { Result = fprintf(*FileFPP, "%s -%s- %s%s", dtstamp(), NUHPT, MessagePT, LINEFEED); }
327 else if (strcasecmp(CommandPT, "ACTION") == FALSE) { Result = fprintf(*FileFPP, "%s * %s %s%s", dtstamp(), NUHPT, MessagePT, LINEFEED); }
328 else if (strcasecmp(CommandPT, "CTCP") == FALSE) {
329 if (MessagePT == NULL) { Result = fprintf(*FileFPP, "%s %s CTCP %s%s", dtstamp(), NUHPT, ParamPT, LINEFEED); }
330 else { Result = fprintf(*FileFPP, "%s %s CTCP %s %s%s", dtstamp(), NUHPT, ParamPT, MessagePT, LINEFEED); }
331 }
332 else if (ChanPT != NULL) {
333 if (strcasecmp(CommandPT, "NICK") == FALSE) { Result = fprintf(*FileFPP, "%s %s (%s@%s) is now known as %s%s", dtstamp(), NickPT, UserPT, HostPT, ParamPT, LINEFEED); }
334 else if (strcasecmp(CommandPT, "QUIT") == FALSE) {
335 if (MessagePT == NULL) { Result = fprintf(*FileFPP, "%s %s quits%s", dtstamp(), NUHPT, LINEFEED); }
336 else { Result = fprintf(*FileFPP, "%s %s quits: %s%s", dtstamp(), NUHPT, MessagePT, LINEFEED); }
337 }
338 else if (strcasecmp(CommandPT, "MODE") == FALSE) { Result = fprintf(*FileFPP, "%s %s sets mode: %s%s", dtstamp(), NUHPT, MessagePT, LINEFEED); }
339 else if (strcasecmp(CommandPT, "JOIN") == FALSE) { Result = fprintf(*FileFPP, "%s %s has joined %s%s", dtstamp(), NUHPT, ChanPT, LINEFEED); }
340 else if (strcasecmp(CommandPT, "PART") == FALSE) {
341 if (MessagePT == NULL) { Result = fprintf(*FileFPP, "%s %s has left %s%s", dtstamp(), NUHPT, ChanPT, LINEFEED); }
342 else { Result = fprintf(*FileFPP, "%s %s has left %s: %s%s", dtstamp(), NUHPT, ChanPT, MessagePT, LINEFEED); }
343 }
344 else if (strcasecmp(CommandPT, "KICK") == FALSE) { Result = fprintf(*FileFPP, "%s %s was kicked by %s: %s%s", dtstamp(), ParamPT, NUHPT, MessagePT, LINEFEED); }
345 else if (strcasecmp(CommandPT, "TOPIC") == FALSE) { Result = fprintf(*FileFPP, "%s %s changed topic to: '%s'%s", dtstamp(), NUHPT, MessagePT, LINEFEED); }
346
347 }
348 }
349
350 if (Result <= ERROR) {
351 ++LogErrors;
352 fclose(*FileFPP);
353 *FileFPP = NULL;
354 if (FilePTT != NULL) FREE(*FilePTT);
355 }
356 else { break; }
357
358 }
359 while (LogErrors < 2);
360
361 if (FileFPP != NULL) fflush(*FileFPP);
362 if (FileFPP == &FileFP) fclose(*FileFPP);
363
364 if (Conn_IsLogHomeDir(ConnS)) { sysseteuidnormal(); }
365
366 if (LogErrors < 2) {
367 if (CommandPT == NULL) { conn_addlog(ConnS, CONN_LOG_TYPE_RAW, ConnS->ServerHostName, LogFileName, LogFileNamePath); }
368 else {
369 if (ChanPT == NULL) { conn_addlog(ConnS, CONN_LOG_TYPE_PRIV, ConnS->Name, LogFileName, LogFileNamePath); }
370 else { conn_addlog(ConnS, CONN_LOG_TYPE_CHAN, ChanPT, LogFileName, LogFileNamePath); }
371 }
372 }
373
374 #if 0
375 for (Index = 0 ; Index < ConnS->Logs ; ++Index) {
376 if (strcasecmp(ConnS->LogFile, LogFileName) == FALSE) { break; }
377 }
378 if (Index == ConnS->Logs) {
379 ++ConnS->Logs;
380 TempPT = realloc(ConnS->LogFile, (sizeof(char *) * ConnS->Logs));
381 if (TempPT == NULL) {
382 sysprint(BITMASK_ERROR, "Memory allocation failure: [%d] %s", errno, strerror(errno));
383 return(ERROR);
384 }
385 ConnS->LogFile = TempPT;
386 ConnS->LogFile[Index] = strdup(LogFileNamePath);
387 }
388 #endif
389
390 return(SUCCESS);
391
392 }
393
394 /* CONN_RAWLOG FUNCTION - JONAS (01.07.2000) */
395
conn_rawlog(struct Conn_Struct * ConnS,const char * const LinePT,...)396 void conn_rawlog(struct Conn_Struct *ConnS, const char *const LinePT, ...) {
397
398 char Line[IRC_MSGLEN+1] = "";
399 va_list Args;
400
401 assert(ConnS != NULL);
402 assert(LinePT != NULL);
403
404 va_start(Args, LinePT);
405 vsnprintf(Line, IRC_MSGLEN+1, LinePT, Args);
406 va_end(Args);
407
408 conn_log(ConnS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, Line);
409
410 }
411
412 /* CONN_LOG_VARIABLE FUNCTION - JONAS (30.09.2001) */
413
conn_log_variable(const char * OldMessagePT,char * NewMessagePT)414 char *conn_log_variable(const char *OldMessagePT, char *NewMessagePT) {
415
416 unsigned long int Len = 0;
417 unsigned long int Index = 0;
418 char *MessagePT = NULL;
419 char *TempPT = NULL;
420 const char *VarNamePT = NULL;
421 const char *VarDataPT = NULL;
422
423 unsigned long int VSLen = 0;
424 unsigned long int VSIndex = 0;
425
426 struct tm *TMPT = NULL;
427 char TimeYear[LINELEN+1] = "";
428 char TimeMonth[LINELEN+1] = "";
429 char TimeWeek[LINELEN+1] = "";
430 char TimeDay[LINELEN+1] = "";
431 char TimeHour[LINELEN+1] = "";
432 char TimeMin[LINELEN+1] = "";
433 char TimeSec[LINELEN+1] = "";
434
435 struct Variable_Struct Variable[] = {
436
437 {
438 "%mhost",
439 HOSTNAME
440 },
441 {
442 "%conn",
443 ((VariableDataS.ConnS == NULL) ? NULL : VariableDataS.ConnS->Name)
444 },
445 {
446 "%serverhost",
447 ((VariableDataS.ConnS == NULL) ? NULL : VariableDataS.ConnS->ServerHostName)
448 },
449 {
450 "%servername",
451 ((VariableDataS.ConnS == NULL) ? NULL : VariableDataS.ConnS->ServerName)
452 },
453 {
454 "%cnick",
455 ((VariableDataS.ConnS == NULL) ? NULL : VariableDataS.ConnS->Nick)
456 },
457 {
458 "%cuser",
459 ((VariableDataS.ConnS == NULL) ? NULL : VariableDataS.ConnS->User)
460 },
461 {
462 "%chost",
463 ((VariableDataS.ConnS == NULL) ? NULL : VariableDataS.ConnS->Host)
464 },
465 {
466 "%anick",
467 ((VariableDataS.ConnS == NULL) ? NULL : VariableDataS.ConnS->IRCNick)
468 },
469 {
470 "%auser",
471 ((VariableDataS.ConnS == NULL) ? NULL : VariableDataS.ConnS->User)
472 },
473 {
474 "%ahost",
475 ((VariableDataS.ConnS == NULL) ? NULL : VariableDataS.ConnS->Host)
476 },
477 {
478 "%nick",
479 VariableDataS.Nick
480 },
481 {
482 "%user",
483 VariableDataS.User
484 },
485 {
486 "%host",
487 VariableDataS.Host
488 },
489 {
490 "%nuh",
491 VariableDataS.NUH
492 },
493 {
494 "%chan",
495 VariableDataS.Chan
496 },
497 {
498 "%y",
499 TimeYear
500 },
501 {
502 "%m",
503 TimeMonth
504 },
505 {
506 "%w",
507 TimeWeek
508 },
509 {
510 "%d",
511 TimeDay
512 },
513 {
514 "%h",
515 TimeHour
516 },
517 {
518 "%n",
519 TimeMin
520 },
521 {
522 "%s",
523 TimeSec
524 },
525
526 };
527
528 VSLen = (sizeof(Variable) / sizeof(*Variable));
529
530 TMPT = localtime(&NOW);
531 strftime(TimeYear, LINELEN, "%Y", TMPT);
532 strftime(TimeMonth, LINELEN, "%m", TMPT);
533 strftime(TimeWeek, LINELEN, "%W", TMPT);
534 strftime(TimeDay, LINELEN, "%d", TMPT);
535 strftime(TimeHour, LINELEN, "%H", TMPT);
536 strftime(TimeMin, LINELEN, "%M", TMPT);
537 strftime(TimeSec, LINELEN, "%S", TMPT);
538
539 for (Len = 1 ; *OldMessagePT != 0 ;) {
540
541 TempPT = strchr(OldMessagePT, '%');
542 if (TempPT == NULL) {
543 Len += strlen(OldMessagePT);
544 MessagePT = realloc(NewMessagePT, Len);
545 if (MessagePT == NULL) {
546 free(NewMessagePT);
547 return(NULL);
548 }
549 NewMessagePT = MessagePT;
550 MessagePT += Index;
551 strcpy(MessagePT, OldMessagePT);
552 OldMessagePT += strlen(OldMessagePT);
553 Index += strlen(OldMessagePT);
554 }
555 else {
556
557 if (TempPT != OldMessagePT) {
558
559 Len += (TempPT - OldMessagePT);
560 MessagePT = realloc(NewMessagePT, Len);
561 if (MessagePT == NULL) {
562 free(NewMessagePT);
563 return(NULL);
564 }
565 NewMessagePT = MessagePT;
566 MessagePT += Index;
567 strncpy(MessagePT, OldMessagePT, (TempPT - OldMessagePT));
568 Index += (TempPT - OldMessagePT);
569 OldMessagePT = TempPT;
570
571 }
572 VarNamePT = NULL;
573 VarDataPT = NULL;
574 for (VSIndex = 0 ; VSIndex < VSLen ; VSIndex++) {
575 if ((Variable[VSIndex].Data != NULL) && (strncasecmp(OldMessagePT, Variable[VSIndex].Name, strlen(Variable[VSIndex].Name)) == FALSE)) {
576 VarNamePT = Variable[VSIndex].Name;
577 VarDataPT = Variable[VSIndex].Data;
578 break;
579 }
580 }
581 if ((VarNamePT != NULL) && (VarDataPT != NULL)) {
582 Len += strlen(VarDataPT);
583 MessagePT = realloc(NewMessagePT, Len);
584 if (MessagePT == NULL) {
585 free(NewMessagePT);
586 return(NULL);
587 }
588 NewMessagePT = MessagePT;
589 MessagePT += Index;
590 strcpy(MessagePT, VarDataPT);
591 OldMessagePT += strlen(VarNamePT);
592 Index += strlen(VarDataPT);
593 }
594 else {
595 Len += strlen(OldMessagePT);
596 MessagePT = realloc(NewMessagePT, Len);
597 if (MessagePT == NULL) {
598 free(NewMessagePT);
599 return(NULL);
600 }
601 NewMessagePT = MessagePT;
602 MessagePT += Index;
603 strcpy(MessagePT, OldMessagePT);
604 OldMessagePT += strlen(OldMessagePT);
605 Index += strlen(OldMessagePT);
606 }
607 }
608 }
609
610 VariableDataS.ConnS = NULL;
611 VariableDataS.ChanS = NULL;
612 VariableDataS.Chan = NULL;
613 VariableDataS.Nick = NULL;
614 VariableDataS.User = NULL;
615 VariableDataS.Host = NULL;
616 VariableDataS.NUH = NULL;
617 VariableDataS.Command = NULL;
618 VariableDataS.Param = NULL;
619 VariableDataS.Message = NULL;
620
621 return(NewMessagePT);
622
623 }
624