hslam_msg/msg_unix.go

122 lines
3.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) 2020 Meng Huang (mhboy@outlook.com)
// This package is licensed under a MIT license that can be found in the LICENSE file.
package msg
import (
"errors"
"syscall"
"unsafe"
)
const (
// IPC_CREAT creates if key is nonexistent
IPC_CREAT = 01000
// IPC_EXCL fails if key exists.
IPC_EXCL = 02000
// IPC_NOWAIT returns error no wait.
IPC_NOWAIT = 04000
// IPC_PRIVATE is private key
IPC_PRIVATE = 00000
// SEM_UNDO sets up adjust on exit entry
SEM_UNDO = 010000
// IPC_RMID removes identifier
IPC_RMID = 0
// IPC_SET sets ipc_perm options.
IPC_SET = 1
// IPC_STAT gets ipc_perm options.
IPC_STAT = 2
maxText = 8192
)
// ErrTooLong is returned when the Text length is bigger than maxText.
var ErrTooLong = errors.New("Text length is too long")
type message struct {
Type uint
Text [maxText]byte
}
// Get calls the msgget system call.
func Get(key int, msgflg int) (int, error) {
r1, _, err := syscall.Syscall(syscall.SYS_MSGGET, uintptr(key), uintptr(msgflg), 0)
msgid := int(r1)
if msgid < 0 {
return msgid, syscall.Errno(err)
}
return msgid, nil
}
// Snd calls the msgsnd system call.
//
// The msgsnd() and msgrcv() system calls are used to send messages to,
// and receive messages from, a System V message queue. The calling
// process must have write permission on the message queue in order to
// send a message, and read permission to receive a message.
// The msgp argument is a pointer to a caller-defined structure of the
// following general form:
//
// struct msgbuf {
// long mtype; /* message type, must be > 0 */
// char mtext[1]; /* message data */
// };
// The mtext field is an array (or other structure) whose size is speci
// fied by msgsz, a nonnegative integer value. Messages of zero length
// (i.e., no mtext field) are permitted. The mtype field must have a
// strictly positive integer value. This value can be used by the re
// ceiving process for message selection (see the description of ms
// grcv() below).
//
func Snd(msgid int, msgp uintptr, msgsz int, msgflg int) error {
_, _, err := syscall.Syscall6(syscall.SYS_MSGSND, uintptr(msgid), uintptr(msgp), uintptr(msgsz), uintptr(msgflg), 0, 0)
if err != 0 {
return err
}
return nil
}
// Rcv calls the msgrcv system call.
func Rcv(msgid int, msgp uintptr, msgsz int, msgtyp uint, msgflg int) (int, error) {
r1, _, err := syscall.Syscall6(syscall.SYS_MSGRCV, uintptr(msgid), msgp, uintptr(msgsz), uintptr(msgtyp), uintptr(msgflg), 0)
length := int(r1)
if err != 0 {
return length, err
}
return length, nil
}
// Send calls the msgsnd system call.
func Send(msgid int, msgType uint, msgText []byte, flags int) error {
if len(msgText) > maxText {
return ErrTooLong
}
m := message{Type: msgType}
copy(m.Text[:], msgText)
return Snd(msgid, uintptr(unsafe.Pointer(&m)), len(msgText), flags)
}
// Receive calls the msgrcv system call.
func Receive(msgid int, msgType uint, flags int) ([]byte, error) {
m := message{Type: msgType}
length, err := Rcv(msgid, uintptr(unsafe.Pointer(&m)), maxText, msgType, flags)
if err != nil {
return nil, err
}
return m.Text[:length], nil
}
// Remove removes the message queue with the given id.
func Remove(msgid int) error {
r1, _, errno := syscall.Syscall(syscall.SYS_MSGCTL, uintptr(msgid), IPC_RMID, 0)
if int(r1) < 0 {
return syscall.Errno(errno)
}
return nil
}