URI:
       posix.c - utmp - simple login manager  
  HTML git clone git://git.suckless.org/utmp
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       posix.c (2790B)
       ---
            1 
            2 #define _POSIX_C_SOURCE        200112L
            3 
            4 #include <errno.h>
            5 #include <ctype.h>
            6 #include <stdlib.h>
            7 #include <stdio.h>
            8 #include <string.h>
            9 #include <time.h>
           10 
           11 #include <sys/types.h>
           12 #include <unistd.h>
           13 #include <pwd.h>
           14 #include <grp.h>
           15 
           16 #ifdef UTMP_SYSTEMV
           17 #include <utmp.h>
           18 #define getutxent getutent
           19 #define getutxid getutid
           20 #define getutxline getutline
           21 #define pututxline pututline
           22 #define setutxent setutent
           23 #define endutxent endutent
           24 #define utmpx utmp
           25 #else
           26 #include <utmpx.h>
           27 #endif
           28 
           29 extern void die(const char *fmt, ...);
           30 static struct utmpx utmp;
           31 extern struct passwd *pw;
           32 extern gid_t egid, gid;
           33 
           34 
           35 /*
           36  * From utmp(5)
           37  * xterm and other terminal emulators directly create a USER_PROCESS
           38  * record and generate the ut_id  by using the string that suffix part of
           39  * the terminal name (the characters  following  /dev/[pt]ty). If they find
           40  * a DEAD_PROCESS for this ID, they recycle it, otherwise they create a new
           41  * entry.  If they can, they will mark it as DEAD_PROCESS on exiting and it
           42  * is advised that they null ut_line, ut_time, ut_user, and ut_host as well.
           43  */
           44 
           45 struct utmpx *
           46 findutmp(int type)
           47 {
           48         struct utmpx *r;
           49 
           50         utmp.ut_type = type;
           51         setutxent();
           52         for(;;) {
           53                /*
           54                 * we can not use getutxline because we can search in
           55                 * DEAD_PROCESS to
           56                 */
           57                if(!(r = getutxid(&utmp)))
           58                        break;
           59                if(!strcmp(r->ut_line, utmp.ut_line))
           60                        break;
           61                memset(r, 0, sizeof(*r)); /* for Solaris, IRIX64 and HPUX */
           62         }
           63         return r;
           64 }
           65 
           66 void
           67 addutmp(void)
           68 {
           69         unsigned ptyid;
           70         char *pts, *cp, buf[5] = {'x'};
           71 
           72         if (strlen(pw->pw_name) > sizeof(utmp.ut_user))
           73                 die("utmp:incorrect username %s", pw->pw_name);
           74 
           75         if ((pts = ttyname(STDIN_FILENO)) == NULL)
           76                 die("utmp:error getting pty name\n");
           77 
           78         for (cp = pts + strlen(pts) - 1; isdigit(*cp); --cp)
           79                 /* nothing */;
           80 
           81         ptyid = atoi(++cp);
           82         if (ptyid > 999 || strlen(pts + 5) > sizeof(utmp.ut_line))
           83                 die("utmp:Incorrect pts name %s\n", pts);
           84         sprintf(buf + 1, "%03d", ptyid);
           85         strncpy(utmp.ut_id, buf, 4);
           86 
           87         /* remove /dev/ part of the string */
           88         strncpy(utmp.ut_line, pts + 5, sizeof(utmp.ut_line));
           89 
           90         if(!findutmp(DEAD_PROCESS))
           91                 findutmp(USER_PROCESS);
           92 
           93         utmp.ut_type = USER_PROCESS;
           94         strncpy(utmp.ut_user, pw->pw_name, sizeof(utmp.ut_user));
           95         utmp.ut_pid = getpid();
           96         utmp.ut_tv.tv_sec = time(NULL);
           97         utmp.ut_tv.tv_usec = 0;
           98          /* don't use no standard fields host and session */
           99 
          100         setegid(egid);
          101         if(!pututxline(&utmp))
          102                 die("utmp:error adding utmp entry:%s", strerror(errno));
          103         setegid(gid);
          104         endutxent();
          105 }
          106 
          107 void
          108 delutmp(void)
          109 {
          110         struct utmpx *r;
          111 
          112         setutxent();
          113         if((r = getutxline(&utmp)) != NULL) {
          114                 r->ut_type = DEAD_PROCESS;
          115                 r->ut_tv.tv_usec = r->ut_tv.tv_sec = 0;
          116                 setgid(egid);
          117                 if (!pututxline(r))
          118                         die("utmp:error removing utmp entry:%s", strerror(errno));
          119                 setgid(gid);
          120         }
          121         endutxent();
          122 }
          123