You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: utmp.go
    path of file: ./repos/shellhub/pkg/agent/server/utmp
    
    the code of the file until where you have to start completion: package utmp

/*	At session start, a utmp record is constructed containing the PID,
	tty name, ID, username, remote host, source IP and time.
	Type is set to UserProcess and the record is written to UtmpxFile.
	If a record with the same ID exists, that record is overwritten;
	otherwise the record is appended to the file.  The same record is
	appended to WtmpxFile.

	At session end, Type is set to DeadProcess, the User and Host fields
	are cleared, time is updated and the record is wrtten to UtmpxFile,
	overwriting the session start record. The same record with ID and
	source IP address cleared is appended to WtmpxFile.
*/

import (
	"bytes"
	"encoding/binary"
	"io"
	"net"
	"os"
	"strings"
	"unsafe"

	"github.com/sirupsen/logrus"
	"golang.org/x/sys/unix"
)

type ExitStatus struct {
	ETermination int16 // Process temination status - not used
	EExit        int16 // Process exit status - not used
}

const (
	UtmpxFile   = "/var/run/utmp"
	WtmpxFile   = "/var/log/wtmp"
	UserProcess = 0x7 // Normal process
	DeadProcess = 0x8 // Terminated process
)

// UtmpStartSession This functi
    
func UtmpStartSession(line, user, remoteAddr string) Utmpx { //nolint:revive
	var u Utmpx

	u.Type = UserProcess
	u.Pid = int32(os.Getpid())

	// There are two versions of the utmpSetTime function
	// defined in utmp_timeval_time??.go, one for systems
	// that write the time fields as 32-bit values and one
	// for systems that write time fields as 64-bit values
	u = utmpSetTime(u)

	// remoteAddr has the form <IPv4 address>:<port>
	// or [<IPv6 address>]:<port>
	// Remove the port suffix and also the square brackets
	// if IPv6, leaving the bare IPv4 or IPv6 address
	host, _, err := net.SplitHostPort(remoteAddr)
	if err != nil {
		logrus.WithFields(logrus.Fields{
			"ip": remoteAddr,
		}).Warn("wrong remoteAddr format")
	} else {
		// Parse IP address to a standard 16-byte representation
		ip := net.ParseIP(host)
		// Check whether IPv4 or IPv6
		if ip4 := ip.To4(); ip4 != nil {
			// This is a 32-bit IPv4 address to be
			// stored in the first element of u.AddrV6
			u.AddrV6[0] = binary.LittleEndian.Uint32(ip4)
		} else {
			// This is a 128-bit IPv6 address. Each 4 bytes
			// of the address is stored as a 32-bit int in
			// successive elements of u.AddrV6
			u.AddrV6[0] = binary.LittleEndian.Uint32(ip[0:4])
			u.AddrV6[1] = binary.LittleEndian.Uint32(ip[4:8])
			u.AddrV6[2] = binary.LittleEndian.Uint32(ip[8:12])
			u.AddrV6[3] = binary.LittleEndian.Uint32(ip[12:16])
		}
	}

	line = strings.TrimPrefix(line, "/dev/")
	// The index to the utmp record is the last 4 chars of line
	id := line[len(line)-4:]

	_ = copy(u.ID[:], id)
	_ = copy(u.Line[:], line)
	_ = copy(u.User[:], user)
	_ = copy(u.Host[:], host)

	updUtmp(u, id)
	updWtmp(u)

	return u
}