(linenum→info "unix/slp.c:2238")

bsd-games/2.17/dm/utmpentry.c

    1: /*      $NetBSD: utmpentry.c,v 1.5 2004/10/22 15:50:47 christos Exp $        */
    2: 
    3: /*-
    4:  * Copyright (c) 2002 The NetBSD Foundation, Inc.
    5:  * All rights reserved.
    6:  *
    7:  * This code is derived from software contributed to The NetBSD Foundation
    8:  * by Christos Zoulas.
    9:  *
   10:  * Redistribution and use in source and binary forms, with or without
   11:  * modification, are permitted provided that the following conditions
   12:  * are met:
   13:  * 1. Redistributions of source code must retain the above copyright
   14:  *    notice, this list of conditions and the following disclaimer.
   15:  * 2. Redistributions in binary form must reproduce the above copyright
   16:  *    notice, this list of conditions and the following disclaimer in the
   17:  *    documentation and/or other materials provided with the distribution.
   18:  * 3. All advertising materials mentioning features or use of this software
   19:  *    must display the following acknowledgement:
   20:  *        This product includes software developed by the NetBSD
   21:  *        Foundation, Inc. and its contributors.
   22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23:  *    contributors may be used to endorse or promote products derived
   24:  *    from this software without specific prior written permission.
   25:  *
   26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36:  * POSSIBILITY OF SUCH DAMAGE.
   37:  */
   38: 
   39: #include <sys/cdefs.h>
   40: #ifndef lint
   41: __RCSID("$NetBSD: utmpentry.c,v 1.5 2004/10/22 15:50:47 christos Exp $");
   42: #endif
   43: 
   44: #include <sys/stat.h>
   45: 
   46: #include <time.h>
   47: #include <string.h>
   48: #include <err.h>
   49: #include <stdlib.h>
   50: 
   51: #ifdef SUPPORT_UTMP
   52: #include <utmp.h>
   53: #endif
   54: #ifdef SUPPORT_UTMPX
   55: #include <utmpx.h>
   56: #endif
   57: 
   58: #include "utmpentry.h"
   59: 
   60: 
   61: #ifdef SUPPORT_UTMP
   62: static void getentry(struct utmpentry *, struct utmp *);
   63: static time_t utmptime = 0;
   64: #endif
   65: #ifdef SUPPORT_UTMPX
   66: static void getentryx(struct utmpentry *, struct utmpx *);
   67: static time_t utmpxtime = 0;
   68: #endif
   69: #if defined(SUPPORT_UTMPX) || defined(SUPPORT_UTMP)
   70: static int setup(const char *);
   71: static void adjust_size(struct utmpentry *e);
   72: #endif
   73: 
   74: int maxname = 8, maxline = 8, maxhost = 16;
   75: static int numutmp = 0;
   76: static struct utmpentry *ehead;
   77: 
   78: #if defined(SUPPORT_UTMPX) || defined(SUPPORT_UTMP)
   79: static void
   80: adjust_size(struct utmpentry *e)
   81: {
   82:         int max;
   83: 
   84:         if ((max = strlen(e->name)) > maxname)
   85:                 maxname = max;
   86:         if ((max = strlen(e->line)) > maxline)
   87:                 maxline = max;
   88:         if ((max = strlen(e->host)) > maxhost)
   89:                 maxhost = max;
   90: }
   91: 
   92: static int
   93: setup(const char *fname)
   94: {
   95:         int what = 3;
   96:         struct stat st;
   97:         const char *sfname;
   98: 
   99:         if (fname == NULL) {
  100: #ifdef SUPPORT_UTMPX
  101:                 setutxent();
  102: #endif
  103: #ifdef SUPPORT_UTMP
  104:                 setutent();
  105: #endif
  106:         } else {
  107:                 size_t len = strlen(fname);
  108:                 if (len == 0)
  109:                         errx(1, "Filename cannot be 0 length.");
  110:                 what = fname[len - 1] == 'x' ? 1 : 2;
  111:                 if (what == 1) {
  112: #ifdef SUPPORT_UTMPX
  113:                         if (utmpxname(fname) == 0)
  114:                                 warnx("Cannot set utmpx file to `%s'",
  115:                                     fname);
  116: #else
  117:                         warnx("utmpx support not compiled in");
  118: #endif
  119:                 } else {
  120: #ifdef SUPPORT_UTMP
  121:                         if (utmpname(fname) == 0)
  122:                                 warnx("Cannot set utmp file to `%s'",
  123:                                     fname);
  124: #else
  125:                         warnx("utmp support not compiled in");
  126: #endif
  127:                 }
  128:         }
  129: #ifdef SUPPORT_UTMPX
  130:         if (what & 1) {
  131:                 sfname = fname ? fname : _PATH_UTMPX;
  132:                 if (stat(sfname, &st) == -1) {
  133:                         warn("Cannot stat `%s'", sfname);
  134:                         what &= ~1;
  135:                 } else {
  136:                         if (st.st_mtime > utmpxtime)
  137:                             utmpxtime = st.st_mtime;
  138:                         else
  139:                             what &= ~1;
  140:                 }
  141:         }
  142: #endif
  143: #ifdef SUPPORT_UTMP
  144:         if (what & 2) {
  145:                 sfname = fname ? fname : _PATH_UTMP;
  146:                 if (stat(sfname, &st) == -1) {
  147:                         warn("Cannot stat `%s'", sfname);
  148:                         what &= ~2;
  149:                 } else {
  150:                         if (st.st_mtime > utmptime)
  151:                                 utmptime = st.st_mtime;
  152:                         else
  153:                                 what &= ~2;
  154:                 }
  155:         }
  156: #endif
  157:         return what;
  158: }
  159: #endif
  160: 
  161: void
  162: freeutentries(struct utmpentry *ep)
  163: {
  164: #ifdef SUPPORT_UTMP
  165:         utmptime = 0;
  166: #endif
  167: #ifdef SUPPORT_UTMPX
  168:         utmpxtime = 0;
  169: #endif
  170:         if (ep == ehead) {
  171:                 ehead = NULL;
  172:                 numutmp = 0;
  173:         }
  174:         while (ep) {
  175:                 struct utmpentry *sep = ep;
  176:                 ep = ep->next;
  177:                 free(sep);
  178:         }
  179: }
  180: 
  181: int
  182: getutentries(const char *fname, struct utmpentry **epp)
  183: {
  184: #ifdef SUPPORT_UTMPX
  185:         struct utmpx *utx;
  186: #endif
  187: #ifdef SUPPORT_UTMP
  188:         struct utmp *ut;
  189: #endif
  190: #if defined(SUPPORT_UTMP) || defined(SUPPORT_UTMPX)
  191:         struct utmpentry *ep;
  192:         int what = setup(fname);
  193:         struct utmpentry **nextp = &ehead;
  194:         switch (what) {
  195:         case 0:
  196:                 /* No updates */
  197:                 *epp = ehead;
  198:                 return numutmp;
  199:         default:
  200:                 /* Need to re-scan */
  201:                 ehead = NULL;
  202:                 numutmp = 0;
  203:         }
  204: #endif
  205: 
  206: #ifdef SUPPORT_UTMPX
  207:         while ((what & 1) && (utx = getutxent()) != NULL) {
  208:                 if (fname == NULL && utx->ut_type != USER_PROCESS)
  209:                         continue;
  210:                 if ((ep = calloc(1, sizeof(struct utmpentry))) == NULL) {
  211:                         warn(NULL);
  212:                         return 0;
  213:                 }
  214:                 getentryx(ep, utx);
  215:                 *nextp = ep;
  216:                 nextp = &(ep->next);
  217:         }
  218: #endif
  219: 
  220: #ifdef SUPPORT_UTMP
  221:         while ((what & 2) && (ut = getutent()) != NULL) {
  222:                 if (fname == NULL && (*ut->ut_name == '\0' ||
  223:                     *ut->ut_line == '\0'))
  224:                         continue;
  225:                 /* Don't process entries that we have utmpx for */
  226:                 for (ep = ehead; ep != NULL; ep = ep->next) {
  227:                         if (strncmp(ep->line, ut->ut_line,
  228:                             sizeof(ut->ut_line)) == 0)
  229:                                 break;
  230:                 }
  231:                 if (ep != NULL)
  232:                         continue;
  233:                 if ((ep = calloc(1, sizeof(struct utmpentry))) == NULL) {
  234:                         warn(NULL);
  235:                         return 0;
  236:                 }
  237:                 getentry(ep, ut);
  238:                 *nextp = ep;
  239:                 nextp = &(ep->next);
  240:         }
  241: #endif
  242:         numutmp = 0;
  243: #if defined(SUPPORT_UTMP) && defined(SUPPORT_UTMPX)
  244:         if (ehead != NULL) {
  245:                 struct utmpentry *from = ehead, *save;
  246:                 
  247:                 ehead = NULL;
  248:                 while (from != NULL) {
  249:                         for (nextp = &ehead;
  250:                             (*nextp) && strcmp(from->line, (*nextp)->line) > 0;
  251:                             nextp = &(*nextp)->next)
  252:                                 continue;
  253:                         save = from;
  254:                         from = from->next;
  255:                         save->next = *nextp;
  256:                         *nextp = save;
  257:                         numutmp++;
  258:                 }
  259:         }
  260:         *epp = ehead;
  261:         return numutmp;
  262: #else
  263:         *epp = NULL;
  264:         return 0;
  265: #endif
  266: }
  267: 
  268: #ifdef SUPPORT_UTMP
  269: static void
  270: getentry(struct utmpentry *e, struct utmp *up)
  271: {
  272:         (void)strncpy(e->name, up->ut_name, sizeof(up->ut_name));
  273:         e->name[sizeof(e->name) - 1] = '\0';
  274:         (void)strncpy(e->line, up->ut_line, sizeof(up->ut_line));
  275:         e->line[sizeof(e->line) - 1] = '\0';
  276:         (void)strncpy(e->host, up->ut_host, sizeof(up->ut_host));
  277:         e->name[sizeof(e->host) - 1] = '\0';
  278:         e->tv.tv_sec = up->ut_time;
  279:         e->tv.tv_usec = 0;
  280:         adjust_size(e);
  281: }
  282: #endif
  283: 
  284: #ifdef SUPPORT_UTMPX
  285: static void
  286: getentryx(struct utmpentry *e, struct utmpx *up)
  287: {
  288:         (void)strncpy(e->name, up->ut_name, sizeof(up->ut_name));
  289:         e->name[sizeof(e->name) - 1] = '\0';
  290:         (void)strncpy(e->line, up->ut_line, sizeof(up->ut_line));
  291:         e->line[sizeof(e->line) - 1] = '\0';
  292:         (void)strncpy(e->host, up->ut_host, sizeof(up->ut_host));
  293:         e->name[sizeof(e->host) - 1] = '\0';
  294:         e->tv = up->ut_tv;
  295:         adjust_size(e);
  296: }
  297: #endif
Syntax (Markdown)