1 /*
2 * log.c: handles the irc session logging functions
3 *
4 * Written By Michael Sandrof
5 *
6 * Copyright (c) 1990 Michael Sandrof.
7 * Copyright (c) 1991, 1992 Troy Rollo.
8 * Copyright (c) 1992-2000 Matthew R. Green.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include "irc.h"
36 IRCII_RCSID("@(#)$Id: log.c,v 1.23 2000/04/04 03:10:55 mrg Exp $");
37
38 #include <sys/stat.h>
39
40 #include "log.h"
41 #include "vars.h"
42 #include "output.h"
43 #include "ircaux.h"
44
45 /* ninja irc stuff! */
46 #include "ninja.h"
47 #include "screen.h"
48 #include "dma.h"
49
50 #if 0
51 #if defined(POSIX)
52 # define fchmod(path, mode) chmod(path, mode)
53 #endif /* POSIX */
54 #endif
55
56 FILE *irclog_fp = (FILE *) 0;
57 FILE *msg_fp = (FILE *) 0;
58
59 static void log_prompt _((u_char *, u_char *));
60
61 FILE *
do_log(flag,logfile,fp)62 do_log(flag, logfile, fp)
63 int flag;
64 u_char *logfile;
65 FILE *fp;
66 {
67 time_t t;
68
69 if (logfile == (u_char *) 0)
70 return ((FILE *) 0);
71 t = time(0);
72 if (flag)
73 {
74 if (fp)
75 say("Logging is already on");
76 else
77 {
78 #ifdef DAEMON_UID
79 if (getuid() == DAEMON_UID)
80 {
81 say("You are not permitted to use LOG");
82 /* fp = (FILE *) 0; unused */
83 }
84 else
85 {
86 #endif /* DAEMON_UID */
87 say("Starting logfile %s", logfile);
88 if ((fp = fopen(CP(logfile), "a")) != NULL)
89 {
90 #ifndef _Windows
91 #ifdef NEED_FCHMOD
92 chmod(logfile, S_IREAD | S_IWRITE);
93 #else
94 #ifndef _IBMR2
95 fchmod(fileno(fp), S_IREAD | S_IWRITE);
96 #else
97 int fd = (int) fileno(fp);
98 fchmod((char *) &fd, S_IREAD | S_IWRITE);
99 #endif /* !_IBMR2 */
100 #endif /* M_UNIX */
101 #endif /* _Windows */
102 /* fprintf(fp, "IRC log started %.16s\n", ctime(&t)); */
103 fprintf(fp, "-+- NinjaIRC log started at %s\n", ninja_strftime(&t, "%I:%M%p on %a, %b %d"));
104 fflush(fp);
105 }
106 else
107 {
108 say("Couldn't open logfile %s: %s", logfile, strerror(errno));
109 fp = (FILE *) 0;
110 }
111 #ifdef DAEMON_UID
112 }
113 #endif /* DAEMON_UID */
114 }
115 }
116 else
117 {
118 if (fp)
119 {
120 /* fprintf(fp, "IRC log ended %.16s\n", ctime(&t)); */
121 fprintf(fp, "-+- NinjaIRC log ended at %s\n", ninja_strftime(&t, "%I:%M%p on %a, %b %d"));
122 fflush(fp);
123 fclose(fp);
124 if (fp == irclog_fp)
125 irclog_fp = (FILE *) 0;
126 fp = (FILE *) 0;
127 say("Logfile ended");
128 }
129 }
130 return (fp);
131 }
132
133 /* logger: if flag is 0, logging is turned off, else it's turned on */
134 void
logger(flag)135 logger(flag)
136 int flag;
137 {
138 u_char *logfile;
139
140 if ((logfile = get_string_var(LOGFILE_VAR)) == (u_char *) 0)
141 {
142 say("You must set the LOGFILE variable first!");
143 set_int_var(LOG_VAR, 0);
144 return;
145 }
146 irclog_fp = do_log(flag, logfile, irclog_fp);
147 if ((irclog_fp == (FILE *) 0) && flag)
148 set_int_var(LOG_VAR, 0);
149 }
150
151 /*
152 * set_log_file: sets the log file name. If logging is on already, this
153 * closes the last log file and reopens it with the new name. This is called
154 * automatically when you SET LOGFILE.
155 */
156 void
set_log_file(filename)157 set_log_file(filename)
158 u_char *filename;
159 {
160 u_char *expanded;
161
162 if (filename)
163 {
164 if (my_strcmp(filename, get_string_var(LOGFILE_VAR)))
165 expanded = expand_twiddle(filename);
166 else
167 expanded = expand_twiddle(get_string_var(LOGFILE_VAR));
168 set_string_var(LOGFILE_VAR, expanded);
169 new_free(&expanded);
170 if (irclog_fp)
171 {
172 logger(0);
173 logger(1);
174 }
175 }
176 }
177
178 /*
179 * add_to_log: add the given line to the log file. If no log file is open
180 * this function does nothing.
181 *
182 * NINJA: if STRIP_LOG_ANSI is on, do it.
183 */
184 void
add_to_log(fp,line)185 add_to_log(fp, line)
186 FILE *fp;
187 u_char *line;
188 {
189 if (fp)
190 {
191 if (get_int_var(STRIP_LOG_ANSI_VAR))
192 fprintf(fp, "%s\n", strip_ansi(line));
193 else
194 fprintf(fp, "%s\n", line);
195 fflush(fp);
196 }
197 }
198
199
200 /* below here are Ninja specific extensions to logging */
201 void
playlog(u_char * command,u_char * args,u_char * subargs)202 playlog(u_char *command, u_char *args, u_char *subargs)
203 {
204 u_char *ptr;
205 struct stat stat_buf;
206 u_char filename[] = NINJA_AWAY_FILE;
207 static u_char buf[BIG_BUFFER_SIZE + 1];
208
209 ptr = expand_twiddle(filename);
210 stat_file(ptr, &stat_buf);
211 strncpy(buf, ptr, sizeof(buf));
212
213 if (stat_buf.st_mode & S_IFDIR)
214 return;
215
216 if ((msg_fp = fopen(ptr, "r")) == NULL)
217 {
218 put_error("Error Opening Log file %s", ptr);
219 dma_Free(&ptr);
220 msg_fp = NULL;
221 return;
222 }
223 dma_Free(&ptr);
224 log_prompt(buf, NULL);
225 }
226
227 static int
show_log(u_char * name)228 show_log(u_char *name)
229 {
230 int rows = 0;
231 u_char line[BIG_BUFFER_SIZE + 1];
232
233 rows = curr_scr_win->display_size;
234 while (--rows)
235 {
236 if (fgets(line, sizeof(line), msg_fp))
237 {
238 if (*(line + strlen(line) - 1) == '\n')
239 *(line + strlen(line) - 1) = (u_char) 0;
240 put_raw("%s", line);
241 }
242 else
243 {
244 if (msg_fp)
245 fclose(msg_fp);
246 msg_fp = NULL;
247 return (0);
248 }
249 }
250 return (1);
251 }
252
253 void
eraselog(u_char * command,u_char * args,u_char * subargs)254 eraselog(u_char *command, u_char *args, u_char *subargs)
255 {
256 u_char *ptr;
257 extern FILE *awayfile;
258
259 if (awayfile == NULL)
260 {
261 ptr = expand_twiddle(NINJA_AWAY_FILE);
262 if (unlink(ptr))
263 {
264 put_error("Could not unlink %s", ptr);
265 dma_Free(&ptr);
266 return;
267 }
268 put_info("Your saved messages have been erased.");
269 dma_Free(&ptr);
270 }
271 else
272 put_info("Not erasing your messages because the awayfile is still open.");
273 }
274
275 void
short_eraselog(u_char * data,u_char * line)276 short_eraselog(u_char * data, u_char * line)
277 {
278 if (!(strcasecmp(line, "Y")))
279 eraselog(NULL, NULL, NULL);
280 }
281
282 void
log_prompt(u_char * name,u_char * line)283 log_prompt(u_char * name, u_char * line)
284 {
285 if (line && ((*line == 'q') || (*line == 'Q')))
286 {
287 if (msg_fp)
288 fclose(msg_fp);
289 msg_fp = NULL;
290 add_wait_prompt("Erase your stored messages? [y/N] ", short_eraselog, "", WAIT_PROMPT_LINE);
291 return;
292 }
293
294 if (show_log(name))
295 add_wait_prompt("More? (Q to quit) ", log_prompt, name, WAIT_PROMPT_KEY);
296 else
297 {
298 if (msg_fp)
299 fclose(msg_fp);
300 msg_fp = NULL;
301 add_wait_prompt("Erase your stored messages? [y/N] ", short_eraselog, "", WAIT_PROMPT_LINE);
302 }
303 }
304