Hi All! Finally I think the library including the utmp wrappers is fit for distribution in unstable. There are several points I have to make, though. There still are programs out there tht will write to utmp using their own functions, nto the libc5 functions. This was bad in the first place and will end in corrupting utmp now. Of all programs I checked, screen and ssh (when linked with libc5) are the only ones writing to utmp using an own function. There probably will be more, so don't be too sure about it. The list below tells about the programs I checked in the source. A lot of programs will stop functioning correctly when this library is installed (namely those reading utmp using a utmp interface of their own). Again some of them are listed below. lastlog and wtmp _will_ be corrupted when libc5 and libc6 programs write to them, as libc5 does not provide library functions to do so. I am working on a program testing these files for new data and fixing it every now and then, but it will be some time until I finish this. I have done some testing on wtmp, and noticed that it will be _very_ hard to do this correctly. As much less programs use wtmp, it should not be hard to make all of them use libc6. Please read this file carefully before installing this library. Probably there will be problems, but I hope it won't be too bad. Have fun, Helmut -------------- utmp-wrapper.README --------------------------- This release of libc 5.4.33 for Debian contains wrapping functions to the main UTMP writing and reading functions. This means that this C library will (differing from the standard release made by H.J. Lu) write UTMP entries in the new format that is used by glibc 2.x . It will not, however, make the advanced features of this UTMP format available to programs compiled and linked with libc5. WARNING: There are still programs out there that may thrash the utmp file. lastlog and wtmp are not at all touched by these wrapper functions. As there will be (at least for a time) both libc5 and libc6 programs writing to these files (and there is no clean way to do so in libc5) these files will be corrupt. I'm working on a deamon fixing these files on a regular basis. glibc 2.1.4 will include a utmp_daemon program that will handle all these problems. It will even be capable of catching programs that do not use the libc functions to interact with the utmp file. It uses, however, features that are not part of 2.0.4, so for now this libc5 wrapper for utmp will be used on Debian. Note that utmp corruptions may happen through direct utmp access. THIS IS HIGHLY EXPERIMENTAL SOFTWARE FOR NOW. I tested it a lot on my system and didn't have any utmp corruption for two weeks. So I hope it won't bite too many people. The only program I found writing to utmp that does not work correctly in hamm is screen. These wrapper functions provide the following functions: void setutent(void); void utmpname(const char *name); struct utmp *getutent(void); struct utmp *getutid(struct utmp *ut); struct utmp *getutline(struct utmp *ut); static struct utmp *_pututline(struct utmp *ut); void pututline(struct utmp *ut); void endutent(void); The following files have been modified to achieve this (all relative to the libc source directory): login/utmp2.c this module is no longer used in the C library, the libc6 routines from utmp_file.c are used instead login/getlogin.c use new_utmp indstead of utmp. inet/ruserpass.c use new_utmp indstead of utmp, convert to old_utmp. these files have been added: login/utmp-wrap.h these two are new, based on the utmp.h files from login/utmp-wrap.c libc5 and glibc 2. login/utmp_file.c (from glibc 2.0.4) this file has been modified to use new_utmp as standard type and to export the functions. see below for exact changes to the glibc 2.0.4 version PROBLEMS and BUGS: Note that the functions in libbsd were not replaced. The only critical of them is logout which does not use the libc function. If there are programs using this, please tell me. Furthermore the lastlog structs are incompatible as well. As there are no lastlog functions in libc5 (only the struct definition) this cannot be solved using this wrapper. The only way to solve this is to modify all programs using lastlog. Something similar hold for all wtmp handling. As there is no clean way to convert utmp on a running system, I recommend rebooting to make all prgrams use the utmp-wrapping functions. The C library run-time package contains a UTMP converter program. You will find this wrapper program at /usr/sbin/utmp-conv. A manpage is available from section 8. -------------- Programs tested ------------------------------ This is a list of programs known to interact with /var run/utmp. I checked the sources of these programs to detect whether they will work with the wrapper functions or not. Programs reading utmp may not work correctly, but will cause no corruption. Luckily nearly all programs writing to utmp (that I tested) do The Right Thing[TM]. !! The notable exception is screen, which uses the libc functions only !! !! when compiled with libc6. !! Some remarks on wtmp: All programs writing/reading to wtmp should use the function logwtmp supplied by libc6 when compiled against it. Programs using utmp in the wrong way: - syslogd: read-only, so not too bad. However, the messaging won't work. Fix: use the fixes below - wall (bsdutils): as above. - write (bsdmainutils): as above. the fix is not optimal. Using getutline and getutid would be better, but I was too lazy to add these changes. - shellutils (who, users) use an own way to access the complete utmp file at once. This is _NOT_ recommended, even for reading. The current version in hamm uses libc6, so there are no problems with compatibility, but it should be fixed nevertheless. - zsh : watch will not work when linked to libc5. the same as above aplies - tcsh: watch and who will not work when linked to libc5. Again the same as above aplies - netstd : all programs I checked use the wrong way. All programs are read-only, though. | - screen does not the Right Thing when compiled with libc5, but it | | does so when compiled with libc6. | | !!! SCREEN DOES WRITE TO UTMP AND DOES NOT THE RIGHT THING !!! | | - ssh does not the Right Thing when compiled with libc5. | | !!! SSH DOES WRITE TO UTMP AND DOES NOT THE RIGHT THING !!! | Programs using utmp in the right way, but need some attention still or will only work correctly when compiled against libc6 for wtmp and/or lastlog: - sysvinit (uses wtmp as well) - shadow ( -"- ) the md5 routines are not included in the libc6 version (as it provides libcrypt). As the routine that is responsible for generating the salt is based on the specific md5 implementation used in this package, it won't compile. As libc6 supports shadow passwd and md5 passwd, this suite should be heaviliy modified to make use of this. A fix to make it compile (and work) with libc6 is to define CRYPTOBJS="md5.o md5crypt.o" regardless of finding a libcrypt. - login (poeigl) (uses wtmp as well) - rxvt (uses wtmp as well) - xterm, sessreg (use wtmp as well) - pppd (uses wtmp as well) Programs completely without problems: - agetty (poeigl) -------------- FIXES ------------------- diff -ur sysklogd-1.3.orig/syslogd.c sysklogd-1.3/syslogd.c --- sysklogd-1.3.orig/syslogd.c Mon Jun 9 19:33:19 1997 +++ sysklogd-1.3/syslogd.c Mon Jun 9 19:39:15 1997 @@ -408,7 +408,6 @@ static int nlogs = -1; static int restart = 0; -#define UNAMESZ 8 /* length of a login name */ #define MAXUNAMES 20 /* maximum number of user names */ #define MAXFNAME 200 /* max file pathname length */ @@ -453,7 +452,7 @@ time_t f_time; /* time this was last written */ u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */ union { - char f_uname[MAXUNAMES][UNAMESZ+1]; + char f_uname[MAXUNAMES][UT_NAMESIZE+1]; struct { char f_hname[MAXHOSTNAMELEN+1]; struct sockaddr_in f_addr; @@ -1628,24 +1627,18 @@ register struct filed *f; struct iovec *iov; { - char p[6 + UNAMESZ]; + char p[6 + UT_LINESIZE]; register int i; int ttyf, len; - FILE *uf; static int reenter = 0; - struct utmp ut; + struct utmp *ut; char greetings[200]; if (reenter++) return; /* open the user login file */ - if ((uf = fopen(UTMP_FILE, "r")) == NULL) { - logerror(UTMP_FILE); - reenter = 0; - return; - } - + setutent(); /* * Might as well fork instead of using nonblocking I/O * and doing notty(). @@ -1664,13 +1657,13 @@ len = strlen(greetings); /* scan the user login file */ - while (fread((char *) &ut, sizeof(ut), 1, uf) == 1) { + while ((ut=getutent())!=NULL) { /* is this slot used? */ - if (ut.ut_name[0] == '\0') + if (ut->ut_name[0] == '\0') continue; - if (ut.ut_type == LOGIN_PROCESS) + if (ut->ut_type == LOGIN_PROCESS) continue; - if (!(strcmp (ut.ut_name,"LOGIN"))) /* paranoia */ + if (!(strcmp (ut->ut_name,"LOGIN"))) /* paranoia */ continue; /* should we send the message to this user? */ @@ -1681,7 +1674,7 @@ break; } if (strncmp(f->f_un.f_uname[i], - ut.ut_name, UNAMESZ) == 0) + ut->ut_name, UT_NAMESIZE) == 0) break; } if (i >= MAXUNAMES) @@ -1690,7 +1683,7 @@ /* compute the device name */ strcpy(p, _PATH_DEV); - strncat(p, ut.ut_line, UNAMESZ); + strncat(p, ut->ut_line, UT_LINESIZE); if (f->f_type == F_WALL) { iov[0].iov_base = greetings; @@ -1716,7 +1709,7 @@ exit(0); } /* close the user login file */ - (void) fclose(uf); + endutent(); reenter = 0; } @@ -2286,9 +2279,9 @@ for (i = 0; i < MAXUNAMES && *p; i++) { for (q = p; *q && *q != ','; ) q++; - (void) strncpy(f->f_un.f_uname[i], p, UNAMESZ); - if ((q - p) > UNAMESZ) - f->f_un.f_uname[i][UNAMESZ] = '\0'; + (void) strncpy(f->f_un.f_uname[i], p, UT_NAMESIZE); + if ((q - p) > UT_NAMESIZE) + f->f_un.f_uname[i][UT_NAMESIZE] = '\0'; else f->f_un.f_uname[i][q - p] = '\0'; while (*q == ',' || *q == ' ') diff -ur bsdmainutils-3.3.orig/write.c bsdmainutils-3.3/write.c --- bsdmainutils-3.3.orig/write.c Wed Mar 12 00:33:57 1997 +++ bsdmainutils-3.3/write.c Mon Jun 9 20:35:49 1997 @@ -141,21 +141,18 @@ utmp_chk(user, tty) char *user, *tty; { - struct utmp u; - int ufd; + struct utmp *u; - if ((ufd = open(_PATH_UTMP, O_RDONLY)) < 0) - return(0); /* ignore error, shouldn't happen anyway */ - - while (read(ufd, (char *) &u, sizeof(u)) == sizeof(u)) - if (u.ut_type == USER_PROCESS && - strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0 && - strncmp(tty, u.ut_line, sizeof(u.ut_line)) == 0) { - (void)close(ufd); + setutent(); + while ((u=getutent())!=NULL) + if (u->ut_type == USER_PROCESS && + strncmp(user, u->ut_name, sizeof(u->ut_name)) == 0 && + strncmp(tty, u->ut_line, sizeof(u->ut_line)) == 0) { + endutent(); return(0); } - (void)close(ufd); + endutent(); return(1); } @@ -174,24 +171,21 @@ char *user, *tty, *mytty; uid_t myuid; { - struct utmp u; + struct utmp *u; time_t bestatime, atime; int ufd, nloggedttys, nttys, msgsok, user_is_me; char atty[UT_LINESIZE + 1]; - if ((ufd = open(_PATH_UTMP, O_RDONLY)) < 0) { - perror("utmp"); - exit(1); - } + setutent(); nloggedttys = nttys = 0; bestatime = 0; user_is_me = 0; - while (read(ufd, (char *) &u, sizeof(u)) == sizeof(u)) - if (u.ut_type == USER_PROCESS && - strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0) { + while ((u=getutent())!=NULL) + if (u->ut_type == USER_PROCESS && + strncmp(user, u->ut_name, sizeof(u->ut_name)) == 0) { ++nloggedttys; - (void)strncpy(atty, u.ut_line, UT_LINESIZE); + (void)strncpy(atty, u->ut_line, UT_LINESIZE); atty[UT_LINESIZE] = '\0'; if (term_chk(atty, &msgsok, &atime, 0)) continue; /* bad term? skip */ @@ -207,15 +201,15 @@ * it, and the atime will be way in the * past. So, if the atime is < utmp creation * time, use the utmp time. */ - if (atime < u.ut_time) - atime = u.ut_time; + if (atime < u->ut_time) + atime = u->ut_time; if (atime > bestatime) { bestatime = atime; (void)strcpy(tty, atty); } } - (void)close(ufd); + endutent(); if (nloggedttys == 0) { (void)fprintf(stderr, "write: %s is not logged in\n", user); exit(1); diff -ur bsdutils-3.2/wall.c bsdutils-3.2.new/wall.c --- bsdutils-3.2/wall.c Sun Jun 1 17:44:40 1997 +++ bsdutils-3.2.new/wall.c Mon Jun 9 19:53:11 1997 @@ -76,10 +76,10 @@ extern int optind; int ch; struct iovec iov; - struct utmp utmp; + struct utmp *utmp; FILE *fp; char *p, *ttymsg(); - char line[sizeof(utmp.ut_line) + 1]; + char line[sizeof(utmp->ut_line) + 1]; while ((ch = getopt(argc, argv, "n")) != EOF) switch (ch) { @@ -101,26 +101,24 @@ makemsg(*argv); - if (!(fp = fopen(_PATH_UTMP, "r"))) { - (void)fprintf(stderr, "wall: cannot read %s.\n", _PATH_UTMP); - exit(1); - } + setutent(); iov.iov_base = mbuf; iov.iov_len = mbufsize; /* NOSTRICT */ - while (fread((char *)&utmp, sizeof(utmp), 1, fp) == 1) { - if (!utmp.ut_name[0] || + while ((utmp=getutent())!=NULL) { + if (!utmp->ut_name[0] || v #ifdef DEBIAN - utmp.ut_type != USER_PROCESS || - !strncmp(utmp.ut_id, ":0", 2) || + utmp->ut_type != USER_PROCESS || + !strncmp(utmp->ut_id, ":0", 2) || #endif /* DEBIAN */ - !strncmp(utmp.ut_name, IGNOREUSER, sizeof(utmp.ut_name))) + !strncmp(utmp->ut_name, IGNOREUSER, sizeof(utmp->ut_name))) continue; - strncpy(line, utmp.ut_line, sizeof(utmp.ut_line)); - line[sizeof(utmp.ut_line)] = '\0'; + strncpy(line, utmp->ut_line, sizeof(utmp->ut_line)); + line[sizeof(utmp->ut_line)] = '\0'; if ((p = ttymsg(&iov, 1, line, 60*5)) != NULL) (void)fprintf(stderr, "wall: %s\n", p); } + endutent(); exit(0); } -- Helmut Geyer Helmut.Geyer@iwr.uni-heidelberg.de public PGP key available : finger geyer@saturn.iwr.uni-heidelberg.de
Attachment:
pgpTvioryOm0x.pgp
Description: PGP signature