| [1] | 1 | /* SAMHAIN file system integrity testing                                   */
 | 
|---|
 | 2 | /* Copyright (C) 1999 Rainer Wichmann                                      */
 | 
|---|
 | 3 | /*                                                                         */
 | 
|---|
 | 4 | /*  This program is free software; you can redistribute it                 */
 | 
|---|
 | 5 | /*  and/or modify                                                          */
 | 
|---|
 | 6 | /*  it under the terms of the GNU General Public License as                */
 | 
|---|
 | 7 | /*  published by                                                           */
 | 
|---|
 | 8 | /*  the Free Software Foundation; either version 2 of the License, or      */
 | 
|---|
 | 9 | /*  (at your option) any later version.                                    */
 | 
|---|
 | 10 | /*                                                                         */
 | 
|---|
 | 11 | /*  This program is distributed in the hope that it will be useful,        */
 | 
|---|
 | 12 | /*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
 | 
|---|
 | 13 | /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
 | 
|---|
 | 14 | /*  GNU General Public License for more details.                           */
 | 
|---|
 | 15 | /*                                                                         */
 | 
|---|
 | 16 | /*  You should have received a copy of the GNU General Public License      */
 | 
|---|
 | 17 | /*  along with this program; if not, write to the Free Software            */
 | 
|---|
 | 18 | /*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
 | 
|---|
 | 19 | 
 | 
|---|
 | 20 | #include "config_xor.h"
 | 
|---|
 | 21 | 
 | 
|---|
 | 22 | #include <stdio.h>
 | 
|---|
 | 23 | #include <stdlib.h>
 | 
|---|
 | 24 | #include <string.h>
 | 
|---|
 | 25 | #include <sys/types.h>
 | 
|---|
 | 26 | #include <sys/stat.h>
 | 
|---|
 | 27 | #include <fcntl.h>
 | 
|---|
 | 28 | #include <errno.h>
 | 
|---|
 | 29 | 
 | 
|---|
 | 30 | #ifdef HAVE_UTADDR
 | 
|---|
 | 31 | #include <sys/socket.h>
 | 
|---|
 | 32 | #include <netinet/in.h>
 | 
|---|
 | 33 | #ifndef S_SPLINT_S
 | 
|---|
 | 34 | #include <arpa/inet.h>
 | 
|---|
 | 35 | #else
 | 
|---|
 | 36 | #define AF_INET 2
 | 
|---|
 | 37 | #endif
 | 
|---|
 | 38 | #endif
 | 
|---|
 | 39 | 
 | 
|---|
 | 40 | #ifdef SH_USE_UTMP
 | 
|---|
 | 41 | 
 | 
|---|
 | 42 | #ifdef HAVE_UTMPX_H
 | 
|---|
 | 43 | 
 | 
|---|
 | 44 | #ifdef S_SPLINT_S
 | 
|---|
 | 45 | typedef pid_t __pid_t;
 | 
|---|
 | 46 | #endif
 | 
|---|
 | 47 | 
 | 
|---|
 | 48 | #include <utmpx.h>
 | 
|---|
 | 49 | #define SH_UTMP_S utmpx
 | 
|---|
 | 50 | #undef  ut_name
 | 
|---|
 | 51 | #define ut_name ut_user
 | 
|---|
 | 52 | #ifdef HAVE_UTXTIME
 | 
|---|
 | 53 | #undef  ut_time
 | 
|---|
 | 54 | #define ut_time        ut_xtime
 | 
|---|
 | 55 | #else
 | 
|---|
 | 56 | #undef  ut_time
 | 
|---|
 | 57 | #define ut_time        ut_tv.tv_sec
 | 
|---|
 | 58 | #endif
 | 
|---|
 | 59 | 
 | 
|---|
 | 60 | #else
 | 
|---|
 | 61 | #include <utmp.h>
 | 
|---|
 | 62 | #define SH_UTMP_S utmp
 | 
|---|
 | 63 | #endif
 | 
|---|
 | 64 | 
 | 
|---|
 | 65 | 
 | 
|---|
 | 66 | #ifdef HAVE_PATHS_H
 | 
|---|
 | 67 | #include <paths.h>
 | 
|---|
 | 68 | #endif
 | 
|---|
 | 69 | 
 | 
|---|
 | 70 | #undef  FIL__
 | 
|---|
 | 71 | #define FIL__  _("sh_utmp.c")
 | 
|---|
 | 72 | 
 | 
|---|
 | 73 | #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) 
 | 
|---|
 | 74 | 
 | 
|---|
 | 75 | 
 | 
|---|
 | 76 | #include "samhain.h"
 | 
|---|
 | 77 | #include "sh_utils.h"
 | 
|---|
 | 78 | #include "sh_error.h"
 | 
|---|
 | 79 | #include "sh_modules.h"
 | 
|---|
 | 80 | #include "sh_utmp.h"
 | 
|---|
| [143] | 81 | #include "sh_pthread.h"
 | 
|---|
| [259] | 82 | #include "sh_inotify.h"
 | 
|---|
| [1] | 83 | 
 | 
|---|
| [143] | 84 | SH_MUTEX_EXTERN(mutex_thread_nolog);
 | 
|---|
| [1] | 85 | 
 | 
|---|
 | 86 | #ifdef TM_IN_SYS_TIME
 | 
|---|
 | 87 | #include <sys/time.h>
 | 
|---|
 | 88 | #else
 | 
|---|
 | 89 | #include <time.h>
 | 
|---|
 | 90 | #endif
 | 
|---|
 | 91 | 
 | 
|---|
 | 92 | #ifdef HAVE_UNISTD_H
 | 
|---|
 | 93 | #include <unistd.h>
 | 
|---|
 | 94 | #endif 
 | 
|---|
 | 95 | 
 | 
|---|
 | 96 | #ifdef HAVE_DIRENT_H
 | 
|---|
 | 97 | #include <dirent.h>
 | 
|---|
 | 98 | #define NAMLEN(dirent) sl_strlen((dirent)->d_name)
 | 
|---|
 | 99 | #else
 | 
|---|
 | 100 | #define dirent direct
 | 
|---|
 | 101 | #define NAMLEN(dirent) (dirent)->d_namlen
 | 
|---|
 | 102 | #ifdef HAVE_SYS_NDIR_H
 | 
|---|
 | 103 | #include <sys/ndir.h>
 | 
|---|
 | 104 | #endif
 | 
|---|
 | 105 | #ifdef HAVE_SYS_DIR_H
 | 
|---|
 | 106 | #include <sys/dir.h>
 | 
|---|
 | 107 | #endif
 | 
|---|
 | 108 | #ifdef HAVE_NDIR_H
 | 
|---|
 | 109 | #include <ndir.h>
 | 
|---|
 | 110 | #endif
 | 
|---|
 | 111 | #endif
 | 
|---|
 | 112 | 
 | 
|---|
 | 113 | #ifndef HAVE_LSTAT
 | 
|---|
 | 114 | #define lstat stat
 | 
|---|
 | 115 | #endif 
 | 
|---|
 | 116 | 
 | 
|---|
 | 117 | #ifndef UT_LINESIZE
 | 
|---|
 | 118 | #ifndef __UT_LINESIZE
 | 
|---|
 | 119 | #define UT_LINESIZE            12
 | 
|---|
 | 120 | #else
 | 
|---|
 | 121 | #define UT_LINESIZE __UT_LINESIZE
 | 
|---|
 | 122 | #endif 
 | 
|---|
 | 123 | #endif
 | 
|---|
 | 124 | 
 | 
|---|
 | 125 | #ifndef UT_NAMESIZE
 | 
|---|
 | 126 | #ifndef __UT_NAMESIZE
 | 
|---|
 | 127 | #define UT_NAMESIZE             8
 | 
|---|
 | 128 | #else
 | 
|---|
 | 129 | #define UT_NAMESIZE __UT_NAMESIZE
 | 
|---|
 | 130 | #endif
 | 
|---|
 | 131 | #endif
 | 
|---|
 | 132 | 
 | 
|---|
 | 133 | #ifndef UT_HOSTSIZE
 | 
|---|
 | 134 | #ifndef __UT_HOSTSIZE
 | 
|---|
 | 135 | #define UT_HOSTSIZE            16
 | 
|---|
 | 136 | #else
 | 
|---|
 | 137 | #define UT_HOSTSIZE __UT_HOSTSIZE
 | 
|---|
 | 138 | #endif
 | 
|---|
 | 139 | #endif
 | 
|---|
 | 140 | 
 | 
|---|
 | 141 | #ifdef HAVE_UTMPX_H
 | 
|---|
 | 142 | 
 | 
|---|
 | 143 | #ifndef _PATH_UTMP
 | 
|---|
 | 144 | #ifdef   UTMPX_FILE
 | 
|---|
 | 145 | #define _PATH_UTMP   UTMPX_FILE
 | 
|---|
 | 146 | #else  
 | 
|---|
 | 147 | #error  You must define UTMPX_FILE in the file config.h 
 | 
|---|
 | 148 | #endif
 | 
|---|
 | 149 | #endif
 | 
|---|
 | 150 | #ifndef _PATH_WTMP
 | 
|---|
 | 151 | #ifdef   WTMPX_FILE
 | 
|---|
 | 152 | #define _PATH_WTMP   WTMPX_FILE
 | 
|---|
 | 153 | #else
 | 
|---|
 | 154 | #error  You must define WTMPX_FILE in the file config.h
 | 
|---|
 | 155 | #endif
 | 
|---|
 | 156 | #endif
 | 
|---|
 | 157 | 
 | 
|---|
 | 158 | #else
 | 
|---|
 | 159 | 
 | 
|---|
 | 160 | #ifndef _PATH_UTMP
 | 
|---|
 | 161 | #ifdef   UTMP_FILE
 | 
|---|
 | 162 | #define _PATH_UTMP   UTMP_FILE
 | 
|---|
 | 163 | #else  
 | 
|---|
 | 164 | #error  You must define UTMP_FILE in the file config.h 
 | 
|---|
 | 165 | #endif
 | 
|---|
 | 166 | #endif
 | 
|---|
 | 167 | #ifndef _PATH_WTMP
 | 
|---|
 | 168 | #ifdef   WTMP_FILE
 | 
|---|
 | 169 | #define _PATH_WTMP   WTMP_FILE
 | 
|---|
 | 170 | #else
 | 
|---|
 | 171 | #error  You must define WTMP_FILE in the file config.h
 | 
|---|
 | 172 | #endif
 | 
|---|
 | 173 | #endif
 | 
|---|
 | 174 | 
 | 
|---|
 | 175 | #endif
 | 
|---|
 | 176 | 
 | 
|---|
 | 177 | typedef struct log_user {
 | 
|---|
 | 178 |   char                ut_tty[UT_LINESIZE+1];    
 | 
|---|
 | 179 |   char                name[UT_NAMESIZE+1];
 | 
|---|
 | 180 |   char                ut_host[UT_HOSTSIZE+1];
 | 
|---|
 | 181 |   char                ut_ship[16]; /* IP address */
 | 
|---|
 | 182 |   time_t              time;
 | 
|---|
 | 183 |   struct log_user   * next;
 | 
|---|
 | 184 | } blah_utmp;
 | 
|---|
 | 185 | 
 | 
|---|
 | 186 | #ifdef HAVE_UTTYPE
 | 
|---|
 | 187 | static char   terminated_line[UT_HOSTSIZE]; 
 | 
|---|
 | 188 | #endif
 | 
|---|
 | 189 | 
 | 
|---|
| [259] | 190 | static char * mode_path[] = { _PATH_WTMP, _PATH_WTMP, _PATH_UTMP };
 | 
|---|
 | 191 | 
 | 
|---|
| [1] | 192 | static struct SH_UTMP_S save_utmp;
 | 
|---|
 | 193 | 
 | 
|---|
 | 194 | static void sh_utmp_logout_morechecks(struct log_user   * user);
 | 
|---|
 | 195 | static void sh_utmp_login_morechecks(struct SH_UTMP_S * ut);
 | 
|---|
 | 196 | static void sh_utmp_addlogin (struct SH_UTMP_S * ut);
 | 
|---|
 | 197 | static void sh_utmp_check_internal(int mode);
 | 
|---|
 | 198 | 
 | 
|---|
 | 199 | static int    ShUtmpLoginSolo    = SH_ERR_INFO;
 | 
|---|
 | 200 | static int    ShUtmpLoginMulti   = SH_ERR_WARN;
 | 
|---|
 | 201 | static int    ShUtmpLogout       = SH_ERR_INFO;
 | 
|---|
 | 202 | static int    ShUtmpActive       = S_TRUE;
 | 
|---|
 | 203 | static time_t ShUtmpInterval     = 300;
 | 
|---|
 | 204 | 
 | 
|---|
 | 205 | sh_rconf sh_utmp_table[] = {
 | 
|---|
 | 206 |   {
 | 
|---|
 | 207 |     N_("severityloginmulti"),
 | 
|---|
 | 208 |     sh_utmp_set_login_multi
 | 
|---|
 | 209 |   },
 | 
|---|
 | 210 |   {
 | 
|---|
 | 211 |     N_("severitylogin"),
 | 
|---|
 | 212 |     sh_utmp_set_login_solo
 | 
|---|
 | 213 |   },
 | 
|---|
 | 214 |   {
 | 
|---|
 | 215 |     N_("severitylogout"),
 | 
|---|
 | 216 |     sh_utmp_set_logout_good
 | 
|---|
 | 217 |   },
 | 
|---|
 | 218 |   {
 | 
|---|
 | 219 |     N_("logincheckactive"),
 | 
|---|
 | 220 |     sh_utmp_set_login_activate
 | 
|---|
 | 221 |   },
 | 
|---|
 | 222 |   {
 | 
|---|
 | 223 |     N_("logincheckinterval"),
 | 
|---|
 | 224 |     sh_utmp_set_login_timer
 | 
|---|
 | 225 |   },
 | 
|---|
 | 226 |   {
 | 
|---|
 | 227 |     NULL,
 | 
|---|
 | 228 |     NULL
 | 
|---|
 | 229 |   },
 | 
|---|
 | 230 | };
 | 
|---|
 | 231 | 
 | 
|---|
| [149] | 232 | static void set_defaults(void)
 | 
|---|
| [1] | 233 | {
 | 
|---|
| [149] | 234 |   ShUtmpLoginSolo    = SH_ERR_INFO;
 | 
|---|
 | 235 |   ShUtmpLoginMulti   = SH_ERR_WARN;
 | 
|---|
 | 236 |   ShUtmpLogout       = SH_ERR_INFO;
 | 
|---|
 | 237 |   ShUtmpActive       = S_TRUE;
 | 
|---|
 | 238 |   ShUtmpInterval     = 300;
 | 
|---|
 | 239 |   return;
 | 
|---|
| [1] | 240 | }
 | 
|---|
 | 241 | 
 | 
|---|
 | 242 | 
 | 
|---|
 | 243 | #if defined (HAVE_SETUTENT) && defined (USE_SETUTENT)
 | 
|---|
 | 244 | 
 | 
|---|
 | 245 | #ifdef HAVE_UTMPX_H
 | 
|---|
 | 246 | 
 | 
|---|
 | 247 | #define sh_utmp_utmpname     utmpxname
 | 
|---|
 | 248 | #define sh_utmp_setutent     setutxent
 | 
|---|
 | 249 | #define sh_utmp_endutent     endutxent
 | 
|---|
 | 250 | #define sh_utmp_getutent     getutxent
 | 
|---|
 | 251 | #define sh_utmp_getutid      getutxid
 | 
|---|
 | 252 | #define sh_utmp_getutline    getutxline
 | 
|---|
 | 253 | 
 | 
|---|
 | 254 | #else
 | 
|---|
 | 255 | 
 | 
|---|
 | 256 | #define sh_utmp_utmpname     utmpname
 | 
|---|
 | 257 | #define sh_utmp_setutent     setutent
 | 
|---|
 | 258 | #define sh_utmp_endutent     endutent
 | 
|---|
 | 259 | #define sh_utmp_getutent     getutent
 | 
|---|
 | 260 | #define sh_utmp_getutid      getutid
 | 
|---|
 | 261 | #define sh_utmp_getutline    getutline
 | 
|---|
 | 262 | 
 | 
|---|
 | 263 | #endif
 | 
|---|
 | 264 | 
 | 
|---|
 | 265 | #else
 | 
|---|
 | 266 | 
 | 
|---|
 | 267 | /* BSD lacks getutent() etc.
 | 
|---|
 | 268 |  * utmpname(), setutent(), and endutent() return void,
 | 
|---|
 | 269 |  * so we do not perform much error handling.
 | 
|---|
 | 270 |  * Errors must be recognized by getutent() returning NULL.
 | 
|---|
 | 271 |  * Apparently, the application cannot check whether wtmp is empty,
 | 
|---|
 | 272 |  * or whether there was an fopen() error.
 | 
|---|
 | 273 |  */
 | 
|---|
 | 274 | 
 | 
|---|
 | 275 | static FILE * sh_utmpfile = NULL;
 | 
|---|
 | 276 | static char   sh_utmppath[80] = _PATH_UTMP;
 | 
|---|
 | 277 | 
 | 
|---|
 | 278 | /* sh_utmp_feed_forward is for optimizing
 | 
|---|
 | 279 |  * (fseek instead of getutent loop)
 | 
|---|
 | 280 |  */
 | 
|---|
 | 281 | static long   sh_utmp_feed_forward = 0;
 | 
|---|
 | 282 | 
 | 
|---|
 | 283 | static void sh_utmp_utmpname(const char * str)
 | 
|---|
 | 284 | {
 | 
|---|
 | 285 |   SL_ENTER(_("sh_utmp_utmpname"));
 | 
|---|
 | 286 |   if (sh_utmpfile != NULL)
 | 
|---|
 | 287 |     {
 | 
|---|
| [252] | 288 |       (void) sl_fclose (FIL__, __LINE__, sh_utmpfile);
 | 
|---|
| [1] | 289 |       sh_utmpfile = NULL;
 | 
|---|
 | 290 |     }
 | 
|---|
 | 291 | 
 | 
|---|
 | 292 |   (void) sl_strlcpy (sh_utmppath, str, 80);
 | 
|---|
 | 293 |   SL_RET0(_("sh_utmp_utmpname"));
 | 
|---|
 | 294 | }
 | 
|---|
 | 295 | 
 | 
|---|
 | 296 | static void sh_utmp_setutent(void)
 | 
|---|
 | 297 | {
 | 
|---|
 | 298 |   int error;
 | 
|---|
 | 299 |   int fd;
 | 
|---|
 | 300 | 
 | 
|---|
 | 301 |   SL_ENTER(_("sh_utmp_setutent"));
 | 
|---|
 | 302 | 
 | 
|---|
 | 303 |   ASSERT((sh_utmppath != NULL), _("sh_utmppath != NULL"));
 | 
|---|
 | 304 | 
 | 
|---|
 | 305 |   if (sh_utmppath == NULL)
 | 
|---|
 | 306 |     SL_RET0(_("sh_utmp_setutent"));
 | 
|---|
 | 307 | 
 | 
|---|
 | 308 |   if (sh_utmpfile == NULL) 
 | 
|---|
 | 309 |     {
 | 
|---|
| [143] | 310 |       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 311 |       fd = (int) aud_open (FIL__, __LINE__, SL_NOPRIV, 
 | 
|---|
 | 312 |                            sh_utmppath, O_RDONLY, 0);
 | 
|---|
| [143] | 313 |       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 314 |       if (fd >= 0)
 | 
|---|
 | 315 |         {
 | 
|---|
 | 316 |           sh_utmpfile = fdopen(fd, "r");
 | 
|---|
 | 317 |         }
 | 
|---|
 | 318 | 
 | 
|---|
 | 319 |       /* -- If (sh_utmpfile == NULL) then either the open() or the fdopen()
 | 
|---|
 | 320 |        *    has failed.
 | 
|---|
 | 321 |        */
 | 
|---|
 | 322 |       if (sh_utmpfile == NULL) 
 | 
|---|
 | 323 |         {
 | 
|---|
 | 324 |           error = errno;
 | 
|---|
| [143] | 325 |           SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 326 |           sh_error_handle ((-1), FIL__, __LINE__, error, MSG_E_ACCESS,
 | 
|---|
 | 327 |                            (long) sh.real.uid, sh_utmppath);
 | 
|---|
| [143] | 328 |           SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 329 |           SL_RET0(_("sh_utmp_setutent"));
 | 
|---|
 | 330 |         }
 | 
|---|
 | 331 |     }
 | 
|---|
 | 332 |   (void) fseek (sh_utmpfile, 0L, SEEK_SET);
 | 
|---|
 | 333 |   if (-1 == fseek (sh_utmpfile, sh_utmp_feed_forward, SEEK_CUR))
 | 
|---|
 | 334 |     {
 | 
|---|
 | 335 |       sh_utmp_feed_forward = 0; /* modified Apr 4, 2004 */
 | 
|---|
 | 336 |       (void) fseek (sh_utmpfile, 0L, SEEK_SET);
 | 
|---|
 | 337 |     }
 | 
|---|
 | 338 |   clearerr (sh_utmpfile);
 | 
|---|
 | 339 |   SL_RET0(_("sh_utmp_setutent"));
 | 
|---|
 | 340 | }
 | 
|---|
 | 341 | 
 | 
|---|
 | 342 | static void sh_utmp_endutent(void)
 | 
|---|
 | 343 | {
 | 
|---|
 | 344 |   SL_ENTER(_("sh_utmp_endutent"));
 | 
|---|
| [30] | 345 |   if (NULL != sh_utmpfile)
 | 
|---|
| [252] | 346 |     (void) sl_fclose(FIL__, __LINE__, sh_utmpfile);
 | 
|---|
| [1] | 347 |   sh_utmpfile = NULL;
 | 
|---|
 | 348 |   SL_RET0(_("sh_utmp_endutent"));
 | 
|---|
 | 349 | }
 | 
|---|
 | 350 | 
 | 
|---|
 | 351 | static struct SH_UTMP_S * sh_utmp_getutent(void)
 | 
|---|
 | 352 | {
 | 
|---|
 | 353 |   size_t in;
 | 
|---|
 | 354 |   static struct SH_UTMP_S out;
 | 
|---|
 | 355 | 
 | 
|---|
 | 356 |   SL_ENTER(_("sh_utmp_getutent"));
 | 
|---|
 | 357 | 
 | 
|---|
 | 358 |   ASSERT_RET((sh_utmpfile != NULL), _("sh_utmpfile != NULL"), (NULL))
 | 
|---|
 | 359 | 
 | 
|---|
 | 360 |   in = fread (&out, sizeof(struct SH_UTMP_S), 1, sh_utmpfile);
 | 
|---|
 | 361 | 
 | 
|---|
 | 362 |   if (in != 1) 
 | 
|---|
 | 363 |     {
 | 
|---|
 | 364 |       if (ferror (sh_utmpfile) != 0) 
 | 
|---|
 | 365 |         {
 | 
|---|
 | 366 |           clearerr (sh_utmpfile);
 | 
|---|
 | 367 |           SL_RETURN(NULL, _("sh_utmp_getutent"));
 | 
|---|
 | 368 |         } 
 | 
|---|
 | 369 |       else 
 | 
|---|
 | 370 |         {
 | 
|---|
 | 371 |           SL_RETURN(NULL, _("sh_utmp_getutent"));
 | 
|---|
 | 372 |         }
 | 
|---|
 | 373 |     }
 | 
|---|
 | 374 |   SL_RETURN(&out, _("sh_utmp_getutent"));
 | 
|---|
 | 375 | }
 | 
|---|
 | 376 | 
 | 
|---|
 | 377 | #ifdef USE_UNUSED
 | 
|---|
 | 378 | 
 | 
|---|
 | 379 | static struct SH_UTMP_S * sh_utmp_getutline(struct SH_UTMP_S * ut)
 | 
|---|
 | 380 | {
 | 
|---|
 | 381 |   struct SH_UTMP_S * out;
 | 
|---|
 | 382 |  
 | 
|---|
 | 383 |   while (1) {
 | 
|---|
 | 384 |       if ((out = sh_utmp_getutent()) == NULL) {
 | 
|---|
 | 385 |         return NULL;
 | 
|---|
 | 386 |       }
 | 
|---|
 | 387 | #ifdef HAVE_UTTYPE  
 | 
|---|
 | 388 |       if (out->ut_type == USER_PROCESS || out->ut_type == LOGIN_PROCESS)
 | 
|---|
 | 389 |         if (sl_strcmp(ut->ut_line, out->ut_line) == 0) 
 | 
|---|
 | 390 |           return out;
 | 
|---|
 | 391 | #else
 | 
|---|
 | 392 |       if ( 0 != sl_strncmp (out->ut_name, "reboot",   6) &&
 | 
|---|
 | 393 |            0 != sl_strncmp (out->ut_name, "shutdown", 8) &&
 | 
|---|
 | 394 |            0 != sl_strncmp (out->ut_name, "date",     4) )
 | 
|---|
 | 395 |         return out;
 | 
|---|
 | 396 | #endif
 | 
|---|
 | 397 |   }
 | 
|---|
 | 398 |   return NULL;
 | 
|---|
 | 399 | }
 | 
|---|
 | 400 | 
 | 
|---|
 | 401 | static struct SH_UTMP_S * sh_utmp_getutid(struct SH_UTMP_S * ut)
 | 
|---|
 | 402 | {
 | 
|---|
 | 403 | #ifdef HAVE_UTTYPE  
 | 
|---|
 | 404 |   struct SH_UTMP_S * out;
 | 
|---|
 | 405 | 
 | 
|---|
 | 406 |   if (ut->ut_type == RUN_LVL  || ut->ut_type == BOOT_TIME ||
 | 
|---|
 | 407 |       ut->ut_type == NEW_TIME || ut->ut_type == OLD_TIME) 
 | 
|---|
 | 408 |     {
 | 
|---|
 | 409 |       while (1) {
 | 
|---|
 | 410 |         if ((out = sh_utmp_getutent()) == NULL) {
 | 
|---|
 | 411 |           return NULL;
 | 
|---|
 | 412 |         }
 | 
|---|
 | 413 |         if (out->ut_type == ut->ut_type) 
 | 
|---|
 | 414 |           return out;
 | 
|---|
 | 415 |       }
 | 
|---|
 | 416 |     } 
 | 
|---|
 | 417 |   else if (ut->ut_type == INIT_PROCESS || ut->ut_type == LOGIN_PROCESS ||
 | 
|---|
 | 418 |            ut->ut_type == USER_PROCESS || ut->ut_type == DEAD_PROCESS ) 
 | 
|---|
 | 419 |     {
 | 
|---|
 | 420 |       while (1) {
 | 
|---|
 | 421 |         if ((out = sh_utmp_getutent()) == NULL) {
 | 
|---|
 | 422 |           return NULL;
 | 
|---|
 | 423 |         }
 | 
|---|
 | 424 |         if (sl_strcmp(ut->ut_id, out->ut_id) == 0) 
 | 
|---|
 | 425 |           return out;
 | 
|---|
 | 426 |       }
 | 
|---|
 | 427 |     }
 | 
|---|
 | 428 | #endif
 | 
|---|
 | 429 |   return NULL;
 | 
|---|
 | 430 | }
 | 
|---|
 | 431 | /* #ifdef USE_UNUSED */
 | 
|---|
 | 432 | #endif
 | 
|---|
 | 433 | 
 | 
|---|
 | 434 | /* #ifdef HAVE_SETUTENT */
 | 
|---|
 | 435 | #endif
 | 
|---|
 | 436 | 
 | 
|---|
 | 437 | #ifdef HAVE_UTADDR
 | 
|---|
 | 438 | #ifdef HAVE_INET_ATON
 | 
|---|
 | 439 | static char * my_inet_ntoa(struct in_addr in)
 | 
|---|
 | 440 | {
 | 
|---|
 | 441 |   return /*@-unrecog@*/inet_ntoa(in)/*@+unrecog@*/;
 | 
|---|
 | 442 | }
 | 
|---|
 | 443 | #else
 | 
|---|
 | 444 | static char * my_inet_ntoa(struct in_addr in)
 | 
|---|
 | 445 | {
 | 
|---|
 | 446 |   unsigned char a, b, c, d;
 | 
|---|
 | 447 |   static char   foo[16];
 | 
|---|
 | 448 |   char          bar[4];
 | 
|---|
 | 449 |   memcpy (bar, &(in.s_addr), 4); /* memory alignment (?) */
 | 
|---|
 | 450 |   memcpy (&a, &bar[0], 1);
 | 
|---|
 | 451 |   memcpy (&b, &bar[1], 1);
 | 
|---|
 | 452 |   memcpy (&c, &bar[2], 1);
 | 
|---|
 | 453 |   memcpy (&d, &bar[3], 1);
 | 
|---|
| [34] | 454 |   sprintf(foo, _("%d.%d.%d.%d"),                        /* known to fit  */
 | 
|---|
| [1] | 455 |           (int) a, (int) b, (int) c, (int) d);
 | 
|---|
 | 456 |   return foo;
 | 
|---|
 | 457 | }
 | 
|---|
 | 458 | #endif
 | 
|---|
 | 459 | /* #ifdef HAVE_UTADDR */
 | 
|---|
 | 460 | #endif
 | 
|---|
 | 461 | 
 | 
|---|
 | 462 | #if defined(__linux__) && !defined(ut_addr)
 | 
|---|
 | 463 | #define ut_addr         ut_addr_v6[0]
 | 
|---|
 | 464 | #endif
 | 
|---|
 | 465 | 
 | 
|---|
 | 466 | 
 | 
|---|
 | 467 | static struct log_user   * userlist   = NULL;
 | 
|---|
 | 468 | static time_t  lastcheck;
 | 
|---|
| [142] | 469 | static int     init_done = 0;
 | 
|---|
| [1] | 470 | 
 | 
|---|
 | 471 | /*************
 | 
|---|
 | 472 |  *
 | 
|---|
 | 473 |  * module init
 | 
|---|
 | 474 |  *
 | 
|---|
 | 475 |  *************/
 | 
|---|
| [142] | 476 | 
 | 
|---|
| [170] | 477 | static int sh_utmp_init_internal (void)
 | 
|---|
| [1] | 478 | {
 | 
|---|
 | 479 | 
 | 
|---|
 | 480 |   SL_ENTER(_("sh_utmp_init"));
 | 
|---|
 | 481 |   if (ShUtmpActive == BAD)
 | 
|---|
 | 482 |     SL_RETURN( (-1), _("sh_utmp_init"));
 | 
|---|
 | 483 | 
 | 
|---|
 | 484 |   /* do not re-initialize after a re-configuration
 | 
|---|
 | 485 |    */
 | 
|---|
| [142] | 486 |   if (init_done == 1) {
 | 
|---|
| [1] | 487 |     SL_RETURN( (0), _("sh_utmp_init"));
 | 
|---|
 | 488 |   }
 | 
|---|
 | 489 |   lastcheck  = time (NULL);
 | 
|---|
 | 490 |   userlist   = NULL;
 | 
|---|
 | 491 |   memset (&save_utmp, 0, sizeof(struct SH_UTMP_S));
 | 
|---|
 | 492 |   sh_utmp_check_internal (2); /* current logins */
 | 
|---|
 | 493 |   sh_utmp_check_internal (0);
 | 
|---|
| [142] | 494 |   init_done = 1;
 | 
|---|
| [1] | 495 |   SL_RETURN( (0), _("sh_utmp_init"));
 | 
|---|
 | 496 | }
 | 
|---|
 | 497 | 
 | 
|---|
| [142] | 498 | int sh_utmp_init (struct mod_type * arg)
 | 
|---|
 | 499 | {
 | 
|---|
 | 500 |   if (ShUtmpActive == BAD)
 | 
|---|
 | 501 |     return SH_MOD_FAILED;
 | 
|---|
 | 502 | #ifdef HAVE_PTHREAD
 | 
|---|
| [144] | 503 |   if (arg != NULL && arg->initval < 0 && 
 | 
|---|
 | 504 |       (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
 | 
|---|
| [142] | 505 |     {
 | 
|---|
 | 506 |       if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
 | 
|---|
 | 507 |         return SH_MOD_THREAD;
 | 
|---|
 | 508 |       else
 | 
|---|
 | 509 |         return SH_MOD_FAILED;
 | 
|---|
 | 510 |     }
 | 
|---|
 | 511 | #endif
 | 
|---|
 | 512 |   return sh_utmp_init_internal();
 | 
|---|
 | 513 | }
 | 
|---|
 | 514 | 
 | 
|---|
| [1] | 515 | /*************
 | 
|---|
 | 516 |  *
 | 
|---|
 | 517 |  * module cleanup
 | 
|---|
 | 518 |  *
 | 
|---|
 | 519 |  *************/
 | 
|---|
 | 520 | #ifdef HAVE_UTTYPE
 | 
|---|
| [170] | 521 | static int sh_utmp_login_clean(void);
 | 
|---|
| [1] | 522 | #endif
 | 
|---|
 | 523 | 
 | 
|---|
| [259] | 524 | #if defined(HAVE_PTHREAD)
 | 
|---|
 | 525 | static sh_watches inotify_watch;
 | 
|---|
 | 526 | #endif
 | 
|---|
 | 527 | 
 | 
|---|
| [1] | 528 | int sh_utmp_end ()
 | 
|---|
 | 529 | {
 | 
|---|
 | 530 |   struct log_user * user    = userlist;
 | 
|---|
 | 531 |   struct log_user * userold;
 | 
|---|
 | 532 | 
 | 
|---|
 | 533 |   SL_ENTER(_("sh_utmp_end"));
 | 
|---|
 | 534 |   while (user)
 | 
|---|
 | 535 |     {
 | 
|---|
 | 536 |       userold = user;
 | 
|---|
 | 537 |       user    = user->next;
 | 
|---|
 | 538 |       SH_FREE(userold);
 | 
|---|
 | 539 |     }
 | 
|---|
 | 540 |   userlist = NULL;
 | 
|---|
 | 541 | #ifdef HAVE_UTTYPE
 | 
|---|
 | 542 |   (void) sh_utmp_login_clean();
 | 
|---|
 | 543 | #endif
 | 
|---|
| [142] | 544 |   /* Reset the flag, such that the module
 | 
|---|
 | 545 |    * can be re-enabled.
 | 
|---|
 | 546 |    */
 | 
|---|
| [149] | 547 |   set_defaults();
 | 
|---|
| [142] | 548 |   init_done          = 0;
 | 
|---|
| [259] | 549 | 
 | 
|---|
 | 550 |   sh_inotify_remove(&inotify_watch);
 | 
|---|
 | 551 | 
 | 
|---|
| [1] | 552 |   SL_RETURN( (0), _("sh_utmp_end"));
 | 
|---|
 | 553 | }
 | 
|---|
 | 554 | 
 | 
|---|
| [259] | 555 | 
 | 
|---|
| [149] | 556 | int sh_utmp_reconf()
 | 
|---|
 | 557 | {
 | 
|---|
 | 558 |   set_defaults();
 | 
|---|
| [259] | 559 |   sh_inotify_remove(&inotify_watch);
 | 
|---|
| [149] | 560 |   return 0;
 | 
|---|
 | 561 | }
 | 
|---|
| [1] | 562 | 
 | 
|---|
| [149] | 563 | 
 | 
|---|
| [1] | 564 | /*************
 | 
|---|
 | 565 |  *
 | 
|---|
 | 566 |  * module timer
 | 
|---|
 | 567 |  *
 | 
|---|
 | 568 |  *************/
 | 
|---|
 | 569 | int sh_utmp_timer (time_t tcurrent)
 | 
|---|
 | 570 | {
 | 
|---|
| [259] | 571 | #if !defined(HAVE_PTHREAD)
 | 
|---|
 | 572 |   retry_msleep(1, 0);
 | 
|---|
 | 573 | 
 | 
|---|
| [1] | 574 |   if ((time_t) (tcurrent - lastcheck) >= ShUtmpInterval)
 | 
|---|
 | 575 |     {
 | 
|---|
 | 576 |       lastcheck  = tcurrent;
 | 
|---|
 | 577 |       return (-1);
 | 
|---|
 | 578 |     }
 | 
|---|
 | 579 |   return 0;
 | 
|---|
| [259] | 580 | #else
 | 
|---|
 | 581 |   int errnum = 0;
 | 
|---|
 | 582 |   
 | 
|---|
| [262] | 583 |   if ( (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE) &&
 | 
|---|
 | 584 |        sh.flag.checkSum != SH_CHECK_INIT )
 | 
|---|
 | 585 |     {
 | 
|---|
 | 586 |       sh_inotify_wait_for_change(mode_path[1], &inotify_watch, 
 | 
|---|
 | 587 |                                  &errnum, ShUtmpInterval);
 | 
|---|
 | 588 |     }
 | 
|---|
 | 589 |   
 | 
|---|
 | 590 |   lastcheck  = tcurrent;
 | 
|---|
| [259] | 591 | 
 | 
|---|
 | 592 |   if (SH_INOTIFY_ERROR(errnum))
 | 
|---|
 | 593 |     {
 | 
|---|
 | 594 |       char ebuf[SH_ERRBUF_SIZE];
 | 
|---|
 | 595 | 
 | 
|---|
 | 596 |       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
 | 597 |       sh_error_message(errnum, ebuf, sizeof(ebuf));
 | 
|---|
 | 598 |       sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, errnum, MSG_E_SUBGEN,
 | 
|---|
 | 599 |                        ebuf,
 | 
|---|
 | 600 |                        _("sh_utmp_timer") );
 | 
|---|
 | 601 |       SH_MUTEX_UNLOCK(mutex_thread_nolog);    
 | 
|---|
 | 602 |     }
 | 
|---|
 | 603 |   return -1;
 | 
|---|
 | 604 | #endif
 | 
|---|
| [1] | 605 | }
 | 
|---|
 | 606 | 
 | 
|---|
 | 607 | /*************
 | 
|---|
 | 608 |  *
 | 
|---|
 | 609 |  * module check
 | 
|---|
 | 610 |  *
 | 
|---|
 | 611 |  *************/
 | 
|---|
 | 612 | int sh_utmp_check ()
 | 
|---|
 | 613 | {
 | 
|---|
 | 614 |   SL_ENTER(_("sh_utmp_check"));
 | 
|---|
| [142] | 615 |   if (ShUtmpActive == BAD)
 | 
|---|
| [259] | 616 |     {
 | 
|---|
 | 617 | #if defined(HAVE_PTHREAD)
 | 
|---|
 | 618 |       sh_inotify_remove(&inotify_watch);
 | 
|---|
 | 619 | #endif
 | 
|---|
 | 620 |       SL_RETURN( (-1), _("sh_utmp_check"));
 | 
|---|
 | 621 |     }
 | 
|---|
| [143] | 622 |   SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 623 |   sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_UT_CHECK);
 | 
|---|
| [143] | 624 |   SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 625 |   sh_utmp_check_internal (1);
 | 
|---|
 | 626 | 
 | 
|---|
 | 627 |   SL_RETURN(0, _("sh_utmp_check"));
 | 
|---|
 | 628 | }
 | 
|---|
 | 629 | 
 | 
|---|
 | 630 | /*************
 | 
|---|
 | 631 |  *
 | 
|---|
 | 632 |  * module setup
 | 
|---|
 | 633 |  *
 | 
|---|
 | 634 |  *************/
 | 
|---|
 | 635 | 
 | 
|---|
| [68] | 636 | int sh_utmp_set_login_solo  (const char * c)
 | 
|---|
| [1] | 637 | {
 | 
|---|
 | 638 |   int retval;
 | 
|---|
 | 639 |   char tmp[32];
 | 
|---|
 | 640 | 
 | 
|---|
 | 641 |   SL_ENTER(_("sh_utmp_set_login_solo"));
 | 
|---|
 | 642 |   tmp[0] = '='; tmp[1] = '\0';
 | 
|---|
 | 643 |   (void) sl_strlcat (tmp, c, 32);
 | 
|---|
| [143] | 644 |   SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 645 |   retval = sh_error_set_level (tmp, &ShUtmpLoginSolo);
 | 
|---|
| [143] | 646 |   SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 647 |   SL_RETURN(retval, _("sh_utmp_set_login_solo"));
 | 
|---|
 | 648 | }
 | 
|---|
 | 649 | 
 | 
|---|
| [68] | 650 | int sh_utmp_set_login_multi (const char * c)
 | 
|---|
| [1] | 651 | {
 | 
|---|
 | 652 |   int retval;
 | 
|---|
 | 653 |   char tmp[32];
 | 
|---|
 | 654 | 
 | 
|---|
 | 655 |   SL_ENTER(_("sh_utmp_set_login_multi"));
 | 
|---|
 | 656 |   tmp[0] = '='; tmp[1] = '\0';
 | 
|---|
 | 657 |   (void) sl_strlcat (tmp, c, 32);
 | 
|---|
| [143] | 658 |   SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 659 |   retval = sh_error_set_level (tmp, &ShUtmpLoginMulti);
 | 
|---|
| [143] | 660 |   SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 661 |   SL_RETURN(retval, _("sh_utmp_set_login_multi"));
 | 
|---|
 | 662 | }
 | 
|---|
 | 663 | 
 | 
|---|
| [68] | 664 | int sh_utmp_set_logout_good (const char * c)
 | 
|---|
| [1] | 665 | {
 | 
|---|
 | 666 |   int retval;
 | 
|---|
 | 667 |   char tmp[32];
 | 
|---|
 | 668 | 
 | 
|---|
 | 669 |   SL_ENTER(_("sh_utmp_set_logout_good"));
 | 
|---|
 | 670 |   tmp[0] = '='; tmp[1] = '\0';
 | 
|---|
 | 671 |   (void) sl_strlcat (tmp, c, 32);
 | 
|---|
| [143] | 672 |   SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 673 |   retval = sh_error_set_level (tmp, &ShUtmpLogout);
 | 
|---|
| [143] | 674 |   SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 675 |   SL_RETURN(retval, _("sh_utmp_set_logout_good"));
 | 
|---|
 | 676 | }
 | 
|---|
 | 677 | 
 | 
|---|
| [68] | 678 | int sh_utmp_set_login_timer (const char * c)
 | 
|---|
| [1] | 679 | {
 | 
|---|
 | 680 |   long val;
 | 
|---|
 | 681 | 
 | 
|---|
 | 682 |   SL_ENTER(_("sh_utmp_set_login_timer"));
 | 
|---|
 | 683 |   val = strtol (c, (char **)NULL, 10);
 | 
|---|
 | 684 |   if (val <= 0)
 | 
|---|
 | 685 |     {
 | 
|---|
| [143] | 686 |       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 687 |       sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
 | 
|---|
 | 688 |                        _("utmp timer"), c);
 | 
|---|
| [143] | 689 |       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [170] | 690 |       SL_RETURN((-1), _("sh_utmp_set_login_timer"));
 | 
|---|
| [1] | 691 |     }
 | 
|---|
 | 692 | 
 | 
|---|
 | 693 |   ShUtmpInterval = (time_t) val;
 | 
|---|
 | 694 |   SL_RETURN(0, _("sh_utmp_set_login_timer"));
 | 
|---|
 | 695 | }
 | 
|---|
 | 696 | 
 | 
|---|
| [68] | 697 | int sh_utmp_set_login_activate (const char * c)
 | 
|---|
| [1] | 698 | {
 | 
|---|
 | 699 |   int i;
 | 
|---|
 | 700 |   SL_ENTER(_("sh_utmp_set_login_activate"));
 | 
|---|
 | 701 |   i = sh_util_flagval(c, &ShUtmpActive);
 | 
|---|
 | 702 |   SL_RETURN(i, _("sh_utmp_set_login_activate"));
 | 
|---|
 | 703 | }
 | 
|---|
 | 704 | 
 | 
|---|
 | 705 | #ifdef HAVE_UTTYPE
 | 
|---|
 | 706 | struct login_ct {
 | 
|---|
 | 707 |   char name[UT_NAMESIZE+1];
 | 
|---|
 | 708 |   int  nlogin;
 | 
|---|
 | 709 |   struct login_ct * next;
 | 
|---|
 | 710 | };
 | 
|---|
 | 711 | 
 | 
|---|
 | 712 | static struct login_ct * login_ct_list = NULL;
 | 
|---|
 | 713 | 
 | 
|---|
| [170] | 714 | static int sh_utmp_login_clean(void)
 | 
|---|
| [1] | 715 | {
 | 
|---|
 | 716 |   struct login_ct * list = login_ct_list;
 | 
|---|
 | 717 |   struct login_ct * old;
 | 
|---|
 | 718 | 
 | 
|---|
 | 719 |   login_ct_list = NULL;
 | 
|---|
 | 720 | 
 | 
|---|
 | 721 |   while (list)
 | 
|---|
 | 722 |     {
 | 
|---|
 | 723 |       old  = list;
 | 
|---|
 | 724 |       list = list->next;
 | 
|---|
 | 725 |       SH_FREE(old);
 | 
|---|
 | 726 |     }
 | 
|---|
 | 727 |   return 0;
 | 
|---|
 | 728 | }
 | 
|---|
 | 729 | 
 | 
|---|
 | 730 | /* add a username to the list of logged-in users
 | 
|---|
 | 731 |  */
 | 
|---|
 | 732 | static int sh_utmp_login_a(char * str)
 | 
|---|
 | 733 | {
 | 
|---|
 | 734 |   struct login_ct * list = login_ct_list;
 | 
|---|
 | 735 | 
 | 
|---|
 | 736 |   while (list)
 | 
|---|
 | 737 |     {
 | 
|---|
 | 738 |       if (0 == sl_strcmp(list->name, str))
 | 
|---|
 | 739 |         {
 | 
|---|
 | 740 |           ++(list->nlogin);
 | 
|---|
 | 741 |           return list->nlogin;
 | 
|---|
 | 742 |         }
 | 
|---|
 | 743 |       list = list->next;
 | 
|---|
 | 744 |     }
 | 
|---|
 | 745 |   list = SH_ALLOC(sizeof(struct login_ct));
 | 
|---|
 | 746 |   (void) sl_strlcpy(list->name, str, UT_NAMESIZE+1);
 | 
|---|
 | 747 |   list->nlogin  = 1;
 | 
|---|
 | 748 |   list->next    = login_ct_list;
 | 
|---|
 | 749 |   login_ct_list = list;
 | 
|---|
 | 750 |   return 1;
 | 
|---|
 | 751 | }
 | 
|---|
 | 752 | 
 | 
|---|
 | 753 | static int sh_utmp_login_r(char * str)
 | 
|---|
 | 754 | {
 | 
|---|
 | 755 |   struct login_ct * list = login_ct_list;
 | 
|---|
 | 756 |   struct login_ct * old  = login_ct_list;
 | 
|---|
 | 757 | 
 | 
|---|
 | 758 |   while (list)
 | 
|---|
 | 759 |     {
 | 
|---|
 | 760 |       if (0 == sl_strcmp(list->name, str))
 | 
|---|
 | 761 |         {
 | 
|---|
 | 762 |           list->nlogin -= 1;
 | 
|---|
 | 763 |           if (list->nlogin > 0)
 | 
|---|
 | 764 |             {
 | 
|---|
 | 765 |               return list->nlogin;
 | 
|---|
 | 766 |             }
 | 
|---|
 | 767 |           if (login_ct_list == list) /* modified Apr 4, 2004 */
 | 
|---|
 | 768 |             {
 | 
|---|
 | 769 |               login_ct_list = list->next;
 | 
|---|
 | 770 |               SH_FREE(list);
 | 
|---|
 | 771 |             }
 | 
|---|
 | 772 |           else
 | 
|---|
 | 773 |             {
 | 
|---|
 | 774 |               old->next = list->next;
 | 
|---|
 | 775 |               SH_FREE(list);
 | 
|---|
 | 776 |             }
 | 
|---|
 | 777 |           return 0;
 | 
|---|
 | 778 |         }
 | 
|---|
 | 779 |       old  = list;
 | 
|---|
 | 780 |       list = list->next;
 | 
|---|
 | 781 |     }
 | 
|---|
 | 782 |   return 0;
 | 
|---|
 | 783 | }
 | 
|---|
 | 784 | 
 | 
|---|
 | 785 | #endif
 | 
|---|
 | 786 | 
 | 
|---|
 | 787 | 
 | 
|---|
 | 788 | /* for each login:
 | 
|---|
 | 789 |  *    - allocate a log record
 | 
|---|
 | 790 |  *    - link device.ut_record -> log_record
 | 
|---|
 | 791 |  *    - link user.ut_record   -> log_record
 | 
|---|
 | 792 |  */
 | 
|---|
| [259] | 793 | 
 | 
|---|
| [1] | 794 | #ifdef HAVE_UTTYPE  
 | 
|---|
 | 795 | static int sh_utmp_is_virtual (char * in_utline, char * in_uthost)
 | 
|---|
 | 796 | {
 | 
|---|
| [259] | 797 | 
 | 
|---|
 | 798 |   if (in_uthost != NULL   &&
 | 
|---|
 | 799 |       in_utline != NULL   &&
 | 
|---|
| [1] | 800 |       in_uthost[0] == ':' && 
 | 
|---|
 | 801 |       in_uthost[1] == '0' && 
 | 
|---|
| [259] | 802 |       0 == sl_strncmp(in_utline, _("pts/"), 4))
 | 
|---|
| [1] | 803 |     {
 | 
|---|
| [259] | 804 |       return 1;
 | 
|---|
| [1] | 805 |     }
 | 
|---|
| [259] | 806 | 
 | 
|---|
 | 807 |   return 0;
 | 
|---|
| [1] | 808 | }
 | 
|---|
 | 809 | #endif
 | 
|---|
 | 810 | 
 | 
|---|
| [154] | 811 | /* These variables are not used anywhere. They only exist
 | 
|---|
 | 812 |  * to assign &userold, &user to them, which keeps gcc from
 | 
|---|
 | 813 |  * putting them into a register, and avoids the 'clobbered
 | 
|---|
 | 814 |  * by longjmp' warning. And no, 'volatile' proved insufficient.
 | 
|---|
 | 815 |  */
 | 
|---|
| [170] | 816 | static void * sh_dummy_userold = NULL;
 | 
|---|
 | 817 | static void * sh_dummy_user    = NULL;
 | 
|---|
| [154] | 818 | 
 | 
|---|
 | 819 | 
 | 
|---|
| [1] | 820 | static void sh_utmp_addlogin (struct SH_UTMP_S * ut)
 | 
|---|
 | 821 | {
 | 
|---|
| [154] | 822 |   struct log_user   * user     = userlist;
 | 
|---|
 | 823 |   struct log_user   * userold  = userlist;
 | 
|---|
| [1] | 824 | #ifdef HAVE_UTTYPE  
 | 
|---|
 | 825 |   struct log_user   * username = userlist;
 | 
|---|
 | 826 | #endif
 | 
|---|
 | 827 | 
 | 
|---|
 | 828 |   char   ttt[TIM_MAX];
 | 
|---|
 | 829 | #ifdef HAVE_UTTYPE
 | 
|---|
| [153] | 830 |   volatile int    status;
 | 
|---|
| [1] | 831 | #endif
 | 
|---|
 | 832 | 
 | 
|---|
 | 833 |   SL_ENTER(_("sh_utmp_addlogin"));
 | 
|---|
 | 834 | 
 | 
|---|
| [154] | 835 |   /* Take the address to keep gcc from putting them into registers. 
 | 
|---|
 | 836 |    * Avoids the 'clobbered by longjmp' warning. 
 | 
|---|
 | 837 |    */
 | 
|---|
 | 838 |   sh_dummy_userold = (void*) &userold;
 | 
|---|
 | 839 |   sh_dummy_user    = (void*) &user;
 | 
|---|
 | 840 | 
 | 
|---|
| [1] | 841 |   if (ut->ut_line[0] == '\0')
 | 
|---|
 | 842 |     SL_RET0(_("sh_utmp_addlogin"));
 | 
|---|
 | 843 | 
 | 
|---|
 | 844 |   /* for some stupid reason, AIX repeats the wtmp entry for logouts
 | 
|---|
 | 845 |    * with ssh
 | 
|---|
 | 846 |    */
 | 
|---|
 | 847 |   if (memcmp (&save_utmp, ut, sizeof(struct SH_UTMP_S)) == 0)
 | 
|---|
 | 848 |     {
 | 
|---|
 | 849 |       memset(&save_utmp, (int) '\0', sizeof(struct SH_UTMP_S));
 | 
|---|
 | 850 |       SL_RET0(_("sh_utmp_addlogin"));
 | 
|---|
 | 851 |     }
 | 
|---|
 | 852 |   memcpy (&save_utmp, ut, sizeof(struct SH_UTMP_S));
 | 
|---|
 | 853 | 
 | 
|---|
 | 854 | 
 | 
|---|
 | 855 |   /* ------- find user -------- 
 | 
|---|
 | 856 |    */
 | 
|---|
 | 857 |   while (user != NULL) 
 | 
|---|
 | 858 |     {
 | 
|---|
| [154] | 859 |       if (0 == sl_strncmp((char*)(user->ut_tty), ut->ut_line, UT_LINESIZE) ) 
 | 
|---|
| [1] | 860 |         break;
 | 
|---|
 | 861 |       userold = user;
 | 
|---|
 | 862 |       user = user->next;
 | 
|---|
 | 863 |     }
 | 
|---|
 | 864 | 
 | 
|---|
 | 865 | #ifdef HAVE_UTTYPE  
 | 
|---|
 | 866 |   while (username != NULL) 
 | 
|---|
 | 867 |     {
 | 
|---|
 | 868 |       if (0 == sl_strncmp(username->name, ut->ut_name, UT_NAMESIZE) ) 
 | 
|---|
 | 869 |         break;
 | 
|---|
 | 870 |       username = username->next;
 | 
|---|
 | 871 |     }
 | 
|---|
 | 872 | #endif
 | 
|---|
 | 873 |   
 | 
|---|
 | 874 | #ifdef HAVE_UTTYPE  
 | 
|---|
 | 875 |   /* ---------- LOGIN -------------- */
 | 
|---|
 | 876 |   if (ut->ut_type == USER_PROCESS) 
 | 
|---|
 | 877 |     {
 | 
|---|
 | 878 |       if (user == NULL)
 | 
|---|
 | 879 |         {
 | 
|---|
 | 880 |           user = SH_ALLOC(sizeof(struct log_user));
 | 
|---|
 | 881 |           user->next       = userlist;
 | 
|---|
| [154] | 882 |           userlist         = (struct log_user *) user;
 | 
|---|
| [1] | 883 |         }
 | 
|---|
| [154] | 884 |       (void) sl_strlcpy((char*)(user->ut_tty),  ut->ut_line, UT_LINESIZE+1);
 | 
|---|
 | 885 |       (void) sl_strlcpy((char*)(user->name),    ut->ut_name, UT_NAMESIZE+1);
 | 
|---|
| [1] | 886 | #ifdef HAVE_UTHOST
 | 
|---|
| [154] | 887 |       (void) sl_strlcpy((char*)(user->ut_host), ut->ut_host, UT_HOSTSIZE+1);
 | 
|---|
| [1] | 888 | #else
 | 
|---|
 | 889 |       user->ut_host[0] = '\0';
 | 
|---|
 | 890 | #endif
 | 
|---|
 | 891 | #ifdef HAVE_UTADDR
 | 
|---|
 | 892 |       /*@-type@*//* ut_addr does exist !!! */
 | 
|---|
| [154] | 893 |       (void) sl_strlcpy((char*)(user->ut_ship), 
 | 
|---|
| [1] | 894 |                         my_inet_ntoa(*(struct in_addr*)&(ut->ut_addr)), 16);
 | 
|---|
 | 895 |       /*@+type@*/
 | 
|---|
 | 896 | #endif
 | 
|---|
 | 897 |       user->time = ut->ut_time;
 | 
|---|
 | 898 | 
 | 
|---|
 | 899 |       if (username == NULL                              /* not yet logged in */
 | 
|---|
 | 900 |           || 0 == sl_strncmp(ut->ut_line, _("ttyp"), 4) /* in virt. console  */
 | 
|---|
 | 901 |           || 0 == sl_strncmp(ut->ut_line, _("ttyq"), 4) /* in virt. console  */
 | 
|---|
 | 902 |           ) {
 | 
|---|
| [154] | 903 |         status = sh_utmp_login_a((char*)user->name);
 | 
|---|
| [143] | 904 |         SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [132] | 905 |         (void) sh_unix_time (user->time, ttt, TIM_MAX);
 | 
|---|
| [1] | 906 |         sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
 | 
|---|
 | 907 | #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
 | 
|---|
 | 908 |                          MSG_UT_LG1X,
 | 
|---|
 | 909 | #elif defined(HAVE_UTHOST)
 | 
|---|
 | 910 |                          MSG_UT_LG1A,
 | 
|---|
 | 911 | #else
 | 
|---|
 | 912 |                          MSG_UT_LG1B,
 | 
|---|
 | 913 | #endif
 | 
|---|
 | 914 |                          user->name,
 | 
|---|
 | 915 |                          user->ut_tty,
 | 
|---|
 | 916 | #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
 | 
|---|
 | 917 |                          user->ut_host,
 | 
|---|
 | 918 |                          user->ut_ship,
 | 
|---|
 | 919 | #elif defined(HAVE_UTHOST)
 | 
|---|
 | 920 |                          user->ut_host,
 | 
|---|
 | 921 | #endif
 | 
|---|
 | 922 |                          ttt,
 | 
|---|
 | 923 |                          status
 | 
|---|
 | 924 |                          );
 | 
|---|
| [143] | 925 |         SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 926 |       } else
 | 
|---|
| [259] | 927 |         if (0 == sh_utmp_is_virtual(ut->ut_line, (char*)user->ut_host))
 | 
|---|
| [1] | 928 |           {       
 | 
|---|
| [154] | 929 |             status = sh_utmp_login_a((char*)user->name);
 | 
|---|
| [143] | 930 |             SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [132] | 931 |             (void) sh_unix_time (user->time, ttt, TIM_MAX);
 | 
|---|
| [1] | 932 |             sh_error_handle( ShUtmpLoginMulti, FIL__, __LINE__, 0,
 | 
|---|
 | 933 | #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
 | 
|---|
 | 934 |                              MSG_UT_LG2X,
 | 
|---|
 | 935 | #elif defined(HAVE_UTHOST)
 | 
|---|
 | 936 |                              MSG_UT_LG2A,
 | 
|---|
 | 937 | #else
 | 
|---|
 | 938 |                              MSG_UT_LG2B,
 | 
|---|
 | 939 | #endif
 | 
|---|
 | 940 |                              user->name,
 | 
|---|
 | 941 |                              user->ut_tty,
 | 
|---|
 | 942 | #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
 | 
|---|
 | 943 |                              user->ut_host,
 | 
|---|
 | 944 |                              user->ut_ship,
 | 
|---|
 | 945 | #elif defined(HAVE_UTHOST)
 | 
|---|
 | 946 |                              user->ut_host,
 | 
|---|
 | 947 | #endif
 | 
|---|
 | 948 |                              ttt,
 | 
|---|
 | 949 |                              status
 | 
|---|
 | 950 |                              );
 | 
|---|
| [143] | 951 |             SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 952 |           }
 | 
|---|
 | 953 |       
 | 
|---|
 | 954 |       sh_utmp_login_morechecks(ut);
 | 
|---|
 | 955 |       SL_RET0(_("sh_utmp_addlogin"));
 | 
|---|
 | 956 |     }
 | 
|---|
 | 957 | 
 | 
|---|
 | 958 | 
 | 
|---|
 | 959 |   /* ---------  LOGOUT ---------------- */
 | 
|---|
 | 960 |   else if (ut->ut_name[0] == '\0'
 | 
|---|
 | 961 |            || ut->ut_type == DEAD_PROCESS  /* solaris does not clear ut_name */
 | 
|---|
 | 962 |            )
 | 
|---|
 | 963 |     {
 | 
|---|
 | 964 |       if (user != NULL)
 | 
|---|
 | 965 |         {
 | 
|---|
| [259] | 966 | #if defined(__linux__)
 | 
|---|
 | 967 |           if (0 == sh_utmp_is_virtual(ut->ut_line, (char*)user->ut_host)) {
 | 
|---|
 | 968 | #endif
 | 
|---|
 | 969 |             status = sh_utmp_login_r((char*)user->name);
 | 
|---|
 | 970 |             SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
 | 971 |             (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
 | 
|---|
 | 972 |             sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
 | 
|---|
| [1] | 973 | #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
 | 
|---|
| [259] | 974 |                              MSG_UT_LG3X,
 | 
|---|
| [1] | 975 | #elif defined(HAVE_UTHOST)
 | 
|---|
| [259] | 976 |                              MSG_UT_LG3A,
 | 
|---|
| [1] | 977 | #else
 | 
|---|
| [259] | 978 |                              MSG_UT_LG3B,
 | 
|---|
| [1] | 979 | #endif
 | 
|---|
| [259] | 980 |                              user->name,
 | 
|---|
 | 981 |                              user->ut_tty,
 | 
|---|
| [1] | 982 | #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
 | 
|---|
| [259] | 983 |                              user->ut_host,
 | 
|---|
 | 984 |                              user->ut_ship,
 | 
|---|
| [1] | 985 | #elif defined(HAVE_UTHOST)
 | 
|---|
| [259] | 986 |                              user->ut_host,
 | 
|---|
| [1] | 987 | #endif
 | 
|---|
| [259] | 988 |                              ttt,
 | 
|---|
 | 989 |                              status
 | 
|---|
 | 990 |                              );
 | 
|---|
 | 991 |             SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
 | 992 |             userold->next = user->next;
 | 
|---|
 | 993 |             if (user == userlist)
 | 
|---|
 | 994 |               userlist = user->next;
 | 
|---|
 | 995 |             sh_utmp_logout_morechecks((struct log_user *)user);
 | 
|---|
 | 996 |             SH_FREE((struct log_user *)user);
 | 
|---|
 | 997 |             user = NULL;
 | 
|---|
 | 998 | #if defined(__linux__)
 | 
|---|
 | 999 |           }
 | 
|---|
 | 1000 | #endif
 | 
|---|
| [1] | 1001 |         }
 | 
|---|
 | 1002 |       else
 | 
|---|
 | 1003 |         {
 | 
|---|
 | 1004 |           (void) sl_strlcpy(terminated_line, ut->ut_line, UT_HOSTSIZE);
 | 
|---|
| [143] | 1005 |           SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [132] | 1006 |           (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
 | 
|---|
| [1] | 1007 |           sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
 | 
|---|
 | 1008 |                            MSG_UT_LG3C,
 | 
|---|
 | 1009 |                            terminated_line,
 | 
|---|
 | 1010 |                            ttt, 0
 | 
|---|
 | 1011 |                            );
 | 
|---|
| [143] | 1012 |           SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 1013 |         }
 | 
|---|
 | 1014 |       SL_RET0(_("sh_utmp_addlogin"));
 | 
|---|
 | 1015 |     }
 | 
|---|
 | 1016 | 
 | 
|---|
 | 1017 |   /* default */
 | 
|---|
 | 1018 |   SL_RET0(_("sh_utmp_addlogin"));
 | 
|---|
 | 1019 | 
 | 
|---|
 | 1020 |   /* #ifdef HAVE_UTTYPE                   */
 | 
|---|
 | 1021 | #else
 | 
|---|
 | 1022 | 
 | 
|---|
 | 1023 |   if (user == NULL)   /* probably a login */
 | 
|---|
 | 1024 |     {
 | 
|---|
 | 1025 |       user = SH_ALLOC(sizeof(struct log_user));
 | 
|---|
 | 1026 |       sl_strlcpy(user->ut_tty,  ut->ut_line, UT_LINESIZE+1);
 | 
|---|
 | 1027 |       sl_strlcpy(user->name,    ut->ut_name, UT_NAMESIZE+1);
 | 
|---|
 | 1028 | #ifdef HAVE_UTHOST
 | 
|---|
 | 1029 |       sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1);
 | 
|---|
 | 1030 | #endif
 | 
|---|
 | 1031 | #ifdef HAVE_UTADDR
 | 
|---|
 | 1032 |       sl_strlcpy(user->ut_ship,my_inet_ntoa((struct in_addr)ut->ut_addr),16);
 | 
|---|
 | 1033 | #endif
 | 
|---|
 | 1034 |       user->time       = ut->ut_time;
 | 
|---|
 | 1035 |       user->next       = userlist;
 | 
|---|
 | 1036 |       userlist         = user;
 | 
|---|
 | 1037 | 
 | 
|---|
| [143] | 1038 |       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [132] | 1039 |       (void) sh_unix_time (user->time, ttt, TIM_MAX);
 | 
|---|
| [1] | 1040 |       sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
 | 
|---|
 | 1041 | #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
 | 
|---|
 | 1042 |                        MSG_UT_LG1X,
 | 
|---|
 | 1043 | #elif defined(HAVE_UTHOST)
 | 
|---|
 | 1044 |                        MSG_UT_LG1A,
 | 
|---|
 | 1045 | #else
 | 
|---|
 | 1046 |                        MSG_UT_LG1B,
 | 
|---|
 | 1047 | #endif
 | 
|---|
 | 1048 |                        user->name,
 | 
|---|
 | 1049 |                        user->ut_tty,
 | 
|---|
 | 1050 | #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
 | 
|---|
 | 1051 |                        user->ut_host,
 | 
|---|
 | 1052 |                        user->ut_ship,
 | 
|---|
 | 1053 | #elif defined(HAVE_UTHOST)
 | 
|---|
 | 1054 |                        user->ut_host,
 | 
|---|
 | 1055 | #endif
 | 
|---|
 | 1056 |                        ttt,
 | 
|---|
 | 1057 |                        1
 | 
|---|
 | 1058 |                        );
 | 
|---|
| [143] | 1059 |       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 1060 |       sh_utmp_login_morechecks(ut);
 | 
|---|
 | 1061 |     }
 | 
|---|
 | 1062 |   else  /* probably a logout */
 | 
|---|
 | 1063 |     {
 | 
|---|
| [143] | 1064 |       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [132] | 1065 |       (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
 | 
|---|
| [1] | 1066 |       sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
 | 
|---|
 | 1067 | #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
 | 
|---|
 | 1068 |                        MSG_UT_LG2X,
 | 
|---|
 | 1069 | #elif defined(HAVE_UTHOST)
 | 
|---|
 | 1070 |                        MSG_UT_LG2A,
 | 
|---|
 | 1071 | #else
 | 
|---|
 | 1072 |                        MSG_UT_LG2B,
 | 
|---|
 | 1073 | #endif
 | 
|---|
 | 1074 |                        user->name,
 | 
|---|
 | 1075 |                        user->ut_tty,
 | 
|---|
 | 1076 | #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
 | 
|---|
 | 1077 |                        user->ut_host,
 | 
|---|
 | 1078 |                        user->ut_ship,
 | 
|---|
 | 1079 | #elif defined(HAVE_UTHOST)
 | 
|---|
 | 1080 |                        user->ut_host,
 | 
|---|
 | 1081 | #endif
 | 
|---|
 | 1082 |                        ttt,
 | 
|---|
 | 1083 |                        1
 | 
|---|
 | 1084 |                        );
 | 
|---|
| [143] | 1085 |       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 1086 |       sh_utmp_logout_morechecks(user);
 | 
|---|
 | 1087 |       userold->next = user->next;
 | 
|---|
 | 1088 |       if (user == userlist)       /* inserted Apr 4, 2004 */
 | 
|---|
 | 1089 |         userlist = user->next;
 | 
|---|
 | 1090 |       SH_FREE(user);
 | 
|---|
 | 1091 |       user = NULL;
 | 
|---|
 | 1092 |     }
 | 
|---|
 | 1093 | 
 | 
|---|
 | 1094 |   SL_RET0(_("sh_utmp_addlogin"));
 | 
|---|
 | 1095 | #endif
 | 
|---|
 | 1096 | }
 | 
|---|
 | 1097 | 
 | 
|---|
 | 1098 | static time_t        lastmod  = 0;
 | 
|---|
 | 1099 | static off_t         lastsize = 0;
 | 
|---|
 | 1100 | static unsigned long lastread = 0;
 | 
|---|
 | 1101 | 
 | 
|---|
 | 1102 | static void sh_utmp_check_internal (int mode)
 | 
|---|
 | 1103 | {
 | 
|---|
 | 1104 |   struct stat   buf;
 | 
|---|
 | 1105 |   int           error;
 | 
|---|
 | 1106 |   struct SH_UTMP_S * ut;
 | 
|---|
| [170] | 1107 |   unsigned long this_read;
 | 
|---|
| [143] | 1108 |   int           val_retry;
 | 
|---|
| [1] | 1109 | 
 | 
|---|
 | 1110 |   SL_ENTER(_("sh_utmp_check_internal"));
 | 
|---|
 | 1111 | 
 | 
|---|
 | 1112 |   /* error if no access
 | 
|---|
 | 1113 |    */
 | 
|---|
| [143] | 1114 |   do {
 | 
|---|
 | 1115 |     val_retry = /*@-unrecog@*/lstat ( mode_path[mode], &buf)/*@+unrecog@*/;
 | 
|---|
 | 1116 |   } while (val_retry < 0 && errno == EINTR);
 | 
|---|
 | 1117 | 
 | 
|---|
 | 1118 |   if (0 != val_retry) 
 | 
|---|
| [1] | 1119 |     {
 | 
|---|
 | 1120 |       error = errno;
 | 
|---|
| [143] | 1121 |       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 1122 |       sh_error_handle((-1), FIL__, __LINE__, error, MSG_E_ACCESS,
 | 
|---|
 | 1123 |                       (long) sh.real.uid, mode_path[mode]);
 | 
|---|
| [143] | 1124 |       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 1125 |       SL_RET0(_("sh_utmp_check_internal"));
 | 
|---|
 | 1126 |     }
 | 
|---|
 | 1127 | 
 | 
|---|
 | 1128 |   /* modification time
 | 
|---|
 | 1129 |    */
 | 
|---|
 | 1130 |   if (mode < 2)
 | 
|---|
 | 1131 |     {
 | 
|---|
 | 1132 |       if (/*@-usedef@*/buf.st_mtime <= lastmod/*@+usedef@*/)
 | 
|---|
 | 1133 |         { 
 | 
|---|
 | 1134 |           SL_RET0(_("sh_utmp_check_internal"));
 | 
|---|
 | 1135 |         }
 | 
|---|
 | 1136 |       else
 | 
|---|
 | 1137 |         lastmod = buf.st_mtime;
 | 
|---|
 | 1138 |     }
 | 
|---|
 | 1139 | 
 | 
|---|
 | 1140 |   /* file size
 | 
|---|
 | 1141 |    */
 | 
|---|
 | 1142 |   if (/*@-usedef@*/buf.st_size < lastsize/*@+usedef@*/ && mode < 2) 
 | 
|---|
 | 1143 |     { 
 | 
|---|
| [143] | 1144 |       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 1145 |       sh_error_handle((-1), FIL__, __LINE__, 0, MSG_UT_ROT,
 | 
|---|
 | 1146 |                       mode_path[mode]);
 | 
|---|
| [143] | 1147 |       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [1] | 1148 |       lastread = 0;
 | 
|---|
 | 1149 | #ifndef USE_SETUTENT
 | 
|---|
 | 1150 |       sh_utmp_feed_forward = 0L;
 | 
|---|
 | 1151 | #endif
 | 
|---|
 | 1152 |     }
 | 
|---|
 | 1153 | 
 | 
|---|
 | 1154 |   if (mode < 2)
 | 
|---|
 | 1155 |     lastsize = buf.st_size;
 | 
|---|
 | 1156 | 
 | 
|---|
 | 1157 |   if (buf.st_size == 0) 
 | 
|---|
 | 1158 |     SL_RET0(_("sh_utmp_check_internal"));
 | 
|---|
 | 1159 | 
 | 
|---|
 | 1160 |   sh_utmp_utmpname(mode_path[mode]);
 | 
|---|
 | 1161 |   sh_utmp_setutent();
 | 
|---|
 | 1162 | 
 | 
|---|
 | 1163 |   /* 
 | 
|---|
 | 1164 |    * feed forward if initializing
 | 
|---|
 | 1165 |    * we need to do this here
 | 
|---|
 | 1166 |    */
 | 
|---|
| [170] | 1167 |   this_read = 0;
 | 
|---|
 | 1168 | 
 | 
|---|
| [1] | 1169 |   if (mode < 2)
 | 
|---|
 | 1170 |     {
 | 
|---|
 | 1171 |       while (this_read < lastread) {
 | 
|---|
 | 1172 |         ut = sh_utmp_getutent();
 | 
|---|
 | 1173 |         ++this_read;
 | 
|---|
 | 1174 |       }
 | 
|---|
 | 1175 |     }
 | 
|---|
 | 1176 | 
 | 
|---|
 | 1177 |   /* start reading
 | 
|---|
 | 1178 |    */
 | 
|---|
 | 1179 |   this_read = 0;
 | 
|---|
 | 1180 |   while (1 == 1) {
 | 
|---|
 | 1181 |     ut = sh_utmp_getutent();
 | 
|---|
 | 1182 |     if (ut == NULL) 
 | 
|---|
 | 1183 |       break;
 | 
|---|
 | 1184 |     /* modified: ut_user --> ut_name */
 | 
|---|
 | 1185 |     if (mode == 1 || (mode == 2 && ut->ut_name[0] != '\0'
 | 
|---|
 | 1186 | #ifdef HAVE_UTTYPE
 | 
|---|
 | 1187 |                       && ut->ut_type != DEAD_PROCESS
 | 
|---|
 | 1188 | #endif
 | 
|---|
 | 1189 |                       ))
 | 
|---|
 | 1190 |       sh_utmp_addlogin (ut);
 | 
|---|
 | 1191 |     ++this_read;
 | 
|---|
 | 1192 |   }
 | 
|---|
 | 1193 | 
 | 
|---|
 | 1194 |   sh_utmp_endutent();
 | 
|---|
 | 1195 | 
 | 
|---|
 | 1196 |   if (mode < 2)
 | 
|---|
 | 1197 |     {
 | 
|---|
 | 1198 |       lastread += this_read;
 | 
|---|
 | 1199 | #ifndef USE_SETUTENT
 | 
|---|
 | 1200 |       sh_utmp_feed_forward += (long) (this_read * sizeof(struct SH_UTMP_S));
 | 
|---|
 | 1201 |       lastread = 0;
 | 
|---|
 | 1202 | #endif
 | 
|---|
 | 1203 |     }
 | 
|---|
 | 1204 | 
 | 
|---|
 | 1205 |   SL_RET0(_("sh_utmp_check_internal"));
 | 
|---|
 | 1206 | }
 | 
|---|
 | 1207 | 
 | 
|---|
 | 1208 | 
 | 
|---|
 | 1209 | static void sh_utmp_login_morechecks(struct SH_UTMP_S * ut)
 | 
|---|
 | 1210 | {
 | 
|---|
 | 1211 |   if (ut)
 | 
|---|
 | 1212 |     return;
 | 
|---|
 | 1213 |   return;
 | 
|---|
 | 1214 | }
 | 
|---|
 | 1215 | 
 | 
|---|
 | 1216 | static void sh_utmp_logout_morechecks(struct log_user * user)
 | 
|---|
 | 1217 | {
 | 
|---|
 | 1218 |   if (user)
 | 
|---|
 | 1219 |     return;
 | 
|---|
 | 1220 |   return;
 | 
|---|
 | 1221 | }
 | 
|---|
 | 1222 | 
 | 
|---|
 | 1223 | #endif
 | 
|---|
 | 1224 | 
 | 
|---|
 | 1225 | 
 | 
|---|
 | 1226 | /* #ifdef SH_USE_UTMP */
 | 
|---|
 | 1227 | #endif
 | 
|---|
 | 1228 | 
 | 
|---|
 | 1229 | 
 | 
|---|
 | 1230 | 
 | 
|---|