summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/misc/Makefile2
-rw-r--r--libc/misc/utmp/Makefile43
-rw-r--r--libc/misc/utmp/utent.c135
-rw-r--r--libc/pwd_grp/Makefile3
-rw-r--r--libc/unistd/Makefile2
-rw-r--r--libc/unistd/getpass.c99
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;
+}