mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Add finger demo to redbean and fix regression
This change fixes a regression in unix.connect() caused by the recent addition of UNIX domain sockets. The BSD finger command has been added to third_party for fun and profit. A new demo has been added to redbean showing how a protocol as simple as finger can be implemented.
This commit is contained in:
parent
2415afab0e
commit
17cbe73411
34 changed files with 2454 additions and 29 deletions
1
Makefile
1
Makefile
|
@ -148,6 +148,7 @@ include third_party/linenoise/linenoise.mk
|
||||||
include third_party/maxmind/maxmind.mk
|
include third_party/maxmind/maxmind.mk
|
||||||
include third_party/lua/lua.mk
|
include third_party/lua/lua.mk
|
||||||
include third_party/make/make.mk
|
include third_party/make/make.mk
|
||||||
|
include third_party/finger/finger.mk
|
||||||
include third_party/argon2/argon2.mk
|
include third_party/argon2/argon2.mk
|
||||||
include third_party/smallz4/smallz4.mk
|
include third_party/smallz4/smallz4.mk
|
||||||
include third_party/sqlite3/sqlite3.mk
|
include third_party/sqlite3/sqlite3.mk
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
* @param service is the port number as a string
|
* @param service is the port number as a string
|
||||||
* @param hints may be passed to specialize behavior (optional)
|
* @param hints may be passed to specialize behavior (optional)
|
||||||
* @param res receives a pointer that must be freed with freeaddrinfo(),
|
* @param res receives a pointer that must be freed with freeaddrinfo(),
|
||||||
* and won't be modified if -1 is returned
|
* and won't be modified if non-zero is returned
|
||||||
* @return 0 on success or EAI_xxx value
|
* @return 0 on success or EAI_xxx value
|
||||||
* @threadsafe
|
* @threadsafe
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
@ -19,8 +19,10 @@
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies memory the legacy way.
|
* Moves memory the BSD way.
|
||||||
|
*
|
||||||
|
* Please use memmove() instead. Note the order of arguments.
|
||||||
*/
|
*/
|
||||||
void *bcopy(void *dst, const void *src, size_t n) {
|
void bcopy(const void *src, void *dest, size_t n) {
|
||||||
return memmove(dst, src, n);
|
memmove(dest, src, n);
|
||||||
}
|
}
|
4
libc/isystem/utmp.h
Normal file
4
libc/isystem/utmp.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_UTMP_H_
|
||||||
|
#define COSMOPOLITAN_LIBC_ISYSTEM_UTMP_H_
|
||||||
|
#include "libc/runtime/utmp.h"
|
||||||
|
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_UTMP_H_ */
|
4
libc/isystem/utmpx.h
Normal file
4
libc/isystem/utmpx.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_UTMPX_H_
|
||||||
|
#define COSMOPOLITAN_LIBC_ISYSTEM_UTMPX_H_
|
||||||
|
#include "libc/runtime/utmpx.h"
|
||||||
|
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_UTMPX_H_ */
|
28
libc/runtime/__utmpxname.S
Normal file
28
libc/runtime/__utmpxname.S
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
|
__utmpxname:
|
||||||
|
.errno
|
||||||
|
mov ENOTSUP(%rip),%edx
|
||||||
|
mov %edx,(%rax)
|
||||||
|
ret
|
||||||
|
.endfn __utmpxname,globl
|
||||||
|
.alias __utmpxname,utmpname
|
||||||
|
.alias __utmpxname,utmpxname
|
47
libc/runtime/utmp.h
Normal file
47
libc/runtime/utmp.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef COSMOPOLITAN_LIBC_RUNTIME_UTMP_H_
|
||||||
|
#define COSMOPOLITAN_LIBC_RUNTIME_UTMP_H_
|
||||||
|
#include "libc/calls/weirdtypes.h"
|
||||||
|
#include "libc/runtime/utmpx.h"
|
||||||
|
|
||||||
|
#define ACCOUNTING 9
|
||||||
|
#define UT_NAMESIZE 32
|
||||||
|
#define UT_HOSTSIZE 256
|
||||||
|
#define UT_LINESIZE 32
|
||||||
|
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
struct lastlog {
|
||||||
|
time_t ll_time;
|
||||||
|
char ll_line[UT_LINESIZE];
|
||||||
|
char ll_host[UT_HOSTSIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ut_time ut_tv.tv_sec
|
||||||
|
#define ut_name ut_user
|
||||||
|
#define ut_addr ut_addr_v6[0]
|
||||||
|
#define utmp utmpx
|
||||||
|
#define e_exit __e_exit
|
||||||
|
#define e_termination __e_termination
|
||||||
|
|
||||||
|
int login_tty(int);
|
||||||
|
int utmpname(const char *);
|
||||||
|
struct utmp *getutent(void);
|
||||||
|
struct utmp *getutid(const struct utmp *);
|
||||||
|
struct utmp *getutline(const struct utmp *);
|
||||||
|
struct utmp *pututline(const struct utmp *);
|
||||||
|
void endutent(void);
|
||||||
|
void setutent(void);
|
||||||
|
void updwtmp(const char *, const struct utmp *);
|
||||||
|
|
||||||
|
#define _PATH_UTMP "/dev/null/utmp"
|
||||||
|
#define _PATH_WTMP "/dev/null/wtmp"
|
||||||
|
|
||||||
|
#define UTMP_FILE _PATH_UTMP
|
||||||
|
#define WTMP_FILE _PATH_WTMP
|
||||||
|
#define UTMP_FILENAME _PATH_UTMP
|
||||||
|
#define WTMP_FILENAME _PATH_WTMP
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_LIBC_RUNTIME_UTMP_H_ */
|
51
libc/runtime/utmpx.h
Normal file
51
libc/runtime/utmpx.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef COSMOPOLITAN_LIBC_RUNTIME_UTMPX_H_
|
||||||
|
#define COSMOPOLITAN_LIBC_RUNTIME_UTMPX_H_
|
||||||
|
#include "libc/calls/struct/timeval.h"
|
||||||
|
#include "libc/calls/weirdtypes.h"
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
struct utmpx {
|
||||||
|
short ut_type;
|
||||||
|
pid_t ut_pid;
|
||||||
|
char ut_line[32];
|
||||||
|
char ut_id[4];
|
||||||
|
char ut_user[32];
|
||||||
|
char ut_host[256];
|
||||||
|
struct {
|
||||||
|
short __e_termination;
|
||||||
|
short __e_exit;
|
||||||
|
} ut_exit;
|
||||||
|
long ut_session;
|
||||||
|
struct timeval ut_tv;
|
||||||
|
unsigned ut_addr_v6[4];
|
||||||
|
char __unused[20];
|
||||||
|
};
|
||||||
|
|
||||||
|
void endutxent(void);
|
||||||
|
struct utmpx *getutxent(void);
|
||||||
|
struct utmpx *getutxid(const struct utmpx *);
|
||||||
|
struct utmpx *getutxline(const struct utmpx *);
|
||||||
|
struct utmpx *pututxline(const struct utmpx *);
|
||||||
|
void setutxent(void);
|
||||||
|
|
||||||
|
#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||||
|
#define e_exit __e_exit
|
||||||
|
#define e_termination __e_termination
|
||||||
|
void updwtmpx(const char *, const struct utmpx *);
|
||||||
|
int utmpxname(const char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define EMPTY 0
|
||||||
|
#define RUN_LVL 1
|
||||||
|
#define BOOT_TIME 2
|
||||||
|
#define NEW_TIME 3
|
||||||
|
#define OLD_TIME 4
|
||||||
|
#define INIT_PROCESS 5
|
||||||
|
#define LOGIN_PROCESS 6
|
||||||
|
#define USER_PROCESS 7
|
||||||
|
#define DEAD_PROCESS 8
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_LIBC_RUNTIME_UTMPX_H_ */
|
|
@ -19,7 +19,9 @@
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/sock/sockdebug.h"
|
#include "libc/sock/sockdebug.h"
|
||||||
#include "libc/sock/syscall_fd.internal.h"
|
#include "libc/sock/syscall_fd.internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
|
@ -89,6 +89,7 @@ void *memcpy(void *restrict, const void *restrict, size_t) memcpyesque;
|
||||||
void *mempcpy(void *restrict, const void *restrict, size_t) memcpyesque;
|
void *mempcpy(void *restrict, const void *restrict, size_t) memcpyesque;
|
||||||
void *memccpy(void *restrict, const void *restrict, int, size_t) memcpyesque;
|
void *memccpy(void *restrict, const void *restrict, int, size_t) memcpyesque;
|
||||||
void *memeqmask(void *, const void *, const void *, size_t) memcpyesque;
|
void *memeqmask(void *, const void *, const void *, size_t) memcpyesque;
|
||||||
|
void bcopy(const void *, void *, size_t) memcpyesque;
|
||||||
void explicit_bzero(void *, size_t);
|
void explicit_bzero(void *, size_t);
|
||||||
|
|
||||||
int bcmp(const void *, const void *, size_t) strlenesque;
|
int bcmp(const void *, const void *, size_t) strlenesque;
|
||||||
|
|
26
libc/stubs/endutxent.S
Normal file
26
libc/stubs/endutxent.S
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
|
// Closes user accounting database.
|
||||||
|
// @note unsupported
|
||||||
|
endutxent:
|
||||||
|
ret
|
||||||
|
.endfn endutxent,globl
|
||||||
|
.alias endutxent,endutent
|
27
libc/stubs/getutxent.S
Normal file
27
libc/stubs/getutxent.S
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
|
// Reads next entry in user accounting database.
|
||||||
|
// @note unsupported
|
||||||
|
getutxent:
|
||||||
|
xor %eax,%eax
|
||||||
|
ret
|
||||||
|
.endfn getutxent,globl
|
||||||
|
.alias getutxent,getutent
|
27
libc/stubs/getutxid.S
Normal file
27
libc/stubs/getutxid.S
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
|
// Searches forward in the user accounting database.
|
||||||
|
// @note unsupported
|
||||||
|
getutxid:
|
||||||
|
xor %eax,%eax
|
||||||
|
ret
|
||||||
|
.endfn getutxid,globl
|
||||||
|
.alias getutxid,getutid
|
27
libc/stubs/getutxline.S
Normal file
27
libc/stubs/getutxline.S
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
|
// Searches forward in the user accounting database.
|
||||||
|
// @note unsupported
|
||||||
|
getutxline:
|
||||||
|
xor %eax,%eax
|
||||||
|
ret
|
||||||
|
.endfn getutxline,globl
|
||||||
|
.alias getutxline,getutline
|
27
libc/stubs/pututxline.S
Normal file
27
libc/stubs/pututxline.S
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
|
// Puts in the user accounting database.
|
||||||
|
// @note unsupported
|
||||||
|
pututxline:
|
||||||
|
xor %eax,%eax
|
||||||
|
ret
|
||||||
|
.endfn pututxline,globl
|
||||||
|
.alias pututxline,pututline
|
26
libc/stubs/setutxent.S
Normal file
26
libc/stubs/setutxent.S
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
|
// Rewinds the user accounting database.
|
||||||
|
// @note unsupported
|
||||||
|
setutxent:
|
||||||
|
ret
|
||||||
|
.endfn setutxent,globl
|
||||||
|
.alias setutxent,setutent
|
26
libc/stubs/updwtmpx.S
Normal file
26
libc/stubs/updwtmpx.S
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
|
// Does something to the user accounting database.
|
||||||
|
// @note unsupported
|
||||||
|
updwtmpx:
|
||||||
|
ret
|
||||||
|
.endfn updwtmpx,globl
|
||||||
|
.alias updwtmpx,updwtmp
|
165
third_party/finger/display.c
vendored
Normal file
165
third_party/finger/display.c
vendored
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1989 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include "libc/calls/ioctl.h"
|
||||||
|
#include "libc/calls/struct/termios.h"
|
||||||
|
#include "libc/calls/struct/winsize.h"
|
||||||
|
#include "libc/calls/termios.h"
|
||||||
|
#include "libc/fmt/fmt.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/sysv/consts/fileno.h"
|
||||||
|
#include "libc/sysv/consts/termios.h"
|
||||||
|
#include "third_party/finger/finger.h"
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
int
|
||||||
|
getscreenwidth(void)
|
||||||
|
{
|
||||||
|
struct winsize ws;
|
||||||
|
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0 || ws.ws_col==0) {
|
||||||
|
return 80;
|
||||||
|
}
|
||||||
|
return ws.ws_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
is8bit(void)
|
||||||
|
{
|
||||||
|
static int cache=-1;
|
||||||
|
struct termios tios;
|
||||||
|
if (cache>=0) return cache;
|
||||||
|
|
||||||
|
if (tcgetattr(STDIN_FILENO, &tios)<0) {
|
||||||
|
/* assume 8-bit; it's 1999 now, not 1972 */
|
||||||
|
cache = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cache = (tios.c_cflag & CSIZE)==CS8;
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************/
|
||||||
|
|
||||||
|
static int send_crs=0;
|
||||||
|
|
||||||
|
void
|
||||||
|
set_crmode(void)
|
||||||
|
{
|
||||||
|
send_crs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
fxputc(FILE *f, int ch)
|
||||||
|
{
|
||||||
|
/* drop any sign */
|
||||||
|
ch = ch&0xff;
|
||||||
|
|
||||||
|
/* on 7-bit terminals, strip high bit */
|
||||||
|
if (!is8bit()) ch &= 0x7f;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assume anything that isn't a control character is printable.
|
||||||
|
* We can't count on locale stuff to tell us what's printable
|
||||||
|
* because we might be looking at someone who uses different
|
||||||
|
* locale settings or is on the other side of the planet. So,
|
||||||
|
* strip 0-31, 127, 128-159, and 255. Note that not stripping
|
||||||
|
* 128-159 is asking for trouble, as 155 (M-esc) is interpreted
|
||||||
|
* as esc-[ by most terminals. Hopefully this won't break anyone's
|
||||||
|
* charset.
|
||||||
|
*
|
||||||
|
* It would be nice if we could set the terminal to display in the
|
||||||
|
* right charset, but we have no way to know what it is. feh.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (((ch&0x7f) >= 32 && (ch&0x7f) != 0x7f) || ch=='\t') {
|
||||||
|
putc(ch, f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch=='\n') {
|
||||||
|
if (send_crs) putc('\r', f);
|
||||||
|
putc('\n', f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch&0x80) {
|
||||||
|
putc('M', f);
|
||||||
|
putc('-', f);
|
||||||
|
ch &= 0x7f;
|
||||||
|
}
|
||||||
|
|
||||||
|
putc('^', f);
|
||||||
|
if (ch==0x7f) putc('?', f);
|
||||||
|
else putc(ch+'@', f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xputc(int ch)
|
||||||
|
{
|
||||||
|
fxputc(stdout, ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fxputs(FILE *f, const char *buf) {
|
||||||
|
int i;
|
||||||
|
for (i=0; buf[i]; i++) fxputc(f, buf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xprintf(const char *fmt, ...) {
|
||||||
|
char buf[1024];
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
fxputs(stdout, buf);
|
||||||
|
|
||||||
|
return strlen(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int eprintf(const char *fmt, ...) {
|
||||||
|
char buf[1024];
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
fxputs(stderr, buf);
|
||||||
|
|
||||||
|
return strlen(buf);
|
||||||
|
}
|
194
third_party/finger/finger.1
vendored
Normal file
194
third_party/finger/finger.1
vendored
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
.\" Copyright (c) 1989, 1990 The Regents of the University of California.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. All advertising materials mentioning features or use of this software
|
||||||
|
.\" must display the following acknowledgement:
|
||||||
|
.\" This product includes software developed by the University of
|
||||||
|
.\" California, Berkeley and its contributors.
|
||||||
|
.\" 4. Neither the name of the University nor the names of its contributors
|
||||||
|
.\" may be used to endorse or promote products derived from this software
|
||||||
|
.\" without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" from: @(#)finger.1 6.14 (Berkeley) 7/27/91
|
||||||
|
.\" $Id: finger.1,v 1.18 2000/07/30 23:56:57 dholland Exp $
|
||||||
|
.\"
|
||||||
|
.Dd August 15, 1999
|
||||||
|
.Dt FINGER 1
|
||||||
|
.Os "Linux NetKit (0.17)"
|
||||||
|
.Sh NAME
|
||||||
|
.Nm finger
|
||||||
|
.Nd user information lookup program
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm finger
|
||||||
|
.Op Fl lmsp
|
||||||
|
.Op Ar user ...
|
||||||
|
.Op Ar user@host ...
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Nm finger
|
||||||
|
displays information about the system users.
|
||||||
|
.Pp
|
||||||
|
Options are:
|
||||||
|
.Bl -tag -width flag
|
||||||
|
.It Fl s
|
||||||
|
.Nm Finger
|
||||||
|
displays the user's login name, real name, terminal name and write
|
||||||
|
status (as a ``*'' after the terminal name if write permission is
|
||||||
|
denied), idle time, login time, office location and office phone
|
||||||
|
number.
|
||||||
|
.Pp
|
||||||
|
Login time is displayed as month, day, hours and minutes, unless
|
||||||
|
more than six months ago, in which case the year is displayed rather
|
||||||
|
than the hours and minutes.
|
||||||
|
.Pp
|
||||||
|
Unknown devices as well as nonexistent idle and login times are
|
||||||
|
displayed as single asterisks.
|
||||||
|
.Pp
|
||||||
|
.It Fl l
|
||||||
|
Produces a multi-line format displaying all of the information
|
||||||
|
described for the
|
||||||
|
.Fl s
|
||||||
|
option as well as the user's home directory, home phone number, login
|
||||||
|
shell, mail status, and the contents of the files
|
||||||
|
.Dq Pa .plan ,
|
||||||
|
.Dq Pa .project ,
|
||||||
|
.Dq Pa .pgpkey
|
||||||
|
and
|
||||||
|
.Dq Pa .forward
|
||||||
|
from the user's home directory.
|
||||||
|
.Pp
|
||||||
|
Phone numbers specified as eleven digits are printed as ``+N-NNN-NNN-NNNN''.
|
||||||
|
Numbers specified as ten or seven digits are printed as the appropriate
|
||||||
|
subset of that string.
|
||||||
|
Numbers specified as five digits are printed as ``xN-NNNN''.
|
||||||
|
Numbers specified as four digits are printed as ``xNNNN''.
|
||||||
|
.Pp
|
||||||
|
If write permission is denied to the device, the phrase ``(messages off)''
|
||||||
|
is appended to the line containing the device name.
|
||||||
|
One entry per user is displayed with the
|
||||||
|
.Fl l
|
||||||
|
option; if a user is logged on multiple times, terminal information
|
||||||
|
is repeated once per login.
|
||||||
|
.Pp
|
||||||
|
Mail status is shown as ``No Mail.'' if there is no mail at all,
|
||||||
|
``Mail last read DDD MMM ## HH:MM YYYY (TZ)'' if the person has looked
|
||||||
|
at their mailbox since new mail arriving, or ``New mail received ...'',
|
||||||
|
`` Unread since ...'' if they have new mail.
|
||||||
|
.Pp
|
||||||
|
.It Fl p
|
||||||
|
Prevents
|
||||||
|
the
|
||||||
|
.Fl l
|
||||||
|
option of
|
||||||
|
.Nm finger
|
||||||
|
from displaying the contents of the
|
||||||
|
.Dq Pa .plan ,
|
||||||
|
.Dq Pa .project
|
||||||
|
and
|
||||||
|
.Dq Pa .pgpkey
|
||||||
|
files.
|
||||||
|
.It Fl m
|
||||||
|
Prevent matching of
|
||||||
|
.Ar user
|
||||||
|
names.
|
||||||
|
.Ar User
|
||||||
|
is usually a login name; however, matching will also be done on the
|
||||||
|
users' real names, unless the
|
||||||
|
.Fl m
|
||||||
|
option is supplied.
|
||||||
|
All name matching performed by
|
||||||
|
.Nm finger
|
||||||
|
is case insensitive.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
If no options are specified,
|
||||||
|
.Nm finger
|
||||||
|
defaults to the
|
||||||
|
.Fl l
|
||||||
|
style output if operands are provided, otherwise to the
|
||||||
|
.Fl s
|
||||||
|
style.
|
||||||
|
Note that some fields may be missing, in either format, if information
|
||||||
|
is not available for them.
|
||||||
|
.Pp
|
||||||
|
If no arguments are specified,
|
||||||
|
.Nm finger
|
||||||
|
will print an entry for each user currently logged into the system.
|
||||||
|
.Pp
|
||||||
|
.Nm Finger
|
||||||
|
may be used to look up users on a remote machine.
|
||||||
|
The format is to specify a
|
||||||
|
.Ar user
|
||||||
|
as
|
||||||
|
.Dq Li user@host ,
|
||||||
|
or
|
||||||
|
.Dq Li @host ,
|
||||||
|
where the default output
|
||||||
|
format for the former is the
|
||||||
|
.Fl l
|
||||||
|
style, and the default output format for the latter is the
|
||||||
|
.Fl s
|
||||||
|
style.
|
||||||
|
The
|
||||||
|
.Fl l
|
||||||
|
option is the only option that may be passed to a remote machine.
|
||||||
|
.Pp
|
||||||
|
If standard output is a socket,
|
||||||
|
.Nm finger
|
||||||
|
will emit a carriage return (^M) before every linefeed (^J). This is
|
||||||
|
for processing remote finger requests when invoked by
|
||||||
|
.Xr fingerd 8 .
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width mmmmmmmmmmmmmmm
|
||||||
|
.It Pa ~/.nofinger
|
||||||
|
If finger finds this file in a user's home directory, it will, for
|
||||||
|
finger requests originating outside the local host, firmly deny the
|
||||||
|
existence of that user. For this to work, the finger program, as
|
||||||
|
started by
|
||||||
|
.Xr fingerd 8 ,
|
||||||
|
must be able to see the
|
||||||
|
.Pa .nofinger
|
||||||
|
file. This generally means that the home directory containing the file
|
||||||
|
must have the other-users-execute bit set (o+w). See
|
||||||
|
.Xr chmod 1 .
|
||||||
|
If you use this feature for privacy, please test it with ``finger
|
||||||
|
@localhost'' before relying on it, just in case.
|
||||||
|
.It ~/.plan
|
||||||
|
.It ~/.project
|
||||||
|
.It ~/.pgp
|
||||||
|
These files are printed as part of a long-format request. The
|
||||||
|
.Pa .project
|
||||||
|
file is limited to one line; the
|
||||||
|
.Pa .plan
|
||||||
|
file may be arbitrarily long.
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr chfn 1 ,
|
||||||
|
.Xr passwd 1 ,
|
||||||
|
.Xr w 1 ,
|
||||||
|
.Xr who 1
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Nm finger
|
||||||
|
command appeared in
|
||||||
|
.Bx 3.0 .
|
333
third_party/finger/finger.c
vendored
Normal file
333
third_party/finger/finger.c
vendored
Normal file
|
@ -0,0 +1,333 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1989 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/struct/stat.h"
|
||||||
|
#include "libc/calls/weirdtypes.h"
|
||||||
|
#include "libc/fmt/fmt.h"
|
||||||
|
#include "libc/nt/struct/msg.h"
|
||||||
|
#include "libc/runtime/utmp.h"
|
||||||
|
#include "libc/sock/sock.h"
|
||||||
|
#include "libc/sysv/consts/fileno.h"
|
||||||
|
#include "libc/time/time.h"
|
||||||
|
#include "third_party/finger/finger.h"
|
||||||
|
#include "third_party/getopt/getopt.h"
|
||||||
|
#include "third_party/musl/passwd.h"
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mail status reporting added 931007 by Luke Mewburn, <zak@rmit.edu.au>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char copyright[] =
|
||||||
|
"@(#) Copyright (c) 1989 The Regents of the University of California.\n"
|
||||||
|
"All rights reserved.\n";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* from: @(#)finger.c 5.22 (Berkeley) 6/29/90
|
||||||
|
*/
|
||||||
|
char finger_rcsid[] = \
|
||||||
|
"$Id: finger.c,v 1.15 1999/12/18 16:41:51 dholland Exp $";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finger prints out information about users. It is not portable since
|
||||||
|
* certain fields (e.g. the full user name, office, and phone numbers) are
|
||||||
|
* extracted from the gecos field of the passwd file which other UNIXes
|
||||||
|
* may not have or may use for other things. (This is not really true any
|
||||||
|
* more, btw.)
|
||||||
|
*
|
||||||
|
* There are currently two output formats; the short format is one line
|
||||||
|
* per user and displays login name, tty, login time, real name, idle time,
|
||||||
|
* and office location/phone number. The long format gives the same
|
||||||
|
* information (in a more legible format) as well as home directory, shell,
|
||||||
|
* mail info, and .plan/.project files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void loginlist(void);
|
||||||
|
static void userlist(int argc, char *argv[]);
|
||||||
|
|
||||||
|
int lflag, pplan;
|
||||||
|
static int sflag, mflag;
|
||||||
|
static int enable_nofinger;
|
||||||
|
|
||||||
|
time_t now;
|
||||||
|
char tbuf[TBUFLEN];
|
||||||
|
|
||||||
|
PERSON *phead, *ptail; /* the linked list of all people */
|
||||||
|
int entries; /* number of people */
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int ch;
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
socklen_t slen = sizeof(sin);
|
||||||
|
|
||||||
|
while ((ch = getopt(argc, argv, "lmps")) != EOF) {
|
||||||
|
switch(ch) {
|
||||||
|
case 'l':
|
||||||
|
lflag = 1; /* long format */
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
mflag = 1; /* do exact match of names */
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
pplan = 1; /* don't show .plan/.project */
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
sflag = 1; /* short format */
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
case 'h':
|
||||||
|
default:
|
||||||
|
eprintf("usage: finger [-lmps] [login ...]\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
if (getsockname(STDOUT_FILENO, (struct sockaddr *)&sin, &slen)==0) {
|
||||||
|
/*
|
||||||
|
* stdout is a socket. must be a network finger request,
|
||||||
|
* so emit CRs with our LFs at the ends of lines.
|
||||||
|
*/
|
||||||
|
set_crmode();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Also, enable .nofinger processing.
|
||||||
|
*/
|
||||||
|
enable_nofinger = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Also check stdin for nofinger processing, because of older
|
||||||
|
* fingerds that make stdout a pipe for CRLF handling.
|
||||||
|
*/
|
||||||
|
if (getsockname(STDIN_FILENO, (struct sockaddr *)&sin, &slen)==0) {
|
||||||
|
enable_nofinger = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
|
||||||
|
setpwent();
|
||||||
|
|
||||||
|
if (!*argv) {
|
||||||
|
/*
|
||||||
|
* Assign explicit "small" format if no names given and -l
|
||||||
|
* not selected. Force the -s BEFORE we get names so proper
|
||||||
|
* screening will be done.
|
||||||
|
*/
|
||||||
|
if (!lflag) {
|
||||||
|
sflag = 1; /* if -l not explicit, force -s */
|
||||||
|
}
|
||||||
|
loginlist();
|
||||||
|
if (entries == 0) {
|
||||||
|
xprintf("No one logged on.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
userlist(argc, argv);
|
||||||
|
/*
|
||||||
|
* Assign explicit "large" format if names given and -s not
|
||||||
|
* explicitly stated. Force the -l AFTER we get names so any
|
||||||
|
* remote finger attempts specified won't be mishandled.
|
||||||
|
*/
|
||||||
|
if (!sflag)
|
||||||
|
lflag = 1; /* if -s not explicit, force -l */
|
||||||
|
}
|
||||||
|
if (entries != 0) {
|
||||||
|
if (lflag) lflag_print();
|
||||||
|
else sflag_print();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns 1 if .nofinger is found and enable_nofinger is set. */
|
||||||
|
static
|
||||||
|
int
|
||||||
|
check_nofinger(struct passwd *pw)
|
||||||
|
{
|
||||||
|
if (enable_nofinger) {
|
||||||
|
char path[PATH_MAX];
|
||||||
|
struct stat tripe;
|
||||||
|
snprintf(path, sizeof(path), "%s/.nofinger", pw->pw_dir);
|
||||||
|
if (stat(path, &tripe)==0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
loginlist(void)
|
||||||
|
{
|
||||||
|
PERSON *pn;
|
||||||
|
struct passwd *pw;
|
||||||
|
struct utmp *uptr;
|
||||||
|
char name[UT_NAMESIZE + 1];
|
||||||
|
|
||||||
|
name[UT_NAMESIZE] = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if (!freopen(_PATH_UTMP, "r", stdin)) {
|
||||||
|
* fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP);
|
||||||
|
* exit(2);
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
setutent();
|
||||||
|
while ((uptr = getutent())!=NULL) {
|
||||||
|
if (!uptr->ut_name[0])
|
||||||
|
continue;
|
||||||
|
#ifdef USER_PROCESS
|
||||||
|
if (uptr->ut_type != USER_PROCESS) continue;
|
||||||
|
#endif
|
||||||
|
if ((pn = find_person(uptr->ut_name)) == NULL) {
|
||||||
|
memcpy(name, uptr->ut_name, UT_NAMESIZE);
|
||||||
|
if ((pw = getpwnam(name)) == NULL)
|
||||||
|
continue;
|
||||||
|
if (check_nofinger(pw))
|
||||||
|
continue;
|
||||||
|
pn = enter_person(pw);
|
||||||
|
}
|
||||||
|
enter_where(uptr, pn);
|
||||||
|
}
|
||||||
|
for (pn = phead; lflag && pn != NULL; pn = pn->next)
|
||||||
|
enter_lastlog(pn);
|
||||||
|
endutent();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void do_local(int argc, char *argv[], int *used) {
|
||||||
|
int i;
|
||||||
|
struct passwd *pw;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* traverse the list of possible login names and check the login name
|
||||||
|
* and real name against the name specified by the user.
|
||||||
|
*/
|
||||||
|
if (mflag) {
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
if (used[i] >= 0 && (pw = getpwnam(argv[i]))) {
|
||||||
|
if (!check_nofinger(pw)) {
|
||||||
|
enter_person(pw);
|
||||||
|
used[i] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else for (pw = getpwent(); pw; pw = getpwent())
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
if (used[i] >= 0 &&
|
||||||
|
(!strcasecmp(pw->pw_name, argv[i]) ||
|
||||||
|
match(pw, argv[i]))) {
|
||||||
|
if (!check_nofinger(pw)) {
|
||||||
|
enter_person(pw);
|
||||||
|
used[i] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* list errors */
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
if (!used[i])
|
||||||
|
(void)eprintf("finger: %s: no such user.\n", argv[i]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
userlist(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
PERSON *pn;
|
||||||
|
PERSON *nethead, **nettail;
|
||||||
|
struct utmp *uptr;
|
||||||
|
int dolocal, *used;
|
||||||
|
|
||||||
|
used = calloc(argc, sizeof(int));
|
||||||
|
if (!used) {
|
||||||
|
eprintf("finger: out of space.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pull out all network requests */
|
||||||
|
for (i = 0, dolocal = 0, nettail = &nethead; i < argc; i++) {
|
||||||
|
if (!strchr(argv[i], '@')) {
|
||||||
|
dolocal = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pn = palloc();
|
||||||
|
*nettail = pn;
|
||||||
|
nettail = &pn->next;
|
||||||
|
pn->name = argv[i];
|
||||||
|
used[i] = -1;
|
||||||
|
}
|
||||||
|
*nettail = NULL;
|
||||||
|
|
||||||
|
if (dolocal) do_local(argc, argv, used);
|
||||||
|
|
||||||
|
/* handle network requests */
|
||||||
|
for (pn = nethead; pn; pn = pn->next) {
|
||||||
|
netfinger(pn->name);
|
||||||
|
if (pn->next || entries)
|
||||||
|
xputc('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scan thru the list of users currently logged in, saving
|
||||||
|
* appropriate data whenever a match occurs.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* if (!freopen(_PATH_UTMP, "r", stdin)) {
|
||||||
|
* (void)fprintf( stderr, "finger: can't read %s.\n", _PATH_UTMP);
|
||||||
|
* exit(1);
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
setutent();
|
||||||
|
while ((uptr = getutent())!=NULL) {
|
||||||
|
if (!uptr->ut_name[0])
|
||||||
|
continue;
|
||||||
|
#ifdef USER_PROCESS
|
||||||
|
if (uptr->ut_type != USER_PROCESS) continue;
|
||||||
|
#endif
|
||||||
|
if ((pn = find_person(uptr->ut_name)) == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
enter_where(uptr, pn);
|
||||||
|
}
|
||||||
|
for (pn = phead; pn != NULL; pn = pn->next) {
|
||||||
|
enter_lastlog(pn);
|
||||||
|
}
|
||||||
|
endutent();
|
||||||
|
}
|
121
third_party/finger/finger.h
vendored
Normal file
121
third_party/finger/finger.h
vendored
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
// clang-format off
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1989 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* from: @(#)finger.h 5.5 (Berkeley) 6/1/90
|
||||||
|
* $Id: finger.h,v 1.7 1999/09/14 10:51:11 dholland Exp $
|
||||||
|
*/
|
||||||
|
#include "third_party/musl/passwd.h"
|
||||||
|
#include "libc/runtime/utmp.h"
|
||||||
|
#include "libc/calls/weirdtypes.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All unique persons are linked in a list headed by "head" and linkd
|
||||||
|
* by the "next" field, as well as kept in a hash table.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct person {
|
||||||
|
struct person *next; /* link to next person */
|
||||||
|
struct person *hlink; /* link to next person in hash bucket */
|
||||||
|
uid_t uid; /* user id */
|
||||||
|
char *dir; /* user's home directory */
|
||||||
|
char *homephone; /* pointer to home phone no. */
|
||||||
|
char *name; /* login name */
|
||||||
|
char *office; /* pointer to office name */
|
||||||
|
char *officephone; /* pointer to office phone no. */
|
||||||
|
char *realname; /* pointer to full name */
|
||||||
|
char *shell; /* user's shell */
|
||||||
|
time_t mailread; /* last time mail was read */
|
||||||
|
time_t mailrecv; /* last time mail was read */
|
||||||
|
struct where *whead, *wtail; /* list of where he is or has been */
|
||||||
|
} PERSON;
|
||||||
|
|
||||||
|
enum status { LASTLOG, LOGGEDIN };
|
||||||
|
|
||||||
|
typedef struct where {
|
||||||
|
struct where *next; /* next place he is or has been */
|
||||||
|
enum status info; /* type/status of request */
|
||||||
|
short writable; /* tty is writable */
|
||||||
|
time_t loginat; /* time of (last) login */
|
||||||
|
time_t idletime; /* how long idle (if logged in) */
|
||||||
|
char tty[UT_LINESIZE+1]; /* null terminated tty line */
|
||||||
|
char host[UT_HOSTSIZE+1]; /* null terminated remote host name */
|
||||||
|
} WHERE;
|
||||||
|
|
||||||
|
extern PERSON *phead, *ptail; /* the linked list of all people */
|
||||||
|
|
||||||
|
extern int entries; /* number of people */
|
||||||
|
|
||||||
|
#define TBUFLEN 1024
|
||||||
|
extern char tbuf[TBUFLEN]; /* temp buffer for anybody */
|
||||||
|
|
||||||
|
extern time_t now;
|
||||||
|
extern int lflag, pplan;
|
||||||
|
|
||||||
|
struct utmp;
|
||||||
|
PERSON *enter_person(struct passwd *);
|
||||||
|
PERSON *find_person(const char *name);
|
||||||
|
PERSON *palloc(void);
|
||||||
|
WHERE *walloc(PERSON *);
|
||||||
|
void lflag_print(void);
|
||||||
|
void sflag_print(void);
|
||||||
|
void enter_where(struct utmp *ut, PERSON *pn);
|
||||||
|
void enter_lastlog(PERSON *pn);
|
||||||
|
int match(struct passwd *pw, const char *user);
|
||||||
|
void netfinger(const char *name);
|
||||||
|
const char *prphone(const char *num);
|
||||||
|
|
||||||
|
#ifndef DAYSPERNYEAR
|
||||||
|
#define DAYSPERNYEAR 365
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SECSPERDAY
|
||||||
|
#define SECSPERDAY (60 * 60 * 24)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* turn on crnl translation on output */
|
||||||
|
void set_crmode(void);
|
||||||
|
|
||||||
|
/* Display, masking control characters and possibly doing crnl translation */
|
||||||
|
void xputc(int ch);
|
||||||
|
void xputs(const char *buf);
|
||||||
|
int xprintf(const char *fmt, ...);
|
||||||
|
|
||||||
|
/* Send to stderr, possibly doing crnl translation */
|
||||||
|
int eprintf(const char *fmt, ...);
|
||||||
|
|
||||||
|
/* terminal inquiries */
|
||||||
|
int is8bit(void);
|
||||||
|
int getscreenwidth(void);
|
68
third_party/finger/finger.mk
vendored
Normal file
68
third_party/finger/finger.mk
vendored
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||||
|
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||||
|
|
||||||
|
PKGS += THIRD_PARTY_FINGER
|
||||||
|
|
||||||
|
THIRD_PARTY_FINGER_ARTIFACTS += THIRD_PARTY_FINGER_A
|
||||||
|
THIRD_PARTY_FINGER = $(THIRD_PARTY_FINGER_A_DEPS) $(THIRD_PARTY_FINGER_A)
|
||||||
|
THIRD_PARTY_FINGER_A = o/$(MODE)/third_party/finger/finger.a
|
||||||
|
THIRD_PARTY_FINGER_A_FILES := $(wildcard third_party/finger/*)
|
||||||
|
THIRD_PARTY_FINGER_A_HDRS = $(filter %.h,$(THIRD_PARTY_FINGER_A_FILES))
|
||||||
|
THIRD_PARTY_FINGER_A_INCS = $(filter %.inc,$(THIRD_PARTY_FINGER_A_FILES))
|
||||||
|
THIRD_PARTY_FINGER_A_SRCS = $(filter %.c,$(THIRD_PARTY_FINGER_A_FILES))
|
||||||
|
THIRD_PARTY_FINGER_A_OBJS = $(THIRD_PARTY_FINGER_A_SRCS:%.c=o/$(MODE)/%.o)
|
||||||
|
|
||||||
|
THIRD_PARTY_FINGER_A_DIRECTDEPS = \
|
||||||
|
LIBC_CALLS \
|
||||||
|
LIBC_FMT \
|
||||||
|
LIBC_INTRIN \
|
||||||
|
LIBC_MEM \
|
||||||
|
LIBC_NEXGEN32E \
|
||||||
|
LIBC_RUNTIME \
|
||||||
|
LIBC_STDIO \
|
||||||
|
LIBC_STR \
|
||||||
|
LIBC_STUBS \
|
||||||
|
LIBC_SYSV \
|
||||||
|
LIBC_DNS \
|
||||||
|
LIBC_SOCK \
|
||||||
|
LIBC_TIME \
|
||||||
|
LIBC_UNICODE \
|
||||||
|
THIRD_PARTY_MUSL \
|
||||||
|
THIRD_PARTY_GETOPT
|
||||||
|
|
||||||
|
THIRD_PARTY_FINGER_A_DEPS := \
|
||||||
|
$(call uniq,$(foreach x,$(THIRD_PARTY_FINGER_A_DIRECTDEPS),$($(x))))
|
||||||
|
|
||||||
|
THIRD_PARTY_FINGER_A_CHECKS = \
|
||||||
|
$(THIRD_PARTY_FINGER_A).pkg
|
||||||
|
|
||||||
|
$(THIRD_PARTY_FINGER_A): \
|
||||||
|
third_party/finger/ \
|
||||||
|
$(THIRD_PARTY_FINGER_A).pkg \
|
||||||
|
$(THIRD_PARTY_FINGER_A_OBJS)
|
||||||
|
|
||||||
|
$(THIRD_PARTY_FINGER_A).pkg: \
|
||||||
|
$(THIRD_PARTY_FINGER_A_OBJS) \
|
||||||
|
$(foreach x,$(THIRD_PARTY_FINGER_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||||
|
|
||||||
|
o/$(MODE)/third_party/finger/finger.com.dbg: \
|
||||||
|
$(THIRD_PARTY_FINGER) \
|
||||||
|
o/$(MODE)/third_party/finger/finger.o \
|
||||||
|
$(CRT) \
|
||||||
|
$(APE_NO_MODIFY_SELF)
|
||||||
|
@$(APELINK)
|
||||||
|
|
||||||
|
THIRD_PARTY_FINGER_COMS = o/$(MODE)/third_party/finger/finger.com
|
||||||
|
THIRD_PARTY_FINGER_BINS = $(THIRD_PARTY_FINGER_COMS) $(THIRD_PARTY_FINGER_COMS:%=%.dbg)
|
||||||
|
THIRD_PARTY_FINGER_LIBS = $(foreach x,$(THIRD_PARTY_FINGER_ARTIFACTS),$($(x)))
|
||||||
|
THIRD_PARTY_FINGER_SRCS = $(foreach x,$(THIRD_PARTY_FINGER_ARTIFACTS),$($(x)_SRCS))
|
||||||
|
THIRD_PARTY_FINGER_HDRS = $(foreach x,$(THIRD_PARTY_FINGER_ARTIFACTS),$($(x)_HDRS))
|
||||||
|
THIRD_PARTY_FINGER_INCS = $(foreach x,$(THIRD_PARTY_FINGER_ARTIFACTS),$($(x)_INCS))
|
||||||
|
THIRD_PARTY_FINGER_CHECKS = $(foreach x,$(THIRD_PARTY_FINGER_ARTIFACTS),$($(x)_CHECKS))
|
||||||
|
THIRD_PARTY_FINGER_OBJS = $(foreach x,$(THIRD_PARTY_FINGER_ARTIFACTS),$($(x)_OBJS))
|
||||||
|
$(THIRD_PARTY_FINGER_OBJS): third_party/finger/finger.mk
|
||||||
|
|
||||||
|
.PHONY: o/$(MODE)/third_party/finger
|
||||||
|
o/$(MODE)/third_party/finger: \
|
||||||
|
$(THIRD_PARTY_FINGER_BINS) \
|
||||||
|
$(THIRD_PARTY_FINGER_CHECKS)
|
361
third_party/finger/lprint.c
vendored
Normal file
361
third_party/finger/lprint.c
vendored
Normal file
|
@ -0,0 +1,361 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1989 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/struct/stat.h"
|
||||||
|
#include "libc/fmt/fmt.h"
|
||||||
|
#include "libc/paths.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/sysv/consts/o.h"
|
||||||
|
#include "libc/sysv/consts/s.h"
|
||||||
|
#include "libc/time/time.h"
|
||||||
|
#include "third_party/finger/finger.h"
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
/*
|
||||||
|
* from: @(#)lprint.c 5.13 (Berkeley) 10/31/90
|
||||||
|
*/
|
||||||
|
char lprint_rcsid[] =
|
||||||
|
"$Id: lprint.c,v 1.11 1999/09/14 10:51:11 dholland Exp $";
|
||||||
|
|
||||||
|
static void lprint(PERSON *pn);
|
||||||
|
static int demi_print(char *str, int oddfield);
|
||||||
|
static int show_text(const char *directory, const char *file_name,
|
||||||
|
const char *header);
|
||||||
|
|
||||||
|
#define LINE_LEN 80
|
||||||
|
#define TAB_LEN 8 /* 8 spaces between tabs */
|
||||||
|
#define _PATH_FORWARD ".forward"
|
||||||
|
#define _PATH_PLAN ".plan"
|
||||||
|
#define _PATH_PROJECT ".project"
|
||||||
|
#define _PATH_PGPKEY ".pgpkey"
|
||||||
|
|
||||||
|
void
|
||||||
|
lflag_print(void)
|
||||||
|
{
|
||||||
|
register PERSON *pn = phead;
|
||||||
|
while (1) {
|
||||||
|
lprint(pn);
|
||||||
|
if (!pplan) {
|
||||||
|
show_text(pn->dir, _PATH_PGPKEY, "PGP key:\n");
|
||||||
|
show_text(pn->dir, _PATH_PROJECT, "Project:\n");
|
||||||
|
if (!show_text(pn->dir, _PATH_PLAN, "Plan:\n")) {
|
||||||
|
xprintf("No Plan.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(pn = pn->next))
|
||||||
|
break;
|
||||||
|
xputc('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lprint(PERSON *pn)
|
||||||
|
{
|
||||||
|
struct tm *delta, *tp;
|
||||||
|
WHERE *w;
|
||||||
|
int cpr, len, maxlen;
|
||||||
|
int oddfield;
|
||||||
|
char timebuf[128];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* long format --
|
||||||
|
* login name
|
||||||
|
* real name
|
||||||
|
* home directory
|
||||||
|
* shell
|
||||||
|
* office, office phone, home phone if available
|
||||||
|
*/
|
||||||
|
xprintf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s",
|
||||||
|
pn->name, pn->realname, pn->dir);
|
||||||
|
xprintf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* try and print office, office phone, and home phone on one line;
|
||||||
|
* if that fails, do line filling so it looks nice.
|
||||||
|
*/
|
||||||
|
#define OFFICE_TAG "Office"
|
||||||
|
#define OFFICE_PHONE_TAG "Office Phone"
|
||||||
|
oddfield = 0;
|
||||||
|
if (pn->office && pn->officephone &&
|
||||||
|
strlen(pn->office) + strlen(pn->officephone) +
|
||||||
|
sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN)
|
||||||
|
{
|
||||||
|
snprintf(tbuf, TBUFLEN, "%s: %s, %s", OFFICE_TAG, pn->office,
|
||||||
|
prphone(pn->officephone));
|
||||||
|
oddfield = demi_print(tbuf, oddfield);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (pn->office) {
|
||||||
|
snprintf(tbuf, TBUFLEN, "%s: %s", OFFICE_TAG,
|
||||||
|
pn->office);
|
||||||
|
oddfield = demi_print(tbuf, oddfield);
|
||||||
|
}
|
||||||
|
if (pn->officephone) {
|
||||||
|
snprintf(tbuf, TBUFLEN, "%s: %s", OFFICE_PHONE_TAG,
|
||||||
|
prphone(pn->officephone));
|
||||||
|
oddfield = demi_print(tbuf, oddfield);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pn->homephone) {
|
||||||
|
snprintf(tbuf, TBUFLEN, "%s: %s", "Home Phone",
|
||||||
|
prphone(pn->homephone));
|
||||||
|
oddfield = demi_print(tbuf, oddfield);
|
||||||
|
}
|
||||||
|
if (oddfield) xputc('\n');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* long format con't: * if logged in
|
||||||
|
* terminal
|
||||||
|
* idle time
|
||||||
|
* if messages allowed
|
||||||
|
* where logged in from
|
||||||
|
* if not logged in
|
||||||
|
* when last logged in
|
||||||
|
*/
|
||||||
|
/* find out longest device name for this user for formatting */
|
||||||
|
for (w = pn->whead, maxlen = -1; w != NULL; w = w->next)
|
||||||
|
if ((len = strlen(w->tty)) > maxlen)
|
||||||
|
maxlen = len;
|
||||||
|
/* find rest of entries for user */
|
||||||
|
for (w = pn->whead; w != NULL; w = w->next) {
|
||||||
|
switch (w->info) {
|
||||||
|
case LOGGEDIN:
|
||||||
|
tp = localtime(&w->loginat);
|
||||||
|
/*
|
||||||
|
* t = asctime(tp);
|
||||||
|
* tzset();
|
||||||
|
* tzn = tzname[daylight];
|
||||||
|
* cpr = printf("On since %.16s (%s) on %s",
|
||||||
|
* t, tzn, w->tty);
|
||||||
|
*/
|
||||||
|
strftime(timebuf, sizeof(timebuf),
|
||||||
|
"%a %b %e %R (%Z)", tp);
|
||||||
|
cpr = xprintf("On since %s on %s", timebuf, w->tty);
|
||||||
|
if (*w->host) {
|
||||||
|
cpr += xprintf(" from %s", w->host);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* idle time is tough; if have one, print a comma,
|
||||||
|
* then spaces to pad out the device name, then the
|
||||||
|
* idle time. Follow with a comma if a remote login.
|
||||||
|
*/
|
||||||
|
delta = gmtime(&w->idletime);
|
||||||
|
if (delta->tm_yday || delta->tm_hour
|
||||||
|
|| delta->tm_min || delta->tm_sec) {
|
||||||
|
if (*w->host)
|
||||||
|
xputc('\n');
|
||||||
|
cpr += xprintf("%-*s",
|
||||||
|
(int) (maxlen - strlen(w->tty) + 3), "");
|
||||||
|
if (delta->tm_yday > 0) {
|
||||||
|
cpr += xprintf("%d day%s ",
|
||||||
|
delta->tm_yday,
|
||||||
|
delta->tm_yday == 1 ? "" : "s");
|
||||||
|
}
|
||||||
|
if (delta->tm_hour > 0) {
|
||||||
|
cpr += xprintf("%d hour%s ",
|
||||||
|
delta->tm_hour,
|
||||||
|
delta->tm_hour == 1 ? "" : "s");
|
||||||
|
}
|
||||||
|
if ((delta->tm_min > 0) && !delta->tm_yday) {
|
||||||
|
cpr += xprintf("%d minute%s ",
|
||||||
|
delta->tm_min,
|
||||||
|
delta->tm_min == 1 ? "" : "s");
|
||||||
|
}
|
||||||
|
if ((delta->tm_sec > 0) && !delta->tm_yday
|
||||||
|
&& !delta->tm_hour) {
|
||||||
|
cpr += xprintf("%d second%s ",
|
||||||
|
delta->tm_sec,
|
||||||
|
delta->tm_sec == 1 ? "" : "s");
|
||||||
|
}
|
||||||
|
cpr += xprintf("idle");
|
||||||
|
}
|
||||||
|
if (!w->writable) {
|
||||||
|
if (delta->tm_yday || delta->tm_hour
|
||||||
|
|| delta->tm_min || delta->tm_sec)
|
||||||
|
cpr += xprintf("\n ");
|
||||||
|
cpr += xprintf(" (messages off)");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LASTLOG:
|
||||||
|
if (w->loginat == 0) {
|
||||||
|
(void)xprintf("Never logged in.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tp = localtime(&w->loginat);
|
||||||
|
/*
|
||||||
|
* t = asctime(tp);
|
||||||
|
* tzset();
|
||||||
|
* tzn = tzname[daylight];
|
||||||
|
* if(now - w->loginat > SECSPERDAY * DAYSPERNYEAR / 2)
|
||||||
|
* cpr =
|
||||||
|
* printf("Last login %.16s %.4s (%s) on %s",
|
||||||
|
* t, t + 20, tzn, w->tty);
|
||||||
|
* else
|
||||||
|
* cpr = printf("Last login %.16s (%s) on %s",
|
||||||
|
* t, tzn, w->tty);
|
||||||
|
*/
|
||||||
|
if (now - w->loginat < SECSPERDAY * DAYSPERNYEAR / 2) {
|
||||||
|
strftime(timebuf, sizeof(timebuf),
|
||||||
|
"%a %b %e %R (%Z)", tp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strftime(timebuf, sizeof(timebuf),
|
||||||
|
"%a %b %e %R %Y (%Z)", tp);
|
||||||
|
}
|
||||||
|
cpr = xprintf("Last login %s on %s", timebuf, w->tty);
|
||||||
|
if (*w->host) {
|
||||||
|
cpr += xprintf(" from %s", w->host);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
xputc('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the user forwards mail elsewhere, tell us about it */
|
||||||
|
show_text(pn->dir, _PATH_FORWARD, "Mail forwarded to ");
|
||||||
|
|
||||||
|
/* Print the standard mailbox information. */
|
||||||
|
if (pn->mailrecv == -1)
|
||||||
|
xprintf("No mail.\n");
|
||||||
|
else if (pn->mailrecv > pn->mailread) {
|
||||||
|
tp = localtime(&pn->mailrecv);
|
||||||
|
/*
|
||||||
|
* t = asctime(tp);
|
||||||
|
* tzset();
|
||||||
|
* tzn = tzname[daylight];
|
||||||
|
* printf("New mail received %.16s %.4s (%s)\n", t,
|
||||||
|
* t + 20, tzn);
|
||||||
|
*/
|
||||||
|
strftime(timebuf, sizeof(timebuf),
|
||||||
|
"%a %b %e %R %Y (%Z)", tp);
|
||||||
|
xprintf("New mail received %s\n", timebuf);
|
||||||
|
tp = localtime(&pn->mailread);
|
||||||
|
/*
|
||||||
|
* t = asctime(tp);
|
||||||
|
* tzset();
|
||||||
|
* tzn = tzname[daylight];
|
||||||
|
* printf(" Unread since %.16s %.4s (%s)\n", t,
|
||||||
|
* t + 20, tzn);
|
||||||
|
*/
|
||||||
|
strftime(timebuf, sizeof(timebuf),
|
||||||
|
"%a %b %e %R %Y (%Z)", tp);
|
||||||
|
xprintf(" Unread since %s\n", timebuf);
|
||||||
|
} else {
|
||||||
|
tp = localtime(&pn->mailread);
|
||||||
|
/*
|
||||||
|
* t = asctime(tp);
|
||||||
|
* tzset();
|
||||||
|
* tzn = tzname[daylight];
|
||||||
|
* printf("Mail last read %.16s %.4s (%s)\n", t,
|
||||||
|
* t + 20, tzn);
|
||||||
|
*/
|
||||||
|
strftime(timebuf, sizeof(timebuf),
|
||||||
|
"%a %b %e %R %Y (%Z)", tp);
|
||||||
|
xprintf("Mail last read %s\n", timebuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
demi_print(char *str, int oddfield)
|
||||||
|
{
|
||||||
|
static int lenlast;
|
||||||
|
int lenthis, maxlen;
|
||||||
|
|
||||||
|
lenthis = strlen(str);
|
||||||
|
if (oddfield) {
|
||||||
|
/*
|
||||||
|
* We left off on an odd number of fields. If we haven't
|
||||||
|
* crossed the midpoint of the screen, and we have room for
|
||||||
|
* the next field, print it on the same line; otherwise,
|
||||||
|
* print it on a new line.
|
||||||
|
*
|
||||||
|
* Note: we insist on having the right hand fields start
|
||||||
|
* no less than 5 tabs out.
|
||||||
|
*/
|
||||||
|
maxlen = 5 * TAB_LEN;
|
||||||
|
if (maxlen < lenlast)
|
||||||
|
maxlen = lenlast;
|
||||||
|
if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) +
|
||||||
|
lenthis) <= LINE_LEN) {
|
||||||
|
while(lenlast < (4 * TAB_LEN)) {
|
||||||
|
xputc('\t');
|
||||||
|
lenlast += TAB_LEN;
|
||||||
|
}
|
||||||
|
(void)xprintf("\t%s\n", str); /* force one tab */
|
||||||
|
} else {
|
||||||
|
(void)xprintf("\n%s", str); /* go to next line */
|
||||||
|
oddfield = !oddfield; /* this'll be undone below */
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
(void)xprintf("%s", str);
|
||||||
|
oddfield = !oddfield; /* toggle odd/even marker */
|
||||||
|
lenlast = lenthis;
|
||||||
|
return(oddfield);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
show_text(const char *directory, const char *file_name, const char *header)
|
||||||
|
{
|
||||||
|
int ch, lastc = 0, fd;
|
||||||
|
FILE *fp;
|
||||||
|
struct stat sbuf1, sbuf2;
|
||||||
|
|
||||||
|
snprintf(tbuf, TBUFLEN, "%s/%s", directory, file_name);
|
||||||
|
|
||||||
|
if (lstat(tbuf, &sbuf1) || !S_ISREG(sbuf1.st_mode)) return 0;
|
||||||
|
fd = open(tbuf, O_RDONLY);
|
||||||
|
if (fd<0) return 0;
|
||||||
|
if (fstat(fd, &sbuf2)) { close(fd); return 0; }
|
||||||
|
/* if we didn't get the same file both times, bail */
|
||||||
|
if (sbuf1.st_dev!=sbuf2.st_dev || sbuf1.st_ino!=sbuf2.st_ino) {
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fp = fdopen(fd, "r");
|
||||||
|
if (fp == NULL) { close(fd); return 0; }
|
||||||
|
|
||||||
|
xprintf("%s", header);
|
||||||
|
while ((ch = getc(fp)) != EOF) {
|
||||||
|
xputc(ch);
|
||||||
|
lastc = ch;
|
||||||
|
}
|
||||||
|
if (lastc != '\n') xputc('\n');
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
153
third_party/finger/net.c
vendored
Normal file
153
third_party/finger/net.c
vendored
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1989 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/dns/ent.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/sock/sock.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/sysv/consts/af.h"
|
||||||
|
#include "libc/sysv/consts/sock.h"
|
||||||
|
#include "third_party/finger/finger.h"
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
/*static char sccsid[] = "from: @(#)net.c 5.5 (Berkeley) 6/1/90";*/
|
||||||
|
char net_rcsid[] = "$Id: net.c,v 1.9 1999/09/14 10:51:11 dholland Exp $";
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
void netfinger(const char *name) {
|
||||||
|
register FILE *fp;
|
||||||
|
struct in_addr defaddr;
|
||||||
|
register int c, sawret, ateol;
|
||||||
|
struct hostent *hp, def;
|
||||||
|
struct servent *sp;
|
||||||
|
struct sockaddr_in sn;
|
||||||
|
int s;
|
||||||
|
char *alist[1], *host;
|
||||||
|
|
||||||
|
host = strrchr(name, '@');
|
||||||
|
if (!host) return;
|
||||||
|
*host++ = '\0';
|
||||||
|
|
||||||
|
memset(&sn, 0, sizeof(sn));
|
||||||
|
|
||||||
|
sp = getservbyname("finger", "tcp");
|
||||||
|
if (!sp) {
|
||||||
|
eprintf("finger: tcp/finger: unknown service\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sn.sin_port = sp->s_port;
|
||||||
|
|
||||||
|
hp = gethostbyname(host);
|
||||||
|
if (!hp) {
|
||||||
|
if (!inet_aton(host, &defaddr)) {
|
||||||
|
eprintf("finger: unknown host: %s\n", host);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
def.h_name = host;
|
||||||
|
def.h_addr_list = alist;
|
||||||
|
def.h_addr = (char *)&defaddr;
|
||||||
|
def.h_length = sizeof(struct in_addr);
|
||||||
|
def.h_addrtype = AF_INET;
|
||||||
|
def.h_aliases = 0;
|
||||||
|
hp = &def;
|
||||||
|
}
|
||||||
|
sn.sin_family = hp->h_addrtype;
|
||||||
|
if (hp->h_length > (int)sizeof(sn.sin_addr)) {
|
||||||
|
hp->h_length = sizeof(sn.sin_addr);
|
||||||
|
}
|
||||||
|
memcpy(&sn.sin_addr, hp->h_addr, hp->h_length);
|
||||||
|
|
||||||
|
if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
|
||||||
|
eprintf("finger: socket: %s\n", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* print hostname before connecting, in case it takes a while */
|
||||||
|
xprintf("[%s]\n", hp->h_name);
|
||||||
|
if (connect(s, (struct sockaddr *)&sn, sizeof(sn)) < 0) {
|
||||||
|
eprintf("finger: connect: %s\n", strerror(errno));
|
||||||
|
close(s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -l flag for remote fingerd */
|
||||||
|
if (lflag) write(s, "/W ", 3);
|
||||||
|
|
||||||
|
/* send the name followed by <CR><LF> */
|
||||||
|
write(s, name, strlen(name));
|
||||||
|
write(s, "\r\n", 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read from the remote system; once we're connected, we assume some
|
||||||
|
* data. If none arrives, we hang until the user interrupts.
|
||||||
|
*
|
||||||
|
* If we see a <CR> or a <CR> with the high bit set, treat it as
|
||||||
|
* a newline; if followed by a newline character, only output one
|
||||||
|
* newline.
|
||||||
|
*
|
||||||
|
* Text is sent to xputc() for printability analysis.
|
||||||
|
*/
|
||||||
|
fp = fdopen(s, "r");
|
||||||
|
if (!fp) {
|
||||||
|
eprintf("finger: fdopen: %s\n", strerror(errno));
|
||||||
|
close(s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sawret = 0;
|
||||||
|
ateol = 1;
|
||||||
|
while ((c = getc(fp)) != EOF) {
|
||||||
|
c &= 0xff;
|
||||||
|
if (c == ('\r'|0x80) || c == ('\n'|0x80)) c &= 0x7f;
|
||||||
|
if (c == '\r') {
|
||||||
|
sawret = ateol = 1;
|
||||||
|
xputc('\n');
|
||||||
|
}
|
||||||
|
else if (sawret && c == '\n') {
|
||||||
|
sawret = 0;
|
||||||
|
/* don't print */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (c == '\n') ateol = 1;
|
||||||
|
sawret = 0;
|
||||||
|
xputc(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ateol) xputc('\n');
|
||||||
|
fclose(fp);
|
||||||
|
}
|
172
third_party/finger/sprint.c
vendored
Normal file
172
third_party/finger/sprint.c
vendored
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1989 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include "libc/alg/alg.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/time/time.h"
|
||||||
|
#include "third_party/finger/finger.h"
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
/*static char sccsid[] = "from: @(#)sprint.c 5.8 (Berkeley) 12/4/90";*/
|
||||||
|
char sprint_rcsid[] = "$Id: sprint.c,v 1.10 1999/12/12 18:59:33 dholland Exp $";
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
static void stimeprint(WHERE *w);
|
||||||
|
static int psort(const void *a, const void *b);
|
||||||
|
static PERSON **sort(void);
|
||||||
|
|
||||||
|
void sflag_print(void) {
|
||||||
|
register PERSON *pn;
|
||||||
|
register WHERE *w;
|
||||||
|
register char *p;
|
||||||
|
PERSON **list;
|
||||||
|
int maxlname, maxrname, space, cnt;
|
||||||
|
|
||||||
|
list = sort();
|
||||||
|
/*
|
||||||
|
* short format --
|
||||||
|
* login name
|
||||||
|
* real name
|
||||||
|
* terminal name
|
||||||
|
* if terminal writeable (add an '*' to the terminal name
|
||||||
|
* if not)
|
||||||
|
* if logged in show idle time and day logged in, else
|
||||||
|
* show last login date and time. If > 6 moths,
|
||||||
|
* show year instead of time.
|
||||||
|
* office location
|
||||||
|
* office phone
|
||||||
|
*/
|
||||||
|
|
||||||
|
maxlname = maxrname = sizeof("Login ");
|
||||||
|
for (cnt = 0; cnt < entries; ++cnt) {
|
||||||
|
int l;
|
||||||
|
pn = list[cnt];
|
||||||
|
l = pn->name ? strlen(pn->name) : 1;
|
||||||
|
if (l > maxlname) maxlname = l;
|
||||||
|
l = pn->realname ? strlen(pn->realname) : 1;
|
||||||
|
if (l > maxrname) maxrname = l;
|
||||||
|
}
|
||||||
|
/* prevent screen overflow */
|
||||||
|
space = getscreenwidth() - 50;
|
||||||
|
if (maxlname + maxrname > space) maxrname = space - maxlname;
|
||||||
|
|
||||||
|
/* add a space if there's room */
|
||||||
|
if (maxlname + maxrname < space-2) { maxlname++; maxrname++; }
|
||||||
|
|
||||||
|
(void)xprintf("%-*s %-*s %s\n", maxlname, "Login", maxrname,
|
||||||
|
"Name", " Tty Idle Login Time Office Office Phone");
|
||||||
|
for (cnt = 0; cnt < entries; ++cnt) {
|
||||||
|
pn = list[cnt];
|
||||||
|
for (w = pn->whead; w != NULL; w = w->next) {
|
||||||
|
(void)xprintf("%-*.*s %-*.*s ", maxlname, maxlname,
|
||||||
|
pn->name, maxrname, maxrname,
|
||||||
|
pn->realname ? pn->realname : "");
|
||||||
|
if (!w->loginat) {
|
||||||
|
(void)xprintf(" * * No logins ");
|
||||||
|
goto office;
|
||||||
|
}
|
||||||
|
(void)xputc(w->info == LOGGEDIN && !w->writable ?
|
||||||
|
'*' : ' ');
|
||||||
|
if (*w->tty)
|
||||||
|
(void)xprintf("%-7.7s ", w->tty);
|
||||||
|
else
|
||||||
|
(void)xprintf(" ");
|
||||||
|
if (w->info == LOGGEDIN) {
|
||||||
|
stimeprint(w);
|
||||||
|
(void)xprintf(" ");
|
||||||
|
} else
|
||||||
|
(void)xprintf(" * ");
|
||||||
|
p = ctime(&w->loginat);
|
||||||
|
(void)xprintf("%.6s", p + 4);
|
||||||
|
if (now - w->loginat >= SECSPERDAY * DAYSPERNYEAR / 2)
|
||||||
|
(void)xprintf(" %.4s", p + 20);
|
||||||
|
else
|
||||||
|
(void)xprintf(" %.5s", p + 11);
|
||||||
|
office:
|
||||||
|
if (w->host[0] != '\0') {
|
||||||
|
xprintf(" (%s)", w->host);
|
||||||
|
} else {
|
||||||
|
if (pn->office)
|
||||||
|
(void)xprintf(" %-10.10s", pn->office);
|
||||||
|
else if (pn->officephone)
|
||||||
|
(void)xprintf(" %-10.10s", " ");
|
||||||
|
if (pn->officephone)
|
||||||
|
(void)xprintf(" %-.14s",
|
||||||
|
prphone(pn->officephone));
|
||||||
|
}
|
||||||
|
xputc('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PERSON **sort(void) {
|
||||||
|
register PERSON *pn, **lp;
|
||||||
|
PERSON **list;
|
||||||
|
|
||||||
|
if (!(list = (PERSON **)malloc((unsigned)(entries * sizeof(PERSON *))))) {
|
||||||
|
eprintf("finger: Out of space.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
for (lp = list, pn = phead; pn != NULL; pn = pn->next)
|
||||||
|
*lp++ = pn;
|
||||||
|
(void)qsort(list, entries, sizeof(PERSON *), psort);
|
||||||
|
return(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int psort(const void *a, const void *b) {
|
||||||
|
const PERSON *const *p = (const PERSON *const *)a;
|
||||||
|
const PERSON *const *t = (const PERSON *const *)b;
|
||||||
|
return(strcmp((*p)->name, (*t)->name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stimeprint(WHERE *w) {
|
||||||
|
register struct tm *delta;
|
||||||
|
|
||||||
|
delta = gmtime(&w->idletime);
|
||||||
|
if (!delta->tm_yday)
|
||||||
|
if (!delta->tm_hour)
|
||||||
|
if (!delta->tm_min)
|
||||||
|
(void)xprintf(" ");
|
||||||
|
else
|
||||||
|
(void)xprintf("%5d", delta->tm_min);
|
||||||
|
else
|
||||||
|
(void)xprintf("%2d:%02d",
|
||||||
|
delta->tm_hour, delta->tm_min);
|
||||||
|
else
|
||||||
|
(void)xprintf("%4dd", delta->tm_yday);
|
||||||
|
}
|
414
third_party/finger/util.c
vendored
Normal file
414
third_party/finger/util.c
vendored
Normal file
|
@ -0,0 +1,414 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1989 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/struct/stat.h"
|
||||||
|
#include "libc/calls/struct/stat.macros.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/fmt/fmt.h"
|
||||||
|
#include "libc/paths.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/sysv/consts/o.h"
|
||||||
|
#include "third_party/finger/finger.h"
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
/*static char sccsid[] = "from: @(#)util.c 5.14 (Berkeley) 1/17/91";*/
|
||||||
|
char util_rcsid[] = "$Id: util.c,v 1.18 1999/09/28 22:53:58 netbug Exp $";
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#define HBITS 8 /* number of bits in hash code */
|
||||||
|
#define HSIZE (1 << 8) /* hash table size */
|
||||||
|
#define HMASK (HSIZE - 1) /* hash code mask */
|
||||||
|
static PERSON *htab[HSIZE]; /* the buckets */
|
||||||
|
|
||||||
|
static int hash(const char *name);
|
||||||
|
|
||||||
|
static void find_idle_and_ttywrite(register WHERE *w) {
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
/* No device for X console. Utmp entry by XDM login (":0"). */
|
||||||
|
if (w->tty[0] == ':') {
|
||||||
|
w->idletime = 0; /* would be nice to have it emit ??? */
|
||||||
|
w->writable = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
snprintf(tbuf, TBUFLEN, "%s/%s", _PATH_DEV, w->tty);
|
||||||
|
if (stat(tbuf, &sb) < 0) {
|
||||||
|
eprintf("finger: %s: %s\n", tbuf, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime;
|
||||||
|
|
||||||
|
#define TALKABLE 0220 /* tty is writable if 220 mode */
|
||||||
|
w->writable = ((sb.st_mode & TALKABLE) == TALKABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void userinfo(PERSON *pn, struct passwd *pw) {
|
||||||
|
char *p;
|
||||||
|
struct stat sb;
|
||||||
|
char *bp;
|
||||||
|
char *rname;
|
||||||
|
int i, j, ct;
|
||||||
|
char *fields[4];
|
||||||
|
int nfields;
|
||||||
|
|
||||||
|
pn->uid = pw->pw_uid;
|
||||||
|
pn->name = strdup(pw->pw_name);
|
||||||
|
pn->dir = strdup(pw->pw_dir);
|
||||||
|
pn->shell = strdup(pw->pw_shell);
|
||||||
|
|
||||||
|
/* make a private copy of gecos to munge */
|
||||||
|
strncpy(tbuf, pw->pw_gecos, TBUFLEN);
|
||||||
|
tbuf[TBUFLEN-1] = 0; /* ensure null termination */
|
||||||
|
bp = tbuf;
|
||||||
|
|
||||||
|
/* why do we skip asterisks!?!? */
|
||||||
|
if (*bp == '*') ++bp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fields[0] -> real name
|
||||||
|
* fields[1] -> office
|
||||||
|
* fields[2] -> officephone
|
||||||
|
* fields[3] -> homephone
|
||||||
|
*/
|
||||||
|
nfields = 0;
|
||||||
|
for (p = strtok(bp, ","); p; p = strtok(NULL, ",")) {
|
||||||
|
if (*p==0) p = NULL; // skip empties
|
||||||
|
if (nfields < 4) fields[nfields++] = p;
|
||||||
|
}
|
||||||
|
while (nfields<4) fields[nfields++] = NULL;
|
||||||
|
|
||||||
|
if (fields[0]) {
|
||||||
|
/*
|
||||||
|
* Ampersands in gecos get replaced by the capitalized login
|
||||||
|
* name. This is a major nuisance and whoever thought it up
|
||||||
|
* should be shot.
|
||||||
|
*/
|
||||||
|
p = fields[0];
|
||||||
|
|
||||||
|
/* First, count the number of ampersands. */
|
||||||
|
for (ct=i=0; p[i]; i++) if (p[i]=='&') ct++;
|
||||||
|
|
||||||
|
/* This tells us how much space we need to copy the name. */
|
||||||
|
rname = malloc(strlen(p) + ct*strlen(pw->pw_name) + 1);
|
||||||
|
if (!rname) {
|
||||||
|
eprintf("finger: Out of space.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now, do it */
|
||||||
|
for (i=j=0; p[i]; i++) {
|
||||||
|
if (p[i]=='&') {
|
||||||
|
strcpy(rname + j, pw->pw_name);
|
||||||
|
if (islower(rname[j])) {
|
||||||
|
rname[j] = toupper(rname[j]);
|
||||||
|
}
|
||||||
|
j += strlen(pw->pw_name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rname[j++] = p[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rname[j] = 0;
|
||||||
|
|
||||||
|
pn->realname = rname;
|
||||||
|
}
|
||||||
|
|
||||||
|
pn->office = fields[1] ? strdup(fields[1]) : NULL;
|
||||||
|
pn->officephone = fields[2] ? strdup(fields[2]) : NULL;
|
||||||
|
pn->homephone = fields[3] ? strdup(fields[3]) : NULL;
|
||||||
|
|
||||||
|
pn->mailrecv = -1; /* -1 == not_valid */
|
||||||
|
pn->mailread = -1; /* -1 == not_valid */
|
||||||
|
|
||||||
|
snprintf(tbuf, TBUFLEN, "%s/%s", _PATH_MAILDIR, pw->pw_name);
|
||||||
|
if (stat(tbuf, &sb) < 0) {
|
||||||
|
if (errno != ENOENT) {
|
||||||
|
eprintf("finger: %s: %s\n", tbuf, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (sb.st_size != 0) {
|
||||||
|
pn->mailrecv = sb.st_mtime;
|
||||||
|
pn->mailread = sb.st_atime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
match(struct passwd *pw, const char *user)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
int i, j, ct, rv=0;
|
||||||
|
char *rname;
|
||||||
|
|
||||||
|
strncpy(tbuf, pw->pw_gecos, TBUFLEN);
|
||||||
|
tbuf[TBUFLEN-1] = 0; /* guarantee null termination */
|
||||||
|
p = tbuf;
|
||||||
|
|
||||||
|
/* why do we skip asterisks!?!? */
|
||||||
|
if (*p == '*') ++p;
|
||||||
|
|
||||||
|
/* truncate the uninteresting stuff off the end of gecos */
|
||||||
|
p = strtok(p, ",");
|
||||||
|
if (!p) return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ampersands get replaced by the login name.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* First, count the number of ampersands. */
|
||||||
|
for (ct=i=0; p[i]; i++) if (p[i]=='&') ct++;
|
||||||
|
|
||||||
|
/* This tells us how much space we need to copy the name. */
|
||||||
|
rname = malloc(strlen(p) + ct*strlen(pw->pw_name) + 1);
|
||||||
|
if (!rname) {
|
||||||
|
eprintf("finger: Out of space.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now, do it */
|
||||||
|
for (i=j=0; p[i]; i++) {
|
||||||
|
if (p[i]=='&') {
|
||||||
|
strcpy(rname + j, pw->pw_name);
|
||||||
|
if (islower(rname[j])) rname[j] = toupper(rname[j]);
|
||||||
|
j += strlen(pw->pw_name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rname[j++] = p[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rname[j] = 0;
|
||||||
|
|
||||||
|
for (p = strtok(rname, "\t "); p && !rv; p = strtok(NULL, "\t ")) {
|
||||||
|
if (!strcasecmp(p, user))
|
||||||
|
rv = 1;
|
||||||
|
}
|
||||||
|
free(rname);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_lastlog(int fd, uid_t uid, struct lastlog *ll) {
|
||||||
|
loff_t pos;
|
||||||
|
if (fd == -1) return -1;
|
||||||
|
pos = (long)uid * sizeof(*ll);
|
||||||
|
if (lseek(fd, pos, SEEK_SET) != pos) return -1;
|
||||||
|
if (read(fd, ll, sizeof(*ll)) != sizeof(*ll)) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void enter_lastlog(PERSON *pn) {
|
||||||
|
static int opened = 0, fd = -1;
|
||||||
|
|
||||||
|
WHERE *w;
|
||||||
|
struct lastlog ll;
|
||||||
|
int doit = 0;
|
||||||
|
|
||||||
|
/* some systems may not maintain lastlog, don't report errors. */
|
||||||
|
if (!opened) {
|
||||||
|
fd = open(_PATH_LASTLOG, O_RDONLY, 0);
|
||||||
|
opened = 1;
|
||||||
|
}
|
||||||
|
if (get_lastlog(fd, pn->uid, &ll)) {
|
||||||
|
/* as if never logged in */
|
||||||
|
ll.ll_line[0] = ll.ll_host[0] = '\0';
|
||||||
|
ll.ll_time = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((w = pn->whead) == NULL)
|
||||||
|
doit = 1;
|
||||||
|
else if (ll.ll_time != 0) {
|
||||||
|
/* if last login is earlier than some current login */
|
||||||
|
for (; !doit && w != NULL; w = w->next)
|
||||||
|
if (w->info == LOGGEDIN && w->loginat < ll.ll_time)
|
||||||
|
doit = 1;
|
||||||
|
/*
|
||||||
|
* and if it's not any of the current logins
|
||||||
|
* can't use time comparison because there may be a small
|
||||||
|
* discrepency since login calls time() twice
|
||||||
|
*/
|
||||||
|
for (w = pn->whead; doit && w != NULL; w = w->next)
|
||||||
|
if (w->info == LOGGEDIN &&
|
||||||
|
strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0)
|
||||||
|
doit = 0;
|
||||||
|
}
|
||||||
|
if (doit) {
|
||||||
|
w = walloc(pn);
|
||||||
|
w->info = LASTLOG;
|
||||||
|
bcopy(ll.ll_line, w->tty, UT_LINESIZE);
|
||||||
|
w->tty[UT_LINESIZE] = 0;
|
||||||
|
bcopy(ll.ll_host, w->host, UT_HOSTSIZE);
|
||||||
|
w->host[UT_HOSTSIZE] = 0;
|
||||||
|
w->loginat = ll.ll_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enter_where(struct utmp *ut, PERSON *pn) {
|
||||||
|
register WHERE *w = walloc(pn);
|
||||||
|
|
||||||
|
w->info = LOGGEDIN;
|
||||||
|
bcopy(ut->ut_line, w->tty, UT_LINESIZE);
|
||||||
|
w->tty[UT_LINESIZE] = 0;
|
||||||
|
bcopy(ut->ut_host, w->host, UT_HOSTSIZE);
|
||||||
|
w->host[UT_HOSTSIZE] = 0;
|
||||||
|
w->loginat = ut->ut_time;
|
||||||
|
find_idle_and_ttywrite(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
PERSON * enter_person(struct passwd *pw) {
|
||||||
|
register PERSON *pn, **pp;
|
||||||
|
|
||||||
|
for (pp = htab + hash(pw->pw_name);
|
||||||
|
*pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0;
|
||||||
|
pp = &(*pp)->hlink)
|
||||||
|
;
|
||||||
|
if ((pn = *pp) == NULL) {
|
||||||
|
pn = palloc();
|
||||||
|
entries++;
|
||||||
|
if (phead == NULL)
|
||||||
|
phead = ptail = pn;
|
||||||
|
else {
|
||||||
|
ptail->next = pn;
|
||||||
|
ptail = pn;
|
||||||
|
}
|
||||||
|
pn->next = NULL;
|
||||||
|
pn->hlink = NULL;
|
||||||
|
*pp = pn;
|
||||||
|
userinfo(pn, pw);
|
||||||
|
pn->whead = NULL;
|
||||||
|
}
|
||||||
|
return(pn);
|
||||||
|
}
|
||||||
|
|
||||||
|
PERSON *find_person(const char *name) {
|
||||||
|
register PERSON *pn;
|
||||||
|
|
||||||
|
/* name may be only UT_NAMESIZE long and not terminated */
|
||||||
|
for (pn = htab[hash(name)];
|
||||||
|
pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0;
|
||||||
|
pn = pn->hlink)
|
||||||
|
;
|
||||||
|
return(pn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hash(const char *name) {
|
||||||
|
register int h, i;
|
||||||
|
|
||||||
|
h = 0;
|
||||||
|
/* name may be only UT_NAMESIZE long and not terminated */
|
||||||
|
for (i = UT_NAMESIZE; --i >= 0 && *name;)
|
||||||
|
h = ((h << 2 | h >> (HBITS - 2)) ^ *name++) & HMASK;
|
||||||
|
return(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
PERSON *palloc(void) {
|
||||||
|
PERSON *p;
|
||||||
|
|
||||||
|
if ((p = (PERSON *)malloc((unsigned) sizeof(PERSON))) == NULL) {
|
||||||
|
eprintf("finger: Out of space.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
WHERE *
|
||||||
|
walloc(PERSON *pn)
|
||||||
|
{
|
||||||
|
register WHERE *w;
|
||||||
|
|
||||||
|
if ((w = (WHERE *)malloc((unsigned) sizeof(WHERE))) == NULL) {
|
||||||
|
eprintf("finger: Out of space.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (pn->whead == NULL)
|
||||||
|
pn->whead = pn->wtail = w;
|
||||||
|
else {
|
||||||
|
pn->wtail->next = w;
|
||||||
|
pn->wtail = w;
|
||||||
|
}
|
||||||
|
w->next = NULL;
|
||||||
|
return(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
prphone(const char *num)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
const char *q;
|
||||||
|
int len;
|
||||||
|
static char pbuf[15];
|
||||||
|
|
||||||
|
/* don't touch anything if the user has their own formatting */
|
||||||
|
for (q = num; *q; ++q)
|
||||||
|
if (!isdigit(*q))
|
||||||
|
return(num);
|
||||||
|
len = q - num;
|
||||||
|
p = pbuf;
|
||||||
|
switch(len) {
|
||||||
|
case 11: /* +0-123-456-7890 */
|
||||||
|
*p++ = '+';
|
||||||
|
*p++ = *num++;
|
||||||
|
*p++ = '-';
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case 10: /* 012-345-6789 */
|
||||||
|
*p++ = *num++;
|
||||||
|
*p++ = *num++;
|
||||||
|
*p++ = *num++;
|
||||||
|
*p++ = '-';
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case 7: /* 012-3456 */
|
||||||
|
*p++ = *num++;
|
||||||
|
*p++ = *num++;
|
||||||
|
*p++ = *num++;
|
||||||
|
break;
|
||||||
|
case 5: /* x0-1234 */
|
||||||
|
case 4: /* x1234 */
|
||||||
|
*p++ = 'x';
|
||||||
|
*p++ = *num++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
if (len != 4) {
|
||||||
|
*p++ = '-';
|
||||||
|
*p++ = *num++;
|
||||||
|
}
|
||||||
|
*p++ = *num++;
|
||||||
|
*p++ = *num++;
|
||||||
|
*p++ = *num++;
|
||||||
|
*p = '\0';
|
||||||
|
return(pbuf);
|
||||||
|
}
|
45
third_party/lua/lunix.c
vendored
45
third_party/lua/lunix.c
vendored
|
@ -101,12 +101,6 @@ struct UnixErrno {
|
||||||
const char *call;
|
const char *call;
|
||||||
};
|
};
|
||||||
|
|
||||||
union SockAddr {
|
|
||||||
struct sockaddr s;
|
|
||||||
struct sockaddr_in i;
|
|
||||||
struct sockaddr_un u;
|
|
||||||
};
|
|
||||||
|
|
||||||
static lua_State *GL;
|
static lua_State *GL;
|
||||||
|
|
||||||
static void *LuaRealloc(lua_State *L, void *p, size_t n) {
|
static void *LuaRealloc(lua_State *L, void *p, size_t n) {
|
||||||
|
@ -225,23 +219,26 @@ static int SysretInteger(lua_State *L, const char *call, int olderr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int MakeSockaddr(lua_State *L, int i, union SockAddr *sa,
|
static int MakeSockaddr(lua_State *L, int i, struct sockaddr_storage *ss,
|
||||||
uint32_t *salen) {
|
uint32_t *salen) {
|
||||||
bzero(sa, sizeof(*sa));
|
bzero(ss, sizeof(*ss));
|
||||||
if (lua_isstring(L, i)) {
|
if (!lua_isinteger(L, i)) {
|
||||||
sa->u.sun_family = AF_UNIX;
|
((struct sockaddr_un *)ss)->sun_family = AF_UNIX;
|
||||||
if (!memccpy(sa->u.sun_path, luaL_checkstring(L, i), 0,
|
if (!memccpy(((struct sockaddr_un *)ss)->sun_path, luaL_checkstring(L, i),
|
||||||
sizeof(sa->u.sun_path))) {
|
0, sizeof(((struct sockaddr_un *)ss)->sun_path))) {
|
||||||
luaL_error(L, "unix path too long");
|
luaL_error(L, "unix path too long");
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
*salen = sizeof(struct sockaddr_un);
|
*salen = sizeof(struct sockaddr_un);
|
||||||
|
kprintf("shit %d\n", ((struct sockaddr_in *)ss)->sin_family);
|
||||||
return i + 1;
|
return i + 1;
|
||||||
} else {
|
} else {
|
||||||
sa->i.sin_family = AF_INET;
|
((struct sockaddr_in *)ss)->sin_family = AF_INET;
|
||||||
sa->i.sin_addr.s_addr = htonl(luaL_optinteger(L, i, 0));
|
((struct sockaddr_in *)ss)->sin_addr.s_addr =
|
||||||
sa->i.sin_port = htons(luaL_optinteger(L, i + 1, 0));
|
htonl(luaL_optinteger(L, i, 0));
|
||||||
|
((struct sockaddr_in *)ss)->sin_port = htons(luaL_optinteger(L, i + 1, 0));
|
||||||
*salen = sizeof(struct sockaddr_in);
|
*salen = sizeof(struct sockaddr_in);
|
||||||
|
kprintf("wut %d\n", ((struct sockaddr_in *)ss)->sin_family);
|
||||||
return i + 2;
|
return i + 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1236,11 +1233,11 @@ static int LuaUnixSocketpair(lua_State *L) {
|
||||||
// └─→ nil, unix.Errno
|
// └─→ nil, unix.Errno
|
||||||
static int LuaUnixBind(lua_State *L) {
|
static int LuaUnixBind(lua_State *L) {
|
||||||
uint32_t salen;
|
uint32_t salen;
|
||||||
union SockAddr sa;
|
struct sockaddr_storage ss;
|
||||||
int olderr = errno;
|
int olderr = errno;
|
||||||
MakeSockaddr(L, 2, &sa, &salen);
|
MakeSockaddr(L, 2, &ss, &salen);
|
||||||
return SysretBool(L, "bind", olderr,
|
return SysretBool(L, "bind", olderr,
|
||||||
bind(luaL_checkinteger(L, 1), &sa.s, salen));
|
bind(luaL_checkinteger(L, 1), &ss, salen));
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.connect(fd:int, ip:uint32, port:uint16)
|
// unix.connect(fd:int, ip:uint32, port:uint16)
|
||||||
|
@ -1249,11 +1246,11 @@ static int LuaUnixBind(lua_State *L) {
|
||||||
// └─→ nil, unix.Errno
|
// └─→ nil, unix.Errno
|
||||||
static int LuaUnixConnect(lua_State *L) {
|
static int LuaUnixConnect(lua_State *L) {
|
||||||
uint32_t salen;
|
uint32_t salen;
|
||||||
union SockAddr sa;
|
struct sockaddr_storage ss;
|
||||||
int olderr = errno;
|
int olderr = errno;
|
||||||
MakeSockaddr(L, 2, &sa, &salen);
|
MakeSockaddr(L, 2, &ss, &salen);
|
||||||
return SysretBool(L, "connect", olderr,
|
return SysretBool(L, "connect", olderr,
|
||||||
connect(luaL_checkinteger(L, 1), &sa.s, salen));
|
connect(luaL_checkinteger(L, 1), &ss, salen));
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.listen(fd:int[, backlog:int])
|
// unix.listen(fd:int[, backlog:int])
|
||||||
|
@ -1510,14 +1507,14 @@ static int LuaUnixSendto(lua_State *L) {
|
||||||
char *data;
|
char *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
uint32_t salen;
|
uint32_t salen;
|
||||||
union SockAddr sa;
|
struct sockaddr_storage ss;
|
||||||
int i, fd, flags, olderr = errno;
|
int i, fd, flags, olderr = errno;
|
||||||
fd = luaL_checkinteger(L, 1);
|
fd = luaL_checkinteger(L, 1);
|
||||||
data = luaL_checklstring(L, 2, &size);
|
data = luaL_checklstring(L, 2, &size);
|
||||||
i = MakeSockaddr(L, 3, &sa, &salen);
|
i = MakeSockaddr(L, 3, &ss, &salen);
|
||||||
flags = luaL_optinteger(L, i, 0);
|
flags = luaL_optinteger(L, i, 0);
|
||||||
return SysretInteger(L, "sendto", olderr,
|
return SysretInteger(L, "sendto", olderr,
|
||||||
sendto(fd, data, size, flags, &sa.s, salen));
|
sendto(fd, data, size, flags, &ss, salen));
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.shutdown(fd:int, how:int)
|
// unix.shutdown(fd:int, how:int)
|
||||||
|
|
1
third_party/third_party.mk
vendored
1
third_party/third_party.mk
vendored
|
@ -8,6 +8,7 @@ o/$(MODE)/third_party: \
|
||||||
o/$(MODE)/third_party/chibicc \
|
o/$(MODE)/third_party/chibicc \
|
||||||
o/$(MODE)/third_party/compiler_rt \
|
o/$(MODE)/third_party/compiler_rt \
|
||||||
o/$(MODE)/third_party/dlmalloc \
|
o/$(MODE)/third_party/dlmalloc \
|
||||||
|
o/$(MODE)/third_party/finger \
|
||||||
o/$(MODE)/third_party/gdtoa \
|
o/$(MODE)/third_party/gdtoa \
|
||||||
o/$(MODE)/third_party/getopt \
|
o/$(MODE)/third_party/getopt \
|
||||||
o/$(MODE)/third_party/libcxx \
|
o/$(MODE)/third_party/libcxx \
|
||||||
|
|
70
tool/net/demo/unix-finger.lua
Normal file
70
tool/net/demo/unix-finger.lua
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
-- UNIX Finger Example
|
||||||
|
|
||||||
|
local function WriteForm(host, user)
|
||||||
|
Write([[<!doctype html>
|
||||||
|
<title>redbean unix finger demo</title>
|
||||||
|
<style>
|
||||||
|
body { padding: 1em; }
|
||||||
|
h1 a { color: inherit; text-decoration: none; }
|
||||||
|
h1 img { border: none; vertical-align: middle; }
|
||||||
|
input { margin: .5em; padding: .25em; }
|
||||||
|
pre { margin-left: 2em; }
|
||||||
|
p { word-break: break-word; max-width: 650px; }
|
||||||
|
dt { font-weight: bold; }
|
||||||
|
dd { margin-top: 1em; margin-bottom: 1em; }
|
||||||
|
.hdr { text-indent: -1em; padding-left: 1em; }
|
||||||
|
</style>
|
||||||
|
<h1>
|
||||||
|
<a href="/"><img src="/redbean.png"></a>
|
||||||
|
<a href="unix-finger.lua">redbean unix finger demo</a>
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
Your redbean is able to function as an finger client. Lua server
|
||||||
|
pages can use the <code>unix</code> module to implement protocols
|
||||||
|
that your redbean wasn't originally intended to support. All it
|
||||||
|
takes is few lines of code!
|
||||||
|
</p>
|
||||||
|
<form action="unix-finger.lua" method="post">
|
||||||
|
<input type="text" id="host" name="host" size="40"
|
||||||
|
value="%s" placeholder="host" autofocus>
|
||||||
|
<label for="host">host</label>
|
||||||
|
<br>
|
||||||
|
<input type="text" id="user" name="user" size="40"
|
||||||
|
value="%s" placeholder="user">
|
||||||
|
<label for="user">user</label>
|
||||||
|
<br>
|
||||||
|
<input type="submit" value="finger">
|
||||||
|
</form>
|
||||||
|
]] % {EscapeHtml(host), EscapeHtml(user)})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function main()
|
||||||
|
if IsPublicIp(GetClientAddr()) then
|
||||||
|
ServeError(403)
|
||||||
|
elseif GetMethod() == 'GET' or GetMethod() == 'HEAD' then
|
||||||
|
WriteForm('graph.no', 'new_york')
|
||||||
|
elseif GetMethod() == 'POST' then
|
||||||
|
ip = assert(ResolveIp(GetParam('host')))
|
||||||
|
fd = assert(unix.socket())
|
||||||
|
assert(unix.connect(fd, ip, 79))
|
||||||
|
assert(unix.write(fd, GetParam('user') .. '\r\n'))
|
||||||
|
response = ''
|
||||||
|
while true do
|
||||||
|
data = assert(unix.read(fd))
|
||||||
|
if data == '' then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
response = response .. data
|
||||||
|
end
|
||||||
|
assert(unix.close(fd))
|
||||||
|
WriteForm(GetParam('host'), GetParam('user'))
|
||||||
|
Write('<pre>\r\n')
|
||||||
|
Write(EscapeHtml(VisualizeControlCodes(response)))
|
||||||
|
Write('</pre>\r\n')
|
||||||
|
else
|
||||||
|
ServeError(405)
|
||||||
|
SetHeader('Allow', 'GET, HEAD, POST')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
main()
|
|
@ -1449,6 +1449,28 @@ FUNCTIONS
|
||||||
value will be the `"0b"`-prefixed binary str. The result is
|
value will be the `"0b"`-prefixed binary str. The result is
|
||||||
currently modulo 2^64. Negative numbers are converted to unsigned.
|
currently modulo 2^64. Negative numbers are converted to unsigned.
|
||||||
|
|
||||||
|
ResolveIp(hostname:str)
|
||||||
|
├─→ ip:uint32
|
||||||
|
└─→ nil, error:str
|
||||||
|
|
||||||
|
Gets IP address associated with hostname.
|
||||||
|
|
||||||
|
This function first checks if hostname is already an IP address, in
|
||||||
|
which case it returns the result of `ParseIp`. Otherwise, it checks
|
||||||
|
HOSTS.TXT on the local system and returns the first IPv4 address
|
||||||
|
associated with hostname. If no such entry is found, a DNS lookup is
|
||||||
|
performed using the system configured (e.g. /etc/resolv.conf) DNS
|
||||||
|
resolution service. If the service returns multiple IN A records
|
||||||
|
then only the first one is reutrned.
|
||||||
|
|
||||||
|
The returned address is word-encoded in host endian order. For
|
||||||
|
example, 1.2.3.4 is encoded as 0x01020304. The `FormatIp` function
|
||||||
|
may be used to turn this value back into a string.
|
||||||
|
|
||||||
|
If no IP address could be found, then nil is returned alongside a
|
||||||
|
string of unspecified format describing the error. Calls to this
|
||||||
|
function may be wrapped in assert() if an exception is desired.
|
||||||
|
|
||||||
|
|
||||||
────────────────────────────────────────────────────────────────────────────────
|
────────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "libc/bits/popcnt.h"
|
#include "libc/bits/popcnt.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/struct/rusage.h"
|
#include "libc/calls/struct/rusage.h"
|
||||||
|
#include "libc/dns/dns.h"
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/fmt/leb128.h"
|
#include "libc/fmt/leb128.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
|
@ -41,7 +42,9 @@
|
||||||
#include "libc/runtime/sysconf.h"
|
#include "libc/runtime/sysconf.h"
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/sysv/consts/af.h"
|
#include "libc/sysv/consts/af.h"
|
||||||
|
#include "libc/sysv/consts/ipproto.h"
|
||||||
#include "libc/sysv/consts/rusage.h"
|
#include "libc/sysv/consts/rusage.h"
|
||||||
|
#include "libc/sysv/consts/sock.h"
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
#include "libc/x/x.h"
|
#include "libc/x/x.h"
|
||||||
#include "net/http/escape.h"
|
#include "net/http/escape.h"
|
||||||
|
@ -379,6 +382,27 @@ int LuaSlurp(lua_State *L) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int LuaResolveIp(lua_State *L) {
|
||||||
|
ssize_t rc;
|
||||||
|
int64_t ip;
|
||||||
|
const char *host;
|
||||||
|
struct addrinfo *ai = NULL;
|
||||||
|
struct addrinfo hint = {AI_NUMERICSERV, AF_INET, SOCK_STREAM, IPPROTO_TCP};
|
||||||
|
host = luaL_checkstring(L, 1);
|
||||||
|
if ((ip = ParseIp(host, -1)) != -1) {
|
||||||
|
lua_pushinteger(L, ntohl(ai->ai_addr4->sin_addr.s_addr));
|
||||||
|
return 1;
|
||||||
|
} else if ((rc = getaddrinfo(host, "0", &hint, &ai)) == EAI_SUCCESS) {
|
||||||
|
lua_pushinteger(L, ntohl(ai->ai_addr4->sin_addr.s_addr));
|
||||||
|
freeaddrinfo(ai);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_pushfstring(L, "%s: DNS lookup failed: EAI_%s", host, gai_strerror(rc));
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int LuaCheckControlFlags(lua_State *L, int idx) {
|
static int LuaCheckControlFlags(lua_State *L, int idx) {
|
||||||
int f = luaL_checkinteger(L, idx);
|
int f = luaL_checkinteger(L, idx);
|
||||||
if (f & ~(kControlWs | kControlC0 | kControlC1)) {
|
if (f & ~(kControlWs | kControlC0 | kControlC1)) {
|
||||||
|
|
|
@ -70,6 +70,7 @@ int LuaRand64(lua_State *);
|
||||||
int LuaRdrand(lua_State *);
|
int LuaRdrand(lua_State *);
|
||||||
int LuaRdseed(lua_State *);
|
int LuaRdseed(lua_State *);
|
||||||
int LuaRdtsc(lua_State *);
|
int LuaRdtsc(lua_State *);
|
||||||
|
int LuaResolveIp(lua_State *);
|
||||||
int LuaSetLogLevel(lua_State *);
|
int LuaSetLogLevel(lua_State *);
|
||||||
int LuaSha1(lua_State *);
|
int LuaSha1(lua_State *);
|
||||||
int LuaSha224(lua_State *);
|
int LuaSha224(lua_State *);
|
||||||
|
|
|
@ -173,6 +173,7 @@ o/$(MODE)/tool/net/demo/unix-subprocess.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/unix-webserver.lua.zip.o \
|
o/$(MODE)/tool/net/demo/unix-webserver.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/unix-dir.lua.zip.o \
|
o/$(MODE)/tool/net/demo/unix-dir.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/unix-info.lua.zip.o \
|
o/$(MODE)/tool/net/demo/unix-info.lua.zip.o \
|
||||||
|
o/$(MODE)/tool/net/demo/unix-finger.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/fetch.lua.zip.o \
|
o/$(MODE)/tool/net/demo/fetch.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/call-lua-module.lua.zip.o \
|
o/$(MODE)/tool/net/demo/call-lua-module.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/store-asset.lua.zip.o \
|
o/$(MODE)/tool/net/demo/store-asset.lua.zip.o \
|
||||||
|
@ -222,6 +223,7 @@ o/$(MODE)/tool/net/redbean-demo.com.dbg: \
|
||||||
o/$(MODE)/tool/net/demo/unix-webserver.lua.zip.o \
|
o/$(MODE)/tool/net/demo/unix-webserver.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/unix-dir.lua.zip.o \
|
o/$(MODE)/tool/net/demo/unix-dir.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/unix-info.lua.zip.o \
|
o/$(MODE)/tool/net/demo/unix-info.lua.zip.o \
|
||||||
|
o/$(MODE)/tool/net/demo/unix-finger.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/fetch.lua.zip.o \
|
o/$(MODE)/tool/net/demo/fetch.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/store-asset.lua.zip.o \
|
o/$(MODE)/tool/net/demo/store-asset.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/call-lua-module.lua.zip.o \
|
o/$(MODE)/tool/net/demo/call-lua-module.lua.zip.o \
|
||||||
|
|
|
@ -5131,6 +5131,7 @@ static const luaL_Reg kLuaFuncs[] = {
|
||||||
{"Rdrand", LuaRdrand}, //
|
{"Rdrand", LuaRdrand}, //
|
||||||
{"Rdseed", LuaRdseed}, //
|
{"Rdseed", LuaRdseed}, //
|
||||||
{"Rdtsc", LuaRdtsc}, //
|
{"Rdtsc", LuaRdtsc}, //
|
||||||
|
{"ResolveIp", LuaResolveIp}, //
|
||||||
{"Route", LuaRoute}, //
|
{"Route", LuaRoute}, //
|
||||||
{"RouteHost", LuaRouteHost}, //
|
{"RouteHost", LuaRouteHost}, //
|
||||||
{"RoutePath", LuaRoutePath}, //
|
{"RoutePath", LuaRoutePath}, //
|
||||||
|
|
Loading…
Reference in a new issue