⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utmp.c

📁 一个使用des加密传输的unix下的login程序的服务器端和客户端
💻 C
字号:
/* * @(#) utmp.c  RCS: $Revision: 1.8 $ $Date: 95/03/08 01:13:19 $ * * This file contains machine specific code for making sure getlogin() works. * See the function setlogin below. * * Make sure login database is updated getut(3c), but this is not  * available in POSIX, or SYSV XPG3; it's only a SYSV XPG2 feature.    * There thus is no machine independent way to make getlogin work. * * There are two distinct flavors of utmp.h files: * * System V style:  SGI's IRIX, Solaris, OSF1, HP-UX, UNICOS #    #define ut_name	ut_user *    struct utmp {  *	 char[] ut_user, ut_id, ut_line; *	 short ut_pid, ut_type; *	 struct { short e_termination; short e_exit } ut_exit;	except linux *	 time_t ut_time; *       char ut_host[]; // HP-UX, OSF1, UNICOS linux only !Solaris <utmp.h> *    } * * UTMPX style: Solaris	<utmpx.h> (*almost* the same as system V style!) *     struct utmpx {			<- different name *        char[] ut_user, ut_id, ut_line; *        pid_t ut_pid; *        short ut_type; *        struct exit_status ut_exit;	<- same *        struct timeval ut_tv;		<- different! (BSD style timeofday) *        long  ut_session; *        short ut_syslen; *        char ut_host[]; *     } * *  BSD style:	Ultrix, SunOS4.2, UNICOS *     struct utmp { *	   char ut_line[8], ut_name[8], ut_host[16]; *	   long ut_time; *     } *  * The least-common denominator of utmp entries: *     char ut_line[] 	  device name without path component (e.g. "ttyp4") *     			  8 chars on BSD, 12 on hp-ux, longer on osf1 *     time_t ut_time	  time entry was made (long on BSD) *     char   ut_name[8]  login name of the user * * The following field is not present on SGI's IRIX and Solaris. *     char   ut_host[16] host name if remote * * Unfortunately, BSD and System V use different names for the field containing * the user login name (ut_name, ut_user respectively).  Fortunately, all * SYSV machines I can find have a #define for ut_name. * * For BSD, empty slots are indicated by ut_name is a null string. * Remote users are indicated by a non-null ut_host field. * * For System V, empty slots are indicated by ut_type field as  * DEAD_PROCESS. All other fields must be valid as usual. * * Solaris has two utmp files with different struct formats: *    /var/adm/utmp  based on <utmp.h>  using struct utmp.	UTMP_FILE *    /var/adm/utmpx based on <utmpx.h> using struct utmpx.	UTMPX_FILE * *    Changes UTMPX_FILE will not be noticed by the "last" and "who" commands  *    unless UTMP_FILE is also updated.  UTMPX_FILE has an rhost field. */#define _POSIX_SOURCE	/* this isn't quite posix source *//* * This is a mess.  HP-UX ANSI C won't define pid_t in <sys/types.h> unless * _POSIX_SOURCE is defined.  Other machines may refuse to define it.  Pick * what's appropriate.  <utmp.h> uses pid_t. */#if defined(__SOLARIS__) /* { */#undef _POSIX_SOURCE	/* allows struct timeval to be defined */#undef _POSIX_C_SOURCE#include <sys/types.h>	/* uid_t size_t */#include <time.h>	/* time (also needed for "utmp.h") */#define _POSIX_SOURCE#define _POSIX_C_SOURCE#else  /* } { */#include <sys/types.h>	/* uid_t size_t */#include <time.h>	/* time (also needed for "utmp.h") */#endif /* } */#include <unistd.h>	/* open read write lseek getuid */#include <stdio.h>#include <fcntl.h>	/* O_RDWR */#include <string.h>	/* strchr memset */#include <pwd.h>	/* struct passwd, getpwuid */#define OFFSET(s, m)	((unsigned) &(((s *)0)->m))#include "utmp.h"	/* UTMP_FILE WTMP_FILE <utmp.h> or <utmpx.h> */#include "log.h"#include "deslogin.h"	/* progName ERRMSG *//* * Update the system's "currently logged in users" file (used by "who") * * Input: *    utmp_file 	- the name of the file to update *    ut		- address of the record insert into file *    utbuf		- storage for a temporary buffer *    utsz		- the size of the ut and utbuf record's storage *    lineoff		- the offset into the record for the ut_line field *    linesz		- the size of the ut_line field * * Must minimize the time the file is open to prevent write conflict with * other processes trying to update utmp.   */int update_utmp(utmp_file, ut, utbuf, utsz, lineoff, linesz)   char *utmp_file;   void *ut, *utbuf;   unsigned utsz, lineoff, linesz;{   int fd, count, res = -1;   long offset = 0, lres;   fd = open(utmp_file, O_RDWR);   if (fd < 0) {      log("%s: (update_utmp) open(\"%s\", O_RDWR) failed -- %s\n", 	 progName, utmp_file, ERRMSG);      return -1;   }   /*     * Find offset of entry with the same line value if present    */   while ((count = read(fd, utbuf, utsz)) == utsz) {      if (strncmp((char *)ut+lineoff, (char *)utbuf+lineoff, linesz) == 0) {	 break;      }      offset += count;   }   if (count < 0) {      log("%s: (update_utmp) read failed from \"%s\" -- %s\n", 	 progName, utmp_file, ERRMSG);      goto utmp_failed;   }   lres = lseek(fd, (off_t) offset, SEEK_SET);   if (lres < 0) {      log("%s: (update_utmp) lseek to offset %ld failed in \"%s\" -- %s\n", 	 progName, offset, utmp_file, ERRMSG);      goto utmp_failed;   }   count = write(fd, (char *) ut, utsz);   if (count < 0) {      log("%s: (update_utmp) write failed to \"%s\" -- %s\n", 	 progName, utmp_file, ERRMSG);      goto utmp_failed;   }   if (count != utsz) {      log("%s: (update_utmp) short write to \"%s\"\n", progName, utmp_file);      goto utmp_failed;   }   res = 0;	/* success */utmp_failed:   close(fd);   return res;}/* * Update the system login history file (used by "last" and "lastb") * * Must minimize the time the file is open to prevent write conflict with * other processes trying to update utmp.   */int update_wtmp(wtmp_file, ut, utsz)   char *wtmp_file;   void *ut;   unsigned utsz;{   int fd, count, res = -1;   fd = open(wtmp_file, O_WRONLY | O_APPEND);   if (fd < 0) {      log("%s: (update_wtmp) open(\"%s\", O_WRONLY|O_APPEND) failed -- %s\n", 	 progName, wtmp_file, ERRMSG);      return -1;   }   count  = write(fd, ut, utsz);   if (count < 0) {      log("%s: (update_wtmp) write failed to \"%s\" -- %s\n", 	 progName, wtmp_file, ERRMSG);      goto wtmp_failed;   }   if (count != utsz) {      log("%s: (update_wtmp) short write to \"%s\"\n", progName, wtmp_file);      goto wtmp_failed;   }   res = 0;	/* success */wtmp_failed:   close(fd);   return res;}/* * The inverse of the POSIX getlogin call.  Setup the login for the given * user name. * * Input: *    tty   = the device file assigned as the controlling terminal *    name  = the login name (only first 8 characters signifacant) *    rhost = the hostname of the remote host (only 1st 16 chars used) *    statloc = the address of the process exit status *              (if zero, then this is a new process stating up) * * The calling process should ensure that it owns the tty before it calls * this routine, or it could overwrite a legitimate processes tty. * * Returns: 0 success, -1 failure. */int setlogin(tty, username, rhost, statloc)   char *tty, *username, *rhost;   int *statloc;{   char         *line, *id;   long         offset;   int          res;   struct utmp  ut, utbuf;#if defined(UTMPX_FILE) 	/* { */   struct utmpx utx, utxbuf;#endif /* } */   if ((tty == 0) || (username == 0) || (rhost == 0)) return -1;   /*    * There are two possibly conflicting ways to get the line:    *   1) take the last component of the path (SYSV) (e.g. fails for /dev/pts/6)    *   2) Strip of the first component of the path. (irix) (/dev/pts/6 = pts/6)    *   3) Don't strip any components at all (Solaris)    *    * Which one is the most "popular"?  Probably should be a compile-time test.    * I'm using the last component of the path.    */   line = strchr(tty, '/');   if (line == tty) {      line = strchr(tty + 1, '/');      if (line == (char *) 0) line = tty;   }   if (line == (char *) 0) line = tty; else line++;   /*    * The id field (for init) is the last two characters of the line on SYSV    * For SOLARIS, id is prefixed by two character service abbreviation.    *    (e.g. Telnet is 'tn', rlogin is 'rl')    * I'm using the last two characters of the line.    */   offset = strlen(line) - 2;   if (offset < 0) offset = 0;   id = line + offset;#if defined(UTMPX_FILE) 	/* { */   memset(&utx, '\0', sizeof utx);#endif /* } */   memset(&ut, '\0', sizeof ut);   time((time_t *) &ut.ut_time);   strncpy(ut.ut_line, line,     sizeof ut.ut_line);   strncpy(ut.ut_name, username, sizeof ut.ut_name); #if defined(USER_PROCESS)		/* { SYSV */   strncpy(ut.ut_id,    id,      sizeof ut.ut_id);   ut.ut_pid  = getpid();   ut.ut_type = USER_PROCESS;		/* assume login until proven othewise */   if (statloc != 0) {		/* process exit */      ut.ut_type = DEAD_PROCESS;#if !defined(_LINUX_SOURCE) /* { */      ut.ut_exit.e_termination = *statloc & 0xff;      ut.ut_exit.e_exit        = (*statloc >> 8) & 0xff;#endif /* } */   }#else 	/* } { BSD */   if (statloc != 0) {      ut.ut_name[0] = '\0';   }#endif	/* } BSD */#if !defined(__sgi) && !defined(__DYNIX__) && !defined(__SOLARIS__) /* { */   strncpy(ut.ut_host, rhost, sizeof ut.ut_host);#endif /* } */   /*    * This used to be broken for __DYNIX__ and __SOLARIS__.    * Version 1.3 fixed this.  If not, mail barrett@asgard.cs.colorado.edu    */   res = update_utmp(UTMP_FILE, &ut, &utbuf, sizeof ut,                      OFFSET(struct utmp, ut_line), sizeof ut.ut_line);   if (res >= 0) {      res = update_wtmp(WTMP_FILE, &ut, sizeof ut);    }#if defined(UTMPX_FILE) /* { __SOLARIS__ <utmpx.h> */   getutmpx(&ut, &utx);		/* no return result */   gettimeofday(&utx.ut_tv);	/* shouldn't be necessary; do it anyway */   strncpy(utx.ut_host, rhost, sizeof utx.ut_host);   if (res >= 0) {      res = update_utmp(UTMPX_FILE, &utx, &utxbuf, sizeof utx, 	                OFFSET(struct utmpx, ut_line), sizeof utx.ut_line);   }   if (res >= 0) {      res = update_wtmp(WTMPX_FILE, &utx, sizeof utx);    }#endif /* } */   return res;}/* * Because of severe braindamage, the POSIX getlogin() call has a  * high-probability of failing to work on many machines.  The things to * consider are: * * This process must have a controlling terminal to determine the tty line * to lookup in utmp. * * There must be a (unique) entry for that line in utmp. *  * There is no guarantee that the contents of utmp is correct. (It's world * writable on most SUN BSD machines for example!  Thus, the login name  * returned there may not be correct at all. * * cuserid() is obsolete.  The problem is that it could return the login * name corresponding to the effective user id instead of the real user id. * * There may be multiple user names corresponding to each user id.   * * The bottom line is that there is *no way* to accurately determine which * of the (possibly many) login names were used to get this particular real * user id. * * I've decided not to trust utmp at all, and just to get the first valid * user id using the POSIX.1 conformant calls to <pwd.h>, getpwuid. * * Note that the only "portable" fields of a struct passwd are: * *    char *pw_name *    char *pw_passwd *    uid_t pw_uid *    gid_t pw_gid * * The only way this routine should fail (returning (char *) 0) is if  * /etc/passwd is not readable.  Note that yellow-pages lookups could occur * as a result of using this function. * * AnnexB.4.2.4:2682-2694 * The getlogin() function returns a pointer to the user's login name.  The * same user ID may be shared by several login names.  If it is desired to get * the user database entry that is used during login, the result of getlogin() * should be used to provide the argument to the getpwnam() function.  (This * might be  used to determine the user's login shell, particularly where a * single user has multiple login shells with distinct login names, but the * same user ID.) *    The information provided by the cuserid() function, which was originally * defined in IEEE Std 1003.1-1990 and subsequently removed, can be obtained * by the following:  getpwuid(geteuid()), while the information provided by * historical implementations of cuserid() can be obtained by: * getpwuid(getuid()). */char *getLoginName() {   register uid_t uid = getuid();   register struct passwd *pwent;      pwent = getpwuid(uid);   if (pwent == (struct passwd *) 0) {      return (char *) 0;   } else {      return pwent->pw_name;   }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -