sysexits

package module
v0.0.0-...-f9dd56e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2023 License: MIT Imports: 1 Imported by: 2

README

sysexits

There is a convention on UNIX systems about what specific application codes mean. Originally from UNIX, these conventions are known as "sysexits.h".

Go, by convention, passes errors around to indicate a failure. It uses an error type to indicate a class of errors and the error value to indicate a specific error condition within an error type.

This package combines these approaches by defining an error type (sysexit) and a series of sysexits conveying the termination of an application.

Usage

See sysexits_test.go for up-to-date examples, but broadly:

// Lets imagine we want to express a specific failure mode — For example, a user lookup:
_, err := user.Lookup("fish")

switch err {
case nil:
    err = sysexits.OK
case user.UnknownUserError("fish"):
    err = fmt.Errorf("%w: %s", sysexits.NoUser, err)
default:
    err = fmt.Errorf("%w: %s", sysexits.Software, err)
}

// Later, in the main function, we want to see whether the program has given us a more
// specific exit code:
var exit sysexits.Sysexit
if errors.As(err, &exit) {
    fmt.Println(exit.Code)
    // Output: 67
}

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// OK indicates nothing is wrong.
	OK = Sysexit{Code: 0, Message: ""}

	// Usage indicates command was used incorrectly, e.g., with the wrong number of arguments, a
	// bad flag, bad syntax in a parameter, or whatever.
	Usage = Sysexit{Code: 64, Message: "command line usage error"}

	// DataErr indicates the input data was incorrect in some way. This should only be used for
	// user's data and not system files.
	DataErr = Sysexit{Code: 65, Message: "data format error"}

	// NoInput indicates he input file (not a system file) did not exist or was not  readable. This
	// could also include errors like "No message" to a mailer (if it cared to catch it).
	NoInput = Sysexit{Code: 66, Message: "cannot open input"}

	// NoUser indicates the user specified does not exist. This might be used for mail addresses or
	// remote logins.
	NoUser = Sysexit{Code: 67, Message: "addressee unknown"}

	// NoHost indicates the host specified does not exist. This is used in mail addresses or network
	// requests.
	NoHost = Sysexit{Code: 68, Message: "host name unknown"}

	// Software indicates the service is uanvailable. This can occur if a support program or file
	// does not exist. This can also be used as a catch-all message when something you wanted to do
	// doesn't work, but you don't know why.
	Unavailable = Sysexit{Code: 69, Message: "service unavailable"}

	// An internal software error has been detected. This should be limited to non-operating system
	// related errors if possible.
	Software = Sysexit{Code: 70, Message: "internal software error"}

	// OSErr indicates an operating system has been detected. This is intended to be used for such
	// things like "cannot fork", "cannot create pipe" or the like. It includes things like getuid(2)
	// returning a user that does not exist in the passwd(5) file.
	OSErr = Sysexit{Code: 71, Message: "system error (e.g., can't fork)"}

	// OSFile indicates Some system file (e.g., /etc/passwd, /etc/utmp, etc.) does not exist, cannot
	// be opened or has some sort of error (e.g., syntax error)
	OSFile = Sysexit{Code: 72, Message: "critical OS file missing"}

	// A (user specified) output file cannot be created.
	CantCreat = Sysexit{Code: 73, Message: "can't create (user) output file"}

	// An error occurred while doing I/O on some file.
	IOErr = Sysexit{Code: 74, Message: "input/output error"}

	// TempFail (or Temporary  failure) indicates something that is not really an error. For
	// example that a mailer could not create a connection, and the request should be  reattempted
	// later.
	TempFail = Sysexit{Code: 75, Message: "temp failure; user is invited to retry"}

	// Protocol indicates the  remote  system  returned  something  that was "not possible" during a
	// protocol exchange.
	Protocol = Sysexit{Code: 76, Message: "remote error in protocol"}

	// NoPerm indicates that permission was denied.
	NoPerm = Sysexit{Code: 77, Message: "permission denied"}

	// Config indicates something was found in an unconfigured or misconfigured state.
	Config = Sysexit{Code: 78, Message: "configuration error"}
)

Variables that describe specific failure modes.

Functions

This section is empty.

Types

type Sysexit

type Sysexit struct {
	// Code is the numeric code that the application is expecte to exit on.
	Code int

	// Message is a represnetation of this underlying failure condition.
	Message string
}

Sysexit is a type that implements the error interface, allowing the application to indicate the failure mode.

func (Sysexit) Error

func (s Sysexit) Error() string

Error allows the sysexits to be treated as a standard error type. This should be used with the error wrapping functionality. For example,

fmt.Errorf("%w: %s", sysexits.OSErr, err)
Example
package main

import (
	"errors"
	"fmt"
	"os/user"

	"github.com/andrewhowdencom/sysexits"
)

func main() {
	// Lets imagine we want to express a specific failure mode — For example, a user lookup:
	_, err := user.Lookup("fish")

	switch err {
	case nil:
		err = sysexits.OK
	case user.UnknownUserError("fish"):
		err = fmt.Errorf("%w: %s", sysexits.NoUser, err)
	default:
		err = fmt.Errorf("%w: %s", sysexits.Software, err)
	}

	// Later, in the main function, we want to see whether the program has given us a more
	// specific exit code:
	var exit sysexits.Sysexit
	if errors.As(err, &exit) {
		fmt.Println(exit.Code)

	}
}
Output:

67

func (Sysexit) Is

func (s Sysexit) Is(err error) bool

Is allows custom sysexits to be compared, where those sysexits have unuual error messages or otherwise are unforseen.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL