diff options
Diffstat (limited to 'libc')
-rw-r--r-- | libc/misc/Makefile | 2 | ||||
-rw-r--r-- | libc/misc/utmp/Makefile | 43 | ||||
-rw-r--r-- | libc/misc/utmp/utent.c | 135 | ||||
-rw-r--r-- | libc/pwd_grp/Makefile | 3 | ||||
-rw-r--r-- | libc/unistd/Makefile | 2 | ||||
-rw-r--r-- | libc/unistd/getpass.c | 99 |
6 files changed, 280 insertions, 4 deletions
diff --git a/libc/misc/Makefile b/libc/misc/Makefile index 32fc4371d..5c16c5478 100644 --- a/libc/misc/Makefile +++ b/libc/misc/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)Rules.mak LIBC=$(TOPDIR)libc.a -DIRS = assert crypt ctype fnmatch glob internals lsearch mntent syslog regex shm time +DIRS = assert crypt ctype fnmatch glob internals lsearch mntent syslog regex shm time utmp all: libc.a diff --git a/libc/misc/utmp/Makefile b/libc/misc/utmp/Makefile new file mode 100644 index 000000000..01b070f3e --- /dev/null +++ b/libc/misc/utmp/Makefile @@ -0,0 +1,43 @@ +# Makefile for uClibc +# +# Copyright (C) 2000 by Lineo, inc. +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Derived in part from the Linux-8086 C library, the GNU C Library, and several +# other sundry sources. Files within this library are copyright by their +# respective copyright holders. + +TOPDIR=../../ +include $(TOPDIR)Rules.mak +LIBC=$(TOPDIR)libc.a + +CSRC=utent.c +COBJS=$(patsubst %.c,%.o, $(CSRC)) +OBJS=$(COBJS) + +all: $(LIBC) + +$(LIBC): ar-target + +ar-target: $(OBJS) + $(AR) $(ARFLAGS) $(LIBC) $(OBJS) + +$(COBJS): + $(CC) $(CFLAGS) $< -c $*.c -o $*.o + $(STRIPTOOL) -x -R .note -R .comment $*.o + +clean: + rm -f *.[oa] *~ core diff --git a/libc/misc/utmp/utent.c b/libc/misc/utmp/utent.c new file mode 100644 index 000000000..f9d098fb3 --- /dev/null +++ b/libc/misc/utmp/utent.c @@ -0,0 +1,135 @@ +/* utent.c <ndf@linux.mit.edu> */ +/* Let it be known that this is very possibly the worst standard ever. HP-UX + does one thing, someone else does another, linux another... If anyone + actually has the standard, please send it to me. + + Note that because of the way this stupid stupid standard works, you + have to call endutent() to close the file even if you've not called + setutent -- getutid and family use the same file descriptor. */ + +#include <unistd.h> +#include <fcntl.h> +#include <paths.h> +#include <errno.h> +#include <string.h> +#include <utmp.h> + +static const char *ut_name = _PATH_UTMP; + +static int ut_fd = -1; + +struct utmp *__getutent(int utmp_fd) +{ + static struct utmp utmp; + if (read(utmp_fd, (char *) &utmp, sizeof(struct utmp)) != + sizeof(struct utmp)) return NULL; + + return &utmp; +} + +void setutent(void) +{ + if (ut_fd != -1) + close(ut_fd); + if ((ut_fd = open(ut_name, O_RDONLY)) < 0) { + perror("setutent: Can't open utmp file"); + ut_fd = -1; + } +} + +void endutent(void) +{ + if (ut_fd != -1) + close(ut_fd); + ut_fd = -1; +} + +struct utmp *getutent(void) +{ + if (ut_fd == -1) + setutent(); + if (ut_fd == -1) + return NULL; + return __getutent(ut_fd); +} + +struct utmp *getutid(struct utmp *utmp_entry) +{ + struct utmp *utmp; + + if (ut_fd == -1) + setutent(); + if (ut_fd == -1) + return NULL; + + while ((utmp = __getutent(ut_fd)) != NULL) { + if ((utmp_entry->ut_type == RUN_LVL || + utmp_entry->ut_type == BOOT_TIME || + utmp_entry->ut_type == NEW_TIME || + utmp_entry->ut_type == OLD_TIME) && + utmp->ut_type == utmp_entry->ut_type) return utmp; + if ((utmp_entry->ut_type == INIT_PROCESS || + utmp_entry->ut_type == DEAD_PROCESS || + utmp_entry->ut_type == LOGIN_PROCESS || + utmp_entry->ut_type == USER_PROCESS) && + !strcmp(utmp->ut_id, utmp_entry->ut_id)) return utmp; + } + + return NULL; +} + +struct utmp *getutline(struct utmp *utmp_entry) +{ + struct utmp *utmp; + + if (ut_fd == -1) + setutent(); + if (ut_fd == -1) + return NULL; + +#if 0 + /* This is driving me nuts. It's not an implementation problem - + it's a matter of how things _SHOULD_ behave. Groan. */ + lseek(ut_fd, SEEK_CUR, -sizeof(struct utmp)); +#endif + + while ((utmp = __getutent(ut_fd)) != NULL) { + if ((utmp->ut_type == USER_PROCESS || + utmp->ut_type == LOGIN_PROCESS) && + !strcmp(utmp->ut_line, utmp_entry->ut_line)) return utmp; + } + + return NULL; +} + +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; +} + +void utmpname(const char *new_ut_name) +{ + if (new_ut_name != NULL) + ut_name = new_ut_name; + + if (ut_fd != -1) + close(ut_fd); +} diff --git a/libc/pwd_grp/Makefile b/libc/pwd_grp/Makefile index 38fa25611..7ed905ad3 100644 --- a/libc/pwd_grp/Makefile +++ b/libc/pwd_grp/Makefile @@ -25,8 +25,7 @@ include $(TOPDIR)Rules.mak LIBC=$(TOPDIR)libc.a CSRC=__getpwent.c pwent.c getpwnam.c getpwuid.c putpwent.c getpw.c fgetpwent.c \ - __getgrent.c grent.c getgrnam.c getgrgid.c fgetgrent.c initgroups.c \ - utent.c getpass.c + __getgrent.c grent.c getgrnam.c getgrgid.c fgetgrent.c initgroups.c COBJS=$(patsubst %.c,%.o, $(CSRC)) OBJS=$(COBJS) diff --git a/libc/unistd/Makefile b/libc/unistd/Makefile index 768437d38..faebda604 100644 --- a/libc/unistd/Makefile +++ b/libc/unistd/Makefile @@ -26,7 +26,7 @@ LIBC=$(TOPDIR)libc.a CSRC=execl.c execlp.c execv.c execvep.c execvp.c getcwd.c getopt.c \ - sleep.c sysconf.c + sleep.c sysconf.c getpass.c COBJS=$(patsubst %.c,%.o, $(CSRC)) OBJS=$(COBJS) diff --git a/libc/unistd/getpass.c b/libc/unistd/getpass.c new file mode 100644 index 000000000..4fcc489c8 --- /dev/null +++ b/libc/unistd/getpass.c @@ -0,0 +1,99 @@ +/* Copyright (C) 1992,93,94,95,96,97,98,99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <stdio.h> +#include <termios.h> +#include <unistd.h> +#include <string.h> + +/* It is desirable to use this bit on systems that have it. + The only bit of terminal state we want to twiddle is echoing, which is + done in software; there is no need to change the state of the terminal + hardware. */ + +#ifndef TCSASOFT +#define TCSASOFT 0 +#endif +#define PWD_BUFFER_SIZE 256 + +char * +getpass (prompt) + const char *prompt; +{ + FILE *in, *out; + struct termios s, t; + int tty_changed; + static char buf[PWD_BUFFER_SIZE]; + int nread; + + /* Try to write to and read from the terminal if we can. + If we can't open the terminal, use stderr and stdin. */ + + in = fopen ("/dev/tty", "w+"); + if (in == NULL) + { + in = stdin; + out = stderr; + } + else + out = in; + + /* Turn echoing off if it is on now. */ + + if (tcgetattr (fileno (in), &t) == 0) + { + /* Save the old one. */ + s = t; + /* Tricky, tricky. */ + t.c_lflag &= ~(ECHO|ISIG); + tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0); + } + else + tty_changed = 0; + + /* Write the prompt. */ + fputs(prompt, out); + fflush(out); + + /* Read the password. */ + fgets (buf, PWD_BUFFER_SIZE-1, in); + nread = strlen(buf); + if (buf != NULL) + { + if (nread < 0) + buf[0] = '\0'; + else if (buf[nread - 1] == '\n') + { + /* Remove the newline. */ + buf[nread - 1] = '\0'; + if (tty_changed) + /* Write the newline that was not echoed. */ + putc('\n', out); + } + } + + /* Restore the original setting. */ + if (tty_changed) + (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s); + + if (in != stdin) + /* We opened the terminal; now close it. */ + fclose (in); + + return buf; +} |