Compare commits

...

8 Commits

Author SHA1 Message Date
Russtopia 73aea4ba72 Update 'README.md' 2023-02-02 19:01:13 -08:00
Russ Magee e75ee8b119 go.mod 2022-03-19 09:01:33 -07:00
Russ Magee 826b4de2a3 Added missing arg for linux test 2022-03-19 00:13:23 -07:00
Russ Magee c3193d4a77 More fixes to +build constraints (oops, freebsd not bsd)
Signed-off-by: Russ Magee <rmagee@gmail.com>
2020-04-25 19:42:32 -07:00
Russ Magee 74d785142e Fixed +build constraints
Signed-off-by: Russ Magee <rmagee@gmail.com>
2020-04-25 18:39:08 -07:00
Russ Magee c076bc0153 FreeBSD 12 support 2020-04-26 00:50:02 +00:00
Russtopia 2b9cd1bafd Update 'README.md' 2019-07-06 00:23:16 -07:00
Russ Magee f388f970e4 Fixed tty logging
Signed-off-by: Russ Magee <rmagee@gmail.com>
2019-07-04 20:23:04 -07:00
6 changed files with 192 additions and 21 deletions

View File

@ -3,15 +3,33 @@ goutmp - Minimal bindings to C stdlib pututmpx(), getutmpx() (/var/log/wtmp) and
Any Go program which allows user shell access should update the standard UNIX files which track user sessions: /var/log/wtmp (for the 'w' and 'who' commands), and /var/log/lastlog (the 'last' and 'lastlog' commands).
```
go doc
$ go doc -all
package goutmp // import "blitter.com/go/goutmp"
Golang bindings for basic login/utmp accounting
type UtmpEntry struct{ ... }
FUNCTIONS
func GetHost(addr string) (h string)
return remote client hostname or IP if host lookup fails addr is expected to
be of the format given by net.Addr.String() eg., "127.0.0.1:80" or
"[::1]:80"
func Put_lastlog_entry(app, usr, ptsname, host string)
Put the login app, username and originating host/IP to lastlog
func Put_lastlog_entry(app string, usr string, host string)
func Unput_utmp(entry UtmpEntry)
func Put_utmp(user string, host string) UtmpEntry
Remove a username/host entry from utmp
TYPES
type UtmpEntry struct {
// Has unexported fields.
}
UtmpEntry wraps the C struct utmp
func Put_utmp(user, ptsName, host string) UtmpEntry
Put a username and the originating host/IP to utmp
```

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module blitter.com/go/goutmp
go 1.17

136
goutmp_bsd.go Normal file
View File

@ -0,0 +1,136 @@
// +build freebsd
// Golang bindings for basic login/utmp accounting
package goutmp
//#include <stdio.h>
//#include <stdlib.h>
//#include <sys/file.h>
//#include <string.h>
//#include <unistd.h>
//#include <stdint.h>
//#include <time.h>
//#include <pwd.h>
//
//#include <utmpx.h>
//
//typedef char char_t;
//
//void pututmpx(struct utmpx* entry, char* uname, char* ptsname, char* host) {
// entry->ut_type = USER_PROCESS;
// entry->ut_pid = getpid();
// strcpy(entry->ut_line, ptsname + strlen("/dev/"));
//
// strcpy(entry->ut_id, ptsname + strlen("/dev/pts/"));
//
// //entry->ut_time = time(NULL);
// strcpy(entry->ut_user, uname);
// strcpy(entry->ut_host, host);
// //entry->ut_addr = 0;
// setutxent();
// pututxline(entry);
//}
//
//void unpututmpx(struct utmpx* entry) {
// entry->ut_type = DEAD_PROCESS;
// entry->ut_line[0] = '\0';
// //entry->ut_time = 0;
// entry->ut_user[0] = '\0';
// setutxent();
// pututxline(entry);
//
// endutxent();
//}
//
//#if 0
//int putlastlogentry(int64_t t, int uid, char* line, char* host) {
// int retval = 0;
// FILE *f;
// struct lastlog l;
//
// strncpy(l.ll_line, line, UT_LINESIZE);
// l.ll_line[UT_LINESIZE-1] = '\0';
// strncpy(l.ll_host, host, UT_HOSTSIZE);
// l.ll_host[UT_HOSTSIZE-1] = '\0';
//
// l.ll_time = (time_t)t;
// //printf("l: ll_line '%s', ll_host '%s', ll_time %d\n", l.ll_line, l.ll_host, l.ll_time);
//
// /* Write lastlog entry at fixed offset (uid * sizeof(struct lastlog) */
// if( NULL != (f = fopen("/var/log/lastlog", "rw+")) ) {
// if( !fseek(f, (uid * sizeof(struct lastlog)), SEEK_SET) ) {
// int fd = fileno(f);
// if( write(fd, &l, sizeof(l)) == sizeof(l) ) {
// retval = 1;
// //int32_t stat = system("echo ---- lastlog ----; lastlog");
// }
// }
// fclose(f);
// }
// return retval;
//}
//#else
//int putlastlogentry(int64_t t, int uid, char* line, char* host) {
// return 0;
//}
//#endif
import "C"
import (
"fmt"
"net"
"os/user"
"strings"
"time"
)
// UtmpEntry wraps the C struct utmp
type UtmpEntry struct {
entry C.struct_utmpx
}
// return remote client hostname or IP if host lookup fails
// addr is expected to be of the format given by net.Addr.String()
// eg., "127.0.0.1:80" or "[::1]:80"
func GetHost(addr string) (h string) {
if !strings.Contains(addr, "[") {
h = strings.Split(addr, ":")[0]
} else {
h = strings.Split(strings.Split(addr, "[")[1], "]")[0]
}
hList, e := net.LookupAddr(h)
//fmt.Printf("lookupAddr:%v\n", hList)
if e == nil {
h = hList[0]
}
return
}
// Put a username and the originating host/IP to utmp
func Put_utmp(user, ptsName, host string) UtmpEntry {
var entry UtmpEntry
//log.Println("Put_utmp:host ", host, " user ", user)
C.pututmpx(&entry.entry, C.CString(user), C.CString(ptsName), C.CString(host))
return entry
}
// Remove a username/host entry from utmp
func Unput_utmp(entry UtmpEntry) {
C.unpututmpx(&entry.entry)
}
// Put the login app, username and originating host/IP to lastlog
func Put_lastlog_entry(app, usr, ptsname, host string) {
u, e := user.Lookup(usr)
if e != nil {
return
}
var uid uint32
fmt.Sscanf(u.Uid, "%d", &uid)
t := time.Now().Unix()
_ = C.putlastlogentry(C.int64_t(t), C.int(uid), C.CString(app), C.CString(host))
//stat := C.putlastlogentry(C.int64_t(t), C.int(uid), C.CString(app), C.CString(host))
//fmt.Println("stat was:",stat)
}

View File

@ -1,3 +1,5 @@
// +build linux
// Golang bindings for basic login/utmp accounting
package goutmp
@ -16,23 +18,15 @@ package goutmp
//typedef char char_t;
//
//
//void pututmp(struct utmp* entry, char* name, char* host) {
// //TODO: if ttyname returns NULL, it's probably a network
// // connection and the pty should be passed in to this func.
// char* stdinName = ttyname(STDIN_FILENO);
// if( !stdinName ) {
// stdinName = "/dev/ptyN";
// }
//
//void pututmp(struct utmp* entry, char* uname, char* ptsname, char* host) {
// entry->ut_type = USER_PROCESS;
// entry->ut_pid = getpid();
// strcpy(entry->ut_line, stdinName + strlen("/dev/"));
// /* only correct for ptys named /dev/tty[pqr][0-9a-z] */
// strcpy(entry->ut_line, ptsname + strlen("/dev/"));
//
// strcpy(entry->ut_id, stdinName + strlen("/dev/tty"));
// strcpy(entry->ut_id, ptsname + strlen("/dev/pts/"));
//
// entry->ut_time = time(NULL);
// strcpy(entry->ut_user, name);
// strcpy(entry->ut_user, uname);
// strcpy(entry->ut_host, host);
// entry->ut_addr = 0;
// setutent();
@ -109,11 +103,11 @@ func GetHost(addr string) (h string) {
}
// Put a username and the originating host/IP to utmp
func Put_utmp(user string, host string) UtmpEntry {
func Put_utmp(user, ptsName, host string) UtmpEntry {
var entry UtmpEntry
//log.Println("Put_utmp:host ", host, " user ", user)
C.pututmp(&entry.entry, C.CString(user), C.CString(host))
C.pututmp(&entry.entry, C.CString(user), C.CString(ptsName), C.CString(host))
return entry
}
@ -123,7 +117,7 @@ func Unput_utmp(entry UtmpEntry) {
}
// Put the login app, username and originating host/IP to lastlog
func Put_lastlog_entry(app string, usr string, host string) {
func Put_lastlog_entry(app, usr, ptsname, host string) {
u, e := user.Lookup(usr)
if e != nil {
return

18
main/test_bsd.go Normal file
View File

@ -0,0 +1,18 @@
// +build freebsd
package main
import (
"time"
"blitter.com/go/goutmp"
)
func main() {
user := "bin"
host := "test.example.com"
utmp := goutmp.Put_utmp(user, "/dev/pts0", host)
goutmp.Put_lastlog_entry("xs", user, "/dev/pts0", host)
time.Sleep(10 * time.Second)
goutmp.Unput_utmp(utmp)
}

View File

@ -1,3 +1,5 @@
// +build linux
package main
import (
@ -9,8 +11,8 @@ import (
func main() {
user := "bin"
host := "test.example.com"
utmp := goutmp.Put_utmp(user, host)
goutmp.Put_lastlog_entry("hkexsh", user, host)
utmp := goutmp.Put_utmp(user, "/dev/pts0", host)
goutmp.Put_lastlog_entry("xs", user, "/dev/pts0", host)
time.Sleep(10 * time.Second)
goutmp.Unput_utmp(utmp)
}