func Close(utmpPath, wtmpPath string, tty *os.File) error {
	ttyName, err := os.Readlink(tty.Name())
	if err != nil {
		return trace.Errorf("failed to resolve soft proc tty link: %v", err)
	}

	// String parameter validation.
	if len(ttyName) > (int)(C.max_len_tty_name()-1) {
		return trace.BadParameter("tty name length exceeds OS limits")
	}

	// Convert Go strings into C strings that we can pass over ffi.
	var cUtmpPath *C.char = nil
	var cWtmpPath *C.char = nil
	if len(utmpPath) > 0 {
		cUtmpPath = C.CString(utmpPath)
		defer C.free(unsafe.Pointer(cUtmpPath))
	}
	if len(wtmpPath) > 0 {
		cWtmpPath = C.CString(wtmpPath)
		defer C.free(unsafe.Pointer(cWtmpPath))
	}
	cTtyName := C.CString(strings.TrimPrefix(ttyName, "/dev/"))
	defer C.free(unsafe.Pointer(cTtyName))

	timestamp := time.Now()
	secondsElapsed := (C.int32_t)(timestamp.Unix())
	microsFraction := (C.int32_t)((timestamp.UnixNano() % int64(time.Second)) / int64(time.Microsecond))

	accountDb.Lock()
	status := C.uacc_mark_utmp_entry_dead(cUtmpPath, cWtmpPath, cTtyName, secondsElapsed, microsFraction)
	accountDb.Unlock()

	switch status {
	case C.UACC_UTMP_MISSING_PERMISSIONS:
		return trace.AccessDenied("missing permissions to write to utmp/wtmp")
	case C.UACC_UTMP_WRITE_ERROR:
		return trace.AccessDenied("failed to add entry to utmp database")
	case C.UACC_UTMP_READ_ERROR:
		return trace.AccessDenied("failed to read and search utmp database")
	case C.UACC_UTMP_FAILED_OPEN:
		code := C.get_errno()
		return trace.AccessDenied("failed to open user account database, code: %d", code)
	case C.UACC_UTMP_FAILED_TO_SELECT_FILE:
		return trace.BadParameter("failed to select file")
	case C.UACC_UTMP_PATH_DOES_NOT_EXIST:
		return trace.NotFound("user accounting files are missing from the system, running in a container?")
	default:
		if status != 0 {
			return trace.Errorf("unknown error with code %d", status)
		}

		return nil
	}
}
// Close marks an entry in the utmp database as DEAD_PROCESS.
// This should be called when an interactive session exits.
//
// The `ttyName` parameter must be the name of the TTY including the `/dev/` prefix.
Close marks an entry in the utmp database as DEAD_PROCESS.
This should be called when an interactive session exits.

The `ttyName` parameter must be the name of the TTY including the `/dev/` prefix.
// Close marks an entry in the utmp database as DEAD_PROCESS . // This should be called when an interactive session exits . // // The ` ttyName ` parameter must be the name of the TTY including the ` / dev / ` prefix .
func Close(utmpPath, wtmpPath string, tty *os.File) error {
	ttyName, err := os.Readlink(tty.Name())
	if err != nil {
		return trace.Errorf("failed to resolve soft proc tty link: %v", err)
	}
	if len(ttyName) > (int)(C.max_len_tty_name()-1) {
		return trace.BadParameter("tty name length exceeds OS limits")
	}
	var cUtmpPath *C.char = nil
	var cWtmpPath *C.char = nil
	if len(utmpPath) > 0 {
		cUtmpPath = C.CString(utmpPath)
		defer C.free(unsafe.Pointer(cUtmpPath))
	}
	if len(wtmpPath) > 0 {
		cWtmpPath = C.CString(wtmpPath)
		defer C.free(unsafe.Pointer(cWtmpPath))
	}
	cTtyName := C.CString(strings.TrimPrefix(ttyName, "/dev/"))
	defer C.free(unsafe.Pointer(cTtyName))
	timestamp := time.Now()
	secondsElapsed := (C.int32_t)(timestamp.Unix())
	microsFraction := (C.int32_t)((timestamp.UnixNano() % int64(time.Second)) / int64(time.Microsecond))
	accountDb.Lock()
	status := C.uacc_mark_utmp_entry_dead(cUtmpPath, cWtmpPath, cTtyName, secondsElapsed, microsFraction)
	accountDb.Unlock()
	switch status {
	case C.UACC_UTMP_MISSING_PERMISSIONS:
		return trace.AccessDenied("missing permissions to write to utmp/wtmp")
	case C.UACC_UTMP_WRITE_ERROR:
		return trace.AccessDenied("failed to add entry to utmp database")
	case C.UACC_UTMP_READ_ERROR:
		return trace.AccessDenied("failed to read and search utmp database")
	case C.UACC_UTMP_FAILED_OPEN:
		code := C.get_errno()
		return trace.AccessDenied("failed to open user account database, code: %d", code)
	case C.UACC_UTMP_FAILED_TO_SELECT_FILE:
		return trace.BadParameter("failed to select file")
	case C.UACC_UTMP_PATH_DOES_NOT_EXIST:
		return trace.NotFound("user accounting files are missing from the system, running in a container?")
	default:
		if status != 0 {
			return trace.Errorf("unknown error with code %d", status)
		}
		return nil
	}
}
func Close ( utmpPath , wtmpPath string , tty * os . File ) error { ttyName , err := os . Readlink ( tty . Name ( ) ) if err != nil { return trace . Errorf ( " " , err ) } if len ( ttyName ) > ( int ) ( C . max_len_tty_name ( ) - 1 ) { return trace . BadParameter ( " " ) } var cUtmpPath * C . char = nil var cWtmpPath * C . char = nil if len ( utmpPath ) > 0 { cUtmpPath = C . CString ( utmpPath ) defer C . free ( unsafe . Pointer ( cUtmpPath ) ) } if len ( wtmpPath ) > 0 { cWtmpPath = C . CString ( wtmpPath ) defer C . free ( unsafe . Pointer ( cWtmpPath ) ) } cTtyName := C . CString ( strings . TrimPrefix ( ttyName , " " ) ) defer C . free ( unsafe . Pointer ( cTtyName ) ) timestamp := time . Now ( ) secondsElapsed := ( C . int32_t ) ( timestamp . Unix ( ) ) microsFraction := ( C . int32_t ) ( ( timestamp . UnixNano ( ) % int64 ( time . Second ) ) / int64 ( time . Microsecond ) ) accountDb . Lock ( ) status := C . uacc_mark_utmp_entry_dead ( cUtmpPath , cWtmpPath , cTtyName , secondsElapsed , microsFraction ) accountDb . Unlock ( ) switch status { case C . UACC_UTMP_MISSING_PERMISSIONS : return trace . AccessDenied ( " " ) case C . UACC_UTMP_WRITE_ERROR : return trace . AccessDenied ( " " ) case C . UACC_UTMP_READ_ERROR : return trace . AccessDenied ( " " ) case C . UACC_UTMP_FAILED_OPEN : code := C . get_errno ( ) return trace . AccessDenied ( " " , code ) case C . UACC_UTMP_FAILED_TO_SELECT_FILE : return trace . BadParameter ( " " ) case C . UACC_UTMP_PATH_DOES_NOT_EXIST : return trace . NotFound ( " " ) default : if status != 0 { return trace . Errorf ( " " , status ) } return nil } }
Close marks an entry in the utmp database as DEAD_PROCESS.
Close marks an entry in the utmp database as DEAD_PROCESS .
// String parameter validation. // Convert Go strings into C strings that we can pass over ffi.