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