Rearrange the python scripting support a bit.
[screen-lua.git] / src / logfile.c
blobedee89dfcf1e0d21f20d0517bbda727dc51cb3fb
1 /* Copyright (c) 2008, 2009
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Micah Cowan (micah@cowan.name)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Copyright (c) 1987 Oliver Laumann
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3, or (at your option)
14 * any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (see the file COPYING); if not, see
23 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
29 #include <sys/types.h> /* dev_t, ino_t, off_t, ... */
30 #include <sys/stat.h> /* struct stat */
31 #include <fcntl.h> /* O_WRONLY for logfile_reopen */
34 #include "config.h"
35 #include "screen.h"
36 #include "extern.h"
37 #include "logfile.h"
39 static void changed_logfile __P((struct logfile *));
40 static struct logfile *lookup_logfile __P((char *));
41 static int stolen_logfile __P((struct logfile *));
43 static struct logfile *logroot = NULL;
45 static void
46 changed_logfile(l)
47 struct logfile *l;
49 struct stat o, *s = l->st;
51 if (fstat(fileno(l->fp), &o) < 0) /* get trouble later */
52 return;
53 if (o.st_size > s->st_size) /* aha, appended text */
55 s->st_size = o.st_size; /* this should have changed */
56 s->st_mtime = o.st_mtime; /* only size and mtime */
61 * Requires fd to be open and need_fd to be closed.
62 * If possible, need_fd will be open afterwards and refer to
63 * the object originally reffered by fd. fd will be closed then.
64 * Works just like ``fcntl(fd, DUPFD, need_fd); close(fd);''
66 * need_fd is returned on success, else -1 is returned.
68 int
69 lf_move_fd(fd, need_fd)
70 int need_fd, fd;
72 int r = -1;
74 if (fd == need_fd)
75 return fd;
76 if (fd >=0 && fd < need_fd)
77 r = lf_move_fd(dup(fd), need_fd);
78 close(fd);
79 return r;
82 static int
83 logfile_reopen(name, wantfd, l)
84 char *name;
85 int wantfd;
86 struct logfile *l;
88 int got_fd;
90 close(wantfd);
91 if (((got_fd = open(name, O_WRONLY | O_CREAT | O_APPEND, 0666)) < 0) ||
92 lf_move_fd(got_fd, wantfd) < 0)
94 logfclose(l);
95 debug1("logfile_reopen: failed for %s\n", name);
96 return -1;
98 changed_logfile(l);
99 debug2("logfile_reopen: %d = %s\n", wantfd, name);
100 return 0;
103 static int (* lf_reopen_fn)() = logfile_reopen;
106 * Whenever logfwrite discoveres that it is required to close and
107 * reopen the logfile, the function registered here is called.
108 * If you do not register anything here, the above logfile_reopen()
109 * will be used instead.
110 * Your function should perform the same steps as logfile_reopen():
111 * a) close the original filedescriptor without flushing any output
112 * b) open a new logfile for future output on the same filedescriptor number.
113 * c) zero out st_dev, st_ino to tell the stolen_logfile() indcator to
114 * reinitialise itself.
115 * d) return 0 on success.
117 void
118 logreopen_register(fn)
119 int (*fn) __P((char *, int, struct logfile *));
121 lf_reopen_fn = fn ? fn : logfile_reopen;
125 * If the logfile has been removed, truncated, unlinked or the like,
126 * return nonzero.
127 * The l->st structure initialised by logfopen is updated
128 * on every call.
130 static int
131 stolen_logfile(l)
132 struct logfile *l;
134 struct stat o, *s = l->st;
136 o = *s;
137 if (fstat(fileno(l->fp), s) < 0) /* remember that stat failed */
138 s->st_ino = s->st_dev = 0;
139 ASSERT(s == l->st);
140 if (!o.st_dev && !o.st_ino) /* nothing to compare with */
141 return 0;
143 if ((!s->st_dev && !s->st_ino) || /* stat failed, that's new! */
144 !s->st_nlink || /* red alert: file unlinked */
145 (s->st_size < o.st_size) || /* file truncated */
146 (s->st_mtime != o.st_mtime) || /* file modified */
147 ((s->st_ctime != o.st_ctime) && /* file changed (moved) */
148 !(s->st_mtime == s->st_ctime && /* and it was not a change */
149 o.st_ctime < s->st_ctime))) /* due to delayed nfs write */
151 debug1("stolen_logfile: %s stolen!\n", l->name);
152 debug3("st_dev %d, st_ino %d, st_nlink %d\n",
153 (int)s->st_dev, (int)s->st_ino, (int)s->st_nlink);
154 debug2("s->st_size %d, o.st_size %d\n", (int)s->st_size, (int)o.st_size);
155 debug2("s->st_mtime %d, o.st_mtime %d\n",
156 (int)s->st_mtime, (int)o.st_mtime);
157 debug2("s->st_ctime %d, o.st_ctime %d\n",
158 (int)s->st_ctime, (int)o.st_ctime);
159 return -1;
162 debug1("stolen_logfile: %s o.k.\n", l->name);
163 return 0;
166 static struct logfile *
167 lookup_logfile(name)
168 char *name;
170 struct logfile *l;
172 for (l = logroot; l; l = l->next)
173 if (!strcmp(name, l->name))
174 return l;
175 return NULL;
178 struct logfile *
179 logfopen(name, fp)
180 char *name;
181 FILE *fp;
183 struct logfile *l;
185 if (!fp)
187 if (!(l = lookup_logfile(name)))
188 return NULL;
189 l->opencount++;
190 return l;
193 if (!(l = (struct logfile *)malloc(sizeof(struct logfile))))
194 return NULL;
195 if (!(l->st = (struct stat *)malloc(sizeof(struct stat))))
197 free((char *)l);
198 return NULL;
201 if (!(l->name = SaveStr(name)))
203 free((char *)l->st);
204 free((char *)l);
205 return NULL;
207 l->fp = fp;
208 l->opencount = 1;
209 l->writecount = 0;
210 l->flushcount = 0;
211 changed_logfile(l);
213 l->next = logroot;
214 logroot = l;
215 return l;
219 islogfile(name)
220 char *name;
222 if (!name)
223 return logroot ? 1 : 0;
224 return lookup_logfile(name) ? 1 : 0;
228 logfclose(l)
229 struct logfile *l;
231 struct logfile **lp;
233 for (lp = &logroot; *lp; lp = &(*lp)->next)
234 if (*lp == l)
235 break;
237 if (!*lp)
238 return -1;
240 if ((--l->opencount) > 0)
241 return 0;
242 if (l->opencount < 0)
243 abort();
245 *lp = l->next;
246 fclose(l->fp);
247 free(l->name);
248 free((char *)l);
249 return 0;
253 * XXX
254 * write and flush both *should* check the file's stat, if it disappeared
255 * or changed, re-open it.
258 logfwrite(l, buf, n)
259 struct logfile *l;
260 char *buf;
261 int n;
263 int r;
265 if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l))
266 return -1;
267 r = fwrite(buf, n, 1, l->fp);
268 l->writecount += l->flushcount + 1;
269 l->flushcount = 0;
270 changed_logfile(l);
271 return r;
275 logfflush(l)
276 struct logfile *l;
278 int r = 0;
280 if (!l)
281 for (l = logroot; l; l = l->next)
283 if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l))
284 return -1;
285 r |= fflush(l->fp);
286 l->flushcount++;
287 changed_logfile(l);
289 else
291 if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l))
292 return -1;
293 r = fflush(l->fp);
294 l->flushcount++;
295 changed_logfile(l);
297 return r;