--- Makefile | 30 ++++++++------- README | 22 +++++++++++ bsd.c | 60 +++++++++++++++++++++++++++++ config.bsd | 16 ++++++++ config.mk | 23 ----------- config.posix | 15 ++++++++ config.sysv | 15 ++++++++ configure | 10 +++++ posix.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ utmp.1 | 5 --- utmp.c | 116 ++++++++----------------------------------------------- 11 files changed, 293 insertions(+), 142 deletions(-) create mode 100644 README create mode 100644 bsd.c create mode 100644 config.bsd delete mode 100644 config.mk create mode 100644 config.posix create mode 100644 config.sysv create mode 100755 configure create mode 100644 posix.c diff --git a/Makefile b/Makefile index 8c36390..a7c37ad 100644 --- a/Makefile +++ b/Makefile _AT_@ -3,37 +3,39 @@ include config.mk -SRC = utmp.c -OBJ = ${SRC:.c=.o} +DIST = LICENSE Makefile config.mk utmp.1 utmp.c bsd.c posix.c +VERSION = 0.2 -all: options utmp +all: options utmp options: _AT_echo utmp build options: _AT_echo "CFLAGS = ${CFLAGS}" + _AT_echo "CPPFLAGS = ${CPPFLAGS}" _AT_echo "LDFLAGS = ${LDFLAGS}" + _AT_echo "LDLIBS = ${LDLIBS}" _AT_echo "CC = ${CC}" .c.o: _AT_echo CC $< - _AT_${CC} -c ${CFLAGS} $< + _AT_${CC} $(CFLAGS) $(CPPFLAGS) -c $< -${OBJ}: config.mk - -utmp: ${OBJ} +utmp: $(OBJS) _AT_echo CC -o $@ - _AT_${CC} -o $@ ${OBJ} ${LDFLAGS} + _AT_$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@ +distclean: clean + _AT_echo cleaning for distribution + _AT_rm config.mk clean: _AT_echo cleaning - _AT_rm -f utmp ${OBJ} utmp-${VERSION}.tar.gz + _AT_rm -f utmp utmp-${VERSION}.tar.gz *.o dist: clean _AT_echo creating dist tarball _AT_mkdir -p utmp-${VERSION} - _AT_cp -R LICENSE Makefile config.mk utmp.1 ${SRC} utmp-${VERSION} - _AT_tar -cf utmp-${VERSION}.tar utmp-${VERSION} - _AT_gzip utmp-${VERSION}.tar + _AT_cp -R $(DIST) utmp-${VERSION} + _AT_tar -cf - utmp-${VERSION} | gzip > utmp-${VERSION}.tar.gz _AT_rm -rf utmp-${VERSION} install: all _AT_@ -43,7 +45,7 @@ install: all _AT_chmod 755 ${DESTDIR}${PREFIX}/bin/utmp _AT_chgrp ${GROUP} ${DESTDIR}${PREFIX}/bin/utmp _AT_chmod g+s ${DESTDIR}${PREFIX}/bin/utmp - _AT_echo installing manual page to ${DESTDIR}${PREFIX}/man1 + _AT_echo installing manual page to ${DESTDIR}${MANPREFIX}/man1 _AT_mkdir -p ${DESTDIR}${MANPREFIX}/man1 _AT_sed "s/VERSION/${VERSION}/g" < utmp.1 > ${DESTDIR}${MANPREFIX}/man1/utmp.1 _AT_chmod 644 ${DESTDIR}${MANPREFIX}/man1/utmp.1 _AT_@ -54,4 +56,4 @@ uninstall: _AT_echo removing manual page from ${DESTDIR}${PREFIX}/man1 _AT_rm -f ${DESTDIR}${MANPREFIX}/man1/utmp.1 -.PHONY: all options clean dist install uninstall +.PHONY: options clean dist install uninstall diff --git a/README b/README new file mode 100644 index 0000000..f578223 --- /dev/null +++ b/README _AT_@ -0,0 +1,22 @@ + +utmp is a small program which update the utmp record of the +current tty. It is designed for helping in some terminal emulators +or session manager which lack support for it. + +Compile: +------- + +There are three different interfaces to utmp; SystemV, BSD and POSIX. +SystemV and POSIX are basically the same interface (POSIX has +better definitons for utmp fields, like for example ut_pid which +in some system was a short instead of a pid_t), but BSD is very +different. utmp has implemented the three interfaces, and +it supplies three different config files, so the user only has +to rename the proper one to config.mk. It is also added a +basic configure, which selects POSIX interface for all plataforms +except for OpenBSD. + + $ ./configure + $ make + # make install + diff --git a/bsd.c b/bsd.c new file mode 100644 index 0000000..29270dd --- /dev/null +++ b/bsd.c _AT_@ -0,0 +1,60 @@ + +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <unistd.h> +#include <util.h> +#include <grp.h> +#include <utmp.h> +#include <pwd.h> + +#include "utmp.h" + +extern struct passwd *pass; +extern gid_t egid, gid; +static struct utmp utmp; + +void +addutmp(void) +{ + unsigned ptyid; + char *pts, *cp, *host; + + + if (!(host = getenv("DISPLAY"))) + host = "-"; + + if (strlen(pass->pw_name) > sizeof(utmp.ut_name)) + die("incorrect username %s", pass->pw_name); + + if ((pts = ttyname(STDIN_FILENO)) == NULL) + die("error getting pty name:%s", strerror(errno)); + + for (cp = pts + strlen(pts) - 1; isdigit(*cp); --cp) + /* nothing */; + + ptyid = atoi(++cp); + if (ptyid > 999 || strlen(pts + 5) > sizeof(utmp.ut_line)) + die("Incorrect pts name %s\n", pts); + + /* remove /dev/ from pts */ + strncpy(utmp.ut_line, pts + 5, sizeof(utmp.ut_line)); + strncpy(utmp.ut_name, pass->pw_name, sizeof(utmp.ut_name)); + strncpy(utmp.ut_host, host, sizeof(utmp.ut_host)); + time(&utmp.ut_time); + + setgid(egid); + login(&utmp); + setgid(gid); +} + +void +delutmp(void) +{ + setgid(egid); + logout(utmp.ut_line); + setgid(gid); +} + diff --git a/config.bsd b/config.bsd new file mode 100644 index 0000000..86a49c0 --- /dev/null +++ b/config.bsd _AT_@ -0,0 +1,16 @@ + +# Customize below to fit your system. +GROUP = utmp + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +# flags +CPPFLAGS += -DVERSION=\"${VERSION}\" +LDLIBS += -lutil + +# Objects + +OBJS = utmp.o bsd.o + diff --git a/config.mk b/config.mk deleted file mode 100644 index 08aa8b3..0000000 --- a/config.mk +++ /dev/null _AT_@ -1,23 +0,0 @@ -# utmp version -VERSION = 0.1 - -# Customize below to fit your system. - -GROUP = utmp - -# paths -PREFIX = /usr/local -MANPREFIX = ${PREFIX}/share/man - -# includes and libs -INCS = -I. -I/usr/include -LIBS = -L/usr/lib -lc - -# flags -CPPFLAGS = -DVERSION=\"${VERSION}\" -CFLAGS += -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} -LDFLAGS += -s ${LIBS} - -# compiler and linker -CC ?= cc - diff --git a/config.posix b/config.posix new file mode 100644 index 0000000..8d8c8c1 --- /dev/null +++ b/config.posix _AT_@ -0,0 +1,15 @@ + +# Customize below to fit your system. +GROUP = utmp + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +# flags +CPPFLAGS += -DVERSION=\"${VERSION}\" + +# Objects + +OBJS = utmp.o posix.o + diff --git a/config.sysv b/config.sysv new file mode 100644 index 0000000..9820595 --- /dev/null +++ b/config.sysv _AT_@ -0,0 +1,15 @@ + +# Customize below to fit your system. +GROUP = utmp + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +# flags +CPPFLAGS += -DUTMP_SYSTEMV -DVERSION=\"${VERSION}\" + +# Objects + +OBJS = utmp.o posix.o + diff --git a/configure b/configure new file mode 100755 index 0000000..8ea80ba --- /dev/null +++ b/configure _AT_@ -0,0 +1,10 @@ +#!/bin/sh + +case `uname` in +OpenBSD) + ln config.bsd config.mk + ;; +*) + ln config.posix config.mk + ;; +esac diff --git a/posix.c b/posix.c new file mode 100644 index 0000000..04f398b --- /dev/null +++ b/posix.c _AT_@ -0,0 +1,123 @@ + +#define _POSIX_C_SOURCE 200112L + +#include <errno.h> +#include <ctype.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#include <sys/types.h> +#include <unistd.h> +#include <utmpx.h> +#include <pwd.h> +#include <grp.h> + +#ifdef UTMP_SYSTEMV +#include <utmp.h> +#define getutxent getutent +#define getutxid getutid +#define getutxline getutline +#define pututxline pututline +#define setutxent setutent +#define endutxent endutent +#define utmpx utmp +#else +#include <utmpx.h> +#endif + +static struct utmpx utmp; +extern struct passwd *pass; +extern gid_t egid, gid; + + +/* + * From utmp(5) + * xterm and other terminal emulators directly create a USER_PROCESS + * record and generate the ut_id by using the string that suffix part of + * the terminal name (the characters following /dev/[pt]ty). If they find + * a DEAD_PROCESS for this ID, they recycle it, otherwise they create a new + * entry. If they can, they will mark it as DEAD_PROCESS on exiting and it + * is advised that they null ut_line, ut_time, ut_user, and ut_host as well. + */ + +struct utmpx * +findutmp(int type) +{ + struct utmpx *r; + + utmp.ut_type = type; + setutxent(); + for(;;) { + /* + * we can not use getutxline because we can search in + * DEAD_PROCESS to + */ + if(!(r = getutxid(&utmp))) + break; + if(!strcmp(r->ut_line, utmp.ut_line)) + break; + memset(r, 0, sizeof(*r)); /* for Solaris, IRIX64 and HPUX */ + } + return r; +} + +void +addutmp(void) +{ + unsigned ptyid; + char *pts, *cp, buf[5] = {'x'}; + + if (strlen(pass->pw_name) > sizeof(utmp.ut_user)) + die("incorrect username %s", pass->pw_name); + + if ((pts = ttyname(STDIN_FILENO)) == NULL) + die("error getting pty name\n"); + + for (cp = pts + strlen(pts) - 1; isdigit(*cp); --cp) + /* nothing */; + + ptyid = atoi(++cp); + if (ptyid > 999 || strlen(pts + 5) > sizeof(utmp.ut_line)) + die("Incorrect pts name %s\n", pts); + sprintf(buf + 1, "%03d", ptyid); + strncpy(utmp.ut_id, buf, 4); + + /* remove /dev/ part of the string */ + strncpy(utmp.ut_line, pts + 5, sizeof(utmp.ut_line)); + + if(!findutmp(DEAD_PROCESS)) + findutmp(USER_PROCESS); + + utmp.ut_type = USER_PROCESS; + strncpy(utmp.ut_user, pass->pw_name, sizeof(utmp.ut_user)); + utmp.ut_pid = getpid(); + utmp.ut_tv.tv_sec = time(NULL); + utmp.ut_tv.tv_usec = 0; + /* don't use no standard fields host and session */ + + setgid(egid); + if(!pututxline(&utmp)) + die("error adding utmp entry:%s", strerror(errno)); + setgid(gid); + endutxent(); +} + +void +delutmp(void) +{ + struct utmpx *r; + + setutxent(); + if((r = getutxline(&utmp)) != NULL) { + r->ut_type = DEAD_PROCESS; + r->ut_tv.tv_usec = r->ut_tv.tv_sec = 0; + setgid(egid); + if (!pututxline(r)) + die("error removing utmp entry:%s", strerror(errno)); + setgid(gid); + } + endutxent(); +} + diff --git a/utmp.1 b/utmp.1 index 7df9cf2..ec2409d 100644 --- a/utmp.1 +++ b/utmp.1 _AT_@ -20,8 +20,3 @@ are passed to the child shell. Written by Roberto E. Vargas Caballero .SH LICENSE See the LICENSE file for the terms of distribution. -.SH BUGS -utmp uses the posix interface defined in POSIX.1-2001. OpenBSD -and others BSD system don't implement these standard functions, so -this code could not be portable to them. - diff --git a/utmp.c b/utmp.c index 013f020..6ab5289 100644 --- a/utmp.c +++ b/utmp.c _AT_@ -1,5 +1,4 @@ -/* See LICENSE for license details. */ -#define _POSIX_C_SOURCE 200112L + #include <errno.h> #include <ctype.h> _AT_@ -7,18 +6,21 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <time.h> #include <sys/types.h> #include <unistd.h> -#include <utmpx.h> #include <pwd.h> #include <grp.h> #include <sys/wait.h> -static struct utmpx utmp; -static struct passwd *pass; -static gid_t egid, gid; + +#ifndef _POSIX_SAVED_IDS +#error "This program needs saved id behaviour" +#endif + + +struct passwd *pass; +gid_t egid, gid; void _AT_@ -27,110 +29,25 @@ die(const char *fmt, ...) va_list va; va_start(va, fmt); vfprintf(stderr, fmt, va); + putc('\n', stderr); va_end(va); exit(EXIT_FAILURE); } -/* - * From utmp(5) - * xterm and other terminal emulators directly create a USER_PROCESS - * record and generate the ut_id by using the string that suffix part of - * the terminal name (the characters following /dev/[pt]ty). If they find - * a DEAD_PROCESS for this ID, they recycle it, otherwise they create a new - * entry. If they can, they will mark it as DEAD_PROCESS on exiting and it - * is advised that they null ut_line, ut_time, ut_user, and ut_host as well. - */ - -struct utmpx * -findutmp(int type) -{ - struct utmpx *r; - - utmp.ut_type = type; - setutxent(); - for(;;) { - /* - * we can not use getutxline because we can search in - * DEAD_PROCESS to - */ - if(!(r = getutxid(&utmp))) - break; - if(!strcmp(r->ut_line, utmp.ut_line)) - break; - memset(r, 0, sizeof(*r)); /* for Solaris, IRIX64 and HPUX */ - } - return r; -} - -void -addutmp(int fd) -{ - unsigned ptyid; - char *pts, *cp, buf[5] = {'x'}; - - if ((pts = ttyname(fd)) == NULL) - die("error getting pty name\n"); - - for (cp = pts + strlen(pts) - 1; isdigit(*cp); --cp) - /* nothing */; - - ptyid = atoi(++cp); - if (ptyid > 999 || strlen(pts + 5) > sizeof(utmp.ut_line)) - die("Incorrect pts name %s\n", pts); - sprintf(buf + 1, "%03d", ptyid); - strncpy(utmp.ut_id, buf, 4); - - /* remove /dev/ part of the string */ - strcpy(utmp.ut_line, pts + 5); - - if(!findutmp(DEAD_PROCESS)) - findutmp(USER_PROCESS); - - utmp.ut_type = USER_PROCESS; - strcpy(utmp.ut_user, pass->pw_name); - utmp.ut_pid = getpid(); - utmp.ut_tv.tv_sec = time(NULL); - utmp.ut_tv.tv_usec = 0; - /* don't use no standard fields host and session */ - - setgid(egid); - if(!pututxline(&utmp)) - perror("add utmp entry"); - setgid(gid); - endutxent(); -} - -void -delutmp(void) -{ - struct utmpx *r; - - setutxent(); - if((r = getutxline(&utmp)) != NULL) { - r->ut_type = DEAD_PROCESS; - r->ut_tv.tv_usec = r->ut_tv.tv_sec = 0; - setgid(egid); - pututxline(r); - setgid(gid); - } - endutxent(); -} - int main(int argc, char *argv[]) { int status; uid_t uid; + extern void addutmp(void), delutmp(void); egid = getegid(); gid = getgid(); setgid(gid); pass = getpwuid(uid = getuid()); - if(!pass || !pass->pw_name || - strlen(pass->pw_name) + 1 > sizeof(utmp.ut_user)) { - die("Process is running with an incorrect uid %d\n", uid); - } + if (!pass || !pass->pw_name) + die("Process is running with an incorrect uid %d", uid); setenv("LOGNAME", pass->pw_name, 1); setenv("USER", pass->pw_name, 1); _AT_@ -140,11 +57,11 @@ main(int argc, char *argv[]) switch (fork()) { case 0: execv(getenv("SHELL"), ++argv); - die("error executing shell:%s\n", strerror(errno)); + die("error executing shell:%s", strerror(errno)); case -1: - die("error spawning child:%s\n", strerror(errno)); + die("error spawning child:%s", strerror(errno)); default: - addutmp(STDIN_FILENO); + addutmp(); if (wait(&status) == -1) { fprintf(stderr, "error waiting child:%s\n", strerror(errno)); _AT_@ -153,4 +70,3 @@ main(int argc, char *argv[]) } return 0; } - -- 1.8.3.3Received on Wed Aug 14 2013 - 16:56:11 CEST
This archive was generated by hypermail 2.3.0 : Wed Aug 14 2013 - 17:00:10 CEST