--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openenvutils/commandshell/shell/src/watch.c Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,606 @@
+#ifndef __SYMBIAN32__
+// watch.c - login/logout watching
+//
+// © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
+//
+/*
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 1992-1997 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.mdh"
+
+/* Headers for utmp/utmpx structures */
+#ifdef HAVE_UTMP_H
+# include <utmp.h>
+#endif
+#ifdef HAVE_UTMPX_H
+#ifndef __SYMBIAN32__
+# include <utmpx.h>
+#endif//__SYMBIAN32__
+#endif
+
+#ifdef __SYMBIAN32__
+#ifdef __WINSCW__
+#pragma warn_unusedarg off
+#pragma warn_possunwant off
+#endif//__WINSCW__
+#endif//__SYMBIAN32__
+
+/* Find utmp file */
+#if !defined(REAL_UTMP_FILE) && defined(UTMP_FILE)
+# define REAL_UTMP_FILE UTMP_FILE
+#endif
+#if !defined(REAL_UTMP_FILE) && defined(_PATH_UTMP)
+# define REAL_UTMP_FILE _PATH_UTMP
+#endif
+#if !defined(REAL_UTMP_FILE) && defined(PATH_UTMP_FILE)
+# define REAL_UTMP_FILE PATH_UTMP_FILE
+#endif
+
+/* Find wtmp file */
+#if !defined(REAL_WTMP_FILE) && defined(WTMP_FILE)
+# define REAL_WTMP_FILE WTMP_FILE
+#endif
+#if !defined(REAL_WTMP_FILE) && defined(_PATH_WTMP)
+# define REAL_WTMP_FILE _PATH_WTMP
+#endif
+#if !defined(REAL_WTMP_FILE) && defined(PATH_WTMP_FILE)
+# define REAL_WTMP_FILE PATH_WTMP_FILE
+#endif
+
+/* Find utmpx file */
+#if !defined(REAL_UTMPX_FILE) && defined(UTMPX_FILE)
+# define REAL_UTMPX_FILE UTMPX_FILE
+#endif
+#if !defined(REAL_UTMPX_FILE) && defined(_PATH_UTMPX)
+# define REAL_UTMPX_FILE _PATH_UTMPX
+#endif
+#if !defined(REAL_UTMPX_FILE) && defined(PATH_UTMPX_FILE)
+# define REAL_UTMPX_FILE PATH_UTMPX_FILE
+#endif
+
+/* Find wtmpx file */
+#if !defined(REAL_WTMPX_FILE) && defined(WTMPX_FILE)
+# define REAL_WTMPX_FILE WTMPX_FILE
+#endif
+#if !defined(REAL_WTMPX_FILE) && defined(_PATH_WTMPX)
+# define REAL_WTMPX_FILE _PATH_WTMPX
+#endif
+#if !defined(REAL_WTMPX_FILE) && defined(PATH_WTMPX_FILE)
+# define REAL_WTMPX_FILE PATH_WTMPX_FILE
+#endif
+
+/* Decide which structure to use. We use a structure that exists in *
+ * the headers, and require that its corresponding utmp file exist. *
+ * (wtmp is less important.) */
+
+#if !defined(WATCH_STRUCT_UTMP) && defined(HAVE_STRUCT_UTMPX) && defined(REAL_UTMPX_FILE)
+# define WATCH_STRUCT_UTMP struct utmpx
+# ifdef HAVE_STRUCT_UTMPX_UT_XTIME
+# undef ut_time
+# define ut_time ut_xtime
+# else /* !HAVE_STRUCT_UTMPX_UT_XTIME */
+# ifdef HAVE_STRUCT_UTMPX_UT_TV
+# undef ut_time
+# define ut_time ut_tv.tv_sec
+# endif /* HAVE_STRUCT_UTMPX_UT_TV */
+# endif /* !HAVE_STRUCT_UTMPX_UT_XTIME */
+# define WATCH_UTMP_FILE REAL_UTMPX_FILE
+# ifdef REAL_WTMPX_FILE
+# define WATCH_WTMP_FILE REAL_WTMPX_FILE
+# endif
+# ifdef HAVE_STRUCT_UTMPX_UT_HOST
+# define WATCH_UTMP_UT_HOST 1
+# endif
+# ifdef __APPLE__
+# define ut_name ut_user
+# endif
+#endif
+
+#if !defined(WATCH_STRUCT_UTMP) && defined(HAVE_STRUCT_UTMP) && defined(REAL_UTMP_FILE)
+# define WATCH_STRUCT_UTMP struct utmp
+# define WATCH_UTMP_FILE REAL_UTMP_FILE
+# ifdef REAL_WTMP_FILE
+# define WATCH_WTMP_FILE REAL_WTMP_FILE
+# endif
+# ifdef HAVE_STRUCT_UTMP_UT_HOST
+# define WATCH_UTMP_UT_HOST 1
+# endif
+#endif
+
+#ifdef WATCH_UTMP_UT_HOST
+# define DEFAULT_WATCHFMT "%n has %a %l from %m."
+#else /* !WATCH_UTMP_UT_HOST */
+# define DEFAULT_WATCHFMT "%n has %a %l."
+#endif /* !WATCH_UTMP_UT_HOST */
+
+/**/
+char const * const default_watchfmt = DEFAULT_WATCHFMT;
+
+#ifdef WATCH_STRUCT_UTMP
+
+# include "watch.pro"
+
+# ifndef WATCH_WTMP_FILE
+# define WATCH_WTMP_FILE "/dev/null"
+# endif
+
+static int wtabsz;
+static WATCH_STRUCT_UTMP *wtab;
+static time_t lastutmpcheck;
+
+/* get the time of login/logout for WATCH */
+
+/**/
+static time_t
+getlogtime(WATCH_STRUCT_UTMP *u, int inout)
+{
+ FILE *in;
+ WATCH_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(WATCH_WTMP_FILE, "r")))
+ return time(NULL);
+ fseek(in, 0, 2);
+ do {
+ if (fseek(in, ((first) ? -1 : -2) * sizeof(WATCH_STRUCT_UTMP), 1)) {
+ fclose(in);
+ return time(NULL);
+ }
+ first = 0;
+ if (!fread(&uu, sizeof(WATCH_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(WATCH_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 ')'
+
+/**/
+static char *
+watch3ary(int inout, WATCH_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 WATCH_UTMP_UT_HOST
+ case 'm':
+ case 'M':
+ truth = (u->ut_host[0] != 0);
+ break;
+# endif /* WATCH_UTMP_UT_HOST */
+ 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 */
+
+/**/
+static char *
+watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini)
+{
+ char buf[40], buf2[80];
+ time_t timet;
+ struct tm *tm;
+ char *fm2;
+# ifdef WATCH_UTMP_UT_HOST
+ char *p;
+ int i;
+# endif /* WATCH_UTMP_UT_HOST */
+
+ 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 WATCH_UTMP_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 /* WATCH_UTMP_UT_HOST */
+ 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 %f";
+ 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 */
+
+/**/
+static void
+watchlog(int inout, WATCH_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 WATCH_UTMP_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 /* WATCH_UTMP_UT_HOST */
+ else
+ break;
+ if (!bad) {
+ (void)watchlog2(inout, u, fmt, 1, 0);
+ return;
+ }
+ }
+}
+
+/* compare 2 utmp entries */
+
+/**/
+static int
+ucmp(WATCH_STRUCT_UTMP *u, WATCH_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 */
+
+/**/
+static void
+readwtab(void)
+{
+ WATCH_STRUCT_UTMP *uptr;
+ int wtabmax = 32;
+ FILE *in;
+
+ wtabsz = 0;
+ if (!(in = fopen(WATCH_UTMP_FILE, "r")))
+ return;
+ uptr = wtab = (WATCH_STRUCT_UTMP *)zalloc(wtabmax * sizeof(WATCH_STRUCT_UTMP));
+ while (fread(uptr, sizeof(WATCH_STRUCT_UTMP), 1, in))
+# ifdef USER_PROCESS
+ if (uptr->ut_type == USER_PROCESS)
+# else /* !USER_PROCESS */
+ if (uptr->ut_name[0])
+# endif /* !USER_PROCESS */
+ {
+ uptr++;
+ if (++wtabsz == wtabmax)
+ uptr = (wtab = (WATCH_STRUCT_UTMP *)realloc((void *) wtab, (wtabmax *= 2) *
+ sizeof(WATCH_STRUCT_UTMP))) + wtabsz;
+ }
+ fclose(in);
+
+ if (wtabsz)
+ qsort((void *) wtab, wtabsz, sizeof(WATCH_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;
+ WATCH_STRUCT_UTMP *utab, *uptr, *wptr;
+ struct stat st;
+ char **s;
+ char *fmt;
+ int utabsz = 0, utabmax = wtabsz + 4;
+ int uct, wct;
+
+ s = watch;
+
+ holdintr();
+ if (!wtab) {
+ readwtab();
+ noholdintr();
+ return;
+ }
+ if ((stat(WATCH_UTMP_FILE, &st) == -1) || (st.st_mtime <= lastutmpcheck)) {
+ noholdintr();
+ return;
+ }
+ lastutmpcheck = st.st_mtime;
+ uptr = utab = (WATCH_STRUCT_UTMP *) zalloc(utabmax * sizeof(WATCH_STRUCT_UTMP));
+
+ if (!(in = fopen(WATCH_UTMP_FILE, "r"))) {
+ free(utab);
+ noholdintr();
+ return;
+ }
+ while (fread(uptr, sizeof *uptr, 1, in))
+# ifdef USER_PROCESS
+ if (uptr->ut_type == USER_PROCESS)
+# else /* !USER_PROCESS */
+ if (uptr->ut_name[0])
+# endif /* !USER_PROCESS */
+ {
+ uptr++;
+ if (++utabsz == utabmax)
+ uptr = (utab = (WATCH_STRUCT_UTMP *)realloc((void *) utab, (utabmax *= 2) *
+ sizeof(WATCH_STRUCT_UTMP))) + utabsz;
+ }
+ fclose(in);
+ noholdintr();
+ if (errflag) {
+ free(utab);
+ return;
+ }
+ if (utabsz)
+ qsort((void *) utab, utabsz, sizeof(WATCH_STRUCT_UTMP),
+ (int (*) _((const void *, const void *)))ucmp);
+
+ wct = wtabsz;
+ uct = utabsz;
+ uptr = utab;
+ wptr = wtab;
+ if (errflag) {
+ free(utab);
+ return;
+ }
+ queue_signals();
+ if (!(fmt = getsparam("WATCHFMT")))
+ fmt = DEFAULT_WATCHFMT;
+ 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--;
+ unqueue_signals();
+ free(wtab);
+ wtab = utab;
+ wtabsz = utabsz;
+ fflush(stdout);
+}
+
+/**/
+int
+bin_log(UNUSED(char *nam), UNUSED(char **argv), UNUSED(Options ops), UNUSED(int func))
+{
+ if (!watch)
+ return 1;
+ if (wtab)
+ free(wtab);
+ wtab = (WATCH_STRUCT_UTMP *)zalloc(1);
+ wtabsz = 0;
+ lastutmpcheck = 0;
+ dowatch();
+ return 0;
+}
+
+#else /* !WATCH_STRUCT_UTMP */
+
+/**/
+void dowatch(void)
+{
+}
+
+/**/
+int
+bin_log(char *nam, char **argv, Options ops, int func)
+{
+ return bin_notavail(nam, argv, ops, func);
+}
+
+#endif /* !WATCH_STRUCT_UTMP */
+
+#endif //__SYMBIAN32__
+