1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
|
/*
** Warn users of impending logout, and zap them if they
** have already been warned.
*/
#include <unistd.h> /* For fork(), alarm(), and sleep() */
#include <setjmp.h>
#include <signal.h>
#include <termios.h>
#include <sys/wait.h> /* For WEXITSTATUS() define */
#include <string.h> /* For strlen(), strcpy(), etc. */
#include <errno.h>
#ifdef __hpux
# include <sys/ptyio.h>
#endif /* __hpux */
#include "idled.h"
#ifdef SYSV
# include <fcntl.h>
#endif /* SYSV */
jmp_buf env_buf;
extern void finish(),
wakeup(),
zap();
extern char *ctime();
time_t time();
extern struct linetime *errorlines;
char *strtime();
#ifndef DEBUG
# define DEBUG 0
#endif
#ifndef DEBUG
# define DEBUG 0
#endif
#if (DEBUG > 0)
# define debug(level,string) if (DEBUG > level) logfile string
#else
# define debug(level,string) /* Erase debug code, since DEBUG is off */
#endif
#define SAY_MORE TRUE
/* Just for ease of consistency to pass the "Error in Warn" message from
* child to parent with this exit code:
*/
#define OPENERROR 5
/**************************************************************************
* Warn the specified user for the particular TYPE of problem: *
* IS_IDLE being idle *
* IS_MULT having multiple logins *
* IS_LIMIT being logged in too long *
* IS_REFU being logged in at all when they are not allowed *
* IS_XLOCK having xlock locking the console for too long *
* *
* If the user has not been warned, do so now, mark them as warned, and *
* return. If they have been warned, then zap them now. *
**************************************************************************/
void warn(i, type, do_msg)
int i;
int type;
int do_msg;
{
register struct user *him;
int opened = 0, status;
FILE *termf;
time_t tempus;
#if (DEBUG > 1) || defined(DISABLE_WARNS)
do_msg = FALSE; /* No warnings when debugging */
#endif
if (type == IS_IDLE || type == IS_XLOCK)
him = &users[i];
else /* type & ( IS_MULT | IS_LIMIT | IS_REFU | IS_CIDLE) */
him = pusers[i];
/* Define BE_NICE to still give warn time, even when they won't be warned,
* which currently only applies to the do_msg = false situation of a user
* on console and not in X-Windows.
*/
#if !defined(BE_NICE)
if (!do_msg)
him->warned |= type;
#endif /* BE_NICE */
switch (fork ())
{
case SYSERROR:
logfile ("Cannot fork in warn: %s",strerror(errno));
finish ();
break;
case 0: /* Child */
break;
default: /* Parent */
if (type == IS_MULT && !(him->warned & IS_MULT))
him->warned |= IS_MULT;
if (type == IS_IDLE && !(him->warned & IS_IDLE))
him->warned |= IS_IDLE;
if (type == IS_LIMIT && !(him->warned & IS_LIMIT))
him->warned |= IS_LIMIT;
wait (&status); /* Parent waits for child to exit */
if (WEXITSTATUS(status) == OPENERROR)
{
/* It died to to "Error in Warn--Cannot open", so we
* need to add this user to the list as a bad line,
* so that it doesn't get logged again.
*/
addlinetime(him,&errorlines);
}
return; /* Then returns back to idled.c */
}
/* Set up the signal catching for alarm() */
(void) signal (SIGALRM, wakeup);
/*
* Normal zero return means we just continue.
* 1 is returned on timeout by SIGALRM, see wakeup
* free FILE without write
*/
if (setjmp (env_buf) == 1)
{
if (opened)
{
/* Prevent the close from flushing unwritten data, since that is
* probably the block that caused us to get here in the first
* place. This probably isn't very portable, but I can't find
* any other method that works (barring changing all the output
* here to use a simple file descriptor instead of a FILE *).
* Linux is the only system I have seen that doesn't have the
* _ptr and _base. Let me know if there are others, or if you
* have a system independant way to fix it!
*/
#if defined(__linux__)
termf->_IO_read_ptr = termf->_IO_read_base;
termf->_IO_write_ptr = termf->_IO_write_base;
#elif defined(BSDI) || defined(BSD_OS2)
termf->_p = (termf->_ub)._base;
#else
termf->_ptr = termf->_base;
#endif
(void) fclose (termf);
}
exit (0);
}
/* Turn on an alarm so if we get stuck writing to the terminal, then
* it will wake us up after 5 seconds.
*/
(void) alarm (5);
if (do_msg)
{
/* Ensure that the line really exists before writing to it
* (in case something is weird, as is too possible with XDM).
*/
if ((termf = fopen (him->line, "r")) == (FILE *) NULL)
do_msg = FALSE; /* Doesn't exist, no warnings, no messages */
else
fclose(termf); /* Just fine. Go ahead and do messages */
if ((termf = fopen (him->line, "w")) == (FILE *) NULL)
{
/* An error! Check to see if we have already logged it. */
if (inlinetime(him,&errorlines))
{
/* We did, so just quit. */
exit (0);
}
else
{
/* Not yet logged. Do so, and return an exit status to tell
* the main parent to add it to the list.
*/
tempus = time ((time_t *) NULL);
logfile("%19.19s: Error in warn--Cannot open %s for %s.",ctime(&tempus), him->line, him->uid);
exit (OPENERROR);
}
}
opened = 1;
}
/* start the terminal if stopped */
if (do_msg)
{
tcflow(fileno(termf), TCOON);
}
tempus = time ((time_t *) NULL);
switch (type)
{
case IS_MULT:
if (him->warned & IS_MULT)
{
zap (him, "multiple", do_msg);
break;
}
if (do_msg)
{
(void) fprintf
(
termf,
"%s%19.19s%s%s%s %d%s %s%s",
"\007\r\n\r\n",
ctime (&tempus),
"\nThis user id is logged on too many times. Please end\r\n",
"some logins to reduce your total number of logins to no\r\n",
"more than ", him->next, ". Please do so in the next",
strtime (sleeptime, !SAY_MORE),
"\r\nor you will be logged out by the system.\r\n\r\n\007"
);
}
break;
case IS_XLOCK:
/* No warns for xlock! */
zap (him, "xlock", do_msg);
break;
case IS_CIDLE:
/* We have already determined guilt here, so just kill it */
zap (him, "console-idle", do_msg);
break;
case IS_IDLE:
if (him->warned & IS_IDLE)
{
zap (him, "idle", do_msg);
break;
}
if (do_msg)
{
(void) fprintf
(
termf,
"%s%19.19s%s %d %s %s %s",
"\007\r\n\r\n",
ctime (&tempus),
"\nThis terminal has been idle",
him->idle / 60,
"minutes. If it remains idle\r\nfor",
strtime (warntime, SAY_MORE),
"it will be logged out by the system.\r\n\r\n\007"
);
}
break;
case IS_LIMIT:
if (him->warned & IS_LIMIT)
{
zap (him, "session", do_msg);
break;
}
if (do_msg)
{
(void) fprintf
(
termf,
"%s%19.19s%s %d %s %s %s",
"\007\r\n\r\n",
ctime (&tempus),
"\nThis terminal has been in use",
him->session / 60,
"minutes.\nIn",
strtime (warntime, !SAY_MORE),
"it will be logged out by the system.\r\n\r\n\007"
);
}
break;
case IS_REFU:
if (do_msg)
{
(void) fprintf
(
termf,
"%s%19.19s%s %s",
"\007\r\n\r\n",
ctime (&tempus),
"\nYour terminal session is about to be",
"terminated by the system.\r\n\r\n\007"
);
}
/* Shut off the alarm so I can sleep as long as I want. */
(void) alarm (0);
(void) sleep ((unsigned) 5);
/* Need that alarm back now. (I'd hate to lock up!) */
(void) alarm (5);
zap (him, "refused", do_msg);
break;
}
if (do_msg)
(void) fclose (termf);
opened = 0;
(void) alarm (0);
exit (0); /* child exits here */
}
/**************************************************************************
* signal handler for SIGALRM *
* This will (hopefully) only get called if we got stuck somewhere, *
* such as having the tty block on us when trying to write to it. *
* Should that happen, this will get us out--we will give up trying *
* to kill the user, but we will still be alive! *
**************************************************************************/
void wakeup()
{
(void)longjmp(env_buf, 1);
}
/**************************************************************************
* This procedure returns a string with the number of minutes/seconds *
* in it. If the number 34 is given, it will return "34 seconds". If *
* 120 is given, it will return "2 minutes". *
**************************************************************************/
char *strtime(seconds,domore)
int seconds;
int domore;
{
static char buffer[32];
char *morestr;
if (domore)
morestr = "more ";
else
morestr = "";
if ((seconds % 60) == 0)
(void) sprintf (buffer,"%d %s%s",seconds / 60,morestr,"minutes");
else
(void) sprintf (buffer,"%d %s%s",seconds,morestr,"seconds");
return buffer;
}
|