This is watch.c in view mode; [Download] [Up]
/* * $Id: watch.c,v 2.3 1996/10/15 20:16:35 hzoli Exp $ * * watch.c - login/logout watching * * This file is part of zsh, the Z shell. * * Copyright (c) 1992-1996 Paul Falstad * All rights reserved. * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and to distribute modified versions of this software for any * purpose, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * In no event shall Paul Falstad or the Zsh Development Group be liable * to any party for direct, indirect, special, incidental, or consequential * damages arising out of the use of this software and its documentation, * even if Paul Falstad and the Zsh Development Group have been advised of * the possibility of such damage. * * Paul Falstad and the Zsh Development Group specifically disclaim any * warranties, including, but not limited to, the implied warranties of * merchantability and fitness for a particular purpose. The software * provided hereunder is on an "as is" basis, and Paul Falstad and the * Zsh Development Group have no obligation to provide maintenance, * support, updates, enhancements, or modifications. * */ #include "zsh.h" static int wtabsz; STRUCT_UTMP *wtab; static time_t lastutmpcheck; /* get the time of login/logout for WATCH */ /**/ time_t getlogtime(STRUCT_UTMP *u, int inout) { FILE *in; STRUCT_UTMP uu; int first = 1; int srchlimit = 50; /* max number of wtmp records to search */ if (inout) return u->ut_time; if (!(in = fopen(WTMP_FILE, "r"))) return time(NULL); fseek(in, 0, 2); do { if (fseek(in, ((first) ? -1 : -2) * sizeof(STRUCT_UTMP), 1)) { fclose(in); return time(NULL); } first = 0; if (!fread(&uu, sizeof(STRUCT_UTMP), 1, in)) { fclose(in); return time(NULL); } if (uu.ut_time < lastwatch || !srchlimit--) { fclose(in); return time(NULL); } } while (memcmp(&uu, u, sizeof(uu))); do if (!fread(&uu, sizeof(STRUCT_UTMP), 1, in)) { fclose(in); return time(NULL); } while (strncmp(uu.ut_line, u->ut_line, sizeof(u->ut_line))); fclose(in); return uu.ut_time; } /* Mutually recursive call to handle ternaries in $WATCHFMT */ #define BEGIN3 '(' #define END3 ')' /**/ char * watch3ary(int inout, STRUCT_UTMP *u, char *fmt, int prnt) { int truth = 1, sep; switch (*fmt++) { case 'n': truth = (u->ut_name[0] != 0); break; case 'a': truth = inout; break; case 'l': if (!strncmp(u->ut_line, "tty", 3)) truth = (u->ut_line[3] != 0); else truth = (u->ut_line[0] != 0); break; #ifdef HAVE_UT_HOST case 'm': case 'M': truth = (u->ut_host[0] != 0); break; #endif default: prnt = 0; /* Skip unknown conditionals entirely */ break; } sep = *fmt++; fmt = watchlog2(inout, u, fmt, (truth && prnt), sep); return watchlog2(inout, u, fmt, (!truth && prnt), END3); } /* print a login/logout event */ /**/ char * watchlog2(int inout, STRUCT_UTMP *u, char *fmt, int prnt, int fini) { char buf[40], buf2[80]; time_t timet; struct tm *tm; char *fm2; #ifdef HAVE_UT_HOST char *p; int i; #endif while (*fmt) if (*fmt == '\\') if (*++fmt) { if (prnt) putchar(*fmt); ++fmt; } else if (fini) return fmt; else break; else if (*fmt == fini) return ++fmt; else if (*fmt != '%') { if (prnt) putchar(*fmt); ++fmt; } else { if (*++fmt == BEGIN3) fmt = watch3ary(inout, u, ++fmt, prnt); else if (!prnt) ++fmt; else switch (*(fm2 = fmt++)) { case 'n': printf("%.*s", (int)sizeof(u->ut_name), u->ut_name); break; case 'a': printf("%s", (!inout) ? "logged off" : "logged on"); break; case 'l': if (!strncmp(u->ut_line, "tty", 3)) printf("%.*s", (int)sizeof(u->ut_line) - 3, u->ut_line + 3); else printf("%.*s", (int)sizeof(u->ut_line), u->ut_line); break; #ifdef HAVE_UT_HOST case 'm': for (p = u->ut_host, i = sizeof(u->ut_host); i && *p; i--, p++) { if (*p == '.' && !idigit(p[1])) break; putchar(*p); } break; case 'M': printf("%.*s", (int)sizeof(u->ut_host), u->ut_host); break; #endif case 'T': case 't': case '@': case 'W': case 'w': case 'D': switch (*fm2) { case '@': case 't': fm2 = "%l:%M%p"; break; case 'T': fm2 = "%k:%M"; break; case 'w': fm2 = "%a %e"; break; case 'W': fm2 = "%m/%d/%y"; break; case 'D': if (fm2[1] == '{') { char *dd, *ss; int n = 79; for (ss = fm2 + 2, dd = buf2; n-- && *ss && *ss != '}'; ++ss, ++dd) *dd = *((*ss == '\\' && ss[1]) ? ++ss : ss); if (*ss == '}') { *dd = '\0'; fmt = ss + 1; fm2 = buf2; } else fm2 = "%y-%m-%d"; } else fm2 = "%y-%m-%d"; break; } timet = getlogtime(u, inout); tm = localtime(&timet); ztrftime(buf, 40, fm2, tm); printf("%s", (*buf == ' ') ? buf + 1 : buf); break; case '%': putchar('%'); break; case 'S': txtset(TXTSTANDOUT); tsetcap(TCSTANDOUTBEG, -1); break; case 's': txtset(TXTDIRTY); txtunset(TXTSTANDOUT); tsetcap(TCSTANDOUTEND, -1); break; case 'B': txtset(TXTDIRTY); txtset(TXTBOLDFACE); tsetcap(TCBOLDFACEBEG, -1); break; case 'b': txtset(TXTDIRTY); txtunset(TXTBOLDFACE); tsetcap(TCALLATTRSOFF, -1); break; case 'U': txtset(TXTUNDERLINE); tsetcap(TCUNDERLINEBEG, -1); break; case 'u': txtset(TXTDIRTY); txtunset(TXTUNDERLINE); tsetcap(TCUNDERLINEEND, -1); break; default: putchar('%'); putchar(*fm2); break; } } if (prnt) putchar('\n'); return fmt; } /* check the List for login/logouts */ /**/ void watchlog(int inout, STRUCT_UTMP *u, char **w, char *fmt) { char *v, *vv, sav; int bad; if (!*u->ut_name) return; if (*w && !strcmp(*w, "all")) { (void)watchlog2(inout, u, fmt, 1, 0); return; } if (*w && !strcmp(*w, "notme") && strncmp(u->ut_name, get_username(), sizeof(u->ut_name))) { (void)watchlog2(inout, u, fmt, 1, 0); return; } for (; *w; w++) { bad = 0; v = *w; if (*v != '@' && *v != '%') { for (vv = v; *vv && *vv != '@' && *vv != '%'; vv++); sav = *vv; *vv = '\0'; if (strncmp(u->ut_name, v, sizeof(u->ut_name))) bad = 1; *vv = sav; v = vv; } for (;;) if (*v == '%') { for (vv = ++v; *vv && *vv != '@'; vv++); sav = *vv; *vv = '\0'; if (strncmp(u->ut_line, v, sizeof(u->ut_line))) bad = 1; *vv = sav; v = vv; } #ifdef HAVE_UT_HOST else if (*v == '@') { for (vv = ++v; *vv && *vv != '%'; vv++); sav = *vv; *vv = '\0'; if (strncmp(u->ut_host, v, strlen(v))) bad = 1; *vv = sav; v = vv; } #endif else break; if (!bad) { (void)watchlog2(inout, u, fmt, 1, 0); return; } } } /* compare 2 utmp entries */ /**/ int ucmp(STRUCT_UTMP *u, STRUCT_UTMP *v) { if (u->ut_time == v->ut_time) return strncmp(u->ut_line, v->ut_line, sizeof(u->ut_line)); return u->ut_time - v->ut_time; } /* initialize the user List */ /**/ void readwtab(void) { STRUCT_UTMP *uptr; int wtabmax = 32; FILE *in; wtabsz = 0; if (!(in = fopen(UTMP_FILE, "r"))) return; uptr = wtab = (STRUCT_UTMP *)zalloc(wtabmax * sizeof(STRUCT_UTMP)); while (fread(uptr, sizeof(STRUCT_UTMP), 1, in)) #ifdef USER_PROCESS if (uptr->ut_type == USER_PROCESS) #else if (uptr->ut_name[0]) #endif { uptr++; if (++wtabsz == wtabmax) uptr = (wtab = (STRUCT_UTMP *)realloc((void *) wtab, (wtabmax *= 2) * sizeof(STRUCT_UTMP))) + wtabsz; } fclose(in); if (wtabsz) qsort((void *) wtab, wtabsz, sizeof(STRUCT_UTMP), (int (*) _((const void *, const void *)))ucmp); } /* Check for login/logout events; executed before * * each prompt if WATCH is set */ /**/ void dowatch(void) { FILE *in; STRUCT_UTMP *utab, *uptr, *wptr; struct stat st; char **s; char *fmt; int utabsz = 0, utabmax = wtabsz + 4; int uct, wct; s = watch; if (!(fmt = getsparam("WATCHFMT"))) fmt = DEFAULT_WATCHFMT; holdintr(); if (!wtab) { readwtab(); noholdintr(); return; } if ((stat(UTMP_FILE, &st) == -1) || (st.st_mtime <= lastutmpcheck)) { noholdintr(); return; } lastutmpcheck = st.st_mtime; uptr = utab = (STRUCT_UTMP *) zalloc(utabmax * sizeof(STRUCT_UTMP)); if (!(in = fopen(UTMP_FILE, "r"))) { free(utab); noholdintr(); return; } while (fread(uptr, sizeof *uptr, 1, in)) #ifdef USER_PROCESS if (uptr->ut_type == USER_PROCESS) #else if (uptr->ut_name[0]) #endif { uptr++; if (++utabsz == utabmax) uptr = (utab = (STRUCT_UTMP *)realloc((void *) utab, (utabmax *= 2) * sizeof(STRUCT_UTMP))) + utabsz; } fclose(in); noholdintr(); if (errflag) { free(utab); return; } if (utabsz) qsort((void *) utab, utabsz, sizeof(STRUCT_UTMP), (int (*) _((const void *, const void *)))ucmp); wct = wtabsz; uct = utabsz; uptr = utab; wptr = wtab; if (errflag) { free(utab); return; } while ((uct || wct) && !errflag) if (!uct || (wct && ucmp(uptr, wptr) > 0)) wct--, watchlog(0, wptr++, s, fmt); else if (!wct || (uct && ucmp(uptr, wptr) < 0)) uct--, watchlog(1, uptr++, s, fmt); else uptr++, wptr++, wct--, uct--; free(wtab); wtab = utab; wtabsz = utabsz; fflush(stdout); } /**/ int bin_log(char *nam, char **argv, char *ops, int func) { if (!watch) return 1; if (wtab) free(wtab); wtab = (STRUCT_UTMP *)zalloc(1); wtabsz = 0; lastutmpcheck = 0; dowatch(); return 0; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.