source: trunk/third/tcsh/tc.who.c @ 22036

Revision 22036, 17.8 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r22035, which included commits to RCS files with non-trunk default branches.
Line 
1/* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/tc.who.c,v 1.1.1.3 2005-06-03 14:35:39 ghudson Exp $ */
2/*
3 * tc.who.c: Watch logins and logouts...
4 */
5/*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33#include "sh.h"
34
35RCSID("$Id: tc.who.c,v 1.1.1.3 2005-06-03 14:35:39 ghudson Exp $")
36
37#include "tc.h"
38
39#ifndef HAVENOUTMP
40/*
41 * kfk 26 Jan 1984 - for login watch functions.
42 */
43#include <ctype.h>
44
45#ifdef HAVE_UTMPX_H
46# include <utmpx.h>
47/* I just redefine a few words here.  Changing every occurrence below
48 * seems like too much of work.  All UTMP functions have equivalent
49 * UTMPX counterparts, so they can be added all here when needed.
50 * Kimmo Suominen, Oct 14 1991
51 */
52# if defined(__UTMPX_FILE) && !defined(UTMPX_FILE)
53#  define TCSH_PATH_UTMP __UTMPX_FILE
54# elif defined(_PATH_UTMPX)
55#  define TCSH_PATH_UTMP _PATH_UTMPX
56# elif defined(UTMPX_FILE)
57#  define TCSH_PATH_UTMP UTMPX_FILE
58# endif /* __UTMPX_FILE && !UTMPX_FILE */
59# ifdef TCSH_PATH_UTMP
60#  define utmp utmpx
61#  if defined(HAVE_STRUCT_UTMP_UT_TV)
62#   define ut_time ut_tv.tv_sec
63#  elif defined(HAVE_STRUCT_UTMP_UT_XTIME)
64#   define ut_time ut_xtime
65#  endif
66#  ifdef HAVE_STRUCT_UTMP_UT_USER
67#   define ut_name ut_user
68#  endif
69#  ifdef HAVE_GETUTENT
70#   define getutent getutxent
71#   define setutent setutxent
72#   define endutent endutxent
73#  endif /* HAVE_GETUTENT */
74# else
75#  ifdef HAVE_UTMP_H
76#   include <utmp.h>
77#  endif /* WINNT_NATIVE */
78# endif /* TCSH_PATH_UTMP */
79#else /* !HAVE_UTMPX_H */
80# ifdef HAVE_UTMP_H
81#  include <utmp.h>
82# endif /* WINNT_NATIVE */
83#endif /* HAVE_UTMPX_H */
84
85#ifndef BROKEN_CC
86# define UTNAMLEN       sizeof(((struct utmp *) 0)->ut_name)
87# define UTLINLEN       sizeof(((struct utmp *) 0)->ut_line)
88# ifdef HAVE_STRUCT_UTMP_UT_HOST
89#  ifdef _SEQUENT_
90#   define UTHOSTLEN    100
91#  else
92#   define UTHOSTLEN    sizeof(((struct utmp *) 0)->ut_host)
93#  endif
94# endif /* HAVE_STRUCT_UTMP_UT_HOST */
95#else
96/* give poor cc a little help if it needs it */
97struct utmp __ut;
98
99# define UTNAMLEN       sizeof(__ut.ut_name)
100# define UTLINLEN       sizeof(__ut.ut_line)
101# ifdef HAVE_STRUCT_UTMP_UT_HOST
102#  ifdef _SEQUENT_
103#   define UTHOSTLEN    100
104#  else
105#   define UTHOSTLEN    sizeof(__ut.ut_host)
106#  endif
107# endif /* HAVE_STRUCT_UTMP_UT_HOST */
108#endif /* BROKEN_CC */
109
110#ifndef TCSH_PATH_UTMP
111# ifdef UTMP_FILE
112#  define TCSH_PATH_UTMP UTMP_FILE
113# elif defined(_PATH_UTMP)
114#  define TCSH_PATH_UTMP _PATH_UTMP
115# else
116#  define TCSH_PATH_UTMP "/etc/utmp"
117# endif /* UTMP_FILE */
118#endif /* TCSH_PATH_UTMP */
119
120
121struct who {
122    struct who *who_next;
123    struct who *who_prev;
124    char    who_name[UTNAMLEN + 1];
125    char    who_new[UTNAMLEN + 1];
126    char    who_tty[UTLINLEN + 1];
127#ifdef HAVE_STRUCT_UTMP_UT_HOST
128    char    who_host[UTHOSTLEN + 1];
129#endif /* HAVE_STRUCT_UTMP_UT_HOST */
130    time_t  who_time;
131    int     who_status;
132};
133
134static struct who whohead, whotail;
135static time_t watch_period = 0;
136static time_t stlast = 0;
137#ifdef WHODEBUG
138static  void    debugwholist    __P((struct who *, struct who *));
139#endif
140static  void    print_who       __P((struct who *));
141
142
143#define ONLINE          01
144#define OFFLINE         02
145#define CHANGED         04
146#define STMASK          07
147#define ANNOUNCE        010
148
149/*
150 * Karl Kleinpaste, 26 Jan 1984.
151 * Initialize the dummy tty list for login watch.
152 * This dummy list eliminates boundary conditions
153 * when doing pointer-chase searches.
154 */
155void
156initwatch()
157{
158    whohead.who_next = &whotail;
159    whotail.who_prev = &whohead;
160    stlast = 1;
161#ifdef WHODEBUG
162    debugwholist(NULL, NULL);
163#endif /* WHODEBUG */
164}
165
166void
167resetwatch()
168{
169    watch_period = 0;
170    stlast = 0;
171}
172
173/*
174 * Karl Kleinpaste, 26 Jan 1984.
175 * Watch /etc/utmp for login/logout changes.
176 */
177void
178watch_login(force)
179    int force;
180{
181    int     comp = -1, alldone;
182    int     firsttime = stlast == 1;
183#ifdef HAVE_GETUTENT
184    struct utmp *uptr;
185#else
186    int utmpfd;
187#endif
188#ifdef BSDSIGS
189    sigmask_t omask;
190#endif                          /* BSDSIGS */
191    struct utmp utmp;
192    struct who *wp, *wpnew;
193    struct varent *v;
194    Char  **vp = NULL;
195    time_t  t, interval = MAILINTVL;
196    struct stat sta;
197#if defined(HAVE_STRUCT_UTMP_UT_HOST) && defined(_SEQUENT_)
198    char   *host, *ut_find_host();
199#endif
200#ifdef WINNT_NATIVE
201    static int ncbs_posted = 0;
202    USE(utmp);
203    USE(utmpfd);
204    USE(sta);
205    USE(wpnew);
206#endif /* WINNT_NATIVE */
207
208    /* stop SIGINT, lest our login list get trashed. */
209#ifdef BSDSIGS
210    omask = sigblock(sigmask(SIGINT));
211#else
212    (void) sighold(SIGINT);
213#endif
214
215    v = adrof(STRwatch);
216    if ((v == NULL || v->vec == NULL) && !force) {
217#ifdef BSDSIGS
218        (void) sigsetmask(omask);
219#else
220        (void) sigrelse(SIGINT);
221#endif
222        return;                 /* no names to watch */
223    }
224    if (!force) {
225        trim(vp = v->vec);
226        if (blklen(vp) % 2)             /* odd # args: 1st == # minutes. */
227            interval = (number(*vp)) ? (getn(*vp++) * 60) : MAILINTVL;
228    }
229    else
230        interval = 0;
231       
232    (void) time(&t);
233#ifdef WINNT_NATIVE
234        /*
235         * Since NCB_ASTATs take time, start em async at least 90 secs
236         * before we are due -amol 6/5/97
237         */
238        if (!ncbs_posted) {
239            unsigned long tdiff = t - watch_period;
240            if (!watch_period || ((tdiff  > 0) && (tdiff > (interval - 90)))) {
241                start_ncbs(vp);
242                ncbs_posted = 1;
243            }
244        }
245#endif /* WINNT_NATIVE */
246    if (t - watch_period < interval) {
247#ifdef BSDSIGS
248        (void) sigsetmask(omask);
249#else
250        (void) sigrelse(SIGINT);
251#endif
252        return;                 /* not long enough yet... */
253    }
254    watch_period = t;
255#ifdef WINNT_NATIVE
256    ncbs_posted = 0;
257#else /* !WINNT_NATIVE */
258
259    /*
260     * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
261     * Don't open utmp all the time, stat it first...
262     */
263    if (stat(TCSH_PATH_UTMP, &sta)) {
264        if (!force)
265            xprintf(CGETS(26, 1,
266                          "cannot stat %s.  Please \"unset watch\".\n"),
267                    TCSH_PATH_UTMP);
268# ifdef BSDSIGS
269        (void) sigsetmask(omask);
270# else
271        (void) sigrelse(SIGINT);
272# endif
273        return;
274    }
275    if (stlast == sta.st_mtime) {
276# ifdef BSDSIGS
277        (void) sigsetmask(omask);
278# else
279        (void) sigrelse(SIGINT);
280# endif
281        return;
282    }
283    stlast = sta.st_mtime;
284#ifdef HAVE_GETUTENT
285    setutent();
286#else
287    if ((utmpfd = open(TCSH_PATH_UTMP, O_RDONLY|O_LARGEFILE)) < 0) {
288        if (!force)
289            xprintf(CGETS(26, 2,
290                          "%s cannot be opened.  Please \"unset watch\".\n"),
291                    TCSH_PATH_UTMP);
292# ifdef BSDSIGS
293        (void) sigsetmask(omask);
294# else
295        (void) sigrelse(SIGINT);
296# endif
297        return;
298    }
299#endif
300
301    /*
302     * xterm clears the entire utmp entry - mark everyone on the status list
303     * OFFLINE or we won't notice X "logouts"
304     */
305    for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) {
306        wp->who_status = OFFLINE;
307        wp->who_time = 0;
308    }
309
310    /*
311     * Read in the utmp file, sort the entries, and update existing entries or
312     * add new entries to the status list.
313     */
314#ifdef HAVE_GETUTENT
315    while ((uptr = getutent()) != NULL) {
316        memcpy(&utmp, uptr, sizeof (utmp));
317#else
318    while (read(utmpfd, (char *) &utmp, sizeof utmp) == sizeof utmp) {
319#endif
320
321# ifdef DEAD_PROCESS
322#  ifndef IRIS4D
323        if (utmp.ut_type != USER_PROCESS)
324            continue;
325#  else
326        /* Why is that? Cause the utmp file is always corrupted??? */
327        if (utmp.ut_type != USER_PROCESS && utmp.ut_type != DEAD_PROCESS)
328            continue;
329#  endif /* IRIS4D */
330# endif /* DEAD_PROCESS */
331
332        if (utmp.ut_name[0] == '\0' && utmp.ut_line[0] == '\0')
333            continue;   /* completely void entry */
334# ifdef DEAD_PROCESS
335        if (utmp.ut_type == DEAD_PROCESS && utmp.ut_line[0] == '\0')
336            continue;
337# endif /* DEAD_PROCESS */
338        wp = whohead.who_next;
339        while (wp->who_next && (comp = strncmp(wp->who_tty, utmp.ut_line, UTLINLEN)) < 0)
340            wp = wp->who_next;/* find that tty! */
341
342        if (wp->who_next && comp == 0) {        /* found the tty... */
343# ifdef DEAD_PROCESS
344            if (utmp.ut_type == DEAD_PROCESS) {
345                wp->who_time = utmp.ut_time;
346                wp->who_status = OFFLINE;
347            }
348            else
349# endif /* DEAD_PROCESS */
350            if (utmp.ut_name[0] == '\0') {
351                wp->who_time = utmp.ut_time;
352                wp->who_status = OFFLINE;
353            }
354            else if (strncmp(utmp.ut_name, wp->who_name, UTNAMLEN) == 0) {
355                /* someone is logged in */
356                wp->who_time = utmp.ut_time;
357                wp->who_status = 0;     /* same guy */
358            }
359            else {
360                (void) strncpy(wp->who_new, utmp.ut_name, UTNAMLEN);
361# ifdef HAVE_STRUCT_UTMP_UT_HOST
362#  ifdef _SEQUENT_
363                host = ut_find_host(wp->who_tty);
364                if (host)
365                    (void) strncpy(wp->who_host, host, UTHOSTLEN);
366                else
367                    wp->who_host[0] = 0;
368#  else
369                (void) strncpy(wp->who_host, utmp.ut_host, UTHOSTLEN);
370#  endif
371# endif /* HAVE_STRUCT_UTMP_UT_HOST */
372                wp->who_time = utmp.ut_time;
373                if (wp->who_name[0] == '\0')
374                    wp->who_status = ONLINE;
375                else
376                    wp->who_status = CHANGED;
377            }
378        }
379        else {          /* new tty in utmp */
380            wpnew = (struct who *) xcalloc(1, sizeof *wpnew);
381            (void) strncpy(wpnew->who_tty, utmp.ut_line, UTLINLEN);
382# ifdef HAVE_STRUCT_UTMP_UT_HOST
383#  ifdef _SEQUENT_
384            host = ut_find_host(wpnew->who_tty);
385            if (host)
386                (void) strncpy(wpnew->who_host, host, UTHOSTLEN);
387            else
388                wpnew->who_host[0] = 0;
389#  else
390            (void) strncpy(wpnew->who_host, utmp.ut_host, UTHOSTLEN);
391#  endif
392# endif /* HAVE_STRUCT_UTMP_UT_HOST */
393            wpnew->who_time = utmp.ut_time;
394# ifdef DEAD_PROCESS
395            if (utmp.ut_type == DEAD_PROCESS)
396                wpnew->who_status = OFFLINE;
397            else
398# endif /* DEAD_PROCESS */
399            if (utmp.ut_name[0] == '\0')
400                wpnew->who_status = OFFLINE;
401            else {
402                (void) strncpy(wpnew->who_new, utmp.ut_name, UTNAMLEN);
403                wpnew->who_status = ONLINE;
404            }
405# ifdef WHODEBUG
406            debugwholist(wpnew, wp);
407# endif /* WHODEBUG */
408
409            wpnew->who_next = wp;       /* link in a new 'who' */
410            wpnew->who_prev = wp->who_prev;
411            wpnew->who_prev->who_next = wpnew;
412            wp->who_prev = wpnew;       /* linked in now */
413        }
414    }
415#ifdef HAVE_GETUTENT
416    endutent();
417#else
418    (void) close(utmpfd);
419#endif
420# if defined(HAVE_STRUCT_UTMP_UT_HOST) && defined(_SEQUENT_)
421    endutent();
422# endif
423#endif /* !WINNT_NATIVE */
424
425    if (force || vp == NULL)
426        return;
427
428    /*
429     * The state of all logins is now known, so we can search the user's list
430     * of watchables to print the interesting ones.
431     */
432    for (alldone = 0; !alldone && *vp != NULL && **vp != '\0' &&
433         *(vp + 1) != NULL && **(vp + 1) != '\0';
434         vp += 2) {             /* args used in pairs... */
435
436        if (eq(*vp, STRany) && eq(*(vp + 1), STRany))
437            alldone = 1;
438
439        for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) {
440            if (wp->who_status & ANNOUNCE ||
441                (!eq(STRany, vp[0]) &&
442                 !Gmatch(str2short(wp->who_name), vp[0]) &&
443                 !Gmatch(str2short(wp->who_new),  vp[0])) ||
444                (!Gmatch(str2short(wp->who_tty),  vp[1]) &&
445                 !eq(STRany, vp[1])))
446                continue;       /* entry doesn't qualify */
447            /* already printed or not right one to print */
448
449
450            if (wp->who_time == 0)/* utmp entry was cleared */
451                wp->who_time = watch_period;
452
453            if ((wp->who_status & OFFLINE) &&
454                (wp->who_name[0] != '\0')) {
455                if (!firsttime)
456                    print_who(wp);
457                wp->who_name[0] = '\0';
458                wp->who_status |= ANNOUNCE;
459                continue;
460            }
461            if (wp->who_status & ONLINE) {
462                if (!firsttime)
463                    print_who(wp);
464                (void) strcpy(wp->who_name, wp->who_new);
465                wp->who_status |= ANNOUNCE;
466                continue;
467            }
468            if (wp->who_status & CHANGED) {
469                if (!firsttime)
470                    print_who(wp);
471                (void) strcpy(wp->who_name, wp->who_new);
472                wp->who_status |= ANNOUNCE;
473                continue;
474            }
475        }
476    }
477#ifdef BSDSIGS
478    (void) sigsetmask(omask);
479#else
480    (void) sigrelse(SIGINT);
481#endif
482}
483
484#ifdef WHODEBUG
485static void
486debugwholist(new, wp)
487    struct who *new, *wp;
488{
489    struct who *a;
490
491    a = whohead.who_next;
492    while (a->who_next != NULL) {
493        xprintf("%s/%s -> ", a->who_name, a->who_tty);
494        a = a->who_next;
495    }
496    xprintf("TAIL\n");
497    if (a != &whotail) {
498        xprintf(CGETS(26, 3, "BUG! last element is not whotail!\n"));
499        abort();
500    }
501    a = whotail.who_prev;
502    xprintf(CGETS(26, 4, "backward: "));
503    while (a->who_prev != NULL) {
504        xprintf("%s/%s -> ", a->who_name, a->who_tty);
505        a = a->who_prev;
506    }
507    xprintf("HEAD\n");
508    if (a != &whohead) {
509        xprintf(CGETS(26, 5, "BUG! first element is not whohead!\n"));
510        abort();
511    }
512    if (new)
513        xprintf(CGETS(26, 6, "new: %s/%s\n"), new->who_name, new->who_tty);
514    if (wp)
515        xprintf("wp: %s/%s\n", wp->who_name, wp->who_tty);
516}
517#endif /* WHODEBUG */
518
519
520static void
521print_who(wp)
522    struct who *wp;
523{
524#ifdef HAVE_STRUCT_UTMP_UT_HOST
525    Char   *cp = str2short(CGETS(26, 7, "%n has %a %l from %m."));
526#else
527    Char   *cp = str2short(CGETS(26, 8, "%n has %a %l."));
528#endif /* HAVE_STRUCT_UTMP_UT_HOST */
529    struct varent *vp = adrof(STRwho);
530    Char buf[BUFSIZE];
531
532    if (vp && vp->vec && vp->vec[0])
533        cp = vp->vec[0];
534
535    tprintf(FMT_WHO, buf, cp, BUFSIZE, NULL, wp->who_time, (ptr_t) wp);
536    for (cp = buf; *cp;)
537        xputwchar(*cp++);
538    xputchar('\n');
539} /* end print_who */
540
541
542const char *
543who_info(ptr, c, wbuf, wbufsiz)
544    ptr_t ptr;
545    int c;
546    char *wbuf;
547    size_t wbufsiz;
548{
549    struct who *wp = (struct who *) ptr;
550#ifdef HAVE_STRUCT_UTMP_UT_HOST
551    char *wb = wbuf;
552    int flg;
553    char *pb;
554#endif /* HAVE_STRUCT_UTMP_UT_HOST */
555
556    switch (c) {
557    case 'n':           /* user name */
558        switch (wp->who_status & STMASK) {
559        case ONLINE:
560        case CHANGED:
561            return wp->who_new;
562        case OFFLINE:
563            return wp->who_name;
564        default:
565            break;
566        }
567        break;
568
569    case 'a':
570        switch (wp->who_status & STMASK) {
571        case ONLINE:
572            return CGETS(26, 9, "logged on");
573        case OFFLINE:
574            return CGETS(26, 10, "logged off");
575        case CHANGED:
576            xsnprintf(wbuf, wbufsiz, CGETS(26, 11, "replaced %s on"),
577                      wp->who_name);
578            return wbuf;
579        default:
580            break;
581        }
582        break;
583
584#ifdef HAVE_STRUCT_UTMP_UT_HOST
585    case 'm':
586        if (wp->who_host[0] == '\0')
587            return CGETS(26, 12, "local");
588        else {
589            /* the ':' stuff is for <host>:<display>.<screen> */
590            for (pb = wp->who_host,
591                flg = isdigit((unsigned char)*pb) ? '\0' : '.';
592                *pb != '\0' && (*pb != flg || ((pb = strchr(pb, ':')) != 0));
593                 pb++) {
594                if (*pb == ':')
595                    flg = '\0';
596                *wb++ = isupper((unsigned char)*pb) ?
597                    tolower((unsigned char)*pb) : *pb;
598            }
599            *wb = '\0';
600            return wbuf;
601        }
602
603    case 'M':
604        if (wp->who_host[0] == '\0')
605            return CGETS(26, 12, "local");
606        else {
607            for (pb = wp->who_host; *pb != '\0'; pb++)
608                *wb++ = isupper((unsigned char)*pb) ?
609                    tolower((unsigned char)*pb) : *pb;
610            *wb = '\0';
611            return wbuf;
612        }
613#endif /* HAVE_STRUCT_UTMP_UT_HOST */
614
615    case 'l':
616        return wp->who_tty;
617
618    default:
619        wbuf[0] = '%';
620        wbuf[1] = (char) c;
621        wbuf[2] = '\0';
622        return wbuf;
623    }
624    return NULL;
625}
626
627void
628/*ARGSUSED*/
629dolog(v, c)
630Char **v;
631struct command *c;
632{
633    struct who *wp;
634    struct varent *vp;
635
636    USE(v);
637    USE(c);
638    vp = adrof(STRwatch);       /* lint insists vp isn't used unless we */
639    if (vp == NULL)             /* unless we assign it outside the if */
640        stderror(ERR_NOWATCH);
641    resetwatch();
642    wp = whohead.who_next;
643    while (wp->who_next != NULL) {
644        wp->who_name[0] = '\0';
645        wp = wp->who_next;
646    }
647}
648
649# ifdef HAVE_STRUCT_UTMP_UT_HOST
650size_t
651utmphostsize()
652{
653    return UTHOSTLEN;
654}
655
656char *
657utmphost()
658{
659    char *tty = short2str(varval(STRtty));
660    struct who *wp;
661    char *host = NULL;
662
663    watch_login(1);
664   
665    for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) {
666        if (strcmp(tty, wp->who_tty) == 0)
667            host = wp->who_host;
668        wp->who_name[0] = '\0';
669    }
670    resetwatch();
671    return host;
672}
673# endif /* HAVE_STRUCT_UTMP_UT_HOST */
674
675#ifdef WINNT_NATIVE
676void add_to_who_list(name, mach_nm)
677    char *name;
678    char *mach_nm;
679{
680
681    struct who *wp, *wpnew;
682    int comp = -1;
683
684    wp = whohead.who_next;
685    while (wp->who_next && (comp = strncmp(wp->who_tty,mach_nm,UTLINLEN)) < 0)
686        wp = wp->who_next;/* find that tty! */
687
688    if (wp->who_next && comp == 0) {    /* found the tty... */
689
690        if (*name == '\0') {
691            wp->who_time = 0;
692            wp->who_status = OFFLINE;
693        }
694        else if (strncmp(name, wp->who_name, UTNAMLEN) == 0) {
695            /* someone is logged in */
696            wp->who_time = 0;
697            wp->who_status = 0; /* same guy */
698        }
699        else {
700            (void) strncpy(wp->who_new, name, UTNAMLEN);
701            wp->who_time = 0;
702            if (wp->who_name[0] == '\0')
703                wp->who_status = ONLINE;
704            else
705                wp->who_status = CHANGED;
706        }
707    }
708    else {
709        wpnew = (struct who *) xcalloc(1, sizeof *wpnew);
710        (void) strncpy(wpnew->who_tty, mach_nm, UTLINLEN);
711        wpnew->who_time = 0;
712        if (*name == '\0')
713            wpnew->who_status = OFFLINE;
714        else {
715            (void) strncpy(wpnew->who_new, name, UTNAMLEN);
716            wpnew->who_status = ONLINE;
717        }
718#ifdef WHODEBUG
719        debugwholist(wpnew, wp);
720#endif /* WHODEBUG */
721
722        wpnew->who_next = wp;   /* link in a new 'who' */
723        wpnew->who_prev = wp->who_prev;
724        wpnew->who_prev->who_next = wpnew;
725        wp->who_prev = wpnew;   /* linked in now */
726    }
727}
728#endif /* WINNT_NATIVE */
729#endif /* HAVENOUTMP */
Note: See TracBrowser for help on using the repository browser.