Пример #1
0
struct utmp *
pututline(struct utmp * utmp_entry)
{
  struct utmp * ut;

  /* Ignore the return value.  That way, if they've already positioned
     the file pointer where they want it, everything will work out. */
  (void) lseek(ut_fd, (off_t) -sizeof(utmp_entry), SEEK_CUR);

  if ((ut=getutid(utmp_entry))!=NULL)
    {
      lseek(ut_fd, (off_t) -sizeof(utmp_entry), SEEK_CUR);
      if (write(ut_fd, (char *) utmp_entry, sizeof(utmp_entry))
	  != sizeof(utmp_entry))
	return NULL;
    }
  else
    {
      lseek(ut_fd, (off_t) 0, SEEK_END);
      if (write(ut_fd, (char *) utmp_entry, sizeof(utmp_entry))
	  != sizeof(utmp_entry))
	return NULL;
    }

  return utmp_entry;
}
Пример #2
0
char
platform_get_runlevel()
{
	char runlevel;
	struct utmp ut, save, *next = NULL;
	struct timeval tv;
	int flag = 0, counter = 0;

	MUTEX_LOCK(utmp_lock);

	memset(&ut, 0, sizeof(struct utmp));
	memset(&save, 0, sizeof(struct utmp));
	memset(&tv, 0, sizeof(struct timeval));

	ut.ut_type = RUN_LVL;

	setutent();
	next = getutid(&ut);

	while (next != NULL) {
		if (next->ut_tv.tv_sec > tv.tv_sec) {
			memcpy(&save, next, sizeof(*next));
			flag = 1;
		} else if (next->ut_tv.tv_sec == tv.tv_sec) {
			if (next->ut_tv.tv_usec > tv.tv_usec) {
				memcpy(&save, next, sizeof(*next));
				flag = 1;
			}
		}

		counter++;
		next = getutid(&ut);
	}

	if (flag) {
		//printf("prev_runlevel=%c, runlevel=%c\n", save.ut_pid / 256, save.ut_pid % 256);
		runlevel = save.ut_pid % 256;
	} else {
		//printf("unknown\n");
		runlevel = 'u';
	}

	MUTEX_UNLOCK(utmp_lock);

	return runlevel;
}
Пример #3
0
int main()
{
	//从utmp文件中查找特定的记录
	struct utmp ut,*u;
	ut.ut_type=RUN_LVL;
	while((u = getutid(&ut)))
	printf("%d %s %s %s\n",u->ut_type,u->ut_user,u->ut_line,u->ut_host);
}
Пример #4
0
Файл: pty.c Проект: cpc26/queue
void 
deallocpty(void) 
{
#ifndef NO_ROOT
  setutent();
  myu.ut_type = DEAD_PROCESS;
  getutid(&myu);
  pututline(&myu);
  endutent();
#endif /*NO_ROOT*/
}
Пример #5
0
int
get_boottime(struct timeval *tv)
{
    struct utmp *ut, key;

    memset(&key, 0, sizeof(key));
    key.ut_type = BOOT_TIME;
    if ((ut = getutid(&key)) != NULL) {
	tv->tv_sec = ut->ut_time;
	tv->tv_usec = 0;
	endutent();
    }
    return ut != NULL;
}
Пример #6
0
struct utmp * get_next_line(char *id, char *line) {
    struct utmp request;

    if (!id && !line)
        return getutent();

    memset(&request, 0, sizeof(request));

    if (line) {
        strncpy(&request.ut_line[0], line, UT_LINESIZE);
        return getutline(&request);
    }

    request.ut_type = INIT_PROCESS;
    strncpy(&request.ut_id[0], id, 4);
    return getutid(&request);
}
Пример #7
0
bool
get_boottime(struct timespec *ts)
{
    struct utmp *ut, key;
    debug_decl(get_boottime, SUDOERS_DEBUG_UTIL)

    memset(&key, 0, sizeof(key));
    key.ut_type = BOOT_TIME;
    setutent();
    if ((ut = getutid(&key)) != NULL) {
	sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
	    "BOOT_TIME: %lld", (long long)ut->ut_time);
	ts->tv_sec = ut->ut_time;
	ts->tv_nsec = 0;
    }
    endutent();
    debug_return_bool(ut != NULL);
}
Пример #8
0
void
get_boot_time_1 (const char *filename, int newest)
{
  struct utmp ut, *utp;
  int desc;

  if (filename)
    {
      /* On some versions of IRIX, opening a nonexistent file name
	 is likely to crash in the utmp routines.  */
      desc = emacs_open (filename, O_RDONLY, 0);
      if (desc < 0)
	return;

      emacs_close (desc);

      utmpname (filename);
    }

  setutent ();

  while (1)
    {
      /* Find the next reboot record.  */
      ut.ut_type = BOOT_TIME;
      utp = getutid (&ut);
      if (! utp)
	break;
      /* Compare reboot times and use the newest one.  */
      if (utp->ut_time > boot_time)
	{
	  boot_time = utp->ut_time;
	  if (! newest)
	    break;
	}
      /* Advance on element in the file
	 so that getutid won't repeat the same one.  */
      utp = getutent ();
      if (! utp)
	break;
    }
  endutent ();
}
Пример #9
0
struct utmp *pututline (const struct utmp *utmp_entry)
{
    __UCLIBC_MUTEX_LOCK(utmplock);
    /* Ignore the return value.  That way, if they've already positioned
       the file pointer where they want it, everything will work out. */
    lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR);

    if (getutid(utmp_entry) != NULL) {
	lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR);
	if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
	    return NULL;
    } else {
	lseek(static_fd, (off_t) 0, SEEK_END);
	if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
	    return NULL;
    }

    __UCLIBC_MUTEX_UNLOCK(utmplock);
    return (struct utmp *)utmp_entry;
}
Пример #10
0
Файл: pty.c Проект: cpc26/queue
void 
mkutmp(char *name, int pty2, int uid, int gid)
{
  char *line;
  char buf[255];
  line = mtos();
  strcpy(myu.ut_user, name);
#ifdef linux
  strncpy(myu.ut_id,line+8,2);
#else
  strncpy(myu.ut_id, line+12,2);
#endif
  strcpy(buf, "/dev/tty");
  strcat(buf, myu.ut_id);
#ifdef linux
  strcpy(myu.ut_line, line+5);
#else
  strcpy(myu.ut_line, line+9);
#endif
  myu.ut_pid = getpid();
  myu.ut_type = USER_PROCESS;
  myu.ut_time = time(NULL);
#ifdef HAVE_UT_ADDR
  strcpy(myu.ut_host, "Queue process");
  myu.ut_addr = 0L;
#endif
  setutent();
  getutid(&myu);
  pututline(&myu);
  fchown(pty2, uid, gid);
  fchmod(pty2, S_IRUSR|S_IWUSR);

  if(!strcmp(buf,"/dev/tty")) {
    syslog(LOG_ERR,"queue: pty.c: mkutmp: bug: buf equals /dev/tty.");
  }
  else {
  chown(buf, uid, gid);
  chmod(buf, S_IRUSR|S_IWUSR);
  }
}
Пример #11
0
static int
check_id (const char *id)
{
  struct utmp *up;
  struct utmp ut;
  int n;

  setutent ();

  ut.ut_type = USER_PROCESS;
  strcpy (ut.ut_id, id);
  up = getutid (&ut);
  if (up == NULL)
    {
      printf ("cannot get entry for ID `%s' (%d)", id, errno);
      ++errors;
      return 1;
    }

  endutent ();

  for (n = 0; n < num_entries; n++)
    {
      if (strcmp (id, entry[n].ut_id) == 0)
	{
	  if (memcmp (up, &entry[n], sizeof (struct utmp)))
	    {
	      printf ("UTMP entry does not match");
	      ++errors;
	      return 1;
	    }

	  return 0;
	}
    }

  printf ("bogus entry for ID `%s'", id);
  ++errors;
  return 1;
}
Пример #12
0
struct utmp *pututline(struct utmp *ut) {
	struct utmp *rec;

	setutent();

	rec = getutid(ut);

	if (NULL == rec) {
		if (utmp_f_end >= MAX_ENT_COUNT) {
			errno = ENOMEM;
			return NULL;
		}

		utmp_f_pos = ++utmp_f_end;
	}

	rec = &utmp_f[--utmp_f_pos];
	++utmp_f_pos;

	return memcpy(rec, ut, sizeof(struct utmp));

}
Пример #13
0
static int
check_type (int type)
{
  struct utmp *up;
  struct utmp ut;
  int n;

  setutent ();

  ut.ut_type = type;
  up = getutid (&ut);
  if (up == NULL)
    {
      printf ("cannot get entry for type `%d' (%d)", type, errno);
      ++errors;
      return 1;
    }

  endutent ();

  for (n = 0; n < num_entries; n++)
    {
      if (type == entry[n].ut_type)
	{
	  if (memcmp (up, &entry[n], sizeof (struct utmp)))
	    {
	      printf ("UTMP entry does not match");
	      ++errors;
	      return 1;
	    }

	  return 0;
	}
    }

  printf ("bogus entry for type `%d'", type);
  ++errors;
  return 1;
}
Пример #14
0
void
get_boot_time_1 (const char *filename, bool newest)
{
    struct utmp ut, *utp;

    if (filename)
    {
        /* On some versions of IRIX, opening a nonexistent file name
        is likely to crash in the utmp routines.  */
        if (faccessat (AT_FDCWD, filename, R_OK, AT_EACCESS) != 0)
            return;

        utmpname (filename);
    }

    setutent ();

    while (1)
    {
        /* Find the next reboot record.  */
        ut.ut_type = BOOT_TIME;
        utp = getutid (&ut);
        if (! utp)
            break;
        /* Compare reboot times and use the newest one.  */
        if (utp->ut_time > boot_time)
        {
            boot_time = utp->ut_time;
            if (! newest)
                break;
        }
        /* Advance on element in the file
        so that getutid won't repeat the same one.  */
        utp = getutent ();
        if (! utp)
            break;
    }
    endutent ();
}
Пример #15
0
struct utmp *
pututline(const struct utmp * utmp_entry)
{
  struct utmp * ut;
  int xerrno=errno;

#if 0
  /* Ignore the return value.  That way, if they've already positioned
     the file pointer where they want it, everything will work out. */
  if (ut_fd!=-1)
  (void) lseek(ut_fd, (off_t) -sizeof(struct utmp), SEEK_CUR);
#endif

  if ((ut=getutid(utmp_entry))!=NULL)
      lseek(ut_fd, (off_t) -sizeof(struct utmp), SEEK_CUR);
  else if( ut_fd==-1 )
      return NULL;
  else
      lseek(ut_fd, (off_t) 0, SEEK_END);

  /*
   * At this point I could make sure the offset we're at is an exact multiple
   * of the sizeof struct utmp. Should I? Up or down?  --RdB
   */

  if (write(ut_fd, (char *) utmp_entry, sizeof(struct utmp))
      != sizeof(struct utmp))
    return NULL;

  /* I think this final lseek gets the result Nat was after ... RdB */
  lseek(ut_fd, (off_t) -sizeof(struct utmp), SEEK_CUR);

  /* Ignoring untrapped errors */
  errno=xerrno;
  return utmp_entry;
}
Пример #16
0
int
main (int argc, char **argv)
{
#if defined(USE_UTMP) && !defined(HAVE_PUTUTLINE)
	int		utmp;
#endif
#ifndef USE_UTMPX
	int		wtmp;
#endif
	time_t		current_time;
#ifdef USE_UTMP
	struct utmp	utmp_entry;
#endif
#ifdef USE_UTMPX
	struct utmpx	utmpx_entry;
#endif
	char *		line = NULL;

	program_name = argv[0];
	while (*++argv && **argv == '-') {
		switch (*++*argv) {
		case 'w':
			wtmp_file = getstring (&argv, &wflag);
			if (!strcmp (wtmp_file, "none"))
				wtmp_none = 1;
#if defined(USE_UTMPX) && defined(HAVE_UPDWTMPX)
			else
				wtmpx_file = wtmp_file;
#endif
			break;
		case 'u':
			utmp_file = getstring (&argv, &uflag);
			if (!strcmp (utmp_file, "none"))
				utmp_none = 1;
#if defined(USE_UTMPX) && defined(HAVE_UTMPXNAME)
			else
				utmpx_file = utmp_file;
#endif
			break;
#ifdef USE_LASTLOG
		case 'L':
			llog_file = getstring (&argv, &Lflag);
			if (!strcmp (llog_file, "none"))
				llog_none = 1;
			break;
#endif
		case 't':
			ttys_file = getstring (&argv, &tflag);
			break;
		case 'l':
			line = getstring (&argv, &lflag);
			break;
		case 'h':
			host_name = getstring (&argv, &hflag);
			break;
		case 's':
#if defined(USE_UTMP) && !defined(HAVE_PUTUTLINE)
			slot_number = atoi (getstring (&argv, &sflag));
#endif
			break;
		case 'x':
			xservers_file = getstring (&argv, &xflag);
			break;
		case 'a':
			aflag++;
			break;
		case 'd':
			dflag++;
			break;
		case 'V':
			printf("%s\n", PACKAGE_STRING);
			exit (0);
		default:
			fprintf (stderr, "%s: unrecognized option '%s'\n",
				 program_name, argv[0]);
			usage (1);
		}
	}
	user_name = *argv++;
	if (user_name == NULL) {
		fprintf (stderr, "%s: missing required user-name argument\n",
			 program_name);
		usage (1);
	}
	if (*argv != NULL) {
		fprintf (stderr, "%s: unrecognized argument '%s'\n",
			 program_name, argv[0]);
		usage (1);
	}
	/*
	 * complain if neither aflag nor dflag are set,
	 * or if both are set.
	 */
	if (!(aflag ^ dflag)) {
		fprintf (stderr, "%s: must specify exactly one of -a or -d\n",
			 program_name);
		usage (1);
	}
	if (xflag && !lflag) {
		fprintf (stderr, "%s: must specify -l when -x is used\n",
			 program_name);
		usage (1);
	}
	/* set up default file names */
	if (!wflag) {
		wtmp_file = WTMP_FILE;
#if defined(USE_UTMPX) && defined(HAVE_UPDWTMPX)
		wtmpx_file = WTMPX_FILE;
#endif
	}
	if (!uflag) {
		utmp_file = UTMP_FILE;
#if defined(USE_UTMPX) && defined(HAVE_UTMPXNAME)
		utmpx_file = UTMPX_FILE;
#endif
	}
#ifdef USE_LASTLOG
	if (!Lflag)
		llog_file = LLOG_FILE;
#endif
#if defined(USE_UTMP) && !defined(HAVE_PUTUTLINE)
	if (!tflag)
		ttys_file = TTYS_FILE;
	if (!sflag && !utmp_none) {
		if (xflag)
			sysnerr (slot_number = Xslot (ttys_file, xservers_file, line, host_name, aflag), "Xslot");
		else
			sysnerr (slot_number = ttyslot (), "ttyslot");
	}
#endif
	if (!lflag) {
		sysnerr ((line = ttyname (0)) != NULL, "ttyname");
		if (strncmp(line, "/dev/", 5) == 0)
			line += 5;
	}
	time (&current_time);
#ifdef USE_UTMP
	set_utmp (&utmp_entry, line, user_name, host_name, current_time, aflag);
#endif

#ifdef USE_UTMPX
	/* need to set utmpxname() before calling set_utmpx() for
	   UtmpxIdOpen to work */
# ifdef HAVE_UTMPXNAME
	if (utmpx_file != NULL) {
		utmpxname (utmpx_file);
	}
# endif
	set_utmpx (&utmpx_entry, line, user_name,
		   host_name, current_time, aflag);
#endif

	if (!utmp_none) {
#ifdef USE_UTMPX
# ifdef HAVE_UTMPXNAME
		if (utmpx_file != NULL)
# endif
		{
			setutxent ();
			(void) getutxid (&utmpx_entry);
			pututxline (&utmpx_entry);
			endutxent ();
		}
#endif
#ifdef USE_UTMP
# ifdef HAVE_PUTUTLINE
		utmpname (utmp_file);
		setutent ();
		(void) getutid (&utmp_entry);
		pututline (&utmp_entry);
		endutent ();
# else
		utmp = open (utmp_file, O_RDWR);
		if (utmp != -1) {
			syserr ((int) lseek (utmp, (long) slot_number * sizeof (struct utmp), 0), "lseek");
			sysnerr (write (utmp, (char *) &utmp_entry, sizeof (utmp_entry))
					== sizeof (utmp_entry), "write utmp entry");
			close (utmp);
		}
# endif
#endif /* USE_UTMP */
	}
	if (!wtmp_none) {
#ifdef USE_UTMPX
# ifdef HAVE_UPDWTMPX
		if (wtmpx_file != NULL) {
			updwtmpx(wtmpx_file, &utmpx_entry);
		}
# endif
#else
		wtmp = open (wtmp_file, O_WRONLY|O_APPEND);
		if (wtmp != -1) {
			sysnerr (write (wtmp, (char *) &utmp_entry, sizeof (utmp_entry))
					== sizeof (utmp_entry), "write wtmp entry");
			close (wtmp);
		}
#endif
	}
#ifdef USE_LASTLOG
	if (aflag && !llog_none) {
		int llog;
		struct passwd *pwd = getpwnam(user_name);

		sysnerr( pwd != NULL, "get user id");
		llog = open (llog_file, O_RDWR);

		if (llog != -1) {
			struct lastlog ll;

			sysnerr (lseek(llog, (long) (pwd->pw_uid*sizeof(ll)), 0)
					!= -1, "seeking lastlog entry");
			memset(&ll, 0, sizeof(ll));
			ll.ll_time = current_time;
			if (line)
			 (void) strncpy (ll.ll_line, line, sizeof (ll.ll_line));
			if (host_name)
			 (void) strncpy (ll.ll_host, host_name, sizeof (ll.ll_host));

			sysnerr (write (llog, (char *) &ll, sizeof (ll))
					== sizeof (ll), "write lastlog entry");
			close (llog);
		}
	}
#endif
	return 0;
}
Пример #17
0
/***************************************************************************
 *
 *  Account
 *
 *  update utmp/wtmp files.  
 ***************************************************************************/
void 
Account( struct display *d, char *user, char *line, pid_t pid,
#if NeedWidePrototypes
        int type,
#else
        short type,
#endif /* NeedWidePrototypes */
        waitType exitcode )
{
#if !defined(CSRG_BASED) /* we cannot do this on BSD ... */
    struct utmp utmp;		/* local struct for new entry	   	   */
    struct utmp *u;		/* pointer to entry in utmp file	   */
    int	fd;
    char	buf[32];
    char* user_str = user ? user : "******";
    char* line_str = line ? line : "NULL";
            
#ifdef __PASSWD_ETC
    struct rtmp rtmp;
    struct rtmp *r;
    int tty_slot;
    int rtmp_fd;
#endif

    if (d->utmpId == NULL) return;
    
    switch (type) {
    
    case INIT_PROCESS:	strcpy(buf, "INIT_PROCESS");	break;
    case LOGIN_PROCESS:	strcpy(buf, "LOGIN_PROCESS");	break;
    case USER_PROCESS:	strcpy(buf, "USER_PROCESS");	break;
    case DEAD_PROCESS:	strcpy(buf, "DEAD_PROCESS");	break;
    default:		strcpy(buf, "UNKNOWN");		break;
    }

    Debug("Account: id=%s, user=%s, line=%s, pid=%d, type=%s\n",
	   d->utmpId, user_str, line_str, pid, buf);

#ifdef PAM
    PamAccounting("dtlogin", d->name, d->utmpId, user, 
		        line, pid, type, exitcode);
#else
#   ifdef SUNAUTH
       solaris_accounting("dtlogin", d->name, d->utmpId, user, 
		           line, pid, type, exitcode);
#   endif
#endif

#ifdef sun
    return;
#else
    bzero(&utmp, sizeof(struct utmp));

    strncpy(utmp.ut_id, d->utmpId, sizeof(u->ut_id));
    utmp.ut_type = LOGIN_PROCESS;
    
    setutent();
    if ( (u = getutid(&utmp)) == NULL ) u = &utmp;

    /*
     *  make sure process ID's match if this is DEAD_PROCESS...
     *  don't update an already DEAD_PROCESS...
     */

    if ((type == DEAD_PROCESS && pid != 0 && u->ut_pid != pid) ||
        (type == DEAD_PROCESS && u->ut_type == DEAD_PROCESS)	) {

	endutent();
	return;
    }


    /*
     *  fill in required fields of utmp structure...
     *
     *  Note: for USER_PRCESS the "e_exit" field is overloaded to contain
     *        the method for counting this user. This is used later to
     *        determine if restricted user licenses have been exceeded.
     *	      Currently, an unlimited number of foreign displays can log in.
     */
     
    if (user) strncpy(u->ut_user, user, sizeof(u->ut_user));
    if (line) {
#ifdef _AIX
/*
      For AIX the Init process writes the exact mapped device name for console
      to the utmp file (like hft/0), if a getty on /dev/console record exists
      in the Inittab file.Hitherto, we need to have a similar logic to make
      sure for having the correct entry in the utmp file in order for the correct
      operation of the GettyRunning function. It should be noted that by having
      the correct value in the d->gettyLine field, the utmp file eventuallly
      updated by the Account function in dm.c will have the right value. And
      thus the GettyRunning function returns the appropriate value. So, it
      is important that the following logic be included here for AIX platform
      only.
      Raghu Krovvidi         07.06.93
 */

        if (!strcmp(line,"console")) {
             char *ttynm;
             int fd=0;

             fd = open("/dev/console",O_RDONLY);
             ttynm = ttyname(fd);
             ttynm += 5;
             strcpy(u->ut_line,ttynm);
             close(fd);
        }
	else
             strncpy(u->ut_line, line, sizeof(u->ut_line));
	     
#else
             strncpy(u->ut_line, line, sizeof(u->ut_line));
#endif
    }
    if (pid ) u->ut_pid = pid;
    if (type) {
	u->ut_type = type;
	if (type == DEAD_PROCESS) {
	    u->ut_exit.e_termination = waitSig(exitcode);
	    u->ut_exit.e_exit = waitCode(exitcode);
#ifndef SVR4
	    (void) memset((char *) u->ut_host, '\0', sizeof(u->ut_host));
#endif
	}

 	if (type == LOGIN_PROCESS && d->displayType.location != Local ) {
#ifndef SVR4
 	    strncpy(u->ut_host, d->name, sizeof(u->ut_host));
#endif
#ifdef __hpux
 	    u->ut_addr = 0;
#endif
 	}
 		    
	if (type == USER_PROCESS)
	    u->ut_exit.e_exit = (d->displayType.location == Local ? 1 : 0 );
    }	

    (void) time(&u->ut_time);

    /* 
     * write to utmp...  
     *
     * (Do not close utmp yet. If "u" points to the static structure, it is
     *  cleared upon close. This does not bode well for the following write
     *  to wtmp!)
     */

    pututline(u);


    /*
     *  write the same entry to wtmp...
     */

    if ((fd = open(WTMP_FILE, O_WRONLY | O_APPEND)) >= 0) {
	write(fd, u, sizeof(utmp));
	close(fd);
    }


    /*
     *  close utmp...
     */
     
    endutent();

#ifdef __PASSWD_ETC
    /* Now fill in the "rgy utmp" struct */
    if (line) strncpy(rtmp.rt_line, u->ut_line, sizeof(u->ut_line));
    bzero(rtmp.rt_host, sizeof(rtmp.rt_host));
    rtmp.rt_time = u->ut_time;
    r = &rtmp;

    /* Write entry to rtmp */
    tty_slot = ttyslot();

    if (tty_slot > 0 && (rtmp_fd = open("/etc/rtmp", O_WRONLY|O_CREAT, 0644)) >= 0) {
         lseek(rtmp_fd, (long) (tty_slot * sizeof(struct rtmp)), 0);
         write(rtmp_fd, (char *) r, sizeof(struct rtmp));
         close(rtmp_fd);
    }
#endif
#if defined(AIXV3) && !defined(_POWER)
	/* Log the lastlogin data ..    RK  09.13.93  */
	/** in AIX 4.1 this is taken care of during authentication **/
    if(type == USER_PROCESS) {
	int loginType;
	char tempTtyName[128];
	char *hostname;

	GetLoginInfo(d, &loginType, tempTtyName, &hostname);
	time(&last_login.stime);

	if(line) {
		Debug("tty_last_login is (line=%s)\n",line);
		last_login.stty = (char *)malloc(strlen(line) + 1);
		strcpy(last_login.stty,line);
	} else {
	    last_login.stty = (char *)malloc(strlen(tempTtyName) + 1);
	    strcpy(last_login.stty,tempTtyName);
	}

        last_login.shost = (char *) malloc (MAXHOSTNAMELEN);
	if (hostname == NULL) {
            gethostname (last_login.shost , MAXHOSTNAMELEN);
	} else {
	    strncpy(last_login.shost, hostname, MAXHOSTNAMELEN);
	    last_login.shost[MAXHOSTNAMELEN -1] = '\0';
	}

	Debug("logging lastlogin entry (user=%s)\n",user);
	dt_lastlogin(user,&last_login); 
	free(last_login.stty);
	free(last_login.shost);
    }
#endif

#endif /* !sun */
#endif /* !CSRG_BASED */
}
Пример #18
0
/* EXTPROTO */
void
rxvt_makeutent(rxvt_t *r, const char *pty, const char *hostname)
{
#ifdef UTEMPTER_SUPPORT
    utempter_add_record (PVTS(r)->cmd_fd, hostname);
#else	/* UTEMPTER_SUPPORT */

#ifdef HAVE_STRUCT_UTMP
    struct utmp    *ut = &(PVTS(r)->ut);
#endif
#if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP)
    struct utmpx   *utx = &(PVTS(r)->utx);
#endif
#ifdef HAVE_UTMP_PID
    int             i;
#endif
    char            ut_id[5];
    struct passwd  *pwent = getpwuid(getuid());

    if (!STRNCMP(pty, "/dev/", 5))
	pty += 5;	/* skip /dev/ prefix */

    if (!STRNCMP(pty, "pty", 3) || !STRNCMP(pty, "tty", 3)) {
	STRNCPY(ut_id, (pty + 3), sizeof(ut_id));
    }
#ifdef HAVE_UTMP_PID
    else if (sscanf(pty, "pts/%d", &i) == 1)
	sprintf(ut_id, "vt%02x", (i & 0xff));	/* sysv naming */
#endif
    else if (STRNCMP(pty, "pty", 3) && STRNCMP(pty, "tty", 3)) {
	rxvt_msg (DBG_ERROR, DBG_LOGGING, "can't parse tty name \"%s\"", pty);
	return;
    }

#ifdef HAVE_STRUCT_UTMP
    MEMSET(ut, 0, sizeof(struct utmp));
# ifdef HAVE_UTMP_PID
    setutent();
    STRNCPY(ut->ut_id, ut_id, sizeof(ut->ut_id));
    ut->ut_type = DEAD_PROCESS;
    getutid(ut);	/* position to entry in utmp file */
    STRNCPY(PVTS(r)->ut_id, ut_id, sizeof(PVTS(r)->ut_id));
# endif
#endif

#if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP)
    MEMSET(utx, 0, sizeof(struct utmpx));
    setutxent();
    STRNCPY(utx->ut_id, ut_id, sizeof(utx->ut_id));
    utx->ut_type = DEAD_PROCESS;
    getutxid(utx);	/* position to entry in utmp file */
    STRNCPY(PVTS(r)->ut_id, ut_id, sizeof(PVTS(r)->ut_id));
#endif

#ifdef HAVE_STRUCT_UTMP
    STRNCPY(ut->ut_line, pty, sizeof(ut->ut_line));
    ut->ut_time = time(NULL);
# ifdef HAVE_UTMP_PID
    STRNCPY(ut->ut_user, (pwent && pwent->pw_name) ? pwent->pw_name : "?",
        sizeof(ut->ut_user));
    STRNCPY(ut->ut_id, ut_id, sizeof(ut->ut_id));
    ut->ut_time = time(NULL);
    ut->ut_pid = PVTS(r)->cmd_pid;
#  ifdef HAVE_UTMP_HOST
    STRNCPY(ut->ut_host, hostname, sizeof(ut->ut_host));
#  endif
    ut->ut_type = USER_PROCESS;
    pututline(ut);
    endutent();		/* close the file */
    PVTS(r)->utmp_pos = 0;
# else
    STRNCPY(ut->ut_name, (pwent && pwent->pw_name) ? pwent->pw_name : "?",
        sizeof(ut->ut_name));
#  ifdef HAVE_UTMP_HOST
    STRNCPY(ut->ut_host, hostname, sizeof(ut->ut_host));
#  endif
# endif
#endif

#if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP)
    STRNCPY(utx->ut_line, pty, sizeof(utx->ut_line));
    STRNCPY(utx->ut_user, (pwent && pwent->pw_name) ? pwent->pw_name : "?",
        sizeof(utx->ut_user));
    STRNCPY(utx->ut_id, ut_id, sizeof(utx->ut_id));
# ifdef HAVE_UTMPX_SESSION
    utx->ut_session = getsid(0);
# endif
    utx->ut_tv.tv_sec = time(NULL);
    utx->ut_tv.tv_usec = 0;
    utx->ut_pid = PVTS(r)->cmd_pid;
# ifdef HAVE_UTMPX_HOST
    STRNCPY(utx->ut_host, hostname, sizeof(utx->ut_host));
# endif
    utx->ut_type = USER_PROCESS;
    pututxline(utx);
    endutxent();	/* close the file */
    PVTS(r)->utmp_pos = 0;
#endif

#if defined(HAVE_STRUCT_UTMP) && !defined(HAVE_UTMP_PID)
    {
	int             i;
# ifdef HAVE_TTYSLOT
	i = ttyslot();
	if (rxvt_write_bsd_utmp(i, ut))
	    PVTS(r)->utmp_pos = i;
# else
	FILE           *fd0;

	if (NOT_NULL(fd0 = fopen(TTYTAB_FILENAME, "r"))) {
	    char            buf[256], name[256];

	    buf[sizeof(buf) - 1] = '\0';
	    for (i = 1; NOT_NULL(fgets(buf, sizeof(buf) - 1, fd0)); ) {
		if (*buf == '#' || sscanf(buf, "%s", name) != 1)
		    continue;
		if (!STRCMP(ut->ut_line, name)) {
		    if (!rxvt_write_bsd_utmp(i, ut))
			i = 0;
		    PVTS(r)->utmp_pos = i;
		    fclose(fd0);
		    break;
		}
		i++;
	    }
	    fclose(fd0);
	}
# endif
    }
#endif

#ifdef WTMP_SUPPORT
# ifdef WTMP_ONLY_ON_LOGIN
    if (ISSET_OPTION(r, Opt_loginShell))
# endif
    {
# ifdef HAVE_STRUCT_UTMP
#  ifdef HAVE_UPDWTMP
	updwtmp(RXVT_WTMP_FILE, ut);
#  else
	rxvt_update_wtmp(RXVT_WTMP_FILE, ut);
#  endif
# endif
# if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP)
#  ifdef HAVE_UPDWTMPX
	updwtmpx(RXVT_WTMPX_FILE, utx);
#  else
	pututxline (utx);
#  endif
# endif
    }
#endif

#endif	/* UTEMPTER_SUPPORT */

#if defined(LASTLOG_SUPPORT) && defined(RXVT_LASTLOG_FILE)
    if (ISSET_OPTION(r, Opt_loginShell))
	rxvt_update_lastlog(RXVT_LASTLOG_FILE, pty, hostname);
#endif

}
Пример #19
0
/* EXTPROTO */
void
rxvt_cleanutent(rxvt_t *r)
{
#ifdef UTEMPTER_SUPPORT
    utempter_remove_record (PVTS(r)->cmd_fd);
#else	/* UTEMPTER_SUPPORT */

#ifdef HAVE_STRUCT_UTMP
    struct utmp    *ut = &(PVTS(r)->ut);
#endif
#if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP)
    struct utmpx   *tmputx, *utx = &(PVTS(r)->utx);
#endif

#ifdef HAVE_STRUCT_UTMP
# ifdef HAVE_UTMP_PID
    MEMSET(ut, 0, sizeof(struct utmp));
    setutent();
    STRNCPY(ut->ut_id, PVTS(r)->ut_id, sizeof(ut->ut_id));
    ut->ut_type = USER_PROCESS;
    {
	struct utmp    *tmput = getutid(ut);

	if (tmput)	/* position to entry in utmp file */
	    ut = tmput;
    }
    ut->ut_type = DEAD_PROCESS;
# else 
    MEMSET(ut->ut_name, 0, sizeof(ut->ut_name));
#  ifdef HAVE_UTMP_HOST
    MEMSET(ut->ut_host, 0, sizeof(ut->ut_host));
#  endif
# endif
    ut->ut_time = time(NULL);
#endif

#if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP)
    MEMSET(utx, 0, sizeof(struct utmpx));
    setutxent();
    STRNCPY(utx->ut_id, PVTS(r)->ut_id, sizeof(utx->ut_id));
    utx->ut_type = USER_PROCESS;
    if ((tmputx = getutxid(utx)))   /* position to entry in utmp file */
	utx = tmputx;
    utx->ut_type = DEAD_PROCESS;
# ifdef HAVE_UTMPX_SESSION
    utx->ut_session = getsid(0);
# endif
    utx->ut_tv.tv_sec = time(NULL);
    utx->ut_tv.tv_usec = 0;
#endif

    /*
     * Write ending wtmp entry
     */
#ifdef WTMP_SUPPORT
# ifdef WTMP_ONLY_ON_LOGIN
    if (ISSET_OPTION(r, Opt_loginShell))
# endif
    {
# ifdef HAVE_STRUCT_UTMP
#  ifdef HAVE_UPDWTMP
	updwtmp(RXVT_WTMP_FILE, ut);
#  else
	rxvt_update_wtmp(RXVT_WTMP_FILE, ut);
#  endif
# endif
# if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP)
#  ifdef HAVE_UPDWTMPX
	updwtmpx(RXVT_WTMPX_FILE, utx);
#  else
	pututxline (utx);
#  endif
# endif
    }
#endif

    /*
     * Write utmp entry
     */
#ifdef HAVE_STRUCT_UTMP
# ifdef HAVE_UTMP_PID
    if (ut->ut_pid == PVTS(r)->cmd_pid)
	pututline(ut);
    endutent();
# else
    MEMSET(ut, 0, sizeof(struct utmp));
    rxvt_write_bsd_utmp(PVTS(r)->utmp_pos, ut);
# endif
#endif
#if defined(HAVE_STRUCT_UTMPX) && !defined(HAVE_STRUCT_UTMP)
    if (utx->ut_pid == PVTS(r)->cmd_pid)
	pututxline(utx);
    endutxent();
#endif

#endif	/* UTEMPTER_SUPPORT */
}
Пример #20
0
/*
 * Update wtmp and utmp logs.
 */
static void log_utmp(struct login_context *cxt)
{
	struct utmp ut;
	struct utmp *utp;
	struct timeval tv;

	utmpname(_PATH_UTMP);
	setutent();

	/* Find pid in utmp.
	 *
	 * login sometimes overwrites the runlevel entry in /var/run/utmp,
	 * confusing sysvinit. I added a test for the entry type, and the
	 * problem was gone. (In a runlevel entry, st_pid is not really a pid
	 * but some number calculated from the previous and current runlevel.)
	 * -- Michael Riepe <*****@*****.**>
	 */
	while ((utp = getutent()))
		if (utp->ut_pid == cxt->pid
		    && utp->ut_type >= INIT_PROCESS
		    && utp->ut_type <= DEAD_PROCESS)
			break;

	/* If we can't find a pre-existing entry by pid, try by line.
	 * BSD network daemons may rely on this. */
	if (utp == NULL && cxt->tty_name) {
		setutent();
		ut.ut_type = LOGIN_PROCESS;
		strncpy(ut.ut_line, cxt->tty_name, sizeof(ut.ut_line));
		utp = getutline(&ut);
	}

	/* If we can't find a pre-existing entry by pid and line, try it by id.
	 * Very stupid telnetd daemons don't set up utmp at all. (kzak) */
	if (utp == NULL && cxt->tty_number) {
	     setutent();
	     ut.ut_type = DEAD_PROCESS;
	     strncpy(ut.ut_id, cxt->tty_number, sizeof(ut.ut_id));
	     utp = getutid(&ut);
	}

	if (utp)
		memcpy(&ut, utp, sizeof(ut));
	else
		/* some gettys/telnetds don't initialize utmp... */
		memset(&ut, 0, sizeof(ut));

	if (cxt->tty_number && ut.ut_id[0] == 0)
		strncpy(ut.ut_id, cxt->tty_number, sizeof(ut.ut_id));
	if (cxt->username)
		strncpy(ut.ut_user, cxt->username, sizeof(ut.ut_user));
	if (cxt->tty_name)
		xstrncpy(ut.ut_line, cxt->tty_name, sizeof(ut.ut_line));

#ifdef _HAVE_UT_TV		/* in <utmpbits.h> included by <utmp.h> */
	gettimeofday(&tv, NULL);
	ut.ut_tv.tv_sec = tv.tv_sec;
	ut.ut_tv.tv_usec = tv.tv_usec;
#else
	{
		time_t t;
		time(&t);
		ut.ut_time = t;	/* ut_time is not always a time_t */
				/* glibc2 #defines it as ut_tv.tv_sec */
	}
#endif
	ut.ut_type = USER_PROCESS;
	ut.ut_pid = cxt->pid;
	if (cxt->hostname) {
		xstrncpy(ut.ut_host, cxt->hostname, sizeof(ut.ut_host));
		if (*cxt->hostaddress)
			memcpy(&ut.ut_addr_v6, cxt->hostaddress,
			       sizeof(ut.ut_addr_v6));
	}

	pututline(&ut);
	endutent();

	updwtmp(_PATH_WTMP, &ut);
}
Пример #21
0
/*
 * remove utmp and wtmp entries
 */
void
ptytty_unix::logout ()
{
  if (!cmd_pid)
    return;

#ifdef HAVE_STRUCT_UTMP
  struct utmp *tmput, *ut = &this->ut;
#endif
#ifdef HAVE_STRUCT_UTMPX
  struct utmpx *tmputx, *utx = &this->utx;
#endif

#ifdef HAVE_STRUCT_UTMP
# ifdef HAVE_UTMP_PID
  memset (ut, 0, sizeof (struct utmp));
  setutent ();
  strncpy (ut->ut_id, this->ut_id, sizeof (ut->ut_id));
  ut->ut_type = USER_PROCESS;
  if ((tmput = getutid (ut)))		/* position to entry in utmp file */
    ut = tmput;
  ut->ut_type = DEAD_PROCESS;
# else
  memset (ut->ut_name, 0, sizeof (ut->ut_name));
#  ifdef HAVE_UTMP_HOST
  memset (ut->ut_host, 0, sizeof (ut->ut_host));
#  endif
# endif
  ut->ut_time = time (NULL);
#endif

#ifdef HAVE_STRUCT_UTMPX
  memset (utx, 0, sizeof (struct utmpx));
  setutxent ();
  strncpy (utx->ut_id, this->ut_id, sizeof (utx->ut_id));
  utx->ut_type = USER_PROCESS;
  if ((tmputx = getutxid (utx)))	/* position to entry in utmp file */
    utx = tmputx;
  utx->ut_type = DEAD_PROCESS;
# if HAVE_UTMPX_SESSION
  utx->ut_session = getsid (0);
# endif
  utx->ut_tv.tv_sec = time (NULL);
  utx->ut_tv.tv_usec = 0;
#endif

  /*
   * Write ending wtmp entry
   */
#ifdef WTMP_SUPPORT
#ifdef LOG_ONLY_ON_LOGIN
  if (login_shell)
#endif
    {
# ifdef HAVE_STRUCT_UTMP
#  ifdef HAVE_UPDWTMP
      updwtmp (WTMP_FILE, ut);
#  else
      update_wtmp (WTMP_FILE, ut);
#  endif
# endif
# if defined(HAVE_STRUCT_UTMPX) && defined(HAVE_UPDWTMPX)
      updwtmpx (WTMPX_FILE, utx);
# endif
    }
#endif

  /*
   * Write utmp entry
   */
#ifdef HAVE_STRUCT_UTMP
# ifdef HAVE_UTMP_PID
  if (ut->ut_pid == cmd_pid)
    pututline (ut);
  endutent ();
# else
  memset (ut, 0, sizeof (struct utmp));
  write_bsd_utmp (utmp_pos, ut);
# endif
#endif
#ifdef HAVE_STRUCT_UTMPX
  if (utx->ut_pid == cmd_pid)
    pututxline (utx);
  endutxent ();
#endif

  cmd_pid = 0;
}
Пример #22
0
/*
 * make and write utmp and wtmp entries
 */
void
ptytty_unix::login (int cmd_pid, bool login_shell, const char *hostname)
{
  const char *pty = name;

  if (!pty || !*pty)
    return;

  this->cmd_pid     = cmd_pid;
  this->login_shell = login_shell;

#ifdef HAVE_STRUCT_UTMP
  struct utmp *ut = &this->ut;
#endif
#ifdef HAVE_STRUCT_UTMPX
  struct utmpx *utx = &this->utx;
#endif
  int i;
  struct passwd *pwent = getpwuid (getuid ());
  const char *name = (pwent && pwent->pw_name) ? pwent->pw_name : "?";

  if (!strncmp (pty, "/dev/", 5))
    pty += 5;		/* skip /dev/ prefix */

#if defined(HAVE_UTMP_PID) || defined(HAVE_STRUCT_UTMPX)
  if (!strncmp (pty, "pty", 3) || !strncmp (pty, "tty", 3))
    strncpy (ut_id, pty + 3, sizeof (ut_id));
  else if (sscanf (pty, "pts/%d", &i) == 1)
    sprintf (ut_id, "vt%02x", (i & 0xff));	/* sysv naming */
  else
    {
      ptytty_warn ("can't parse tty name \"%s\", not adding utmp entry.\n", pty);
      return;
    }
#endif

#ifdef HAVE_STRUCT_UTMP
  memset (ut, 0, sizeof (struct utmp));
# ifdef HAVE_UTMP_PID
  setutent ();
  strncpy (ut->ut_id, ut_id, sizeof (ut->ut_id));
  ut->ut_type = DEAD_PROCESS;
  getutid (ut);		/* position to entry in utmp file */
# endif
#endif

#ifdef HAVE_STRUCT_UTMPX
  memset (utx, 0, sizeof (struct utmpx));
  setutxent ();
  strncpy (utx->ut_id, ut_id, sizeof (utx->ut_id));
  utx->ut_type = DEAD_PROCESS;
  getutxid (utx);		/* position to entry in utmp file */
#endif

#ifdef HAVE_STRUCT_UTMP
  strncpy (ut->ut_line, pty, sizeof (ut->ut_line));
# ifdef HAVE_UTMP_HOST
  strncpy (ut->ut_host, hostname, sizeof (ut->ut_host));
# endif
  ut->ut_time = time (NULL);
# ifdef HAVE_UTMP_PID
  strncpy (ut->ut_user, name, sizeof (ut->ut_user));
  strncpy (ut->ut_id, ut_id, sizeof (ut->ut_id));
  ut->ut_pid = cmd_pid;
  ut->ut_type = USER_PROCESS;
  pututline (ut);
  endutent ();			/* close the file */
  utmp_pos = 0;
# else
  strncpy (ut->ut_name, name, sizeof (ut->ut_name));
# endif
#endif

#ifdef HAVE_STRUCT_UTMPX
  strncpy (utx->ut_line, pty, sizeof (utx->ut_line));
  strncpy (utx->ut_user, name, sizeof (utx->ut_user));
  strncpy (utx->ut_id, ut_id, sizeof (utx->ut_id));
# if HAVE_UTMPX_SESSION
  utx->ut_session = getsid (0);
# endif
  utx->ut_tv.tv_sec = time (NULL);
  utx->ut_tv.tv_usec = 0;
  utx->ut_pid = cmd_pid;
# ifdef HAVE_UTMPX_HOST
  strncpy (utx->ut_host, hostname, sizeof (utx->ut_host));
#  if 0
  {
    char           *colon;

    if ((colon = strrchr (ut->ut_host, ':')) != NULL)
      *colon = '\0';
  }
#  endif
# endif
  utx->ut_type = USER_PROCESS;
  pututxline (utx);
  endutxent ();		/* close the file */
  utmp_pos = 0;
#endif

#if defined(HAVE_STRUCT_UTMP) && !defined(HAVE_UTMP_PID)
  {
# if 1
    int fdstdin = dup (STDIN_FILENO);
    dup2 (tty, STDIN_FILENO);

    i = ttyslot ();
    if (write_bsd_utmp (i, ut))
      utmp_pos = i;

    dup2 (fdstdin, STDIN_FILENO);
    close (fdstdin);
# endif
  }
#endif

#ifdef WTMP_SUPPORT
#ifdef LOG_ONLY_ON_LOGIN
  if (login_shell)
#endif
    {
# ifdef HAVE_STRUCT_UTMP
#  ifdef HAVE_UPDWTMP
      updwtmp (WTMP_FILE, ut);
#  else
      update_wtmp (WTMP_FILE, ut);
#  endif
# endif
# if defined(HAVE_STRUCT_UTMPX) && defined(HAVE_UPDWTMPX)
      updwtmpx (WTMPX_FILE, utx);
# endif
    }
#endif
#if defined(LASTLOG_SUPPORT) && defined(LASTLOG_FILE)
#ifdef LOG_ONLY_ON_LOGIN
  if (login_shell)
#endif
    update_lastlog (LASTLOG_FILE, pty, hostname);
#endif
}
Пример #23
0
/* EXTPROTO */
void
rxvt_cleanutent(rxvt_t *r)
{
#ifdef HAVE_STRUCT_UTMP
    struct utmp    *tmput, *ut = &(r->h->ut);
#endif
#ifdef HAVE_STRUCT_UTMPX
    struct utmpx   *tmputx, *utx = &(r->h->utx);
#endif

#ifdef HAVE_STRUCT_UTMP
# ifdef RXVT_UTMP_PID
    MEMSET(ut, 0, sizeof(struct utmp));
    setutent();
    STRNCPY(ut->ut_id, r->h->ut_id, sizeof(ut->ut_id));
    ut->ut_type = USER_PROCESS;
    if ((tmput = getutid(ut)))	/* position to entry in utmp file */
	ut = tmput;
    ut->ut_type = DEAD_PROCESS;
# else 
    MEMSET(ut->ut_name, 0, sizeof(ut->ut_name));
    MEMSET(ut->ut_host, 0, sizeof(ut->ut_host));
# endif
    ut->ut_time = time(NULL);
#endif

#ifdef HAVE_STRUCT_UTMPX
    MEMSET(utx, 0, sizeof(struct utmpx));
    setutxent();
    STRNCPY(utx->ut_id, r->h->ut_id, sizeof(utx->ut_id));
    utx->ut_type = USER_PROCESS;
    if ((tmputx = getutxid(utx)))	/* position to entry in utmp file */
	utx = tmputx;
    utx->ut_type = DEAD_PROCESS;
    utx->ut_session = getsid(0);
    utx->ut_tv.tv_sec = time(NULL);
    utx->ut_tv.tv_usec = 0;
#endif

    /*
     * Write ending wtmp entry
     */
#ifdef WTMP_SUPPORT
# ifdef WTMP_ONLY_ON_LOGIN
    if (r->Options & Opt_loginShell)
# endif
    {
# ifdef HAVE_STRUCT_UTMP
#  ifdef HAVE_UPDWTMP
	updwtmp(RXVT_WTMP_FILE, ut);
#  else
	rxvt_update_wtmp(RXVT_WTMP_FILE, ut);
#  endif
# endif
# ifdef HAVE_STRUCT_UTMPX
	updwtmpx(RXVT_WTMPX_FILE, utx);
# endif
#endif
    }

    /*
     * Write utmp entry
     */
#ifdef HAVE_STRUCT_UTMP
# ifdef RXVT_UTMP_PID
    if (ut->ut_pid == r->h->cmd_pid)
	pututline(ut);
    endutent();
# else
    if (r->h->utmp_pos > 0) {
	MEMSET(ut, 0, sizeof(struct utmp));
	rxvt_write_bsd_utmp(r->h->utmp_pos, ut);
    }
# endif
#endif
#ifdef HAVE_STRUCT_UTMPX
    if (utx->ut_pid == r->h->cmd_pid)
	pututxline(utx);
    endutxent();
#endif
}
Пример #24
0
void
ptytty_unix::log_session (bool login, const char *hostname)
{
  struct passwd *pwent = getpwuid (getuid ());
  const char *user = (pwent && pwent->pw_name) ? pwent->pw_name : "?";

  const char *pty = name;

  if (!strncmp (pty, "/dev/", 5))
    pty += 5;		/* skip /dev/ prefix */

#ifdef HAVE_STRUCT_UTMP
  struct utmp *tmput;
  struct utmp ut;
  fill_utmp (&ut, login, cmd_pid, pty, user, hostname);
#endif

#ifdef HAVE_STRUCT_UTMPX
  struct utmpx *tmputx;
  struct utmpx utx;
  fill_utmpx (&utx, login, cmd_pid, pty, user, hostname);
#endif

#ifdef HAVE_STRUCT_UTMP
# ifdef HAVE_UTMP_PID
  setutent ();
  if (login || ((tmput = getutid (&ut)) && tmput->ut_pid == cmd_pid))
    pututline (&ut);
  endutent ();
# else
  write_bsd_utmp (utmp_pos, &ut);
# endif
#endif

#ifdef HAVE_STRUCT_UTMPX
  setutxent ();
  if (login || ((tmputx = getutxid (&utx)) && tmputx->ut_pid == cmd_pid))
    pututxline (&utx);
  endutxent ();
#endif

#ifdef WTMP_SUPPORT
  if (login_shell)
    {
# ifdef HAVE_STRUCT_UTMP
#  ifdef HAVE_UPDWTMP
      updwtmp (WTMP_FILE, &ut);
#  else
      update_wtmp (WTMP_FILE, &ut);
#  endif
# endif
# if defined(HAVE_STRUCT_UTMPX) && defined(HAVE_UPDWTMPX)
      updwtmpx (WTMPX_FILE, &utx);
# endif
    }
#endif

#ifdef LASTLOG_SUPPORT
  if (login_shell)
    if (login)
      {
        if (pwent)
          update_lastlog (pty, hostname);
        else
          PTYTTY_WARN ("no entry in password file, not updating lastlog.\n");
      }
#endif
}