mirror of
https://github.com/therootcompany/serviceman.git
synced 2025-04-21 14:50:45 +00:00
Compare commits
No commits in common. "master" and "v0.2.2" have entirely different histories.
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,10 +1,3 @@
|
||||
/serviceman
|
||||
/manager/static/ab0x.go
|
||||
dist
|
||||
xversion.go
|
||||
|
||||
*~
|
||||
.*~
|
||||
# ---> Go
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
|
@ -1,36 +0,0 @@
|
||||
before:
|
||||
hooks:
|
||||
- go mod download
|
||||
- go generate ./...
|
||||
builds:
|
||||
- env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
- windows
|
||||
- darwin
|
||||
goarch:
|
||||
- 386
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
goarm:
|
||||
- 6
|
||||
- 7
|
||||
archives:
|
||||
- replacements:
|
||||
386: i386
|
||||
amd64: x86_64
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
snapshot:
|
||||
name_template: '{{ .Tag }}-next'
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
exclude:
|
||||
- '^docs:'
|
||||
- '^test:'
|
339
README.md
339
README.md
@ -1,114 +1,69 @@
|
||||
# New, Rewritten Version at New Repo
|
||||
# go-serviceman
|
||||
|
||||
See <https://github.com/bnnanet/serviceman>.
|
||||
A cross-platform service manager.
|
||||
|
||||
## [serviceman-sh](https://github.com/bnnanet/serviceman)
|
||||
Because debugging launchctl, systemd, etc absolutely sucks!
|
||||
|
||||
The new version is rewritten in POSIX script.
|
||||
|
||||
The **transitional version 0.9.x** will print several **warnings for options that have changed**, except `--user`, which is now `--agent` (as it was rarely used, and most often caused confusion).
|
||||
|
||||
See [Changes in v1.0](https://github.com/bnnanet/serviceman?tab=readme-ov-file#changes-in-v10) for details.
|
||||
|
||||
# [go-serviceman](https://git.rootprojects.org/root/serviceman) (DEPRECATED)
|
||||
|
||||
Cross-platform service management made easy.
|
||||
|
||||
> sudo serviceman add --name foo ./serve.js --port 3000
|
||||
|
||||
> Success: "foo" started as a "launchd" SYSTEM service, running as "root"
|
||||
|
||||
## Why?
|
||||
|
||||
Because it sucks to debug launchctl, systemd, etc.
|
||||
|
||||
Also, I wanted a reasonable way to install [Telebit](https://telebit.io) on Windows.
|
||||
(see more in the **More Why** section below)
|
||||
...and I wanted a reasonable way to install [Telebit](https://telebit.io) on Windows.
|
||||
(see more in the **Why** section below)
|
||||
|
||||
## Features
|
||||
|
||||
- Unprivileged (User Mode) Services with `--user` (_Default_)
|
||||
- [x] Linux (`sytemctl --user`)
|
||||
- [x] MacOS (`launchctl`)
|
||||
- [x] Windows (`HKEY_CURRENT_USER/.../Run`)
|
||||
- Privileged (System) Services with `--system` (_Default_ for `root`)
|
||||
- [x] Linux (`sudo sytemctl`)
|
||||
- [x] MacOS (`sudo launchctl`)
|
||||
- [ ] Windows (_not yet implemented_)
|
||||
- Unprivileged (User Mode) Services
|
||||
- [x] Linux (`sytemctl --user`)
|
||||
- [x] MacOS (`launchctl`)
|
||||
- [x] Windows (`HKEY_CURRENT_USER/.../Run`)
|
||||
- Privileged (System) Services
|
||||
- [x] Linux (`sudo sytemctl`)
|
||||
- [x] MacOS (`sudo launchctl`)
|
||||
- [ ] Windows (_not yet implemented_)
|
||||
|
||||
# Table of Contents
|
||||
|
||||
- Usage
|
||||
- Install
|
||||
- Examples
|
||||
- compiled programs
|
||||
- scripts
|
||||
- bash
|
||||
- node
|
||||
- python
|
||||
- ruby
|
||||
- PATH
|
||||
- Logging
|
||||
- Debugging
|
||||
- Windows
|
||||
- Building
|
||||
- More Why
|
||||
- Legal
|
||||
- Usage
|
||||
- Install
|
||||
- Examples
|
||||
- compiled programs
|
||||
- scripts
|
||||
- bash
|
||||
- node
|
||||
- python
|
||||
- ruby
|
||||
- Logging
|
||||
- Debugging
|
||||
- Windows
|
||||
- Building
|
||||
- Why
|
||||
- Legal
|
||||
|
||||
# Usage (DEPRECATED)
|
||||
# Usage
|
||||
|
||||
The basic pattern of usage:
|
||||
The basic pattern of usage, and what that might look like:
|
||||
|
||||
```bash
|
||||
sudo serviceman add --name "foobar" [options] [interpreter] <service> [--] [service options]
|
||||
sudo serviceman start <service>
|
||||
sudo serviceman stop <service>
|
||||
sudo serviceman list --all
|
||||
serviceman version
|
||||
```
|
||||
serviceman add [options] [interpreter] <service> -- [service options]
|
||||
```
|
||||
|
||||
And what that might look like:
|
||||
|
||||
```bash
|
||||
sudo serviceman add --name "foo" foo.exe -c ./config.json
|
||||
```
|
||||
serviceman add foo.exe
|
||||
```
|
||||
|
||||
You can also view the help:
|
||||
```
|
||||
serviceman add --title "Foo App" node ./foo.js -- --bar
|
||||
```
|
||||
|
||||
You can also view the help and the version:
|
||||
|
||||
```
|
||||
serviceman add --help
|
||||
```
|
||||
|
||||
# System Services VS User Mode Services
|
||||
|
||||
User services start **on login**.
|
||||
|
||||
System services start **on boot**.
|
||||
|
||||
The **default** is to register a _user_ services. To register a _system_ service, use `sudo` or run as `root`.
|
||||
```
|
||||
serviceman version
|
||||
```
|
||||
|
||||
# Install
|
||||
|
||||
**Note**: v0.9.x+ install from <https://github.com/bnnanet/serviceman>.
|
||||
|
||||
You can install `serviceman` directly from the official git releases with [`webi`](https://webinstall.dev/serviceman):
|
||||
|
||||
**Mac**, **Linux**:
|
||||
|
||||
```bash
|
||||
curl -sL https://webinstall.dev/serviceman | bash
|
||||
```
|
||||
|
||||
**Windows 10**:
|
||||
|
||||
```pwsh
|
||||
curl.exe -sLA "MS" https://webinstall.dev/serviceman | powershell
|
||||
```
|
||||
|
||||
You can run this from cmd.exe or PowerShell (curl.exe is a native part of Windows 10).
|
||||
|
||||
## Manual Install
|
||||
|
||||
There are a number of pre-built binaries.
|
||||
|
||||
If none of them work for you, or you prefer to build from source,
|
||||
@ -116,25 +71,14 @@ see the instructions for building far down below.
|
||||
|
||||
## Downloads
|
||||
|
||||
```
|
||||
curl -fsSL "https://rootprojects.org/serviceman/dist/$(uname -s)/$(uname -m)/serviceman" -o serviceman
|
||||
chmod +x ./serviceman
|
||||
```
|
||||
|
||||
### MacOS
|
||||
|
||||
<details>
|
||||
<summary>See download options</summary>
|
||||
|
||||
MacOS (darwin): [64-bit Download ](https://rootprojects.org/serviceman/dist/darwin/amd64/serviceman)
|
||||
|
||||
```
|
||||
curl https://rootprojects.org/serviceman/dist/darwin/amd64/serviceman -o serviceman
|
||||
chmod +x ./serviceman
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Windows
|
||||
|
||||
<details>
|
||||
@ -167,7 +111,6 @@ powershell.exe "(New-Object Net.WebClient).DownloadFile('https://rootprojects.or
|
||||
|
||||
### Linux
|
||||
|
||||
|
||||
<details>
|
||||
<summary>See download options</summary>
|
||||
|
||||
@ -175,14 +118,12 @@ Linux (64-bit): [Download](https://rootprojects.org/serviceman/dist/linux/amd64/
|
||||
|
||||
```
|
||||
curl https://rootprojects.org/serviceman/dist/linux/amd64/serviceman -o serviceman
|
||||
chmod +x ./serviceman
|
||||
```
|
||||
|
||||
Linux (32-bit): [Download](https://rootprojects.org/serviceman/dist/linux/386/serviceman)
|
||||
|
||||
```
|
||||
curl https://rootprojects.org/serviceman/dist/linux/386/serviceman -o serviceman
|
||||
chmod +x ./serviceman
|
||||
```
|
||||
|
||||
</details>
|
||||
@ -196,28 +137,24 @@ RPi 4 (64-bit armv8): [Download](https://rootprojects.org/serviceman/dist/linux/
|
||||
|
||||
```
|
||||
curl https://rootprojects.org/serviceman/dist/linux/armv8/serviceman -o serviceman`
|
||||
chmod +x ./serviceman
|
||||
```
|
||||
|
||||
RPi 3 (armv7): [Download](https://rootprojects.org/serviceman/dist/linux/armv7/serviceman)
|
||||
|
||||
```
|
||||
curl https://rootprojects.org/serviceman/dist/linux/armv7/serviceman -o serviceman
|
||||
chmod +x ./serviceman
|
||||
```
|
||||
|
||||
ARMv6: [Download](https://rootprojects.org/serviceman/dist/linux/armv6/serviceman)
|
||||
|
||||
```
|
||||
curl https://rootprojects.org/serviceman/dist/linux/armv6/serviceman -o serviceman
|
||||
chmod +x ./serviceman
|
||||
```
|
||||
|
||||
RPi Zero (armv5): [Download](https://rootprojects.org/serviceman/dist/linux/armv5/serviceman)
|
||||
|
||||
```
|
||||
curl https://rootprojects.org/serviceman/dist/linux/armv5/serviceman -o serviceman
|
||||
chmod +x ./serviceman
|
||||
```
|
||||
|
||||
</details>
|
||||
@ -228,8 +165,8 @@ chmod +x ./serviceman
|
||||
|
||||
```
|
||||
mkdir %userprofile%\bin
|
||||
move serviceman.exe %userprofile%\bin\serviceman.exe
|
||||
reg add HKEY_CURRENT_USER\Environment /v PATH /d "%PATH%;%userprofile%\bin"
|
||||
move serviceman.exe %userprofile%\bin\serviceman.exe
|
||||
```
|
||||
|
||||
**All Others**
|
||||
@ -240,100 +177,43 @@ sudo mv ./serviceman /usr/local/bin/
|
||||
|
||||
# Examples
|
||||
|
||||
```bash
|
||||
sudo serviceman add --name <name> <program> [options] [--] [raw options]
|
||||
|
||||
# Example
|
||||
sudo serviceman add --name "gizmo" gizmo --foo bar/baz
|
||||
```
|
||||
|
||||
Anything that looks like file or directory will be **resolved to its absolute path**:
|
||||
|
||||
```bash
|
||||
# Example of path resolution
|
||||
gizmo --foo /User/me/gizmo/bar/baz
|
||||
```
|
||||
|
||||
Use `--` to prevent this behavior:
|
||||
|
||||
```bash
|
||||
# Complex Example
|
||||
sudo serviceman add --name "gizmo" gizmo -c ./config.ini -- --separator .
|
||||
```
|
||||
|
||||
For native **Windows** programs that use `/` for flags, you'll need to resolve some paths yourself:
|
||||
|
||||
```bash
|
||||
# Windows Example
|
||||
serviceman add --name "gizmo" gizmo.exe .\input.txt -- /c \User\me\gizmo\config.ini /q /s .
|
||||
```
|
||||
|
||||
In this case `./config.ini` would still be resolved (before `--`), but `.` would not (after `--`)
|
||||
> **serviceman add** <program> **--** <program options>
|
||||
|
||||
<details>
|
||||
<summary>Compiled Programs</summary>
|
||||
|
||||
Normally you might your program somewhat like this:
|
||||
|
||||
```bash
|
||||
gizmo run --port 8421 --config envs/prod.ini
|
||||
```
|
||||
dinglehopper --port 8421
|
||||
```
|
||||
|
||||
Adding a service for that program with `serviceman` would look like this:
|
||||
|
||||
```bash
|
||||
sudo serviceman add --name "gizmo" gizmo run --port 8421 --config envs/prod.ini
|
||||
```
|
||||
> **serviceman add** dinglehopper **--** --port 8421
|
||||
|
||||
serviceman will find `gizmo` in your PATH and resolve `envs/prod.ini` to its absolute path.
|
||||
serviceman will find dinglehopper in your PATH.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Using with scripts</summary>
|
||||
|
||||
```bash
|
||||
./snarfblat.sh --port 8421
|
||||
```
|
||||
|
||||
Although your text script may be executable, you'll need to specify the interpreter
|
||||
in order for `serviceman` to configure the service correctly.
|
||||
|
||||
This can be done in two ways:
|
||||
For example, if you had a bash script that you normally ran like this:
|
||||
|
||||
1. Put a **hashbang** in your script, such as `#!/bin/bash`.
|
||||
2. Prepend the **interpreter** explicitly to your command, such as `bash ./dinglehopper.sh`.
|
||||
|
||||
For example, suppose you had a script like this:
|
||||
|
||||
`iamok.sh`:
|
||||
|
||||
```bash
|
||||
while true; do
|
||||
sleep 1; echo "Still Alive, Still Alive!"
|
||||
done
|
||||
```
|
||||
./snarfblat.sh --port 8421
|
||||
```
|
||||
|
||||
Normally you would run the script like this:
|
||||
You'd create a system service for it like this:
|
||||
|
||||
```bash
|
||||
./imok.sh
|
||||
```
|
||||
> serviceman add **bash** ./snarfblat.sh **--** --port 8421
|
||||
|
||||
So you'd either need to modify the script to include a hashbang:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
while true; do
|
||||
sleep 1; echo "I'm Ok!"
|
||||
done
|
||||
```
|
||||
|
||||
Or you'd need to prepend it with `bash` when creating a service for it:
|
||||
|
||||
```bash
|
||||
sudo serviceman add --name "imok" bash ./imok.sh
|
||||
```
|
||||
`serviceman` will resolve `./snarfblat.sh` correctly because it comes
|
||||
before the **--**.
|
||||
|
||||
**Background Information**
|
||||
|
||||
@ -357,8 +237,6 @@ like this:
|
||||
#!/usr/local/bin/node --harmony --inspect
|
||||
```
|
||||
|
||||
Serviceman understands all 3 of those approaches.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
@ -367,37 +245,14 @@ Serviceman understands all 3 of those approaches.
|
||||
If normally you run your node script something like this:
|
||||
|
||||
```bash
|
||||
pushd ~/my-node-project/
|
||||
npm start
|
||||
node ./demo.js --foo bar --baz
|
||||
```
|
||||
|
||||
Then you would add it as a system service like this:
|
||||
|
||||
```bash
|
||||
sudo serviceman add npm start
|
||||
```
|
||||
> **serviceman add** node ./demo.js **--** --foo bar --baz
|
||||
|
||||
If normally you run your node script something like this:
|
||||
|
||||
```bash
|
||||
pushd ~/my-node-project/
|
||||
node ./serve.js --foo bar --baz
|
||||
```
|
||||
|
||||
Then you would add it as a system service like this:
|
||||
|
||||
```bash
|
||||
sudo serviceman add node ./serve.js --foo bar --baz
|
||||
```
|
||||
|
||||
It's important that any paths start with `./` and have the `.js`
|
||||
so that serviceman knows to resolve the full path.
|
||||
|
||||
```bash
|
||||
# Bad Examples
|
||||
sudo serviceman add node ./demo # Wouldn't work for 'demo.js' - not a real filename
|
||||
sudo serviceman add node demo # Wouldn't work for './demo/' - doesn't look like a directory
|
||||
```
|
||||
It is important that you specify `node ./demo.js` and not just `./demo.js`
|
||||
|
||||
See **Using with scripts** for more detailed information.
|
||||
|
||||
@ -409,15 +264,14 @@ See **Using with scripts** for more detailed information.
|
||||
If normally you run your python script something like this:
|
||||
|
||||
```bash
|
||||
pushd ~/my-python-project/
|
||||
python ./serve.py --config ./config.ini
|
||||
python ./demo.py --foo bar --baz
|
||||
```
|
||||
|
||||
Then you would add it as a system service like this:
|
||||
|
||||
```bash
|
||||
sudo serviceman add python ./serve.py --config ./config.ini
|
||||
```
|
||||
> **serviceman add** python ./demo.py **--** --foo bar --baz
|
||||
|
||||
It is important that you specify `python ./demo.py` and not just `./demo.py`
|
||||
|
||||
See **Using with scripts** for more detailed information.
|
||||
|
||||
@ -429,65 +283,35 @@ See **Using with scripts** for more detailed information.
|
||||
If normally you run your ruby script something like this:
|
||||
|
||||
```bash
|
||||
pushd ~/my-ruby-project/
|
||||
ruby ./serve.rb --config ./config.yaml
|
||||
ruby ./demo.rb --foo bar --baz
|
||||
```
|
||||
|
||||
Then you would add it as a system service like this:
|
||||
|
||||
```bash
|
||||
sudo serviceman add ruby ./serve.rb --config ./config.yaml
|
||||
```
|
||||
> **serviceman add** ruby ./demo.rb **--** --foo bar --baz
|
||||
|
||||
It is important that you specify `ruby ./demo.rb` and not just `./demo.rb`
|
||||
|
||||
See **Using with scripts** for more detailed information.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Setting PATH</summary>
|
||||
## Relative vs Absolute Paths
|
||||
|
||||
You can set the `$PATH` (`%PATH%` on Windows) for your service like this:
|
||||
|
||||
```bash
|
||||
sudo serviceman add ./myservice --path "/home/myuser/bin"
|
||||
```
|
||||
|
||||
Snapshot your actual path like this:
|
||||
|
||||
```bash
|
||||
sudo serviceman add ./myservice --path "$PATH"
|
||||
```
|
||||
|
||||
Remember that this takes a snapshot and sets it in the configuration, it's not
|
||||
a live reference to your path.
|
||||
|
||||
</details>
|
||||
|
||||
## Hints
|
||||
|
||||
- If something goes wrong, read the output **completely** - it'll probably be helpful
|
||||
- Run `serviceman` from your **project directory**, just as you would run it normally
|
||||
- Otherwise specify `--name <service-name>` and `--workdir <project directory>`
|
||||
- Use `--` in front of arguments that should not be resolved as paths
|
||||
- This also holds true if you need `--` as an argument, such as `-- --foo -- --bar`
|
||||
Although serviceman can expand the executable's path,
|
||||
if you have any arguments with relative paths
|
||||
you should switch to using absolute paths.
|
||||
|
||||
```
|
||||
# Example of a / that isn't a path
|
||||
# (it needs to be escaped with --)
|
||||
sudo serviceman add dinglehopper config/prod -- --category color/blue
|
||||
dinglehopper --config ./conf.json
|
||||
```
|
||||
|
||||
```
|
||||
serviceman add dinglehopper -- --config /Users/me/dinglehopper/conf.json
|
||||
```
|
||||
|
||||
# Logging
|
||||
|
||||
### Linux
|
||||
|
||||
```bash
|
||||
sudo journalctl -xef --unit <NAME>
|
||||
sudo journalctl -xef --user-unit <NAME>
|
||||
```
|
||||
|
||||
### Mac, Windows
|
||||
|
||||
When you run `serviceman add` it will either give you an error or
|
||||
will print out the location where logs will be found.
|
||||
|
||||
@ -498,14 +322,14 @@ By default it's one of these:
|
||||
```
|
||||
|
||||
```txt
|
||||
/opt/<NAME>/var/log/<NAME>.log
|
||||
/var/log/<NAME>/var/log/<NAME>.log
|
||||
```
|
||||
|
||||
You set it with one of these:
|
||||
|
||||
- `--logdir <path>` (cli)
|
||||
- `"logdir": "<path>"` (json)
|
||||
- `Logdir: "<path>"` (go)
|
||||
- `--logdir <path>` (cli)
|
||||
- `"logdir": "<path>"` (json)
|
||||
- `Logdir: "<path>"` (go)
|
||||
|
||||
If anything about the logging sucks, tell me... unless they're your logs
|
||||
(which they probably are), in which case _you_ should fix them.
|
||||
@ -515,9 +339,6 @@ why your app failed to start.
|
||||
|
||||
# Debugging
|
||||
|
||||
- `serviceman add --dryrun <normal options>`
|
||||
- `serviceman run --config <special config>`
|
||||
|
||||
One of the most irritating problems with all of these launchers is that they're
|
||||
terrible to debug - it's often difficult to find the logs, and nearly impossible
|
||||
to interpret them, if they exist at all.
|
||||
@ -644,7 +465,7 @@ go build -mod=vendor -ldflags "-H=windowsgui" -o serviceman.exe
|
||||
go build -mod=vendor -o /usr/local/bin/serviceman
|
||||
```
|
||||
|
||||
# More Why
|
||||
# Why
|
||||
|
||||
I created this for two reasons:
|
||||
|
||||
|
@ -39,5 +39,5 @@ echo "RPi Zero ARMv5"
|
||||
GOOS=linux GOARCH=arm GOARM=5 go build -mod=vendor -o dist/linux/armv5/${exe} $gocmd
|
||||
|
||||
echo ""
|
||||
#rsync -av ./dist/ ubuntu@rootprojects.org:/srv/www/rootprojects.org/serviceman/dist/
|
||||
rsync -av ./dist/ ubuntu@rootprojects.org:/srv/www/rootprojects.org/serviceman/dist/
|
||||
# https://rootprojects.org/serviceman/dist/windows/amd64/serviceman.exe
|
||||
|
5
go.mod
5
go.mod
@ -1,11 +1,10 @@
|
||||
module git.rootprojects.org/root/serviceman
|
||||
module git.rootprojects.org/root/go-serviceman
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
git.rootprojects.org/root/go-gitver/v2 v2.0.2
|
||||
git.rootprojects.org/root/go-gitver v1.1.2
|
||||
github.com/UnnoTed/fileb0x v1.1.3
|
||||
github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936
|
||||
golang.org/x/net v0.0.0-20180921000356-2f5d2388922f
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb
|
||||
)
|
||||
|
6
go.sum
6
go.sum
@ -1,5 +1,5 @@
|
||||
git.rootprojects.org/root/go-gitver/v2 v2.0.2 h1:T+Je13wrY1jz4OPJF98HnuCNp6n2Xe2uK6/NNF6a4+0=
|
||||
git.rootprojects.org/root/go-gitver/v2 v2.0.2/go.mod h1:ur82M/jZcvr1WWihyVtNEgDBqIjo22o56wcVHeVJFh8=
|
||||
git.rootprojects.org/root/go-gitver v1.1.2 h1:AQhr8ktJyP+X+jFbtLavCi/FQLSmB6xvdG2Nfp+J2JA=
|
||||
git.rootprojects.org/root/go-gitver v1.1.2/go.mod h1:Rj1v3TBhvdaSphFEqMynUYwAz/4f+wY/+syBTvRrmlI=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/UnnoTed/fileb0x v1.1.3 h1:TUfJRey+psXuivBqasgp7Du3iXB4hzjI5UXDl+BCrzE=
|
||||
@ -26,8 +26,6 @@ github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
|
||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936 h1:kw1v0NlnN+GZcU8Ma8CLF2Zzgjfx95gs3/GN3vYAPpo=
|
||||
github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/nsf/termbox-go v0.0.0-20180819125858-b66b20ab708e h1:fvw0uluMptljaRKSU8459cJ4bmi3qUYyMs5kzpic2fY=
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated for serviceman. Edit as you wish, but leave this line. -->
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
@ -28,8 +27,6 @@
|
||||
{{if .User -}}
|
||||
<key>UserName</key>
|
||||
<string>{{ .User }}</string>
|
||||
{{end -}}
|
||||
{{if .Group -}}
|
||||
<key>GroupName</key>
|
||||
<string>{{ .Group }}</string>
|
||||
<key>InitGroups</key>
|
||||
|
@ -1,4 +1,3 @@
|
||||
# Generated for serviceman. Edit as you wish, but leave this line.
|
||||
# Pre-req
|
||||
# sudo mkdir -p {{ .Local }}/opt/{{ .Name }}/ {{ .Local }}/var/log/{{ .Name }}
|
||||
{{ if .System -}}
|
||||
@ -13,20 +12,18 @@
|
||||
# sudo journalctl {{ if not .System -}} --user {{ end -}} -xefu {{ .Name }}
|
||||
|
||||
[Unit]
|
||||
Description={{ .Title }} {{ if .Desc }}- {{ .Desc }}{{ end }}
|
||||
{{ if .URL -}}
|
||||
Description={{ .Title }} - {{ .Desc }}
|
||||
Documentation={{ .URL }}
|
||||
{{ end -}}
|
||||
{{ if .System -}}
|
||||
After=network-online.target
|
||||
Wants=network-online.target systemd-networkd-wait-online.service
|
||||
{{- end }}
|
||||
|
||||
{{ end -}}
|
||||
[Service]
|
||||
# Restart on crash (bad signal), but not on 'clean' failure (error exit code)
|
||||
# Allow up to 3 restarts within 10 seconds
|
||||
# (it's unlikely that a user or properly-running script will do this)
|
||||
Restart=always
|
||||
Restart=on-abnormal
|
||||
StartLimitInterval=10
|
||||
StartLimitBurst=3
|
||||
|
||||
@ -36,13 +33,10 @@ User={{ .User }}
|
||||
Group={{ .Group }}
|
||||
|
||||
{{ end -}}
|
||||
{{- if .Envs }}
|
||||
Environment="{{- range $key, $value := .Envs }}{{ $key }}={{ $value }};{{- end }}"
|
||||
{{- end }}
|
||||
{{ if .Workdir -}}
|
||||
WorkingDirectory={{ .Workdir }}
|
||||
{{ end -}}
|
||||
ExecStart={{if .Interpreter }}{{ .Interpreter }} {{ end }}{{ .Exec }}{{ range $arg := .Argv }} {{ $arg }}{{ end }}
|
||||
ExecStart={{if .Interpreter }}{{ .Interpreter }} {{ end }}{{ .Exec }} {{- range $arg := .Argv }}{{ $arg }} {{- end }}
|
||||
ExecReload=/bin/kill -USR1 $MAINPID
|
||||
|
||||
{{if .Production -}}
|
||||
|
@ -7,14 +7,13 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.rootprojects.org/root/serviceman/service"
|
||||
"git.rootprojects.org/root/go-serviceman/service"
|
||||
)
|
||||
|
||||
// Install will do a best-effort attempt to install a start-on-startup
|
||||
// user or system service via systemd, launchd, or reg.exe
|
||||
func Install(c *service.Service) (string, error) {
|
||||
func Install(c *service.Service) error {
|
||||
if "" == c.Exec {
|
||||
c.Exec = c.Name
|
||||
}
|
||||
@ -24,35 +23,23 @@ func Install(c *service.Service) (string, error) {
|
||||
if nil != err {
|
||||
fmt.Fprintf(os.Stderr, "Unrecoverable Error: %s", err)
|
||||
os.Exit(4)
|
||||
return "", err
|
||||
return err
|
||||
} else {
|
||||
c.Home = home
|
||||
}
|
||||
}
|
||||
|
||||
name, err := install(c)
|
||||
err := install(c)
|
||||
if nil != err {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.MkdirAll(c.Logdir, 0755)
|
||||
if nil != err {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
|
||||
return name, nil
|
||||
}
|
||||
|
||||
func Start(conf *service.Service) error {
|
||||
return start(conf)
|
||||
}
|
||||
|
||||
func Stop(conf *service.Service) error {
|
||||
return stop(conf)
|
||||
}
|
||||
|
||||
func List(conf *service.Service) ([]string, []string, []error) {
|
||||
return list(conf)
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsPrivileged returns true if we suspect that the current user (or process) will be able
|
||||
@ -70,22 +57,3 @@ func WhereIs(exe string) (string, error) {
|
||||
}
|
||||
return filepath.Abs(filepath.ToSlash(exepath))
|
||||
}
|
||||
|
||||
type ManageError struct {
|
||||
Name string
|
||||
Hint string
|
||||
Parent error
|
||||
}
|
||||
|
||||
func (e *ManageError) Error() string {
|
||||
return e.Name + ": " + e.Hint + ": " + e.Parent.Error()
|
||||
}
|
||||
|
||||
type ErrDaemonize struct {
|
||||
DaemonArgs []string
|
||||
error string
|
||||
}
|
||||
|
||||
func (e *ErrDaemonize) Error() string {
|
||||
return e.error + "\nYou need to switch on ErrDaemonize, and use .DaemonArgs, which would run this:" + strings.Join(e.DaemonArgs, " ")
|
||||
}
|
||||
|
@ -6,169 +6,66 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"git.rootprojects.org/root/serviceman/manager/static"
|
||||
"git.rootprojects.org/root/serviceman/service"
|
||||
"git.rootprojects.org/root/go-serviceman/manager/static"
|
||||
"git.rootprojects.org/root/go-serviceman/service"
|
||||
)
|
||||
|
||||
const (
|
||||
srvExt = ".plist"
|
||||
srvSysPath = "/Library/LaunchDaemons"
|
||||
srvUserPath = "Library/LaunchAgents"
|
||||
)
|
||||
func install(c *service.Service) error {
|
||||
// Darwin-specific config options
|
||||
if c.PrivilegedPorts {
|
||||
if !c.System {
|
||||
return fmt.Errorf("You must use root-owned LaunchDaemons (not user-owned LaunchAgents) to use priveleged ports on OS X")
|
||||
}
|
||||
}
|
||||
plistDir := "/Library/LaunchDaemons/"
|
||||
if !c.System {
|
||||
plistDir = filepath.Join(c.Home, "Library/LaunchAgents")
|
||||
}
|
||||
|
||||
var srvLen int
|
||||
|
||||
func init() {
|
||||
srvLen = len(srvExt)
|
||||
}
|
||||
|
||||
func start(conf *service.Service) error {
|
||||
system := conf.System
|
||||
home := conf.Home
|
||||
rdns := conf.ReverseDNS
|
||||
|
||||
service, err := getService(system, home, rdns)
|
||||
// Check paths first
|
||||
err := os.MkdirAll(filepath.Dir(plistDir), 0755)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
cmds := []Runnable{
|
||||
Runnable{
|
||||
Exec: "launchctl",
|
||||
Args: []string{"unload", "-w", service},
|
||||
Must: false,
|
||||
},
|
||||
Runnable{
|
||||
Exec: "launchctl",
|
||||
Args: []string{"load", "-w", service},
|
||||
Must: true,
|
||||
Badwords: []string{"No such file or directory", "service already loaded"},
|
||||
},
|
||||
}
|
||||
|
||||
cmds = adjustPrivs(system, cmds)
|
||||
|
||||
typ := "USER"
|
||||
if system {
|
||||
typ = "SYSTEM"
|
||||
}
|
||||
fmt.Printf("Starting launchd %s service...\n\n", typ)
|
||||
for i := range cmds {
|
||||
exe := cmds[i]
|
||||
fmt.Println("\t" + exe.String())
|
||||
err := exe.Run()
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func stop(conf *service.Service) error {
|
||||
system := conf.System
|
||||
home := conf.Home
|
||||
rdns := conf.ReverseDNS
|
||||
|
||||
service, err := getService(system, home, rdns)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
cmds := []Runnable{
|
||||
Runnable{
|
||||
Exec: "launchctl",
|
||||
Args: []string{"unload", service},
|
||||
Must: false,
|
||||
Badwords: []string{"No such file or directory", "Cound not find specified service"},
|
||||
},
|
||||
}
|
||||
|
||||
cmds = adjustPrivs(system, cmds)
|
||||
|
||||
fmt.Println()
|
||||
typ := "USER"
|
||||
if system {
|
||||
typ = "SYSTEM"
|
||||
}
|
||||
fmt.Printf("Stopping launchd %s service...\n", typ)
|
||||
for i := range cmds {
|
||||
exe := cmds[i]
|
||||
fmt.Println("\t" + exe.String())
|
||||
err := exe.Run()
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Render will create a launchd .plist file using the simple internal template
|
||||
func Render(c *service.Service) ([]byte, error) {
|
||||
// Create service file from template
|
||||
b, err := static.ReadFile("dist/Library/LaunchDaemons/_rdns_.plist.tmpl")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
s := string(b)
|
||||
rw := &bytes.Buffer{}
|
||||
// not sure what the template name does, but whatever
|
||||
tmpl, err := template.New("service").Parse(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
err = tmpl.Execute(rw, c)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rw.Bytes(), nil
|
||||
}
|
||||
|
||||
func install(c *service.Service) (string, error) {
|
||||
// Darwin-specific config options
|
||||
if c.PrivilegedPorts {
|
||||
if !c.System {
|
||||
return "", fmt.Errorf("You must use root-owned LaunchDaemons (not user-owned LaunchAgents) to use priveleged ports on OS X")
|
||||
}
|
||||
}
|
||||
plistDir := srvSysPath
|
||||
if !c.System {
|
||||
plistDir = filepath.Join(c.Home, srvUserPath)
|
||||
}
|
||||
|
||||
// Check paths first
|
||||
err := os.MkdirAll(plistDir, 0755)
|
||||
if nil != err {
|
||||
return "", err
|
||||
}
|
||||
|
||||
b, err := Render(c)
|
||||
if nil != err {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
|
||||
// Write the file out
|
||||
// TODO rdns
|
||||
plistName := c.ReverseDNS + ".plist"
|
||||
plistPath := filepath.Join(plistDir, plistName)
|
||||
if err := ioutil.WriteFile(plistPath, b, 0644); err != nil {
|
||||
return "", fmt.Errorf("Error writing %s: %v", plistPath, err)
|
||||
}
|
||||
if err := ioutil.WriteFile(plistPath, rw.Bytes(), 0644); err != nil {
|
||||
|
||||
// TODO --no-start
|
||||
err = start(c)
|
||||
if nil != err {
|
||||
fmt.Printf("If things don't go well you should be able to get additional logging from launchctl:\n")
|
||||
fmt.Printf("\tsudo launchctl log level debug\n")
|
||||
fmt.Printf("\ttail -f /var/log/system.log\n")
|
||||
return "", err
|
||||
return fmt.Errorf("ioutil.WriteFile error: %v", err)
|
||||
}
|
||||
fmt.Printf("Installed. To start '%s' run the following:\n", c.Name)
|
||||
// TODO template config file
|
||||
if "" != c.Home {
|
||||
plistPath = strings.Replace(plistPath, c.Home, "~", 1)
|
||||
}
|
||||
sudo := ""
|
||||
if c.System {
|
||||
sudo = "sudo "
|
||||
}
|
||||
fmt.Printf("\t%slaunchctl load -w %s\n", sudo, plistPath)
|
||||
|
||||
return "launchd", nil
|
||||
return nil
|
||||
}
|
||||
|
@ -8,225 +8,11 @@ import (
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
|
||||
"git.rootprojects.org/root/serviceman/manager/static"
|
||||
"git.rootprojects.org/root/serviceman/service"
|
||||
"git.rootprojects.org/root/go-serviceman/manager/static"
|
||||
"git.rootprojects.org/root/go-serviceman/service"
|
||||
)
|
||||
|
||||
var (
|
||||
srvLen int
|
||||
srvExt = ".service"
|
||||
srvSysPath = "/etc/systemd/system"
|
||||
|
||||
// Not sure which of these it's supposed to be...
|
||||
// * ~/.local/share/systemd/user/watchdog.service
|
||||
// * ~/.config/systemd/user/watchdog.service
|
||||
// https://wiki.archlinux.org/index.php/Systemd/User
|
||||
// This seems to work on Ubuntu
|
||||
srvUserPath = ".config/systemd/user"
|
||||
)
|
||||
|
||||
func init() {
|
||||
srvLen = len(srvExt)
|
||||
}
|
||||
|
||||
func start(conf *service.Service) error {
|
||||
system := conf.System
|
||||
home := conf.Home
|
||||
name := conf.ReverseDNS
|
||||
|
||||
_, err := getService(system, home, name)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
var cmds []Runnable
|
||||
if system {
|
||||
cmds = []Runnable{
|
||||
Runnable{
|
||||
Exec: "systemctl",
|
||||
Args: []string{"daemon-reload"},
|
||||
Must: false,
|
||||
},
|
||||
Runnable{
|
||||
Exec: "systemctl",
|
||||
Args: []string{"stop", name + ".service"},
|
||||
Must: false,
|
||||
},
|
||||
Runnable{
|
||||
Exec: "systemctl",
|
||||
Args: []string{"enable", name + ".service"},
|
||||
Badwords: []string{"not found", "failed"},
|
||||
Must: true,
|
||||
},
|
||||
Runnable{
|
||||
Exec: "systemctl",
|
||||
Args: []string{"start", name + ".service"},
|
||||
Badwords: []string{"not found", "failed"},
|
||||
Must: true,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
cmds = []Runnable{
|
||||
Runnable{
|
||||
Exec: "systemctl",
|
||||
Args: []string{"--user", "daemon-reload"},
|
||||
Must: false,
|
||||
},
|
||||
Runnable{
|
||||
Exec: "systemctl",
|
||||
Args: []string{"stop", "--user", name + ".service"},
|
||||
Must: false,
|
||||
},
|
||||
Runnable{
|
||||
Exec: "systemctl",
|
||||
Args: []string{"start", "--user", name + ".service"},
|
||||
Badwords: []string{"not found", "failed"},
|
||||
Must: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
cmds = adjustPrivs(system, cmds)
|
||||
|
||||
typ := "USER MODE"
|
||||
if system {
|
||||
typ = "SYSTEM"
|
||||
}
|
||||
fmt.Printf("Starting systemd %s service unit...\n\n", typ)
|
||||
for i := range cmds {
|
||||
exe := cmds[i]
|
||||
fmt.Println("\t" + exe.String())
|
||||
err := exe.Run()
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func stop(conf *service.Service) error {
|
||||
system := conf.System
|
||||
home := conf.Home
|
||||
name := conf.ReverseDNS
|
||||
|
||||
_, err := getService(system, home, name)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
var cmds []Runnable
|
||||
badwords := []string{"Failed to stop"}
|
||||
if system {
|
||||
cmds = []Runnable{
|
||||
Runnable{
|
||||
Exec: "systemctl",
|
||||
Args: []string{"stop", name + ".service"},
|
||||
Must: true,
|
||||
Badwords: badwords,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
cmds = []Runnable{
|
||||
Runnable{
|
||||
Exec: "systemctl",
|
||||
Args: []string{"stop", "--user", name + ".service"},
|
||||
Must: true,
|
||||
Badwords: badwords,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
cmds = adjustPrivs(system, cmds)
|
||||
|
||||
fmt.Println()
|
||||
typ := "USER MODE"
|
||||
if system {
|
||||
typ = "SYSTEM"
|
||||
}
|
||||
fmt.Printf("Stopping systemd %s service...\n", typ)
|
||||
for i := range cmds {
|
||||
exe := cmds[i]
|
||||
fmt.Println("\t" + exe.String())
|
||||
err := exe.Run()
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Render will create a systemd .service file using the simple internal template
|
||||
func Render(c *service.Service) ([]byte, error) {
|
||||
defaultUserGroup(c)
|
||||
|
||||
// Create service file from template
|
||||
b, err := static.ReadFile("dist/etc/systemd/system/_name_.service.tmpl")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := string(b)
|
||||
rw := &bytes.Buffer{}
|
||||
// not sure what the template name does, but whatever
|
||||
tmpl, err := template.New("service").Parse(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = tmpl.Execute(rw, c)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rw.Bytes(), nil
|
||||
}
|
||||
|
||||
func install(c *service.Service) (string, error) {
|
||||
defaultUserGroup(c)
|
||||
|
||||
// Check paths first
|
||||
serviceDir := srvSysPath
|
||||
if !c.System {
|
||||
serviceDir = filepath.Join(c.Home, srvUserPath)
|
||||
err := os.MkdirAll(serviceDir, 0755)
|
||||
if nil != err {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
b, err := Render(c)
|
||||
if nil != err {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Write the file out
|
||||
serviceName := c.Name + ".service"
|
||||
servicePath := filepath.Join(serviceDir, serviceName)
|
||||
if err := ioutil.WriteFile(servicePath, b, 0644); err != nil {
|
||||
return "", fmt.Errorf("Error writing %s: %v", servicePath, err)
|
||||
}
|
||||
|
||||
// TODO --no-start
|
||||
err = start(c)
|
||||
if nil != err {
|
||||
sudo := ""
|
||||
// --user-unit rather than --user --unit for older systemd
|
||||
unit := "--user-unit"
|
||||
if c.System {
|
||||
sudo = "sudo "
|
||||
unit = "--unit"
|
||||
}
|
||||
fmt.Printf("If things don't go well you should be able to get additional logging from journalctl:\n")
|
||||
fmt.Printf("\t%sjournalctl -xe %s %s.service\n", sudo, unit, c.Name)
|
||||
return "", err
|
||||
}
|
||||
|
||||
return "systemd", nil
|
||||
}
|
||||
|
||||
func defaultUserGroup(c *service.Service) {
|
||||
func install(c *service.Service) error {
|
||||
// Linux-specific config options
|
||||
if c.System {
|
||||
if "" == c.User {
|
||||
@ -236,4 +22,56 @@ func defaultUserGroup(c *service.Service) {
|
||||
if "" == c.Group {
|
||||
c.Group = c.User
|
||||
}
|
||||
serviceDir := "/etc/systemd/system/"
|
||||
|
||||
// Check paths first
|
||||
serviceName := c.Name + ".service"
|
||||
if !c.System {
|
||||
// Not sure which of these it's supposed to be...
|
||||
// * ~/.local/share/systemd/user/watchdog.service
|
||||
// * ~/.config/systemd/user/watchdog.service
|
||||
// https://wiki.archlinux.org/index.php/Systemd/User
|
||||
serviceDir = filepath.Join(c.Home, ".local/share/systemd/user")
|
||||
err := os.MkdirAll(filepath.Dir(serviceDir), 0755)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Create service file from template
|
||||
b, err := static.ReadFile("dist/etc/systemd/system/_name_.service.tmpl")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s := string(b)
|
||||
rw := &bytes.Buffer{}
|
||||
// not sure what the template name does, but whatever
|
||||
tmpl, err := template.New("service").Parse(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tmpl.Execute(rw, c)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write the file out
|
||||
servicePath := filepath.Join(serviceDir, serviceName)
|
||||
if err := ioutil.WriteFile(servicePath, rw.Bytes(), 0644); err != nil {
|
||||
return fmt.Errorf("ioutil.WriteFile error: %v", err)
|
||||
}
|
||||
|
||||
// TODO template this as well?
|
||||
userspace := ""
|
||||
sudo := "sudo "
|
||||
if !c.System {
|
||||
userspace = "--user "
|
||||
sudo = ""
|
||||
}
|
||||
fmt.Printf("System service installed as '%s'.\n", servicePath)
|
||||
fmt.Printf("Run the following to start '%s':\n", c.Name)
|
||||
fmt.Printf("\t" + sudo + "systemctl " + userspace + "daemon-reload\n")
|
||||
fmt.Printf("\t"+sudo+"systemctl "+userspace+"restart %s.service\n", c.Name)
|
||||
fmt.Printf("\t"+sudo+"journalctl "+userspace+"-xefu %s\n", c.Name)
|
||||
return nil
|
||||
}
|
||||
|
@ -1,74 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
package manager
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.rootprojects.org/root/serviceman/service"
|
||||
)
|
||||
|
||||
// this code is shared between Mac and Linux, but may diverge in the future
|
||||
func list(c *service.Service) ([]string, []string, []error) {
|
||||
confDir := srvSysPath
|
||||
if !c.System {
|
||||
confDir = filepath.Join(c.Home, srvUserPath)
|
||||
}
|
||||
|
||||
// Enuser path exists
|
||||
err := os.MkdirAll(confDir, 0755)
|
||||
if nil != err {
|
||||
return nil, nil, []error{err}
|
||||
}
|
||||
|
||||
fis, err := ioutil.ReadDir(confDir)
|
||||
if nil != err {
|
||||
return nil, nil, []error{err}
|
||||
}
|
||||
|
||||
managed := []string{}
|
||||
others := []string{}
|
||||
errs := []error{}
|
||||
b := make([]byte, 256)
|
||||
for i := range fis {
|
||||
fi := fis[i]
|
||||
if !strings.HasSuffix(strings.ToLower(fi.Name()), srvExt) || len(fi.Name()) <= srvLen {
|
||||
continue
|
||||
}
|
||||
|
||||
confFile := filepath.Join(confDir, fi.Name())
|
||||
r, err := os.Open(confFile)
|
||||
if nil != err {
|
||||
errs = append(errs, &ManageError{
|
||||
Name: confFile,
|
||||
Hint: "Open file",
|
||||
Parent: err,
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
n, err := r.Read(b)
|
||||
if nil != err {
|
||||
errs = append(errs, &ManageError{
|
||||
Name: confFile,
|
||||
Hint: "Read file",
|
||||
Parent: err,
|
||||
})
|
||||
continue
|
||||
}
|
||||
b = b[:n]
|
||||
|
||||
name := fi.Name()[:len(fi.Name())-srvLen]
|
||||
if bytes.Contains(b, []byte("for serviceman.")) {
|
||||
managed = append(managed, name)
|
||||
} else {
|
||||
others = append(others, name)
|
||||
}
|
||||
}
|
||||
|
||||
return managed, others, errs
|
||||
}
|
@ -3,13 +3,9 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"git.rootprojects.org/root/serviceman/service"
|
||||
"git.rootprojects.org/root/go-serviceman/service"
|
||||
)
|
||||
|
||||
func Render(c *service.Service) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func install(c *service.Service) error {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -6,32 +6,19 @@ import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.rootprojects.org/root/serviceman/runner"
|
||||
"git.rootprojects.org/root/serviceman/service"
|
||||
"git.rootprojects.org/root/go-serviceman/service"
|
||||
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
var (
|
||||
srvLen int
|
||||
srvExt = ".json"
|
||||
srvSysPath = "/opt/serviceman/etc"
|
||||
srvUserPath = ".local/opt/serviceman/etc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
srvLen = len(srvExt)
|
||||
}
|
||||
|
||||
// TODO nab some goodness from https://github.com/takama/daemon
|
||||
|
||||
// TODO system service requires elevated privileges
|
||||
// See https://coolaj86.com/articles/golang-and-windows-and-admins-oh-my/
|
||||
func install(c *service.Service) (string, error) {
|
||||
func install(c *service.Service) error {
|
||||
/*
|
||||
// LEAVE THIS DOCUMENTATION HERE
|
||||
reg.exe
|
||||
@ -69,12 +56,9 @@ func install(c *service.Service) (string, error) {
|
||||
}
|
||||
defer k.Close()
|
||||
|
||||
// Try to stop before trying to copy the file
|
||||
_ = runner.Stop(c)
|
||||
|
||||
args, err := installServiceman(c)
|
||||
if nil != err {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
|
||||
/*
|
||||
@ -101,7 +85,7 @@ func install(c *service.Service) (string, error) {
|
||||
|
||||
regSZ := fmt.Sprintf(`"%s" %s`, args[0], strings.Join(args[1:], " "))
|
||||
if len(regSZ) > 260 {
|
||||
return "", fmt.Errorf("data value is too long for registry entry")
|
||||
return fmt.Errorf("data value is too long for registry entry")
|
||||
}
|
||||
// In order for a windows gui program to not show a console,
|
||||
// it has to not output any messages?
|
||||
@ -109,193 +93,24 @@ func install(c *service.Service) (string, error) {
|
||||
//fmt.Println(autorunKey, c.Title, regSZ)
|
||||
k.SetStringValue(c.Title, regSZ)
|
||||
|
||||
err = start(c)
|
||||
return "serviceman", err
|
||||
}
|
||||
|
||||
func Render(c *service.Service) ([]byte, error) {
|
||||
b, err := json.Marshal(c)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func start(conf *service.Service) error {
|
||||
args := getRunnerArgs(conf)
|
||||
args = append(args, "--daemon")
|
||||
return Run(args[0], args[1:]...)
|
||||
}
|
||||
|
||||
func stop(conf *service.Service) error {
|
||||
return runner.Stop(conf)
|
||||
}
|
||||
|
||||
func list(c *service.Service) ([]string, []string, []error) {
|
||||
var errs []error
|
||||
|
||||
regs, err := listRegistry(c)
|
||||
if nil != err {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
cfgs, errors := listConfigs(c)
|
||||
if 0 != len(errors) {
|
||||
errs = append(errs, errors...)
|
||||
}
|
||||
|
||||
managed := []string{}
|
||||
for i := range cfgs {
|
||||
managed = append(managed, cfgs[i].Name)
|
||||
}
|
||||
|
||||
others := []string{}
|
||||
for i := range regs {
|
||||
reg := regs[i]
|
||||
if 0 == len(cfgs) {
|
||||
others = append(others, reg)
|
||||
continue
|
||||
}
|
||||
|
||||
var found bool
|
||||
for j := range cfgs {
|
||||
cfg := cfgs[j]
|
||||
// Registry Value Names are case-insensitive
|
||||
if strings.ToLower(reg) == strings.ToLower(cfg.Title) {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
others = append(others, reg)
|
||||
}
|
||||
}
|
||||
|
||||
return managed, others, errs
|
||||
}
|
||||
|
||||
func getRunnerArgs(c *service.Service) []string {
|
||||
self := os.Args[0]
|
||||
debug := ""
|
||||
if strings.Contains(self, "debug.exe") {
|
||||
debug = "debug."
|
||||
}
|
||||
|
||||
smdir := `\opt\serviceman`
|
||||
// TODO support service level services (which probably wouldn't need serviceman)
|
||||
smdir = filepath.Join(c.Home, ".local", smdir)
|
||||
// for now we'll scope the runner to the name of the application
|
||||
smbin := filepath.Join(smdir, `bin\serviceman.`+debug+c.Name+`.exe`)
|
||||
|
||||
confpath := filepath.Join(smdir, `etc`)
|
||||
conffile := filepath.Join(confpath, c.Name+`.json`)
|
||||
|
||||
return []string{
|
||||
smbin,
|
||||
"run",
|
||||
"--config",
|
||||
conffile,
|
||||
}
|
||||
}
|
||||
|
||||
type winConf struct {
|
||||
Filename string `json:"-"`
|
||||
Name string `json:"name"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
func listConfigs(c *service.Service) ([]winConf, []error) {
|
||||
var errs []error
|
||||
|
||||
smdir := `\opt\serviceman`
|
||||
if !c.System {
|
||||
smdir = filepath.Join(c.Home, ".local", smdir)
|
||||
}
|
||||
confpath := filepath.Join(smdir, `etc`)
|
||||
|
||||
infos, err := ioutil.ReadDir(confpath)
|
||||
if nil != err {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
errs = append(errs, &ManageError{
|
||||
Name: confpath,
|
||||
Hint: "Read directory",
|
||||
Parent: err,
|
||||
})
|
||||
return nil, errs
|
||||
}
|
||||
|
||||
// TODO report active status
|
||||
srvs := []winConf{}
|
||||
for i := range infos {
|
||||
filename := strings.ToLower(infos[i].Name())
|
||||
if len(filename) <= srvLen || !strings.HasSuffix(filename, srvExt) {
|
||||
continue
|
||||
}
|
||||
|
||||
name := filename[:len(filename)-srvLen]
|
||||
b, err := ioutil.ReadFile(filepath.Join(confpath, filename))
|
||||
if nil != err {
|
||||
errs = append(errs, &ManageError{
|
||||
Name: name,
|
||||
Hint: "Read file",
|
||||
Parent: err,
|
||||
})
|
||||
continue
|
||||
}
|
||||
cfg := winConf{Filename: filename}
|
||||
err = json.Unmarshal(b, &cfg)
|
||||
if nil != err {
|
||||
errs = append(errs, &ManageError{
|
||||
Name: name,
|
||||
Hint: "Parse JSON",
|
||||
Parent: err,
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
srvs = append(srvs, cfg)
|
||||
}
|
||||
|
||||
return srvs, errs
|
||||
}
|
||||
|
||||
func listRegistry(c *service.Service) ([]string, error) {
|
||||
autorunKey := `SOFTWARE\Microsoft\Windows\CurrentVersion\Run`
|
||||
k, _, err := registry.CreateKey(
|
||||
registry.CURRENT_USER,
|
||||
autorunKey,
|
||||
registry.QUERY_VALUE,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer k.Close()
|
||||
|
||||
return k.ReadValueNames(-1)
|
||||
return nil
|
||||
}
|
||||
|
||||
// copies self to install path and returns config path
|
||||
func installServiceman(c *service.Service) ([]string, error) {
|
||||
// TODO check version and upgrade or dismiss
|
||||
self := os.Args[0]
|
||||
|
||||
args := getRunnerArgs(c)
|
||||
smbin := args[0]
|
||||
conffile := args[len(args)-1]
|
||||
smdir := `\opt\serviceman`
|
||||
// TODO support service level services (which probably wouldn't need serviceman)
|
||||
smdir = filepath.Join(c.Home, ".local", smdir)
|
||||
// for now we'll scope the runner to the name of the application
|
||||
smbin := filepath.Join(smdir, `bin\serviceman.`+c.Name+`.exe`)
|
||||
|
||||
if smbin != self {
|
||||
err := os.MkdirAll(filepath.Dir(smbin), 0755)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
// Note: self may be the short name, in which case
|
||||
// we should just use whatever is closest in the path
|
||||
// exec.LookPath will handle this correctly
|
||||
self, err = exec.LookPath(self)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
bin, err := ioutil.ReadFile(self)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
@ -306,19 +121,26 @@ func installServiceman(c *service.Service) ([]string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
b, err := Render(c)
|
||||
b, err := json.Marshal(c)
|
||||
if nil != err {
|
||||
// this should be impossible, so we'll just panic
|
||||
panic(err)
|
||||
}
|
||||
err = os.MkdirAll(filepath.Dir(conffile), 0755)
|
||||
confpath := filepath.Join(smdir, `etc`)
|
||||
err = os.MkdirAll(confpath, 0755)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
conffile := filepath.Join(confpath, c.Name+`.json`)
|
||||
err = ioutil.WriteFile(conffile, b, 0640)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return args, nil
|
||||
return []string{
|
||||
smbin,
|
||||
"run",
|
||||
"--config",
|
||||
conffile,
|
||||
}, nil
|
||||
}
|
||||
|
253
manager/start.go
253
manager/start.go
@ -1,253 +0,0 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getService(system bool, home string, name string) (string, error) {
|
||||
sys, user, err := getMatchingSrvs(home, name)
|
||||
if nil != err {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var service string
|
||||
if system {
|
||||
service, err = getOneSysSrv(sys, user, name)
|
||||
if nil != err {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
service, err = getOneUserSrv(home, sys, user, name)
|
||||
if nil != err {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return service, nil
|
||||
}
|
||||
|
||||
// Runnable defines a command to run, along with its arguments,
|
||||
// and whether or not failing to exit successfully matters.
|
||||
// It also defines whether certains words must exist (or not exist)
|
||||
// in its output, apart from existing successfully, to determine
|
||||
// whether or not it was actually successful.
|
||||
type Runnable struct {
|
||||
Exec string
|
||||
Args []string
|
||||
Must bool
|
||||
Keywords []string
|
||||
Badwords []string
|
||||
}
|
||||
|
||||
func (x Runnable) Run() error {
|
||||
cmd := exec.Command(x.Exec, x.Args...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if !x.Must {
|
||||
return nil
|
||||
}
|
||||
|
||||
good := true
|
||||
str := string(out)
|
||||
for j := range x.Keywords {
|
||||
if !strings.Contains(str, x.Keywords[j]) {
|
||||
good = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if good && 0 != len(x.Badwords) {
|
||||
for j := range x.Badwords {
|
||||
if "" != x.Badwords[j] && !strings.Contains(str, x.Badwords[j]) {
|
||||
good = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if nil != err {
|
||||
var comment string
|
||||
if len(x.Keywords) > 0 {
|
||||
comment += "# output must match all of:\n"
|
||||
comment += "# \t" + strings.Join(x.Keywords, "\n#\t") + "\n"
|
||||
}
|
||||
if len(x.Badwords) > 0 {
|
||||
comment += "# output must not match any of:\n"
|
||||
comment += "# \t" + strings.Join(x.Badwords, "\n#\t") + "\n"
|
||||
}
|
||||
return fmt.Errorf("Failed to run %s %s\n%s\n%s\n", x.Exec, strings.Join(x.Args, " "), str, comment)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x Runnable) String() string {
|
||||
var must = "true"
|
||||
|
||||
if x.Must {
|
||||
must = "exit"
|
||||
}
|
||||
|
||||
return strings.TrimSpace(fmt.Sprintf(
|
||||
"%s %s || %s\n",
|
||||
x.Exec,
|
||||
strings.Join(x.Args, " "),
|
||||
must,
|
||||
))
|
||||
}
|
||||
|
||||
func getSrvs(dir string) ([]string, error) {
|
||||
plists := []string{}
|
||||
|
||||
infos, err := ioutil.ReadDir(dir)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range infos {
|
||||
x := infos[i]
|
||||
fname := strings.ToLower(x.Name())
|
||||
if strings.HasSuffix(fname, srvExt) {
|
||||
plists = append(plists, x.Name())
|
||||
}
|
||||
}
|
||||
|
||||
return plists, nil
|
||||
}
|
||||
|
||||
func getSystemSrvs() ([]string, error) {
|
||||
return getSrvs(srvSysPath)
|
||||
}
|
||||
|
||||
func getUserSrvs(home string) ([]string, error) {
|
||||
confDir := filepath.Join(home, srvUserPath)
|
||||
err := os.MkdirAll(confDir, 0755)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return getSrvs(confDir)
|
||||
}
|
||||
|
||||
// "come.example.foo.plist" matches "foo"
|
||||
func filterMatchingSrvs(plists []string, name string) []string {
|
||||
filtered := []string{}
|
||||
|
||||
for i := range plists {
|
||||
pname := plists[i]
|
||||
lname := strings.ToLower(pname)
|
||||
n := len(lname)
|
||||
if strings.HasSuffix(lname[:n-srvLen], strings.ToLower(name)) {
|
||||
filtered = append(filtered, pname)
|
||||
}
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func getMatchingSrvs(home string, name string) ([]string, []string, error) {
|
||||
sysPlists, err := getSystemSrvs()
|
||||
if nil != err {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var userPlists []string
|
||||
if "" != home {
|
||||
userPlists, err = getUserSrvs(home)
|
||||
if nil != err {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return filterMatchingSrvs(sysPlists, name), filterMatchingSrvs(userPlists, name), nil
|
||||
}
|
||||
|
||||
func getExactSrvMatch(srvs []string, name string) string {
|
||||
for i := range srvs {
|
||||
srv := srvs[i]
|
||||
n := len(srv)
|
||||
if srv[:n-srvLen] == strings.ToLower(name) {
|
||||
return srv
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func getOneSysSrv(sys []string, user []string, name string) (string, error) {
|
||||
if service := getExactSrvMatch(user, name); "" != service {
|
||||
return filepath.Join(srvSysPath, service), nil
|
||||
}
|
||||
|
||||
n := len(sys)
|
||||
switch {
|
||||
case 0 == n:
|
||||
errstr := fmt.Sprintf("Didn't find user service matching %q\n", name)
|
||||
if 0 != len(user) {
|
||||
errstr += fmt.Sprintf("Did you intend to run a user service instead?\n\t%s\n", strings.Join(user, "\n\t"))
|
||||
}
|
||||
return "", fmt.Errorf(errstr)
|
||||
case n > 1:
|
||||
errstr := fmt.Sprintf("Found more than one matching service:\n\t%s\n", strings.Join(sys, "\n\t"))
|
||||
return "", fmt.Errorf(errstr)
|
||||
default:
|
||||
return filepath.Join(srvSysPath, sys[0]), nil
|
||||
}
|
||||
}
|
||||
|
||||
func getOneUserSrv(home string, sys []string, user []string, name string) (string, error) {
|
||||
if service := getExactSrvMatch(user, name); "" != service {
|
||||
return filepath.Join(home, srvUserPath, service), nil
|
||||
}
|
||||
|
||||
n := len(user)
|
||||
switch {
|
||||
case 0 == n:
|
||||
errstr := fmt.Sprintf("Didn't find user service matching %q\n", name)
|
||||
if 0 != len(sys) {
|
||||
errstr += fmt.Sprintf("Did you intend to run a system service instead?\n\t%s\n", strings.Join(sys, "\n\t"))
|
||||
}
|
||||
return "", fmt.Errorf(errstr)
|
||||
case n > 1:
|
||||
errstr := fmt.Sprintf("Found more than one matching service:\n\t%s\n", strings.Join(user, "\n\t"))
|
||||
return "", fmt.Errorf(errstr)
|
||||
default:
|
||||
return filepath.Join(home, srvUserPath, user[0]), nil
|
||||
}
|
||||
}
|
||||
|
||||
func adjustPrivs(system bool, cmds []Runnable) []Runnable {
|
||||
if !system || isPrivileged() {
|
||||
return cmds
|
||||
}
|
||||
|
||||
sudos := cmds
|
||||
cmds = []Runnable{}
|
||||
for i := range sudos {
|
||||
exe := sudos[i]
|
||||
exe.Args = append([]string{exe.Exec}, exe.Args...)
|
||||
exe.Exec = "sudo"
|
||||
cmds = append(cmds, exe)
|
||||
}
|
||||
|
||||
return cmds
|
||||
}
|
||||
|
||||
func Run(bin string, args ...string) error {
|
||||
cmd := exec.Command(bin, args...)
|
||||
// for debugging
|
||||
/*
|
||||
out, err := cmd.CombinedOutput()
|
||||
if nil != err {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
*/
|
||||
|
||||
err := cmd.Start()
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEmptyUserServicePath(t *testing.T) {
|
||||
srvs, err := getUserSrvs("/tmp/fakeuser")
|
||||
if nil != err {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(srvs) > 0 {
|
||||
t.Fatal(fmt.Errorf("sanity fail: shouldn't get services from empty directory"))
|
||||
}
|
||||
|
||||
dirs, err := ioutil.ReadDir(filepath.Join("/tmp/fakeuser", srvUserPath))
|
||||
if nil != err {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(dirs) > 0 {
|
||||
t.Fatal(fmt.Errorf("sanity fail: shouldn't get listing from empty directory"))
|
||||
}
|
||||
|
||||
err = os.RemoveAll("/tmp/fakeuser")
|
||||
if nil != err {
|
||||
panic("couldn't remove /tmp/fakeuser")
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
1
npm/.gitignore
vendored
1
npm/.gitignore
vendored
@ -1 +0,0 @@
|
||||
node_modules
|
@ -1,28 +0,0 @@
|
||||
# serviceman
|
||||
|
||||
A cross-platform service manager
|
||||
|
||||
```bash
|
||||
serviceman add --name "my-project" node ./serve.js --port 3000
|
||||
serviceman stop my-project
|
||||
serviceman start my-project
|
||||
```
|
||||
|
||||
Works with launchd (Mac), systemd (Linux), or standalone (Windows).
|
||||
|
||||
## Meta Package
|
||||
|
||||
This is a meta-package to fetch and install the correction version of
|
||||
[go-serviceman](https://git.rootprojects.org/root/serviceman)
|
||||
for your architecture and platform.
|
||||
|
||||
```bash
|
||||
npm install serviceman
|
||||
```
|
||||
|
||||
## How does it work?
|
||||
|
||||
1. Resolves executable from PATH, or hashbang (ex: `#!/usr/bin/env node`)
|
||||
2. Resolves file and directory paths to absolute paths (ex: `/Users/me/my-project/serve.js`)
|
||||
3. Creates a template `.plist` (Mac), `.service` (Linux), or `.json` (Windows) file
|
||||
4. Calls `launchd` (Mac), `systemd` (Linux), or `serviceman-runner` (Windows) to enable/start/stop/etc
|
@ -1 +0,0 @@
|
||||
# this will be replaced by the postinstall script
|
18
npm/package-lock.json
generated
18
npm/package-lock.json
generated
@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "serviceman",
|
||||
"version": "0.5.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@root/mkdirp": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@root/mkdirp/-/mkdirp-1.0.0.tgz",
|
||||
"integrity": "sha512-hxGAYUx5029VggfG+U9naAhQkoMSXtOeXtbql97m3Hi6/sQSRL/4khKZPyOF6w11glyCOU38WCNLu9nUcSjOfA=="
|
||||
},
|
||||
"@root/request": {
|
||||
"version": "1.3.11",
|
||||
"resolved": "https://registry.npmjs.org/@root/request/-/request-1.3.11.tgz",
|
||||
"integrity": "sha512-3a4Eeghcjsfe6zh7EJ+ni1l8OK9Fz2wL1OjP4UCa0YdvtH39kdXB9RGWuzyNv7dZi0+Ffkc83KfH0WbPMiuJFw=="
|
||||
}
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
{
|
||||
"name": "serviceman",
|
||||
"version": "0.7.0",
|
||||
"description": "A cross-platform service manager",
|
||||
"main": "index.js",
|
||||
"homepage": "https://git.rootprojects.org/root/serviceman/src/branch/master/npm",
|
||||
"files": [
|
||||
"bin/",
|
||||
"scripts/"
|
||||
],
|
||||
"bin": {
|
||||
"serviceman": "bin/serviceman"
|
||||
},
|
||||
"scripts": {
|
||||
"serviceman": "serviceman",
|
||||
"postinstall": "node scripts/fetch-serviceman.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.rootprojects.org/root/serviceman.git"
|
||||
},
|
||||
"keywords": [
|
||||
"launchd",
|
||||
"systemd",
|
||||
"winsvc",
|
||||
"launchctl",
|
||||
"systemctl",
|
||||
"HKEY_CURRENT_USER",
|
||||
"HKCU",
|
||||
"Run"
|
||||
],
|
||||
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
|
||||
"license": "MPL-2.0",
|
||||
"dependencies": {
|
||||
"@root/mkdirp": "^1.0.0",
|
||||
"@root/request": "^1.3.11"
|
||||
}
|
||||
}
|
@ -1,269 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
var path = require('path');
|
||||
var os = require('os');
|
||||
|
||||
// https://nodejs.org/api/os.html#os_os_arch
|
||||
// 'arm', 'arm64', 'ia32', 'mips', 'mipsel', 'ppc', 'ppc64', 's390', 's390x', 'x32', and 'x64'
|
||||
var arch = os.arch(); // process.arch
|
||||
|
||||
// https://nodejs.org/api/os.html#os_os_platform
|
||||
// 'aix', 'darwin', 'freebsd', 'linux', 'openbsd', 'sunos', 'win32'
|
||||
var platform = os.platform(); // process.platform
|
||||
var ext = /^win/i.test(platform) ? '.exe' : '';
|
||||
|
||||
// This is _probably_ right. It's good enough for us
|
||||
// https://github.com/nodejs/node/issues/13629
|
||||
if ('arm' === arch) {
|
||||
arch += 'v' + process.config.variables.arm_version;
|
||||
}
|
||||
|
||||
var map = {
|
||||
// arches
|
||||
armv6: 'armv6',
|
||||
armv7: 'armv7',
|
||||
arm64: 'armv8',
|
||||
ia32: '386',
|
||||
x32: '386',
|
||||
x64: 'amd64',
|
||||
// platforms
|
||||
darwin: 'darwin',
|
||||
linux: 'linux',
|
||||
win32: 'windows'
|
||||
};
|
||||
|
||||
arch = map[arch];
|
||||
platform = map[platform];
|
||||
|
||||
if (!arch || !platform) {
|
||||
console.error(
|
||||
"'" + os.platform() + "' on '" + os.arch() + "' isn't supported yet."
|
||||
);
|
||||
console.error(
|
||||
'Please open an issue at https://git.rootprojects.org/root/serviceman/issues'
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var newVer = require('../package.json').version;
|
||||
var fs = require('fs');
|
||||
var exec = require('child_process').exec;
|
||||
var request = require('@root/request');
|
||||
var mkdirp = require('@root/mkdirp');
|
||||
|
||||
function needsUpdate(oldVer, newVer) {
|
||||
// "v1.0.0-pre" is BEHIND "v1.0.0"
|
||||
newVer = newVer
|
||||
.replace(/^v/, '')
|
||||
.split(/[\.\-\+]/)
|
||||
.filter(Boolean);
|
||||
oldVer = oldVer
|
||||
.replace(/^v/, '')
|
||||
.split(/[\.\-\+]/)
|
||||
.filter(Boolean);
|
||||
|
||||
if (!oldVer.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ex: v1.0.0-pre vs v1.0.0
|
||||
if (newVer[3] && !oldVer[3]) {
|
||||
// don't install beta over stable
|
||||
return false;
|
||||
}
|
||||
|
||||
// ex: old is v1.0.0-pre
|
||||
if (oldVer[3]) {
|
||||
if (oldVer[2] > 0) {
|
||||
oldVer[2] -= 1;
|
||||
} else if (oldVer[1] > 0) {
|
||||
oldVer[2] = 999;
|
||||
oldVer[1] -= 1;
|
||||
} else if (oldVer[0] > 0) {
|
||||
oldVer[2] = 999;
|
||||
oldVer[1] = 999;
|
||||
oldVer[0] -= 1;
|
||||
} else {
|
||||
// v0.0.0
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ex: v1.0.1 vs v1.0.0-pre
|
||||
if (newVer[3]) {
|
||||
if (newVer[2] > 0) {
|
||||
newVer[2] -= 1;
|
||||
} else if (newVer[1] > 0) {
|
||||
newVer[2] = 999;
|
||||
newVer[1] -= 1;
|
||||
} else if (newVer[0] > 0) {
|
||||
newVer[2] = 999;
|
||||
newVer[1] = 999;
|
||||
newVer[0] -= 1;
|
||||
} else {
|
||||
// v0.0.0
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ex: v1.0.1 vs v1.0.0
|
||||
if (oldVer[0] > newVer[0]) {
|
||||
return false;
|
||||
} else if (oldVer[0] < newVer[0]) {
|
||||
return true;
|
||||
} else if (oldVer[1] > newVer[1]) {
|
||||
return false;
|
||||
} else if (oldVer[1] < newVer[1]) {
|
||||
return true;
|
||||
} else if (oldVer[2] > newVer[2]) {
|
||||
return false;
|
||||
} else if (oldVer[2] < newVer[2]) {
|
||||
return true;
|
||||
} else if (!oldVer[3] && newVer[3]) {
|
||||
return false;
|
||||
} else if (oldVer[3] && !newVer[3]) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Same version
|
||||
console.log(false === needsUpdate('0.5.0', '0.5.0'));
|
||||
// No previous version
|
||||
console.log(true === needsUpdate('', '0.5.1'));
|
||||
// The new version is slightly newer
|
||||
console.log(true === needsUpdate('0.5.0', '0.5.1'));
|
||||
console.log(true === needsUpdate('0.4.999-pre1', '0.5.0-pre1'));
|
||||
// The new version is slightly older
|
||||
console.log(false === needsUpdate('0.5.0', '0.5.0-pre1'));
|
||||
console.log(false === needsUpdate('0.5.1', '0.5.0'));
|
||||
*/
|
||||
|
||||
function install(name, bindirs, getVersion, parseVersion, urlTpl) {
|
||||
exec(getVersion, { windowsHide: true }, function(err, stdout) {
|
||||
var oldVer = parseVersion(stdout);
|
||||
//console.log('old:', oldVer, 'new:', newVer);
|
||||
if (!needsUpdate(oldVer, newVer)) {
|
||||
console.info(
|
||||
'Current ' + name + ' version is new enough:',
|
||||
oldVer,
|
||||
newVer
|
||||
);
|
||||
return;
|
||||
//} else {
|
||||
// console.info('Current serviceman version is older:', oldVer, newVer);
|
||||
}
|
||||
|
||||
var url = urlTpl
|
||||
.replace(/{{ .Version }}/g, newVer)
|
||||
.replace(/{{ .Platform }}/g, platform)
|
||||
.replace(/{{ .Arch }}/g, arch)
|
||||
.replace(/{{ .Ext }}/g, ext);
|
||||
|
||||
console.info('Installing from', url);
|
||||
return request({ uri: url, encoding: null }, function(err, resp) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
//console.log(resp.body.byteLength);
|
||||
//console.log(typeof resp.body);
|
||||
var bin = name + ext;
|
||||
function next() {
|
||||
if (!bindirs.length) {
|
||||
return;
|
||||
}
|
||||
var bindir = bindirs.pop();
|
||||
return mkdirp(bindir, function(err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
var localsrv = path.join(bindir, bin);
|
||||
return fs.writeFile(localsrv, resp.body, function(err) {
|
||||
next();
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
fs.chmodSync(localsrv, parseInt('0755', 8));
|
||||
console.info('Wrote', bin, 'to', bindir);
|
||||
});
|
||||
});
|
||||
}
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function winstall(name, bindir) {
|
||||
try {
|
||||
fs.writeFileSync(
|
||||
path.join(bindir, name),
|
||||
'#!/usr/bin/env bash\n"$(dirname "$0")/serviceman.exe" "$@"\nexit $?'
|
||||
);
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
// because bugs in npm + git bash oddities, of course
|
||||
// https://npm.community/t/globally-installed-package-does-not-execute-in-git-bash-on-windows/9394
|
||||
try {
|
||||
fs.writeFileSync(
|
||||
path.join(path.join(__dirname, '../../.bin'), name),
|
||||
[
|
||||
'#!/bin/sh',
|
||||
'# manual bugfix patch for npm on windows',
|
||||
'basedir=$(dirname "$(echo "$0" | sed -e \'s,\\\\,/,g\')")',
|
||||
'"$basedir/../' + name + '/bin/' + name + '" "$@"',
|
||||
'exit $?'
|
||||
].join('\n')
|
||||
);
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
fs.writeFileSync(
|
||||
path.join(path.join(__dirname, '../../..'), name),
|
||||
[
|
||||
'#!/bin/sh',
|
||||
'# manual bugfix patch for npm on windows',
|
||||
'basedir=$(dirname "$(echo "$0" | sed -e \'s,\\\\,/,g\')")',
|
||||
'"$basedir/node_modules/' + name + '/bin/' + name + '" "$@"',
|
||||
'exit $?'
|
||||
].join('\n')
|
||||
);
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
// end bugfix
|
||||
}
|
||||
|
||||
function run() {
|
||||
//var homedir = require('os').homedir();
|
||||
//var bindir = path.join(homedir, '.local', 'bin');
|
||||
var bindir = path.resolve(__dirname, '..', 'bin');
|
||||
var name = 'serviceman';
|
||||
if ('.exe' === ext) {
|
||||
winstall(name, bindir);
|
||||
}
|
||||
|
||||
return install(
|
||||
name,
|
||||
[bindir],
|
||||
'serviceman version',
|
||||
function parseVersion(stdout) {
|
||||
return (stdout || '').split(' ')[0];
|
||||
},
|
||||
'https://rootprojects.org/serviceman/dist/{{ .Platform }}/{{ .Arch }}/serviceman{{ .Ext }}'
|
||||
);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
run();
|
||||
}
|
149
runner/runner.go
149
runner/runner.go
@ -2,17 +2,13 @@ package runner
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rootprojects.org/root/serviceman/service"
|
||||
|
||||
ps "github.com/mitchellh/go-ps"
|
||||
"git.rootprojects.org/root/go-serviceman/service"
|
||||
)
|
||||
|
||||
// Filled in on init by runner_windows.go
|
||||
@ -21,9 +17,7 @@ var shellArgs = []string{}
|
||||
// Notes on spawning a child process
|
||||
// https://groups.google.com/forum/#!topic/golang-nuts/shST-SDqIp4
|
||||
|
||||
// Start will execute the service, and write the PID and logs out to the log directory
|
||||
func Start(conf *service.Service) error {
|
||||
pid := os.Getpid()
|
||||
func Run(conf *service.Service) {
|
||||
originalBackoff := 1 * time.Second
|
||||
maxBackoff := 1 * time.Minute
|
||||
threshold := 5 * time.Second
|
||||
@ -32,17 +26,6 @@ func Start(conf *service.Service) error {
|
||||
failures := 0
|
||||
logfile := filepath.Join(conf.Logdir, conf.Name+".log")
|
||||
|
||||
if oldPid, exename, err := getProcess(conf); nil == err {
|
||||
return fmt.Errorf("%q may already be running as %q (pid %d)", conf.Name, exename, oldPid)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
maybeWritePidFile(pid, conf)
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}()
|
||||
|
||||
binpath := conf.Exec
|
||||
args := []string{}
|
||||
if "" != conf.Interpreter {
|
||||
@ -78,11 +61,6 @@ func Start(conf *service.Service) error {
|
||||
if "" != conf.Workdir {
|
||||
cmd.Dir = conf.Workdir
|
||||
}
|
||||
if len(conf.Envs) > 0 {
|
||||
for k, v := range conf.Envs {
|
||||
cmd.Env = append(cmd.Env, k+"="+v)
|
||||
}
|
||||
}
|
||||
err = cmd.Start()
|
||||
if nil != err {
|
||||
fmt.Fprintf(lf, "[%s] Could not start %q process: %s\n", time.Now(), conf.Name, err)
|
||||
@ -106,7 +84,7 @@ func Start(conf *service.Service) error {
|
||||
backoff = originalBackoff
|
||||
failures = 0
|
||||
} else {
|
||||
failures++
|
||||
failures += 1
|
||||
fmt.Fprintf(lf, "Waiting %s to restart %q (%d consequtive immediate exits)\n", backoff, conf.Name, failures)
|
||||
time.Sleep(backoff)
|
||||
backoff *= 2
|
||||
@ -115,125 +93,4 @@ func Start(conf *service.Service) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop will find and stop another serviceman runner instance by it's PID
|
||||
func Stop(conf *service.Service) error {
|
||||
i := 0
|
||||
var err error
|
||||
for {
|
||||
if i >= 3 {
|
||||
return err
|
||||
}
|
||||
i++
|
||||
oldPid, exename, err2 := getProcess(conf)
|
||||
err = err2
|
||||
switch err {
|
||||
case nil:
|
||||
fmt.Printf("killing old process %q with pid %d\n", exename, oldPid)
|
||||
err := kill(oldPid)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
return waitForProcessToDie(oldPid)
|
||||
case ErrNoPidFile:
|
||||
return err
|
||||
case ErrNoProcess:
|
||||
return err
|
||||
case ErrInvalidPidFile:
|
||||
fallthrough
|
||||
default:
|
||||
// waiting a little bit since the PID is written every second
|
||||
time.Sleep(400 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
// Restart calls Stop, ignoring any failure, and then Start, returning any failure
|
||||
func Restart(conf *service.Service) error {
|
||||
_ = Stop(conf)
|
||||
return Start(conf)
|
||||
}
|
||||
|
||||
var ErrNoPidFile = fmt.Errorf("no pid file")
|
||||
var ErrInvalidPidFile = fmt.Errorf("malformed pid file")
|
||||
var ErrNoProcess = fmt.Errorf("process not found by pid")
|
||||
|
||||
func waitForProcessToDie(pid int) error {
|
||||
exename := "unknown"
|
||||
for i := 0; i < 10; i++ {
|
||||
px, err := ps.FindProcess(pid)
|
||||
if nil != err {
|
||||
return nil
|
||||
}
|
||||
if nil == px {
|
||||
return nil
|
||||
}
|
||||
exename = px.Executable()
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
return fmt.Errorf("process %q (%d) just won't die", exename, pid)
|
||||
}
|
||||
|
||||
func getProcess(conf *service.Service) (int, string, error) {
|
||||
// TODO make Pidfile() a property of conf?
|
||||
pidFile := filepath.Join(conf.Logdir, conf.Name+".pid")
|
||||
b, err := ioutil.ReadFile(pidFile)
|
||||
if nil != err {
|
||||
return 0, "", ErrNoPidFile
|
||||
}
|
||||
|
||||
s := strings.TrimSpace(string(b))
|
||||
oldPid, err := strconv.Atoi(s)
|
||||
if nil != err {
|
||||
return 0, "", ErrInvalidPidFile
|
||||
}
|
||||
|
||||
px, err := ps.FindProcess(oldPid)
|
||||
if nil != err {
|
||||
return 0, "", err
|
||||
}
|
||||
if nil == px {
|
||||
return 0, "", ErrNoProcess
|
||||
}
|
||||
|
||||
_, err = os.FindProcess(oldPid)
|
||||
if nil != err {
|
||||
return 0, "", err
|
||||
}
|
||||
|
||||
exename := px.Executable()
|
||||
return oldPid, exename, nil
|
||||
}
|
||||
|
||||
// TODO error out if can't write to PID or log
|
||||
func maybeWritePidFile(pid int, conf *service.Service) bool {
|
||||
newPid := []byte(strconv.Itoa(pid))
|
||||
|
||||
// TODO use a specific PID dir? meh...
|
||||
pidFile := filepath.Join(conf.Logdir, conf.Name+".pid")
|
||||
b, err := ioutil.ReadFile(pidFile)
|
||||
if nil != err {
|
||||
ioutil.WriteFile(pidFile, newPid, 0644)
|
||||
return true
|
||||
}
|
||||
|
||||
s := strings.TrimSpace(string(b))
|
||||
oldPid, err := strconv.Atoi(s)
|
||||
if nil != err {
|
||||
ioutil.WriteFile(pidFile, newPid, 0644)
|
||||
return true
|
||||
}
|
||||
|
||||
if oldPid != pid {
|
||||
Stop(conf)
|
||||
ioutil.WriteFile(pidFile, newPid, 0644)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
@ -2,19 +2,7 @@
|
||||
|
||||
package runner
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
import "os/exec"
|
||||
|
||||
func backgroundCmd(cmd *exec.Cmd) {
|
||||
}
|
||||
|
||||
func kill(pid int) error {
|
||||
p, err := os.FindProcess(pid)
|
||||
// already died
|
||||
if nil != err {
|
||||
return nil
|
||||
}
|
||||
return p.Kill()
|
||||
}
|
||||
|
@ -1,23 +1,10 @@
|
||||
package runner
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func backgroundCmd(cmd *exec.Cmd) {
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
||||
}
|
||||
|
||||
func kill(pid int) error {
|
||||
// Kill the whole processes tree (all children and grandchildren)
|
||||
cmd := exec.Command("taskkill", "/pid", strconv.Itoa(pid), "/T", "/F")
|
||||
b, err := cmd.CombinedOutput()
|
||||
if nil != err {
|
||||
return fmt.Errorf("%s: %s", err.Error(), string(b))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ type Service struct {
|
||||
MultiuserProtection bool `json:"multiuser_protection,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Service) NormalizeWithoutPath() {
|
||||
func (s *Service) Normalize(force bool) {
|
||||
if "" == s.Name {
|
||||
ext := filepath.Ext(s.Exec)
|
||||
base := filepath.Base(s.Exec[:len(s.Exec)-len(ext)])
|
||||
@ -93,16 +93,11 @@ func (s *Service) NormalizeWithoutPath() {
|
||||
os.Exit(4)
|
||||
return
|
||||
}
|
||||
s.Home = home
|
||||
s.Local = filepath.Join(home, ".local")
|
||||
s.Logdir = filepath.Join(home, ".local", "share", s.Name, "var", "log")
|
||||
} else {
|
||||
s.Logdir = "/var/log/" + s.Name
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) Normalize(force bool) {
|
||||
s.NormalizeWithoutPath()
|
||||
|
||||
// Check to see if Exec exists
|
||||
// /whatever => must exist exactly
|
||||
@ -116,7 +111,7 @@ func (s *Service) Normalize(force bool) {
|
||||
_, err := os.Stat(optpath)
|
||||
if nil == err {
|
||||
bad = false
|
||||
//fmt.Fprintf(os.Stderr, "Using '%s' for '%s'\n", optpath, s.Exec)
|
||||
fmt.Fprintf(os.Stderr, "Using '%s' for '%s'\n", optpath, s.Exec)
|
||||
s.Exec = optpath
|
||||
}
|
||||
}
|
||||
|
578
serviceman.go
578
serviceman.go
@ -1,6 +1,5 @@
|
||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2
|
||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver
|
||||
|
||||
// main runs the things and does the stuff
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -10,49 +9,24 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"git.rootprojects.org/root/serviceman/manager"
|
||||
"git.rootprojects.org/root/serviceman/runner"
|
||||
"git.rootprojects.org/root/serviceman/service"
|
||||
"git.rootprojects.org/root/go-serviceman/manager"
|
||||
"git.rootprojects.org/root/go-serviceman/runner"
|
||||
"git.rootprojects.org/root/go-serviceman/service"
|
||||
)
|
||||
|
||||
var (
|
||||
// commit refers to the abbreviated commit hash
|
||||
commit = "0000000"
|
||||
// version refers to the most recent tag, plus any commits made since then
|
||||
version = "v0.0.0-pre0+0000000"
|
||||
// date refers to the timestamp of the most recent commit
|
||||
date = time.Now().Format(time.RFC3339)
|
||||
)
|
||||
|
||||
func ver() string {
|
||||
return fmt.Sprintf("serviceman %s (%s) %s", version, commit[:7], date)
|
||||
}
|
||||
var GitRev = "000000000"
|
||||
var GitVersion = "v0.0.0"
|
||||
var GitTimestamp = time.Now().Format(time.RFC3339)
|
||||
|
||||
func usage() {
|
||||
fmt.Println("Usage:")
|
||||
fmt.Println("\tserviceman <command> --help")
|
||||
fmt.Println("\tserviceman add ./foo-app -- --foo-arg")
|
||||
fmt.Println("\tserviceman run --config ./foo-app.json")
|
||||
fmt.Println("\tserviceman list --all")
|
||||
fmt.Println("\tserviceman start <name>")
|
||||
fmt.Println("\tserviceman stop <name>")
|
||||
fmt.Println("Usage: serviceman add ./foo-app -- --foo-arg")
|
||||
fmt.Println("Usage: serviceman run --config ./foo-app.json")
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) >= 2 {
|
||||
if "version" == strings.TrimLeft(os.Args[1], "-") {
|
||||
fmt.Printf("%s\n", ver())
|
||||
os.Exit(0)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Fprintf(os.Stderr, "Too few arguments: %s\n", strings.Join(os.Args, " "))
|
||||
usage()
|
||||
@ -63,17 +37,11 @@ func main() {
|
||||
os.Args = append(os.Args[:1], os.Args[2:]...)
|
||||
switch top {
|
||||
case "version":
|
||||
fmt.Println(ver())
|
||||
case "run":
|
||||
run()
|
||||
fmt.Println(GitVersion, GitTimestamp, GitRev)
|
||||
case "add":
|
||||
add()
|
||||
case "start":
|
||||
start()
|
||||
case "stop":
|
||||
stop()
|
||||
case "list":
|
||||
list()
|
||||
case "run":
|
||||
run()
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "Unknown argument %s\n", top)
|
||||
usage()
|
||||
@ -86,488 +54,87 @@ func add() {
|
||||
Restart: true,
|
||||
}
|
||||
|
||||
args := []string{}
|
||||
for i := range os.Args {
|
||||
if "--" == os.Args[i] {
|
||||
if len(os.Args) > i+1 {
|
||||
args = os.Args[i+1:]
|
||||
}
|
||||
os.Args = os.Args[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
conf.Argv = args
|
||||
|
||||
force := false
|
||||
forUser := false
|
||||
forSystem := false
|
||||
dryrun := false
|
||||
pathEnv := ""
|
||||
flag.StringVar(&conf.Title, "title", "", "a human-friendly name for the service")
|
||||
flag.StringVar(&conf.Desc, "desc", "", "a human-friendly description of the service (ex: Foo App)")
|
||||
flag.StringVar(&conf.Name, "name", "", "a computer-friendly name for the service (ex: foo-app)")
|
||||
flag.StringVar(&conf.URL, "url", "", "the documentation on home page of the service")
|
||||
flag.StringVar(&conf.Workdir, "workdir", "", "the directory in which the service should be started (if supported)")
|
||||
//flag.StringVar(&conf.Workdir, "workdir", "", "the directory in which the service should be started")
|
||||
flag.StringVar(&conf.ReverseDNS, "rdns", "", "a plist-friendly Reverse DNS name for launchctl (ex: com.example.foo-app)")
|
||||
flag.BoolVar(&forSystem, "system", false, "attempt to add system service as an unprivileged/unelevated user")
|
||||
flag.BoolVar(&forUser, "user", false, "add user space / user mode service even when admin/root/sudo/elevated")
|
||||
flag.BoolVar(&force, "force", false, "if the interpreter or executable doesn't exist, or things don't make sense, try anyway")
|
||||
flag.StringVar(&pathEnv, "path", "", "set the path for the resulting systemd service")
|
||||
flag.StringVar(&conf.User, "username", "", "run the service as this user")
|
||||
flag.StringVar(&conf.Group, "groupname", "", "run the service as this group")
|
||||
flag.BoolVar(&conf.PrivilegedPorts, "cap-net-bind", false, "this service should have access to privileged ports")
|
||||
flag.BoolVar(&dryrun, "dryrun", false, "output the service file without modifying anything on disk")
|
||||
flag.Parse()
|
||||
flagargs := flag.Args()
|
||||
args = flag.Args()
|
||||
|
||||
// You must have something to run, duh
|
||||
n := len(flagargs)
|
||||
if forUser && forSystem {
|
||||
fmt.Println("Pfff! You can't --user AND --system! What are you trying to pull?")
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
if forUser {
|
||||
conf.System = false
|
||||
} else if forSystem {
|
||||
conf.System = true
|
||||
} else {
|
||||
conf.System = manager.IsPrivileged()
|
||||
}
|
||||
|
||||
n := len(args)
|
||||
if 0 == n {
|
||||
fmt.Println("Usage: serviceman add ./foo-app --foo-arg")
|
||||
fmt.Println("Usage: serviceman add ./foo-app -- --foo-arg")
|
||||
os.Exit(2)
|
||||
return
|
||||
}
|
||||
|
||||
if forUser && forSystem {
|
||||
fmt.Println("Pfff! You can't --user AND --system! What are you trying to pull?")
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
// There are three groups of flags
|
||||
// serviceman --flag1 arg1 non-flag-arg --child1 -- --raw1 -- --raw2
|
||||
// serviceman --flag1 arg1 // these belong to serviceman
|
||||
// non-flag-arg --child1 // these will be interpretted
|
||||
// -- // separator
|
||||
// --raw1 -- --raw2 // after the separater (including additional separators) will be ignored
|
||||
rawargs := []string{}
|
||||
for i := range flagargs {
|
||||
if "--" == flagargs[i] {
|
||||
if len(flagargs) > i+1 {
|
||||
rawargs = flagargs[i+1:]
|
||||
}
|
||||
flagargs = flagargs[:i]
|
||||
break
|
||||
execpath, err := manager.WhereIs(args[0])
|
||||
if nil != err {
|
||||
fmt.Fprintf(os.Stderr, "Error: '%s' could not be found.\n", args[0])
|
||||
if !force {
|
||||
os.Exit(3)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Assumptions
|
||||
ass := []string{}
|
||||
if forUser {
|
||||
conf.System = false
|
||||
} else if forSystem {
|
||||
conf.System = true
|
||||
} else {
|
||||
conf.System = manager.IsPrivileged()
|
||||
if conf.System {
|
||||
ass = append(ass, "# Because you're a privileged user")
|
||||
ass = append(ass, " --system")
|
||||
ass = append(ass, "")
|
||||
} else {
|
||||
ass = append(ass, "# Because you're a unprivileged user")
|
||||
ass = append(ass, " --user")
|
||||
ass = append(ass, "")
|
||||
}
|
||||
args[0] = execpath
|
||||
}
|
||||
if "" == conf.Workdir {
|
||||
dir, _ := os.Getwd()
|
||||
conf.Workdir = dir
|
||||
ass = append(ass, "# Because this is your current working directory")
|
||||
ass = append(ass, fmt.Sprintf(" --workdir %s", conf.Workdir))
|
||||
ass = append(ass, "")
|
||||
}
|
||||
if "" == conf.Name {
|
||||
name, _ := os.Getwd()
|
||||
base := filepath.Base(name)
|
||||
ext := filepath.Ext(base)
|
||||
n := (len(base) - len(ext))
|
||||
name = base[:n]
|
||||
if "" == name {
|
||||
name = base
|
||||
}
|
||||
conf.Name = name
|
||||
ass = append(ass, "# Because this is the name of your current working directory")
|
||||
ass = append(ass, fmt.Sprintf(" --name %s", conf.Name))
|
||||
ass = append(ass, "")
|
||||
}
|
||||
if "" != pathEnv {
|
||||
conf.Envs = make(map[string]string)
|
||||
conf.Envs["PATH"] = pathEnv
|
||||
conf.Exec = args[0]
|
||||
args = args[1:]
|
||||
|
||||
if n >= 2 {
|
||||
conf.Interpreter = conf.Exec
|
||||
conf.Exec = args[0]
|
||||
conf.Argv = append(args[1:], conf.Argv...)
|
||||
}
|
||||
|
||||
exepath, err := findExec(flagargs[0], force)
|
||||
if nil != err {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||
os.Exit(3)
|
||||
return
|
||||
}
|
||||
flagargs[0] = exepath
|
||||
|
||||
exeargs, err := testScript(flagargs[0], force)
|
||||
if nil != err {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||
os.Exit(3)
|
||||
return
|
||||
}
|
||||
|
||||
flagargs = append(exeargs, flagargs...)
|
||||
// TODO
|
||||
for i := range flagargs {
|
||||
arg := flagargs[i]
|
||||
arg = filepath.ToSlash(arg)
|
||||
// Paths considered to be anything starting with ./, .\, /, \, C:
|
||||
if "." == arg || strings.Contains(arg, "/") {
|
||||
//if "." == arg || (len(arg) >= 2 && "./" == arg[:2] || '/' == arg[0] || "C:" == strings.ToUpper(arg[:1])) {
|
||||
var err error
|
||||
arg, err = filepath.Abs(arg)
|
||||
if nil == err {
|
||||
_, err = os.Stat(arg)
|
||||
}
|
||||
if nil != err {
|
||||
fmt.Printf("%q appears to be a file path, but %q could not be read\n", flagargs[i], arg)
|
||||
if !force {
|
||||
os.Exit(7)
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if '\\' != os.PathSeparator {
|
||||
// Convert paths back to .\ for Windows
|
||||
arg = filepath.FromSlash(arg)
|
||||
}
|
||||
|
||||
// Lookin' good
|
||||
flagargs[i] = arg
|
||||
}
|
||||
}
|
||||
|
||||
// We won't bother with Interpreter here
|
||||
// (it's really just for documentation),
|
||||
// but we will add any and all unchecked args to the full slice
|
||||
conf.Exec = flagargs[0]
|
||||
conf.Argv = append(flagargs[1:], rawargs...)
|
||||
|
||||
// TODO update docs: go to the work directory
|
||||
// TODO test with "npm start"
|
||||
|
||||
conf.NormalizeWithoutPath()
|
||||
conf.Normalize(force)
|
||||
|
||||
//fmt.Printf("\n%#v\n\n", conf)
|
||||
if conf.System && !manager.IsPrivileged() {
|
||||
fmt.Fprintf(os.Stderr, "Warning: You may need to use 'sudo' to add %q as a privileged system service.\n", conf.Name)
|
||||
}
|
||||
|
||||
if len(ass) > 0 {
|
||||
fmt.Printf("OPTIONS: Making some assumptions...\n\n")
|
||||
for i := range ass {
|
||||
fmt.Println("\t" + ass[i])
|
||||
}
|
||||
}
|
||||
|
||||
// Find who this is running as
|
||||
// And pretty print the command to run
|
||||
runAs := conf.User
|
||||
var wasflag bool
|
||||
fmt.Printf("COMMAND: Service %q will be run like this (more or less):\n\n", conf.Title)
|
||||
if conf.System {
|
||||
if "" == runAs {
|
||||
runAs = "root"
|
||||
}
|
||||
fmt.Printf("\t# Starts on system boot, as %q\n", runAs)
|
||||
} else {
|
||||
u, _ := user.Current()
|
||||
runAs = u.Name
|
||||
if "" == runAs {
|
||||
runAs = u.Username
|
||||
}
|
||||
fmt.Printf("\t# Starts as %q, when %q logs in\n", runAs, u.Username)
|
||||
}
|
||||
//fmt.Printf("\tpushd %s\n", conf.Workdir)
|
||||
fmt.Printf("\t%s\n", conf.Exec)
|
||||
for i := range conf.Argv {
|
||||
arg := conf.Argv[i]
|
||||
if '-' == arg[0] {
|
||||
if wasflag {
|
||||
fmt.Println()
|
||||
}
|
||||
wasflag = true
|
||||
fmt.Printf("\t\t%s", arg)
|
||||
} else {
|
||||
if wasflag {
|
||||
fmt.Printf(" %s\n", arg)
|
||||
} else {
|
||||
fmt.Printf("\t\t%s\n", arg)
|
||||
}
|
||||
wasflag = false
|
||||
}
|
||||
}
|
||||
if wasflag {
|
||||
fmt.Println()
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
// TODO output config without installing
|
||||
if dryrun {
|
||||
b, err := manager.Render(conf)
|
||||
if nil != err {
|
||||
fmt.Fprintf(os.Stderr, "Error rendering: %s\n", err)
|
||||
os.Exit(10)
|
||||
}
|
||||
fmt.Println(string(b))
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("LAUNCHER: ")
|
||||
servicetype, err := manager.Install(conf)
|
||||
err = manager.Install(conf)
|
||||
if nil != err {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||
os.Exit(500)
|
||||
return
|
||||
fmt.Fprintf(os.Stderr, "Use 'sudo' to add service as a privileged system service.\n")
|
||||
fmt.Fprintf(os.Stderr, "Use '--user' to add service as an user service.\n")
|
||||
}
|
||||
|
||||
fmt.Printf("LOGS: ")
|
||||
printLogMessage(conf)
|
||||
fmt.Println()
|
||||
|
||||
servicemode := "USER MODE"
|
||||
if conf.System {
|
||||
servicemode = "SYSTEM"
|
||||
}
|
||||
fmt.Printf(
|
||||
"SUCCESS:\n\n\t%q started as a %s %s service, running as %q\n",
|
||||
conf.Name,
|
||||
servicetype,
|
||||
servicemode,
|
||||
runAs,
|
||||
)
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func list() {
|
||||
var verbose bool
|
||||
forUser := false
|
||||
forSystem := false
|
||||
flag.BoolVar(&forSystem, "system", false, "attempt to add system service as an unprivileged/unelevated user")
|
||||
flag.BoolVar(&forUser, "user", false, "add user space / user mode service even when admin/root/sudo/elevated")
|
||||
flag.BoolVar(&verbose, "all", false, "show all services (even those not managed by serviceman)")
|
||||
flag.Parse()
|
||||
|
||||
if forUser && forSystem {
|
||||
fmt.Println("Pfff! You can't --user AND --system! What are you trying to pull?")
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
conf := &service.Service{}
|
||||
if forUser {
|
||||
conf.System = false
|
||||
} else if forSystem {
|
||||
conf.System = true
|
||||
} else {
|
||||
conf.System = manager.IsPrivileged()
|
||||
}
|
||||
|
||||
// Pretty much just for HomeDir
|
||||
conf.NormalizeWithoutPath()
|
||||
|
||||
managed, others, errs := manager.List(conf)
|
||||
for i := range errs {
|
||||
fmt.Fprintf(os.Stderr, "possible error: %s\n", errs[i])
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
fmt.Fprintf(os.Stderr, "\n")
|
||||
}
|
||||
|
||||
fmt.Printf("serviceman-managed services:\n\n")
|
||||
for i := range managed {
|
||||
fmt.Println("\t" + managed[i])
|
||||
}
|
||||
if 0 == len(managed) {
|
||||
fmt.Println("\t(none)")
|
||||
}
|
||||
fmt.Println("")
|
||||
|
||||
if verbose {
|
||||
fmt.Printf("other services:\n\n")
|
||||
for i := range others {
|
||||
fmt.Println("\t" + others[i])
|
||||
}
|
||||
if 0 == len(others) {
|
||||
fmt.Println("\t(none)")
|
||||
}
|
||||
fmt.Println("")
|
||||
}
|
||||
}
|
||||
|
||||
func findExec(exe string, force bool) (string, error) {
|
||||
// ex: node => /usr/local/bin/node
|
||||
// ex: ./demo.js => /Users/aj/project/demo.js
|
||||
exepath, err := exec.LookPath(exe)
|
||||
if nil != err {
|
||||
var msg string
|
||||
if strings.Contains(filepath.ToSlash(exe), "/") {
|
||||
if _, err := os.Stat(exe); err != nil {
|
||||
msg = fmt.Sprintf("Error: '%s' could not be found in PATH or working directory.\n", exe)
|
||||
} else {
|
||||
msg = fmt.Sprintf("Error: '%s' is not an executable.\nYou may be able to fix that. Try running this:\n\tchmod a+x %s\n", exe, exe)
|
||||
}
|
||||
} else {
|
||||
if _, err := os.Stat(exe); err != nil {
|
||||
msg = fmt.Sprintf("Error: '%s' could not be found in PATH", exe)
|
||||
} else {
|
||||
msg = fmt.Sprintf("Error: '%s' could not be found in PATH, did you mean './%s'?\n", exe, exe)
|
||||
}
|
||||
}
|
||||
if !force {
|
||||
return "", fmt.Errorf(msg)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "%s\n", msg)
|
||||
return exe, nil
|
||||
}
|
||||
|
||||
// ex: \Users\aj\project\demo.js => /Users/aj/project/demo.js
|
||||
// Can't have an error here when lookpath succeeded
|
||||
exepath, _ = filepath.Abs(filepath.ToSlash(exepath))
|
||||
return exepath, nil
|
||||
}
|
||||
|
||||
func testScript(exepath string, force bool) ([]string, error) {
|
||||
f, err := os.Open(exepath)
|
||||
b := make([]byte, 256)
|
||||
if nil == err {
|
||||
_, err = f.Read(b)
|
||||
}
|
||||
if nil != err || len(b) < len("#!/x") {
|
||||
msg := fmt.Sprintf("Error when testing if '%s' is a binary or script: could not read file: %s\n", exepath, err)
|
||||
if !force {
|
||||
return nil, fmt.Errorf(msg)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "%s\n", msg)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Nott sure if this is more readable and idiomatic as if else or switch
|
||||
// However, the order matters
|
||||
switch {
|
||||
case utf8.Valid(b):
|
||||
// Looks like an executable script
|
||||
if "#!/" == string(b[:3]) {
|
||||
break
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("Error: %q looks like a script, but we don't know the interpreter.\nYou can probably fix this by...\n"+
|
||||
"\tExplicitly naming the interpreter (ex: 'python my-script.py' instead of just 'my-script.py')\n"+
|
||||
"\tPlacing a hashbang at the top of the script (ex: '#!/usr/bin/env python')", exepath)
|
||||
|
||||
if !force {
|
||||
return nil, fmt.Errorf(msg)
|
||||
}
|
||||
return nil, nil
|
||||
case "#!/" != string(b[:3]):
|
||||
// Looks like a normal binary
|
||||
return nil, nil
|
||||
default:
|
||||
// Looks like a corrupt script file
|
||||
msg := "Error: It looks like you've specified a corrupt script file."
|
||||
if !force {
|
||||
return nil, fmt.Errorf(msg)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Deal with #!/whatever
|
||||
|
||||
// Get that first line
|
||||
// "#!/usr/bin/env node" => ["/usr/bin/env", "node"]
|
||||
// "#!/usr/bin/node --harmony => ["/usr/bin/node", "--harmony"]
|
||||
s := string(b[2:]) // strip leading #!
|
||||
s = strings.Split(strings.Replace(s, "\r\n", "\n", -1), "\n")[0]
|
||||
allargs := strings.Split(strings.TrimSpace(s), " ")
|
||||
args := []string{}
|
||||
for i := range allargs {
|
||||
arg := strings.TrimSpace(allargs[i])
|
||||
if "" != arg {
|
||||
args = append(args, arg)
|
||||
}
|
||||
}
|
||||
if strings.HasSuffix(args[0], "/env") && len(args) > 1 {
|
||||
// TODO warn that "env" is probably not an executable if 1 = len(args)?
|
||||
args = args[1:]
|
||||
}
|
||||
exepath, err = findExec(args[0], force)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
args[0] = exepath
|
||||
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func start() {
|
||||
forUser := false
|
||||
forSystem := false
|
||||
flag.BoolVar(&forSystem, "system", false, "attempt to add system service as an unprivileged/unelevated user")
|
||||
flag.BoolVar(&forUser, "user", false, "add user space / user mode service even when admin/root/sudo/elevated")
|
||||
flag.Parse()
|
||||
|
||||
args := flag.Args()
|
||||
if 1 != len(args) {
|
||||
fmt.Println("Usage: serviceman start <name>")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if forUser && forSystem {
|
||||
fmt.Println("Pfff! You can't --user AND --system! What are you trying to pull?")
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
conf := &service.Service{
|
||||
Name: args[0],
|
||||
Restart: false,
|
||||
}
|
||||
if forUser {
|
||||
conf.System = false
|
||||
} else if forSystem {
|
||||
conf.System = true
|
||||
} else {
|
||||
conf.System = manager.IsPrivileged()
|
||||
}
|
||||
conf.NormalizeWithoutPath()
|
||||
|
||||
err := manager.Start(conf)
|
||||
if nil != err {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||
os.Exit(500)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func stop() {
|
||||
forUser := false
|
||||
forSystem := false
|
||||
flag.BoolVar(&forSystem, "system", false, "attempt to add system service as an unprivileged/unelevated user")
|
||||
flag.BoolVar(&forUser, "user", false, "add user space / user mode service even when admin/root/sudo/elevated")
|
||||
flag.Parse()
|
||||
|
||||
args := flag.Args()
|
||||
if 1 != len(args) {
|
||||
fmt.Println("Usage: serviceman stop <name>")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if forUser && forSystem {
|
||||
fmt.Println("Pfff! You can't --user AND --system! What are you trying to pull?")
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
conf := &service.Service{
|
||||
Name: args[0],
|
||||
Restart: false,
|
||||
}
|
||||
if forUser {
|
||||
conf.System = false
|
||||
} else if forSystem {
|
||||
conf.System = true
|
||||
} else {
|
||||
conf.System = manager.IsPrivileged()
|
||||
}
|
||||
conf.NormalizeWithoutPath()
|
||||
|
||||
if err := manager.Stop(conf); nil != err {
|
||||
fmt.Println(err)
|
||||
os.Exit(127)
|
||||
}
|
||||
fmt.Printf("Once started, logs will be found at:\n\t%s\n", conf.Logdir)
|
||||
}
|
||||
|
||||
func run() {
|
||||
@ -578,7 +145,7 @@ func run() {
|
||||
flag.Parse()
|
||||
|
||||
if "" == confpath {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", strings.Join(flag.Args(), " "))
|
||||
fmt.Fprintf(os.Stderr, "%s", strings.Join(flag.Args(), " "))
|
||||
fmt.Fprintf(os.Stderr, "--config /path/to/config.json is required\n")
|
||||
usage()
|
||||
os.Exit(1)
|
||||
@ -614,8 +181,7 @@ func run() {
|
||||
os.Exit(400)
|
||||
}
|
||||
|
||||
force := false
|
||||
s.Normalize(force)
|
||||
s.Normalize(false)
|
||||
fmt.Printf("All output will be directed to the logs at:\n\t%s\n", s.Logdir)
|
||||
err = os.MkdirAll(s.Logdir, 0755)
|
||||
if nil != err {
|
||||
@ -625,11 +191,23 @@ func run() {
|
||||
|
||||
if !daemonize {
|
||||
//fmt.Fprintf(os.Stdout, "Running %s %s %s\n", s.Interpreter, s.Exec, strings.Join(s.Argv, " "))
|
||||
if err := runner.Start(s); nil != err {
|
||||
fmt.Println("Error:", err)
|
||||
}
|
||||
runner.Run(s)
|
||||
return
|
||||
}
|
||||
|
||||
manager.Run(os.Args[0], "run", "--config", confpath)
|
||||
cmd := exec.Command(os.Args[0], "run", "--config", confpath)
|
||||
// for debugging
|
||||
/*
|
||||
out, err := cmd.CombinedOutput()
|
||||
if nil != err {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
*/
|
||||
|
||||
err = cmd.Start()
|
||||
if nil != err {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||
os.Exit(500)
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.rootprojects.org/root/serviceman/service"
|
||||
)
|
||||
|
||||
func printLogMessage(conf *service.Service) {
|
||||
fmt.Printf("If all went well the logs should have been created at:\n\n\t%s\n", conf.Logdir)
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.rootprojects.org/root/serviceman/manager"
|
||||
"git.rootprojects.org/root/serviceman/service"
|
||||
)
|
||||
|
||||
func printLogMessage(conf *service.Service) {
|
||||
sudo := ""
|
||||
unit := "--unit"
|
||||
if conf.System {
|
||||
if !manager.IsPrivileged() {
|
||||
sudo = "sudo"
|
||||
}
|
||||
} else {
|
||||
unit = "--user-unit"
|
||||
}
|
||||
fmt.Println("If all went well you should be able to see some goodies in the logs:\n")
|
||||
fmt.Printf("\t%sjournalctl -xe %s %s.service\n", sudo, unit, conf.Name)
|
||||
if !conf.System {
|
||||
fmt.Println("\nIf that's not the case, see https://unix.stackexchange.com/a/486566/45554.")
|
||||
fmt.Println("(you may need to run `systemctl restart systemd-journald`)")
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.rootprojects.org/root/serviceman/service"
|
||||
)
|
||||
|
||||
func printLogMessage(conf *service.Service) {
|
||||
fmt.Printf("If all went well the logs should have been created at:\n\n\t%s\n", conf.Logdir)
|
||||
}
|
@ -3,6 +3,6 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
_ "git.rootprojects.org/root/go-gitver/v2"
|
||||
_ "git.rootprojects.org/root/go-gitver"
|
||||
_ "github.com/UnnoTed/fileb0x"
|
||||
)
|
||||
|
@ -1,10 +1,6 @@
|
||||
xversion.go
|
||||
zversion.go
|
||||
|
||||
/go-gitver
|
||||
hello
|
||||
examples/*/*.sum
|
||||
|
||||
# ---> Go
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
@ -1,79 +1,24 @@
|
||||
# [Go GitVer](https://git.rootprojects.org/root/go-gitver)
|
||||
# git-version.go
|
||||
|
||||
Use **git tags** to add (GoRelesear-compatible) [**semver**](https://semver.org/)
|
||||
to your go package in under 150
|
||||
[lines of code](https://git.rootprojects.org/root/go-gitver/src/branch/master/gitver/gitver.go).
|
||||
Use git tags to add semver to your go package.
|
||||
|
||||
```txt
|
||||
Goals:
|
||||
|
||||
1. Use an exact `git tag` version, like v1.0.0, when clean
|
||||
2. Translate the `git describe` version (v1.0.0-4-g0000000)
|
||||
to semver (1.0.1-pre4+g0000000) in between releases
|
||||
3. Note when `dirty` (and have build timestamp)
|
||||
Goal: Either use an exact version like v1.0.0
|
||||
or translate the git version like v1.0.0-4-g0000000
|
||||
to a semver like v1.0.1-pre4+g0000000
|
||||
|
||||
Fail gracefully when git repo isn't available.
|
||||
```
|
||||
|
||||
# GoDoc
|
||||
|
||||
See <https://pkg.go.dev/git.rootprojects.org/root/go-gitver/v2>.
|
||||
|
||||
# How it works
|
||||
|
||||
1. You define the fallback version and version printing in `main.go`:
|
||||
|
||||
```go
|
||||
//go:generate go run git.rootprojects.org/root/go-gitver/v2
|
||||
|
||||
package main
|
||||
|
||||
var (
|
||||
commit = "0000000"
|
||||
version = "0.0.0-pre0+0000000"
|
||||
date = "0000-00-00T00:00:00+0000"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if (len(os.Args) > 1 && "version" === os.Args[1]) {
|
||||
fmt.Printf("Foobar v%s (%s) %s\n", version, commit[:7], date)
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
2. You `go generate` or `go run git.rootprojects.org/root/go-gitver/v2` to generate `xversion.go`:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
func init() {
|
||||
commit = "0921ed1e"
|
||||
version = "1.1.2"
|
||||
date = "2019-07-01T02:32:58-06:00"
|
||||
}
|
||||
```
|
||||
|
||||
# Demo
|
||||
|
||||
Generate an `xversion.go` file:
|
||||
|
||||
```bash
|
||||
go run git.rootprojects.org/root/go-gitver/v2
|
||||
go run git.rootprojects.org/root/go-gitver
|
||||
cat xversion.go
|
||||
```
|
||||
|
||||
```go
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
package main
|
||||
|
||||
func init() {
|
||||
commit = "6dace8255b52e123297a44629bc32c015add310a"
|
||||
version = "1.1.4-pre2+g6dace82"
|
||||
date = "2020-07-16T20:48:15-06:00"
|
||||
}
|
||||
```
|
||||
|
||||
<small>**Note**: The file is named `xversion.go` by default so that the
|
||||
generated file's `init()` will come later, and thus take priority, over
|
||||
most other files.</small>
|
||||
@ -81,21 +26,15 @@ most other files.</small>
|
||||
See `go-gitver`s self-generated version:
|
||||
|
||||
```bash
|
||||
go run git.rootprojects.org/root/go-gitver/v2 version
|
||||
```
|
||||
|
||||
```txt
|
||||
6dace8255b52e123297a44629bc32c015add310a
|
||||
v1.1.4-pre2+g6dace82
|
||||
2020-07-16T20:48:15-06:00
|
||||
go run git.rootprojects.org/root/go-gitver version
|
||||
```
|
||||
|
||||
# QuickStart
|
||||
|
||||
Add this to the top of your main file, so that it runs with `go generate`:
|
||||
Add this to the top of your main file:
|
||||
|
||||
```go
|
||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2
|
||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver
|
||||
|
||||
```
|
||||
|
||||
@ -106,7 +45,7 @@ Add a file that imports go-gitver (for versioning)
|
||||
|
||||
package example
|
||||
|
||||
import _ "git.rootprojects.org/root/go-gitver/v2"
|
||||
import _ "git.rootprojects.org/root/go-gitver"
|
||||
```
|
||||
|
||||
Change you build instructions to be something like this:
|
||||
@ -117,7 +56,7 @@ go generate -mod=vendor ./...
|
||||
go build -mod=vendor -o example cmd/example/*.go
|
||||
```
|
||||
|
||||
You don't have to use `-mod=vendor`, but I highly recommend it (just `go mod tidy; go mod vendor` to start).
|
||||
You don't have to use `mod vendor`, but I highly recommend it.
|
||||
|
||||
# Options
|
||||
|
||||
@ -138,12 +77,12 @@ GITVER_FAIL=true
|
||||
For example:
|
||||
|
||||
```go
|
||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 --fail
|
||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver --fail
|
||||
|
||||
```
|
||||
|
||||
```bash
|
||||
go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 version
|
||||
go run -mod=vendor git.rootprojects.org/root/go-gitver version
|
||||
```
|
||||
|
||||
# Usage
|
||||
@ -152,9 +91,9 @@ See `examples/basic`
|
||||
|
||||
1. Create a `tools` package in your project
|
||||
2. Guard it against regular builds with `// +build tools`
|
||||
3. Include `_ "git.rootprojects.org/root/go-gitver/v2"` in the imports
|
||||
4. Declare `var commit, version, date string` in your `package main`
|
||||
5. Include `//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2` as well
|
||||
3. Include `_ "git.rootprojects.org/root/go-gitver"` in the imports
|
||||
4. Declare `var GitRev, GitVersion, GitTimestamp string` in your `package main`
|
||||
5. Include `//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver` as well
|
||||
|
||||
`tools/tools.go`:
|
||||
|
||||
@ -165,29 +104,29 @@ See `examples/basic`
|
||||
package tools
|
||||
|
||||
import (
|
||||
_ "git.rootprojects.org/root/go-gitver/v2"
|
||||
_ "git.rootprojects.org/root/go-gitver"
|
||||
)
|
||||
```
|
||||
|
||||
`main.go`:
|
||||
|
||||
```go
|
||||
//go:generate go run git.rootprojects.org/root/go-gitver/v2 --fail
|
||||
//go:generate go run git.rootprojects.org/root/go-gitver --fail
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
var (
|
||||
commit = "0000000"
|
||||
version = "0.0.0-pre0+0000000"
|
||||
date = "0000-00-00T00:00:00+0000"
|
||||
GitRev = "0000000"
|
||||
GitVersion = "v0.0.0-pre0+0000000"
|
||||
GitTimestamp = "0000-00-00T00:00:00+0000"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(commit)
|
||||
fmt.Println(version)
|
||||
fmt.Println(date)
|
||||
fmt.Println(GitRev)
|
||||
fmt.Println(GitVersion)
|
||||
fmt.Println(GitTimestamp)
|
||||
}
|
||||
```
|
||||
|
||||
@ -195,7 +134,7 @@ If you're using `go mod vendor` (which I highly recommend that you do),
|
||||
you'd modify the `go:generate` ever so slightly:
|
||||
|
||||
```go
|
||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 --fail
|
||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver --fail
|
||||
```
|
||||
|
||||
The only reason I didn't do that in the example is that I'd be included
|
||||
@ -203,7 +142,7 @@ the repository in itself and that would be... weird.
|
||||
|
||||
# Why a tools package?
|
||||
|
||||
> import "git.rootprojects.org/root/go-gitver/v2" is a program, not an importable package
|
||||
> import "git.rootprojects.org/root/go-gitver" is a program, not an importable package
|
||||
|
||||
Having a tools package with a build tag that you don't use is a nice way to add exact
|
||||
versions of a command package used for tooling to your `go.mod` with `go mod tidy`,
|
||||
@ -243,8 +182,8 @@ git rev-parse HEAD
|
||||
### cannot find package "."
|
||||
|
||||
```txt
|
||||
package git.rootprojects.org/root/go-gitver/v2: cannot find package "." in:
|
||||
/Users/me/go-example/vendor/git.rootprojects.org/root/go-gitver/v2
|
||||
package git.rootprojects.org/root/go-gitver: cannot find package "." in:
|
||||
/Users/me/go-example/vendor/git.rootprojects.org/root/go-gitver
|
||||
cmd/example/example.go:1: running "go": exit status 1
|
||||
```
|
||||
|
@ -1,4 +1,4 @@
|
||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2
|
||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver
|
||||
|
||||
package main
|
||||
|
||||
@ -6,14 +6,15 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"log"
|
||||
"os"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"git.rootprojects.org/root/go-gitver/v2/gitver"
|
||||
"git.rootprojects.org/root/go-gitver/gitver"
|
||||
)
|
||||
|
||||
var commit, version, date string
|
||||
var GitRev, GitVersion, GitTimestamp string
|
||||
var exitCode int
|
||||
var verFile = "xversion.go"
|
||||
|
||||
@ -32,9 +33,9 @@ func main() {
|
||||
pkg = args[i+1]
|
||||
args[i+1] = ""
|
||||
} else if "-V" == arg || "version" == arg || "-version" == arg || "--version" == arg {
|
||||
fmt.Println(commit)
|
||||
fmt.Println(version)
|
||||
fmt.Println(date)
|
||||
fmt.Println(GitRev)
|
||||
fmt.Println(GitVersion)
|
||||
fmt.Println(GitTimestamp)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
@ -44,13 +45,8 @@ func main() {
|
||||
|
||||
v, err := gitver.ExecAndParse()
|
||||
if nil != err {
|
||||
fmt.Fprintf(os.Stderr, "Failed to get git version: %s\n", err)
|
||||
if exitCode > 0 {
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
v = &gitver.Versions{
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
log.Fatalf("Failed to get git version: %s\n", err)
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
// Create or overwrite the go file from template
|
||||
@ -59,12 +55,12 @@ func main() {
|
||||
Package string
|
||||
Timestamp string
|
||||
Version string
|
||||
Commit string
|
||||
GitRev string
|
||||
}{
|
||||
Package: pkg,
|
||||
Timestamp: v.Timestamp.Format(time.RFC3339),
|
||||
Version: v.Version,
|
||||
Commit: v.Rev,
|
||||
GitRev: v.Rev,
|
||||
}); nil != err {
|
||||
panic(err)
|
||||
}
|
||||
@ -93,12 +89,10 @@ var versionTpl = template.Must(template.New("").Parse(`// Code generated by go g
|
||||
package {{ .Package }}
|
||||
|
||||
func init() {
|
||||
{{ if .Commit -}}
|
||||
commit = "{{ .Commit }}"
|
||||
GitRev = "{{ .GitRev }}"
|
||||
{{ if .Version -}}
|
||||
GitVersion = "{{ .Version }}"
|
||||
{{ end -}}
|
||||
{{ if .Version -}}
|
||||
version = "{{ .Version }}"
|
||||
{{ end -}}
|
||||
date = "{{ .Timestamp }}"
|
||||
GitTimestamp = "{{ .Timestamp }}"
|
||||
}
|
||||
`))
|
@ -21,14 +21,12 @@ func init() {
|
||||
gitVer = regexp.MustCompile(`^(v\d+\.\d+)\.(\d+)(-(\d+))?(-(g[0-9a-f]+))?(-(dirty))?`)
|
||||
}
|
||||
|
||||
// Versions describes the various version properties
|
||||
type Versions struct {
|
||||
Timestamp time.Time
|
||||
Version string
|
||||
Rev string
|
||||
}
|
||||
|
||||
// ExecAndParse will run git and parse the output
|
||||
func ExecAndParse() (*Versions, error) {
|
||||
desc, err := gitDesc()
|
||||
if nil != err {
|
||||
@ -60,7 +58,7 @@ func gitDesc() (string, error) {
|
||||
out, err := cmd.CombinedOutput()
|
||||
if nil != err {
|
||||
// Don't panic, just carry on
|
||||
//out = []byte("0.0.0-0-g0000000")
|
||||
//out = []byte("v0.0.0-0-g0000000")
|
||||
return "", err
|
||||
}
|
||||
return strings.TrimSpace(string(out)), nil
|
||||
@ -85,7 +83,7 @@ func gitRev() (string, error) {
|
||||
func semVer(desc string) (string, error) {
|
||||
if exactVer.MatchString(desc) {
|
||||
// v1.0.0
|
||||
return strings.TrimPrefix(desc, "v"), nil
|
||||
return desc, nil
|
||||
}
|
||||
|
||||
if !gitVer.MatchString(desc) {
|
||||
@ -124,19 +122,10 @@ func semVer(desc string) (string, error) {
|
||||
ver += vers[8]
|
||||
}
|
||||
|
||||
return strings.TrimPrefix(ver, "v"), nil
|
||||
return ver, nil
|
||||
}
|
||||
|
||||
func gitTimestamp(desc string) (time.Time, error) {
|
||||
// Other options:
|
||||
//
|
||||
// Commit Date
|
||||
// git log -1 --format=%cd --date=format:%Y-%m-%dT%H:%M:%SZ%z
|
||||
//
|
||||
// Author Date
|
||||
// git log -1 --format=%ad --date=format:%Y-%m-%dT%H:%M:%SZ%z
|
||||
//
|
||||
// I think I chose this because it would account for dirty-ness better... maybe?
|
||||
args := []string{
|
||||
"git",
|
||||
"show", desc,
|
3
vendor/git.rootprojects.org/root/go-gitver/go.mod
generated
vendored
Normal file
3
vendor/git.rootprojects.org/root/go-gitver/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module git.rootprojects.org/root/go-gitver
|
||||
|
||||
go 1.12
|
1
vendor/git.rootprojects.org/root/go-gitver/v2/.prettierrc
generated
vendored
1
vendor/git.rootprojects.org/root/go-gitver/v2/.prettierrc
generated
vendored
@ -1 +0,0 @@
|
||||
{}
|
3
vendor/git.rootprojects.org/root/go-gitver/v2/go.mod
generated
vendored
3
vendor/git.rootprojects.org/root/go-gitver/v2/go.mod
generated
vendored
@ -1,3 +0,0 @@
|
||||
module git.rootprojects.org/root/go-gitver/v2
|
||||
|
||||
go 1.12
|
2
vendor/git.rootprojects.org/root/go-gitver/v2/go.sum
generated
vendored
2
vendor/git.rootprojects.org/root/go-gitver/v2/go.sum
generated
vendored
@ -1,2 +0,0 @@
|
||||
git.rootprojects.org/root/go-gitver v1.1.3 h1:/qR9z53vY+IFhWRxLkF9cjaiWh8xRJIm6gyuW+MG81A=
|
||||
git.rootprojects.org/root/go-gitver v1.1.3/go.mod h1:Rj1v3TBhvdaSphFEqMynUYwAz/4f+wY/+syBTvRrmlI=
|
@ -3,7 +3,7 @@ package main
|
||||
// use recently generated version info as a fallback
|
||||
// for when git isn't present (i.e. go run <url>)
|
||||
func init() {
|
||||
commit = "37c1fd4b5694fd62c9f0d6ad1df47d938accbeec"
|
||||
version = "2.0.0-pre1-dirty"
|
||||
date = "2020-10-10T16:05:59-06:00"
|
||||
GitRev = "0b8c2d86df4bfe32ff4534eec84cd56909c398e9"
|
||||
GitVersion = "v1.1.1"
|
||||
GitTimestamp = "2019-06-21T00:18:13-06:00"
|
||||
}
|
1
vendor/github.com/mitchellh/go-ps/.gitignore
generated
vendored
1
vendor/github.com/mitchellh/go-ps/.gitignore
generated
vendored
@ -1 +0,0 @@
|
||||
.vagrant/
|
4
vendor/github.com/mitchellh/go-ps/.travis.yml
generated
vendored
4
vendor/github.com/mitchellh/go-ps/.travis.yml
generated
vendored
@ -1,4 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.2.1
|
21
vendor/github.com/mitchellh/go-ps/LICENSE.md
generated
vendored
21
vendor/github.com/mitchellh/go-ps/LICENSE.md
generated
vendored
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Mitchell Hashimoto
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
34
vendor/github.com/mitchellh/go-ps/README.md
generated
vendored
34
vendor/github.com/mitchellh/go-ps/README.md
generated
vendored
@ -1,34 +0,0 @@
|
||||
# Process List Library for Go
|
||||
|
||||
go-ps is a library for Go that implements OS-specific APIs to list and
|
||||
manipulate processes in a platform-safe way. The library can find and
|
||||
list processes on Linux, Mac OS X, Solaris, and Windows.
|
||||
|
||||
If you're new to Go, this library has a good amount of advanced Go educational
|
||||
value as well. It uses some advanced features of Go: build tags, accessing
|
||||
DLL methods for Windows, cgo for Darwin, etc.
|
||||
|
||||
How it works:
|
||||
|
||||
* **Darwin** uses the `sysctl` syscall to retrieve the process table.
|
||||
* **Unix** uses the procfs at `/proc` to inspect the process tree.
|
||||
* **Windows** uses the Windows API, and methods such as
|
||||
`CreateToolhelp32Snapshot` to get a point-in-time snapshot of
|
||||
the process table.
|
||||
|
||||
## Installation
|
||||
|
||||
Install using standard `go get`:
|
||||
|
||||
```
|
||||
$ go get github.com/mitchellh/go-ps
|
||||
...
|
||||
```
|
||||
|
||||
## TODO
|
||||
|
||||
Want to contribute? Here is a short TODO list of things that aren't
|
||||
implemented for this library that would be nice:
|
||||
|
||||
* FreeBSD support
|
||||
* Plan9 support
|
43
vendor/github.com/mitchellh/go-ps/Vagrantfile
generated
vendored
43
vendor/github.com/mitchellh/go-ps/Vagrantfile
generated
vendored
@ -1,43 +0,0 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
||||
VAGRANTFILE_API_VERSION = "2"
|
||||
|
||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
config.vm.box = "chef/ubuntu-12.04"
|
||||
|
||||
config.vm.provision "shell", inline: $script
|
||||
|
||||
["vmware_fusion", "vmware_workstation"].each do |p|
|
||||
config.vm.provider "p" do |v|
|
||||
v.vmx["memsize"] = "1024"
|
||||
v.vmx["numvcpus"] = "2"
|
||||
v.vmx["cpuid.coresPerSocket"] = "1"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
$script = <<SCRIPT
|
||||
SRCROOT="/opt/go"
|
||||
|
||||
# Install Go
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential mercurial
|
||||
sudo hg clone -u release https://code.google.com/p/go ${SRCROOT}
|
||||
cd ${SRCROOT}/src
|
||||
sudo ./all.bash
|
||||
|
||||
# Setup the GOPATH
|
||||
sudo mkdir -p /opt/gopath
|
||||
cat <<EOF >/tmp/gopath.sh
|
||||
export GOPATH="/opt/gopath"
|
||||
export PATH="/opt/go/bin:\$GOPATH/bin:\$PATH"
|
||||
EOF
|
||||
sudo mv /tmp/gopath.sh /etc/profile.d/gopath.sh
|
||||
sudo chmod 0755 /etc/profile.d/gopath.sh
|
||||
|
||||
# Make sure the gopath is usable by bamboo
|
||||
sudo chown -R vagrant:vagrant $SRCROOT
|
||||
sudo chown -R vagrant:vagrant /opt/gopath
|
||||
SCRIPT
|
40
vendor/github.com/mitchellh/go-ps/process.go
generated
vendored
40
vendor/github.com/mitchellh/go-ps/process.go
generated
vendored
@ -1,40 +0,0 @@
|
||||
// ps provides an API for finding and listing processes in a platform-agnostic
|
||||
// way.
|
||||
//
|
||||
// NOTE: If you're reading these docs online via GoDocs or some other system,
|
||||
// you might only see the Unix docs. This project makes heavy use of
|
||||
// platform-specific implementations. We recommend reading the source if you
|
||||
// are interested.
|
||||
package ps
|
||||
|
||||
// Process is the generic interface that is implemented on every platform
|
||||
// and provides common operations for processes.
|
||||
type Process interface {
|
||||
// Pid is the process ID for this process.
|
||||
Pid() int
|
||||
|
||||
// PPid is the parent process ID for this process.
|
||||
PPid() int
|
||||
|
||||
// Executable name running this process. This is not a path to the
|
||||
// executable.
|
||||
Executable() string
|
||||
}
|
||||
|
||||
// Processes returns all processes.
|
||||
//
|
||||
// This of course will be a point-in-time snapshot of when this method was
|
||||
// called. Some operating systems don't provide snapshot capability of the
|
||||
// process table, in which case the process table returned might contain
|
||||
// ephemeral entities that happened to be running when this was called.
|
||||
func Processes() ([]Process, error) {
|
||||
return processes()
|
||||
}
|
||||
|
||||
// FindProcess looks up a single process by pid.
|
||||
//
|
||||
// Process will be nil and error will be nil if a matching process is
|
||||
// not found.
|
||||
func FindProcess(pid int) (Process, error) {
|
||||
return findProcess(pid)
|
||||
}
|
138
vendor/github.com/mitchellh/go-ps/process_darwin.go
generated
vendored
138
vendor/github.com/mitchellh/go-ps/process_darwin.go
generated
vendored
@ -1,138 +0,0 @@
|
||||
// +build darwin
|
||||
|
||||
package ps
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type DarwinProcess struct {
|
||||
pid int
|
||||
ppid int
|
||||
binary string
|
||||
}
|
||||
|
||||
func (p *DarwinProcess) Pid() int {
|
||||
return p.pid
|
||||
}
|
||||
|
||||
func (p *DarwinProcess) PPid() int {
|
||||
return p.ppid
|
||||
}
|
||||
|
||||
func (p *DarwinProcess) Executable() string {
|
||||
return p.binary
|
||||
}
|
||||
|
||||
func findProcess(pid int) (Process, error) {
|
||||
ps, err := processes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, p := range ps {
|
||||
if p.Pid() == pid {
|
||||
return p, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func processes() ([]Process, error) {
|
||||
buf, err := darwinSyscall()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
procs := make([]*kinfoProc, 0, 50)
|
||||
k := 0
|
||||
for i := _KINFO_STRUCT_SIZE; i < buf.Len(); i += _KINFO_STRUCT_SIZE {
|
||||
proc := &kinfoProc{}
|
||||
err = binary.Read(bytes.NewBuffer(buf.Bytes()[k:i]), binary.LittleEndian, proc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
k = i
|
||||
procs = append(procs, proc)
|
||||
}
|
||||
|
||||
darwinProcs := make([]Process, len(procs))
|
||||
for i, p := range procs {
|
||||
darwinProcs[i] = &DarwinProcess{
|
||||
pid: int(p.Pid),
|
||||
ppid: int(p.PPid),
|
||||
binary: darwinCstring(p.Comm),
|
||||
}
|
||||
}
|
||||
|
||||
return darwinProcs, nil
|
||||
}
|
||||
|
||||
func darwinCstring(s [16]byte) string {
|
||||
i := 0
|
||||
for _, b := range s {
|
||||
if b != 0 {
|
||||
i++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return string(s[:i])
|
||||
}
|
||||
|
||||
func darwinSyscall() (*bytes.Buffer, error) {
|
||||
mib := [4]int32{_CTRL_KERN, _KERN_PROC, _KERN_PROC_ALL, 0}
|
||||
size := uintptr(0)
|
||||
|
||||
_, _, errno := syscall.Syscall6(
|
||||
syscall.SYS___SYSCTL,
|
||||
uintptr(unsafe.Pointer(&mib[0])),
|
||||
4,
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&size)),
|
||||
0,
|
||||
0)
|
||||
|
||||
if errno != 0 {
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
bs := make([]byte, size)
|
||||
_, _, errno = syscall.Syscall6(
|
||||
syscall.SYS___SYSCTL,
|
||||
uintptr(unsafe.Pointer(&mib[0])),
|
||||
4,
|
||||
uintptr(unsafe.Pointer(&bs[0])),
|
||||
uintptr(unsafe.Pointer(&size)),
|
||||
0,
|
||||
0)
|
||||
|
||||
if errno != 0 {
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
return bytes.NewBuffer(bs[0:size]), nil
|
||||
}
|
||||
|
||||
const (
|
||||
_CTRL_KERN = 1
|
||||
_KERN_PROC = 14
|
||||
_KERN_PROC_ALL = 0
|
||||
_KINFO_STRUCT_SIZE = 648
|
||||
)
|
||||
|
||||
type kinfoProc struct {
|
||||
_ [40]byte
|
||||
Pid int32
|
||||
_ [199]byte
|
||||
Comm [16]byte
|
||||
_ [301]byte
|
||||
PPid int32
|
||||
_ [84]byte
|
||||
}
|
260
vendor/github.com/mitchellh/go-ps/process_freebsd.go
generated
vendored
260
vendor/github.com/mitchellh/go-ps/process_freebsd.go
generated
vendored
@ -1,260 +0,0 @@
|
||||
// +build freebsd,amd64
|
||||
|
||||
package ps
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// copied from sys/sysctl.h
|
||||
const (
|
||||
CTL_KERN = 1 // "high kernel": proc, limits
|
||||
KERN_PROC = 14 // struct: process entries
|
||||
KERN_PROC_PID = 1 // by process id
|
||||
KERN_PROC_PROC = 8 // only return procs
|
||||
KERN_PROC_PATHNAME = 12 // path to executable
|
||||
)
|
||||
|
||||
// copied from sys/user.h
|
||||
type Kinfo_proc struct {
|
||||
Ki_structsize int32
|
||||
Ki_layout int32
|
||||
Ki_args int64
|
||||
Ki_paddr int64
|
||||
Ki_addr int64
|
||||
Ki_tracep int64
|
||||
Ki_textvp int64
|
||||
Ki_fd int64
|
||||
Ki_vmspace int64
|
||||
Ki_wchan int64
|
||||
Ki_pid int32
|
||||
Ki_ppid int32
|
||||
Ki_pgid int32
|
||||
Ki_tpgid int32
|
||||
Ki_sid int32
|
||||
Ki_tsid int32
|
||||
Ki_jobc [2]byte
|
||||
Ki_spare_short1 [2]byte
|
||||
Ki_tdev int32
|
||||
Ki_siglist [16]byte
|
||||
Ki_sigmask [16]byte
|
||||
Ki_sigignore [16]byte
|
||||
Ki_sigcatch [16]byte
|
||||
Ki_uid int32
|
||||
Ki_ruid int32
|
||||
Ki_svuid int32
|
||||
Ki_rgid int32
|
||||
Ki_svgid int32
|
||||
Ki_ngroups [2]byte
|
||||
Ki_spare_short2 [2]byte
|
||||
Ki_groups [64]byte
|
||||
Ki_size int64
|
||||
Ki_rssize int64
|
||||
Ki_swrss int64
|
||||
Ki_tsize int64
|
||||
Ki_dsize int64
|
||||
Ki_ssize int64
|
||||
Ki_xstat [2]byte
|
||||
Ki_acflag [2]byte
|
||||
Ki_pctcpu int32
|
||||
Ki_estcpu int32
|
||||
Ki_slptime int32
|
||||
Ki_swtime int32
|
||||
Ki_cow int32
|
||||
Ki_runtime int64
|
||||
Ki_start [16]byte
|
||||
Ki_childtime [16]byte
|
||||
Ki_flag int64
|
||||
Ki_kiflag int64
|
||||
Ki_traceflag int32
|
||||
Ki_stat [1]byte
|
||||
Ki_nice [1]byte
|
||||
Ki_lock [1]byte
|
||||
Ki_rqindex [1]byte
|
||||
Ki_oncpu [1]byte
|
||||
Ki_lastcpu [1]byte
|
||||
Ki_ocomm [17]byte
|
||||
Ki_wmesg [9]byte
|
||||
Ki_login [18]byte
|
||||
Ki_lockname [9]byte
|
||||
Ki_comm [20]byte
|
||||
Ki_emul [17]byte
|
||||
Ki_sparestrings [68]byte
|
||||
Ki_spareints [36]byte
|
||||
Ki_cr_flags int32
|
||||
Ki_jid int32
|
||||
Ki_numthreads int32
|
||||
Ki_tid int32
|
||||
Ki_pri int32
|
||||
Ki_rusage [144]byte
|
||||
Ki_rusage_ch [144]byte
|
||||
Ki_pcb int64
|
||||
Ki_kstack int64
|
||||
Ki_udata int64
|
||||
Ki_tdaddr int64
|
||||
Ki_spareptrs [48]byte
|
||||
Ki_spareint64s [96]byte
|
||||
Ki_sflag int64
|
||||
Ki_tdflags int64
|
||||
}
|
||||
|
||||
// UnixProcess is an implementation of Process that contains Unix-specific
|
||||
// fields and information.
|
||||
type UnixProcess struct {
|
||||
pid int
|
||||
ppid int
|
||||
state rune
|
||||
pgrp int
|
||||
sid int
|
||||
|
||||
binary string
|
||||
}
|
||||
|
||||
func (p *UnixProcess) Pid() int {
|
||||
return p.pid
|
||||
}
|
||||
|
||||
func (p *UnixProcess) PPid() int {
|
||||
return p.ppid
|
||||
}
|
||||
|
||||
func (p *UnixProcess) Executable() string {
|
||||
return p.binary
|
||||
}
|
||||
|
||||
// Refresh reloads all the data associated with this process.
|
||||
func (p *UnixProcess) Refresh() error {
|
||||
|
||||
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, int32(p.pid)}
|
||||
|
||||
buf, length, err := call_syscall(mib)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
proc_k := Kinfo_proc{}
|
||||
if length != uint64(unsafe.Sizeof(proc_k)) {
|
||||
return err
|
||||
}
|
||||
|
||||
k, err := parse_kinfo_proc(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.ppid, p.pgrp, p.sid, p.binary = copy_params(&k)
|
||||
return nil
|
||||
}
|
||||
|
||||
func copy_params(k *Kinfo_proc) (int, int, int, string) {
|
||||
n := -1
|
||||
for i, b := range k.Ki_comm {
|
||||
if b == 0 {
|
||||
break
|
||||
}
|
||||
n = i + 1
|
||||
}
|
||||
comm := string(k.Ki_comm[:n])
|
||||
|
||||
return int(k.Ki_ppid), int(k.Ki_pgid), int(k.Ki_sid), comm
|
||||
}
|
||||
|
||||
func findProcess(pid int) (Process, error) {
|
||||
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, int32(pid)}
|
||||
|
||||
_, _, err := call_syscall(mib)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newUnixProcess(pid)
|
||||
}
|
||||
|
||||
func processes() ([]Process, error) {
|
||||
results := make([]Process, 0, 50)
|
||||
|
||||
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0}
|
||||
buf, length, err := call_syscall(mib)
|
||||
if err != nil {
|
||||
return results, err
|
||||
}
|
||||
|
||||
// get kinfo_proc size
|
||||
k := Kinfo_proc{}
|
||||
procinfo_len := int(unsafe.Sizeof(k))
|
||||
count := int(length / uint64(procinfo_len))
|
||||
|
||||
// parse buf to procs
|
||||
for i := 0; i < count; i++ {
|
||||
b := buf[i*procinfo_len : i*procinfo_len+procinfo_len]
|
||||
k, err := parse_kinfo_proc(b)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
p, err := newUnixProcess(int(k.Ki_pid))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
p.ppid, p.pgrp, p.sid, p.binary = copy_params(&k)
|
||||
|
||||
results = append(results, p)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func parse_kinfo_proc(buf []byte) (Kinfo_proc, error) {
|
||||
var k Kinfo_proc
|
||||
br := bytes.NewReader(buf)
|
||||
err := binary.Read(br, binary.LittleEndian, &k)
|
||||
if err != nil {
|
||||
return k, err
|
||||
}
|
||||
|
||||
return k, nil
|
||||
}
|
||||
|
||||
func call_syscall(mib []int32) ([]byte, uint64, error) {
|
||||
miblen := uint64(len(mib))
|
||||
|
||||
// get required buffer size
|
||||
length := uint64(0)
|
||||
_, _, err := syscall.RawSyscall6(
|
||||
syscall.SYS___SYSCTL,
|
||||
uintptr(unsafe.Pointer(&mib[0])),
|
||||
uintptr(miblen),
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&length)),
|
||||
0,
|
||||
0)
|
||||
if err != 0 {
|
||||
b := make([]byte, 0)
|
||||
return b, length, err
|
||||
}
|
||||
if length == 0 {
|
||||
b := make([]byte, 0)
|
||||
return b, length, err
|
||||
}
|
||||
// get proc info itself
|
||||
buf := make([]byte, length)
|
||||
_, _, err = syscall.RawSyscall6(
|
||||
syscall.SYS___SYSCTL,
|
||||
uintptr(unsafe.Pointer(&mib[0])),
|
||||
uintptr(miblen),
|
||||
uintptr(unsafe.Pointer(&buf[0])),
|
||||
uintptr(unsafe.Pointer(&length)),
|
||||
0,
|
||||
0)
|
||||
if err != 0 {
|
||||
return buf, length, err
|
||||
}
|
||||
|
||||
return buf, length, nil
|
||||
}
|
||||
|
||||
func newUnixProcess(pid int) (*UnixProcess, error) {
|
||||
p := &UnixProcess{pid: pid}
|
||||
return p, p.Refresh()
|
||||
}
|
35
vendor/github.com/mitchellh/go-ps/process_linux.go
generated
vendored
35
vendor/github.com/mitchellh/go-ps/process_linux.go
generated
vendored
@ -1,35 +0,0 @@
|
||||
// +build linux
|
||||
|
||||
package ps
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Refresh reloads all the data associated with this process.
|
||||
func (p *UnixProcess) Refresh() error {
|
||||
statPath := fmt.Sprintf("/proc/%d/stat", p.pid)
|
||||
dataBytes, err := ioutil.ReadFile(statPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// First, parse out the image name
|
||||
data := string(dataBytes)
|
||||
binStart := strings.IndexRune(data, '(') + 1
|
||||
binEnd := strings.IndexRune(data[binStart:], ')')
|
||||
p.binary = data[binStart : binStart+binEnd]
|
||||
|
||||
// Move past the image name and start parsing the rest
|
||||
data = data[binStart+binEnd+2:]
|
||||
_, err = fmt.Sscanf(data,
|
||||
"%c %d %d %d",
|
||||
&p.state,
|
||||
&p.ppid,
|
||||
&p.pgrp,
|
||||
&p.sid)
|
||||
|
||||
return err
|
||||
}
|
96
vendor/github.com/mitchellh/go-ps/process_solaris.go
generated
vendored
96
vendor/github.com/mitchellh/go-ps/process_solaris.go
generated
vendored
@ -1,96 +0,0 @@
|
||||
// +build solaris
|
||||
|
||||
package ps
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type ushort_t uint16
|
||||
|
||||
type id_t int32
|
||||
type pid_t int32
|
||||
type uid_t int32
|
||||
type gid_t int32
|
||||
|
||||
type dev_t uint64
|
||||
type size_t uint64
|
||||
type uintptr_t uint64
|
||||
|
||||
type timestruc_t [16]byte
|
||||
|
||||
// This is copy from /usr/include/sys/procfs.h
|
||||
type psinfo_t struct {
|
||||
Pr_flag int32 /* process flags (DEPRECATED; do not use) */
|
||||
Pr_nlwp int32 /* number of active lwps in the process */
|
||||
Pr_pid pid_t /* unique process id */
|
||||
Pr_ppid pid_t /* process id of parent */
|
||||
Pr_pgid pid_t /* pid of process group leader */
|
||||
Pr_sid pid_t /* session id */
|
||||
Pr_uid uid_t /* real user id */
|
||||
Pr_euid uid_t /* effective user id */
|
||||
Pr_gid gid_t /* real group id */
|
||||
Pr_egid gid_t /* effective group id */
|
||||
Pr_addr uintptr_t /* address of process */
|
||||
Pr_size size_t /* size of process image in Kbytes */
|
||||
Pr_rssize size_t /* resident set size in Kbytes */
|
||||
Pr_pad1 size_t
|
||||
Pr_ttydev dev_t /* controlling tty device (or PRNODEV) */
|
||||
|
||||
// Guess this following 2 ushort_t values require a padding to properly
|
||||
// align to the 64bit mark.
|
||||
Pr_pctcpu ushort_t /* % of recent cpu time used by all lwps */
|
||||
Pr_pctmem ushort_t /* % of system memory used by process */
|
||||
Pr_pad64bit [4]byte
|
||||
|
||||
Pr_start timestruc_t /* process start time, from the epoch */
|
||||
Pr_time timestruc_t /* usr+sys cpu time for this process */
|
||||
Pr_ctime timestruc_t /* usr+sys cpu time for reaped children */
|
||||
Pr_fname [16]byte /* name of execed file */
|
||||
Pr_psargs [80]byte /* initial characters of arg list */
|
||||
Pr_wstat int32 /* if zombie, the wait() status */
|
||||
Pr_argc int32 /* initial argument count */
|
||||
Pr_argv uintptr_t /* address of initial argument vector */
|
||||
Pr_envp uintptr_t /* address of initial environment vector */
|
||||
Pr_dmodel [1]byte /* data model of the process */
|
||||
Pr_pad2 [3]byte
|
||||
Pr_taskid id_t /* task id */
|
||||
Pr_projid id_t /* project id */
|
||||
Pr_nzomb int32 /* number of zombie lwps in the process */
|
||||
Pr_poolid id_t /* pool id */
|
||||
Pr_zoneid id_t /* zone id */
|
||||
Pr_contract id_t /* process contract */
|
||||
Pr_filler int32 /* reserved for future use */
|
||||
Pr_lwp [128]byte /* information for representative lwp */
|
||||
}
|
||||
|
||||
func (p *UnixProcess) Refresh() error {
|
||||
var psinfo psinfo_t
|
||||
|
||||
path := fmt.Sprintf("/proc/%d/psinfo", p.pid)
|
||||
fh, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fh.Close()
|
||||
|
||||
err = binary.Read(fh, binary.LittleEndian, &psinfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.ppid = int(psinfo.Pr_ppid)
|
||||
p.binary = toString(psinfo.Pr_fname[:], 16)
|
||||
return nil
|
||||
}
|
||||
|
||||
func toString(array []byte, len int) string {
|
||||
for i := 0; i < len; i++ {
|
||||
if array[i] == 0 {
|
||||
return string(array[:i])
|
||||
}
|
||||
}
|
||||
return string(array[:])
|
||||
}
|
101
vendor/github.com/mitchellh/go-ps/process_unix.go
generated
vendored
101
vendor/github.com/mitchellh/go-ps/process_unix.go
generated
vendored
@ -1,101 +0,0 @@
|
||||
// +build linux solaris
|
||||
|
||||
package ps
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// UnixProcess is an implementation of Process that contains Unix-specific
|
||||
// fields and information.
|
||||
type UnixProcess struct {
|
||||
pid int
|
||||
ppid int
|
||||
state rune
|
||||
pgrp int
|
||||
sid int
|
||||
|
||||
binary string
|
||||
}
|
||||
|
||||
func (p *UnixProcess) Pid() int {
|
||||
return p.pid
|
||||
}
|
||||
|
||||
func (p *UnixProcess) PPid() int {
|
||||
return p.ppid
|
||||
}
|
||||
|
||||
func (p *UnixProcess) Executable() string {
|
||||
return p.binary
|
||||
}
|
||||
|
||||
func findProcess(pid int) (Process, error) {
|
||||
dir := fmt.Sprintf("/proc/%d", pid)
|
||||
_, err := os.Stat(dir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newUnixProcess(pid)
|
||||
}
|
||||
|
||||
func processes() ([]Process, error) {
|
||||
d, err := os.Open("/proc")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer d.Close()
|
||||
|
||||
results := make([]Process, 0, 50)
|
||||
for {
|
||||
fis, err := d.Readdir(10)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, fi := range fis {
|
||||
// We only care about directories, since all pids are dirs
|
||||
if !fi.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
// We only care if the name starts with a numeric
|
||||
name := fi.Name()
|
||||
if name[0] < '0' || name[0] > '9' {
|
||||
continue
|
||||
}
|
||||
|
||||
// From this point forward, any errors we just ignore, because
|
||||
// it might simply be that the process doesn't exist anymore.
|
||||
pid, err := strconv.ParseInt(name, 10, 0)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
p, err := newUnixProcess(int(pid))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
results = append(results, p)
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func newUnixProcess(pid int) (*UnixProcess, error) {
|
||||
p := &UnixProcess{pid: pid}
|
||||
return p, p.Refresh()
|
||||
}
|
119
vendor/github.com/mitchellh/go-ps/process_windows.go
generated
vendored
119
vendor/github.com/mitchellh/go-ps/process_windows.go
generated
vendored
@ -1,119 +0,0 @@
|
||||
// +build windows
|
||||
|
||||
package ps
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Windows API functions
|
||||
var (
|
||||
modKernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
procCloseHandle = modKernel32.NewProc("CloseHandle")
|
||||
procCreateToolhelp32Snapshot = modKernel32.NewProc("CreateToolhelp32Snapshot")
|
||||
procProcess32First = modKernel32.NewProc("Process32FirstW")
|
||||
procProcess32Next = modKernel32.NewProc("Process32NextW")
|
||||
)
|
||||
|
||||
// Some constants from the Windows API
|
||||
const (
|
||||
ERROR_NO_MORE_FILES = 0x12
|
||||
MAX_PATH = 260
|
||||
)
|
||||
|
||||
// PROCESSENTRY32 is the Windows API structure that contains a process's
|
||||
// information.
|
||||
type PROCESSENTRY32 struct {
|
||||
Size uint32
|
||||
CntUsage uint32
|
||||
ProcessID uint32
|
||||
DefaultHeapID uintptr
|
||||
ModuleID uint32
|
||||
CntThreads uint32
|
||||
ParentProcessID uint32
|
||||
PriorityClassBase int32
|
||||
Flags uint32
|
||||
ExeFile [MAX_PATH]uint16
|
||||
}
|
||||
|
||||
// WindowsProcess is an implementation of Process for Windows.
|
||||
type WindowsProcess struct {
|
||||
pid int
|
||||
ppid int
|
||||
exe string
|
||||
}
|
||||
|
||||
func (p *WindowsProcess) Pid() int {
|
||||
return p.pid
|
||||
}
|
||||
|
||||
func (p *WindowsProcess) PPid() int {
|
||||
return p.ppid
|
||||
}
|
||||
|
||||
func (p *WindowsProcess) Executable() string {
|
||||
return p.exe
|
||||
}
|
||||
|
||||
func newWindowsProcess(e *PROCESSENTRY32) *WindowsProcess {
|
||||
// Find when the string ends for decoding
|
||||
end := 0
|
||||
for {
|
||||
if e.ExeFile[end] == 0 {
|
||||
break
|
||||
}
|
||||
end++
|
||||
}
|
||||
|
||||
return &WindowsProcess{
|
||||
pid: int(e.ProcessID),
|
||||
ppid: int(e.ParentProcessID),
|
||||
exe: syscall.UTF16ToString(e.ExeFile[:end]),
|
||||
}
|
||||
}
|
||||
|
||||
func findProcess(pid int) (Process, error) {
|
||||
ps, err := processes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, p := range ps {
|
||||
if p.Pid() == pid {
|
||||
return p, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func processes() ([]Process, error) {
|
||||
handle, _, _ := procCreateToolhelp32Snapshot.Call(
|
||||
0x00000002,
|
||||
0)
|
||||
if handle < 0 {
|
||||
return nil, syscall.GetLastError()
|
||||
}
|
||||
defer procCloseHandle.Call(handle)
|
||||
|
||||
var entry PROCESSENTRY32
|
||||
entry.Size = uint32(unsafe.Sizeof(entry))
|
||||
ret, _, _ := procProcess32First.Call(handle, uintptr(unsafe.Pointer(&entry)))
|
||||
if ret == 0 {
|
||||
return nil, fmt.Errorf("Error retrieving process info.")
|
||||
}
|
||||
|
||||
results := make([]Process, 0, 50)
|
||||
for {
|
||||
results = append(results, newWindowsProcess(&entry))
|
||||
|
||||
ret, _, _ := procProcess32Next.Call(handle, uintptr(unsafe.Pointer(&entry)))
|
||||
if ret == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
39
vendor/github.com/nsf/termbox-go/syscalls.go
generated
vendored
Normal file
39
vendor/github.com/nsf/termbox-go/syscalls.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// +build ignore
|
||||
|
||||
package termbox
|
||||
|
||||
/*
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type syscall_Termios C.struct_termios
|
||||
|
||||
const (
|
||||
syscall_IGNBRK = C.IGNBRK
|
||||
syscall_BRKINT = C.BRKINT
|
||||
syscall_PARMRK = C.PARMRK
|
||||
syscall_ISTRIP = C.ISTRIP
|
||||
syscall_INLCR = C.INLCR
|
||||
syscall_IGNCR = C.IGNCR
|
||||
syscall_ICRNL = C.ICRNL
|
||||
syscall_IXON = C.IXON
|
||||
syscall_OPOST = C.OPOST
|
||||
syscall_ECHO = C.ECHO
|
||||
syscall_ECHONL = C.ECHONL
|
||||
syscall_ICANON = C.ICANON
|
||||
syscall_ISIG = C.ISIG
|
||||
syscall_IEXTEN = C.IEXTEN
|
||||
syscall_CSIZE = C.CSIZE
|
||||
syscall_PARENB = C.PARENB
|
||||
syscall_CS8 = C.CS8
|
||||
syscall_VMIN = C.VMIN
|
||||
syscall_VTIME = C.VTIME
|
||||
|
||||
// on darwin change these to (on *bsd too?):
|
||||
// C.TIOCGETA
|
||||
// C.TIOCSETA
|
||||
syscall_TCGETS = C.TCGETS
|
||||
syscall_TCSETS = C.TCSETS
|
||||
)
|
94
vendor/golang.org/x/net/webdav/litmus_test_server.go
generated
vendored
Normal file
94
vendor/golang.org/x/net/webdav/litmus_test_server.go
generated
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program is a server for the WebDAV 'litmus' compliance test at
|
||||
http://www.webdav.org/neon/litmus/
|
||||
To run the test:
|
||||
|
||||
go run litmus_test_server.go
|
||||
|
||||
and separately, from the downloaded litmus-xxx directory:
|
||||
|
||||
make URL=http://localhost:9999/ check
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"golang.org/x/net/webdav"
|
||||
)
|
||||
|
||||
var port = flag.Int("port", 9999, "server port")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
log.SetFlags(0)
|
||||
h := &webdav.Handler{
|
||||
FileSystem: webdav.NewMemFS(),
|
||||
LockSystem: webdav.NewMemLS(),
|
||||
Logger: func(r *http.Request, err error) {
|
||||
litmus := r.Header.Get("X-Litmus")
|
||||
if len(litmus) > 19 {
|
||||
litmus = litmus[:16] + "..."
|
||||
}
|
||||
|
||||
switch r.Method {
|
||||
case "COPY", "MOVE":
|
||||
dst := ""
|
||||
if u, err := url.Parse(r.Header.Get("Destination")); err == nil {
|
||||
dst = u.Path
|
||||
}
|
||||
o := r.Header.Get("Overwrite")
|
||||
log.Printf("%-20s%-10s%-30s%-30so=%-2s%v", litmus, r.Method, r.URL.Path, dst, o, err)
|
||||
default:
|
||||
log.Printf("%-20s%-10s%-30s%v", litmus, r.Method, r.URL.Path, err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// The next line would normally be:
|
||||
// http.Handle("/", h)
|
||||
// but we wrap that HTTP handler h to cater for a special case.
|
||||
//
|
||||
// The propfind_invalid2 litmus test case expects an empty namespace prefix
|
||||
// declaration to be an error. The FAQ in the webdav litmus test says:
|
||||
//
|
||||
// "What does the "propfind_invalid2" test check for?...
|
||||
//
|
||||
// If a request was sent with an XML body which included an empty namespace
|
||||
// prefix declaration (xmlns:ns1=""), then the server must reject that with
|
||||
// a "400 Bad Request" response, as it is invalid according to the XML
|
||||
// Namespace specification."
|
||||
//
|
||||
// On the other hand, the Go standard library's encoding/xml package
|
||||
// accepts an empty xmlns namespace, as per the discussion at
|
||||
// https://github.com/golang/go/issues/8068
|
||||
//
|
||||
// Empty namespaces seem disallowed in the second (2006) edition of the XML
|
||||
// standard, but allowed in a later edition. The grammar differs between
|
||||
// http://www.w3.org/TR/2006/REC-xml-names-20060816/#ns-decl and
|
||||
// http://www.w3.org/TR/REC-xml-names/#dt-prefix
|
||||
//
|
||||
// Thus, we assume that the propfind_invalid2 test is obsolete, and
|
||||
// hard-code the 400 Bad Request response that the test expects.
|
||||
http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("X-Litmus") == "props: 3 (propfind_invalid2)" {
|
||||
http.Error(w, "400 Bad Request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
h.ServeHTTP(w, r)
|
||||
}))
|
||||
|
||||
addr := fmt.Sprintf(":%d", *port)
|
||||
log.Printf("Serving %v", addr)
|
||||
log.Fatal(http.ListenAndServe(addr, nil))
|
||||
}
|
61
vendor/golang.org/x/sys/unix/mkasm_darwin.go
generated
vendored
Normal file
61
vendor/golang.org/x/sys/unix/mkasm_darwin.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go.
|
||||
//This program must be run after mksyscall.go.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
in1, err := ioutil.ReadFile("syscall_darwin.go")
|
||||
if err != nil {
|
||||
log.Fatalf("can't open syscall_darwin.go: %s", err)
|
||||
}
|
||||
arch := os.Args[1]
|
||||
in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch))
|
||||
if err != nil {
|
||||
log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err)
|
||||
}
|
||||
in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch))
|
||||
if err != nil {
|
||||
log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err)
|
||||
}
|
||||
in := string(in1) + string(in2) + string(in3)
|
||||
|
||||
trampolines := map[string]bool{}
|
||||
|
||||
var out bytes.Buffer
|
||||
|
||||
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
|
||||
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
|
||||
fmt.Fprintf(&out, "\n")
|
||||
fmt.Fprintf(&out, "// +build go1.12\n")
|
||||
fmt.Fprintf(&out, "\n")
|
||||
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
|
||||
for _, line := range strings.Split(in, "\n") {
|
||||
if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") {
|
||||
continue
|
||||
}
|
||||
fn := line[5 : len(line)-13]
|
||||
if !trampolines[fn] {
|
||||
trampolines[fn] = true
|
||||
fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn)
|
||||
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
|
||||
}
|
||||
}
|
||||
err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644)
|
||||
if err != nil {
|
||||
log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err)
|
||||
}
|
||||
}
|
122
vendor/golang.org/x/sys/unix/mkpost.go
generated
vendored
Normal file
122
vendor/golang.org/x/sys/unix/mkpost.go
generated
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// mkpost processes the output of cgo -godefs to
|
||||
// modify the generated types. It is used to clean up
|
||||
// the sys API in an architecture specific manner.
|
||||
//
|
||||
// mkpost is run after cgo -godefs; see README.md.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
||||
goos := os.Getenv("GOOS")
|
||||
goarch := os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
// Check that we are using the Docker-based build system if we should be.
|
||||
if goos == "linux" {
|
||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
|
||||
os.Stderr.WriteString("In the Docker-based build system, mkpost should not be called directly.\n")
|
||||
os.Stderr.WriteString("See README.md\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if goos == "aix" {
|
||||
// Replace type of Atim, Mtim and Ctim by Timespec in Stat_t
|
||||
// to avoid having both StTimespec and Timespec.
|
||||
sttimespec := regexp.MustCompile(`_Ctype_struct_st_timespec`)
|
||||
b = sttimespec.ReplaceAll(b, []byte("Timespec"))
|
||||
}
|
||||
|
||||
// Intentionally export __val fields in Fsid and Sigset_t
|
||||
valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__(bits|val)(\s+\S+\s+)}`)
|
||||
b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$4}"))
|
||||
|
||||
// Intentionally export __fds_bits field in FdSet
|
||||
fdSetRegex := regexp.MustCompile(`type (FdSet) struct {(\s+)X__fds_bits(\s+\S+\s+)}`)
|
||||
b = fdSetRegex.ReplaceAll(b, []byte("type $1 struct {${2}Bits$3}"))
|
||||
|
||||
// If we have empty Ptrace structs, we should delete them. Only s390x emits
|
||||
// nonempty Ptrace structs.
|
||||
ptraceRexexp := regexp.MustCompile(`type Ptrace((Psw|Fpregs|Per) struct {\s*})`)
|
||||
b = ptraceRexexp.ReplaceAll(b, nil)
|
||||
|
||||
// Replace the control_regs union with a blank identifier for now.
|
||||
controlRegsRegex := regexp.MustCompile(`(Control_regs)\s+\[0\]uint64`)
|
||||
b = controlRegsRegex.ReplaceAll(b, []byte("_ [0]uint64"))
|
||||
|
||||
// Remove fields that are added by glibc
|
||||
// Note that this is unstable as the identifers are private.
|
||||
removeFieldsRegex := regexp.MustCompile(`X__glibc\S*`)
|
||||
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
|
||||
// Convert [65]int8 to [65]byte in Utsname members to simplify
|
||||
// conversion to string; see golang.org/issue/20753
|
||||
convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`)
|
||||
b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte"))
|
||||
|
||||
// Convert [1024]int8 to [1024]byte in Ptmget members
|
||||
convertPtmget := regexp.MustCompile(`([SC]n)(\s+)\[(\d+)\]u?int8`)
|
||||
b = convertPtmget.ReplaceAll(b, []byte("$1[$3]byte"))
|
||||
|
||||
// Remove spare fields (e.g. in Statx_t)
|
||||
spareFieldsRegex := regexp.MustCompile(`X__spare\S*`)
|
||||
b = spareFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
|
||||
// Remove cgo padding fields
|
||||
removePaddingFieldsRegex := regexp.MustCompile(`Pad_cgo_\d+`)
|
||||
b = removePaddingFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
|
||||
// Remove padding, hidden, or unused fields
|
||||
removeFieldsRegex = regexp.MustCompile(`\b(X_\S+|Padding)`)
|
||||
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
|
||||
// Remove the first line of warning from cgo
|
||||
b = b[bytes.IndexByte(b, '\n')+1:]
|
||||
// Modify the command in the header to include:
|
||||
// mkpost, our own warning, and a build tag.
|
||||
replacement := fmt.Sprintf(`$1 | go run mkpost.go
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s,%s`, goarch, goos)
|
||||
cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`)
|
||||
b = cgoCommandRegex.ReplaceAll(b, []byte(replacement))
|
||||
|
||||
// Rename Stat_t time fields
|
||||
if goos == "freebsd" && goarch == "386" {
|
||||
// Hide Stat_t.[AMCB]tim_ext fields
|
||||
renameStatTimeExtFieldsRegex := regexp.MustCompile(`[AMCB]tim_ext`)
|
||||
b = renameStatTimeExtFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
}
|
||||
renameStatTimeFieldsRegex := regexp.MustCompile(`([AMCB])(?:irth)?time?(?:spec)?\s+(Timespec|StTimespec)`)
|
||||
b = renameStatTimeFieldsRegex.ReplaceAll(b, []byte("${1}tim ${2}"))
|
||||
|
||||
// gofmt
|
||||
b, err = format.Source(b)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
os.Stdout.Write(b)
|
||||
}
|
407
vendor/golang.org/x/sys/unix/mksyscall.go
generated
vendored
Normal file
407
vendor/golang.org/x/sys/unix/mksyscall.go
generated
vendored
Normal file
@ -0,0 +1,407 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_darwin.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named errno.
|
||||
|
||||
A line beginning with //sysnb is like //sys, except that the
|
||||
goroutine will not be suspended during the execution of the system
|
||||
call. This must only be used for system calls which can never
|
||||
block, as otherwise the system call could cause all goroutines to
|
||||
hang.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
plan9 = flag.Bool("plan9", false, "plan9")
|
||||
openbsd = flag.Bool("openbsd", false, "openbsd")
|
||||
netbsd = flag.Bool("netbsd", false, "netbsd")
|
||||
dragonfly = flag.Bool("dragonfly", false, "dragonfly")
|
||||
arm = flag.Bool("arm", false, "arm") // 64-bit value should use (even, odd)-pair
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
filename = flag.String("output", "", "output file name (standard output if omitted)")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
||||
goos := os.Getenv("GOOS")
|
||||
if goos == "" {
|
||||
fmt.Fprintln(os.Stderr, "GOOS not defined in environment")
|
||||
os.Exit(1)
|
||||
}
|
||||
goarch := os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
|
||||
// Check that we are using the Docker-based build system if we should
|
||||
if goos == "linux" {
|
||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
|
||||
fmt.Fprintf(os.Stderr, "In the Docker-based build system, mksyscall should not be called directly.\n")
|
||||
fmt.Fprintf(os.Stderr, "See README.md\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
libc := false
|
||||
if goos == "darwin" && strings.Contains(buildTags(), ",go1.12") {
|
||||
libc = true
|
||||
}
|
||||
trampolines := map[string]bool{}
|
||||
|
||||
text := ""
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, errno error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, sysname := f[2], f[3], f[4], f[5]
|
||||
|
||||
// ClockGettime doesn't have a syscall number on Darwin, only generate libc wrappers.
|
||||
if goos == "darwin" && !libc && funct == "ClockGettime" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
|
||||
// Go function header.
|
||||
outDecl := ""
|
||||
if len(out) > 0 {
|
||||
outDecl = fmt.Sprintf(" (%s)", strings.Join(out, ", "))
|
||||
}
|
||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outDecl)
|
||||
|
||||
// Check if err return available
|
||||
errvar := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare arguments to Syscall.
|
||||
var args []string
|
||||
n := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))")
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n)
|
||||
text += fmt.Sprintf("\t_p%d, %s = BytePtrFromString(%s)\n", n, errvar, p.Name)
|
||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n)
|
||||
text += fmt.Sprintf("\t_p%d, _ = BytePtrFromString(%s)\n", n, p.Name)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass dummy pointer in that case.
|
||||
// Used to pass nil, but some OSes or simulators reject write(fd, nil, 0).
|
||||
text += fmt.Sprintf("\tvar _p%d unsafe.Pointer\n", n)
|
||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = unsafe.Pointer(&%s[0])\n\t}", p.Name, n, p.Name)
|
||||
text += fmt.Sprintf(" else {\n\t\t_p%d = unsafe.Pointer(&_zero)\n\t}\n", n)
|
||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n), fmt.Sprintf("uintptr(len(%s))", p.Name))
|
||||
n++
|
||||
} else if p.Type == "int64" && (*openbsd || *netbsd) {
|
||||
args = append(args, "0")
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else if endianness == "little-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
} else if p.Type == "int64" && *dragonfly {
|
||||
if regexp.MustCompile(`^(?i)extp(read|write)`).FindStringSubmatch(funct) == nil {
|
||||
args = append(args, "0")
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else if endianness == "little-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
} else if (p.Type == "int64" || p.Type == "uint64") && endianness != "" {
|
||||
if len(args)%2 == 1 && *arm {
|
||||
// arm abi specifies 64-bit argument uses
|
||||
// (even, odd) pair
|
||||
args = append(args, "0")
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
}
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
}
|
||||
|
||||
// Determine which form to use; pad args with zeros.
|
||||
asm := "Syscall"
|
||||
if nonblock != nil {
|
||||
if errvar == "" && goos == "linux" {
|
||||
asm = "RawSyscallNoError"
|
||||
} else {
|
||||
asm = "RawSyscall"
|
||||
}
|
||||
} else {
|
||||
if errvar == "" && goos == "linux" {
|
||||
asm = "SyscallNoError"
|
||||
}
|
||||
}
|
||||
if len(args) <= 3 {
|
||||
for len(args) < 3 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else if len(args) <= 6 {
|
||||
asm += "6"
|
||||
for len(args) < 6 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else if len(args) <= 9 {
|
||||
asm += "9"
|
||||
for len(args) < 9 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s too many arguments to system call\n", path, funct)
|
||||
}
|
||||
|
||||
// System call number.
|
||||
if sysname == "" {
|
||||
sysname = "SYS_" + funct
|
||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
||||
sysname = strings.ToUpper(sysname)
|
||||
}
|
||||
|
||||
var libcFn string
|
||||
if libc {
|
||||
asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call
|
||||
sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_
|
||||
sysname = strings.ToLower(sysname) // lowercase
|
||||
if sysname == "getdirentries64" {
|
||||
// Special case - libSystem name and
|
||||
// raw syscall name don't match.
|
||||
sysname = "__getdirentries64"
|
||||
}
|
||||
libcFn = sysname
|
||||
sysname = "funcPC(libc_" + sysname + "_trampoline)"
|
||||
}
|
||||
|
||||
// Actual call.
|
||||
arglist := strings.Join(args, ", ")
|
||||
call := fmt.Sprintf("%s(%s, %s)", asm, sysname, arglist)
|
||||
|
||||
// Assign return values.
|
||||
body := ""
|
||||
ret := []string{"_", "_", "_"}
|
||||
doErrno := false
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" && !*plan9 {
|
||||
reg = "e1"
|
||||
ret[2] = reg
|
||||
doErrno = true
|
||||
} else if p.Name == "err" && *plan9 {
|
||||
ret[0] = "r0"
|
||||
ret[2] = "e1"
|
||||
break
|
||||
} else {
|
||||
reg = fmt.Sprintf("r%d", i)
|
||||
ret[i] = reg
|
||||
}
|
||||
if p.Type == "bool" {
|
||||
reg = fmt.Sprintf("%s != 0", reg)
|
||||
}
|
||||
if p.Type == "int64" && endianness != "" {
|
||||
// 64-bit number in r1:r0 or r0:r1.
|
||||
if i+2 > len(out) {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s not enough registers for int64 return\n", path, funct)
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1)
|
||||
} else {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i)
|
||||
}
|
||||
ret[i] = fmt.Sprintf("r%d", i)
|
||||
ret[i+1] = fmt.Sprintf("r%d", i+1)
|
||||
}
|
||||
if reg != "e1" || *plan9 {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" {
|
||||
text += fmt.Sprintf("\t%s\n", call)
|
||||
} else {
|
||||
if errvar == "" && goos == "linux" {
|
||||
// raw syscall without error on Linux, see golang.org/issue/22924
|
||||
text += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], call)
|
||||
} else {
|
||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call)
|
||||
}
|
||||
}
|
||||
text += body
|
||||
|
||||
if *plan9 && ret[2] == "e1" {
|
||||
text += "\tif int32(r0) == -1 {\n"
|
||||
text += "\t\terr = e1\n"
|
||||
text += "\t}\n"
|
||||
} else if doErrno {
|
||||
text += "\tif e1 != 0 {\n"
|
||||
text += "\t\terr = errnoErr(e1)\n"
|
||||
text += "\t}\n"
|
||||
}
|
||||
text += "\treturn\n"
|
||||
text += "}\n\n"
|
||||
|
||||
if libc && !trampolines[libcFn] {
|
||||
// some system calls share a trampoline, like read and readlen.
|
||||
trampolines[libcFn] = true
|
||||
// Declare assembly trampoline.
|
||||
text += fmt.Sprintf("func libc_%s_trampoline()\n", libcFn)
|
||||
// Assembly trampoline calls the libc_* function, which this magic
|
||||
// redirects to use the function from libSystem.
|
||||
text += fmt.Sprintf("//go:linkname libc_%s libc_%s\n", libcFn, libcFn)
|
||||
text += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"/usr/lib/libSystem.B.dylib\"\n", libcFn, libcFn)
|
||||
text += "\n"
|
||||
}
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var _ syscall.Errno
|
||||
|
||||
%s
|
||||
`
|
415
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go
generated
vendored
Normal file
415
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go
generated
vendored
Normal file
@ -0,0 +1,415 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_aix.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named err.
|
||||
* If go func name needs to be different than its libc name,
|
||||
* or the function is not in libc, name could be specified
|
||||
* at the end, after "=" sign, like
|
||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
aix = flag.Bool("aix", false, "aix")
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
pack := ""
|
||||
text := ""
|
||||
cExtern := "/*\n#include <stdint.h>\n#include <stddef.h>\n"
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
||||
pack = p[1]
|
||||
}
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
inps = strings.Join(in, ", ")
|
||||
outps = strings.Join(out, ", ")
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
|
||||
// Check if value return, err return available
|
||||
errvar := ""
|
||||
retvar := ""
|
||||
rettype := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
} else {
|
||||
retvar = p.Name
|
||||
rettype = p.Type
|
||||
}
|
||||
}
|
||||
|
||||
// System call name.
|
||||
if sysname == "" {
|
||||
sysname = funct
|
||||
}
|
||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
||||
|
||||
cRettype := ""
|
||||
if rettype == "unsafe.Pointer" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "uintptr" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "int" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int32" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int64" {
|
||||
cRettype = "long long"
|
||||
} else if rettype == "uint32" {
|
||||
cRettype = "unsigned int"
|
||||
} else if rettype == "uint64" {
|
||||
cRettype = "unsigned long long"
|
||||
} else {
|
||||
cRettype = "int"
|
||||
}
|
||||
if sysname == "exit" {
|
||||
cRettype = "void"
|
||||
}
|
||||
|
||||
// Change p.Types to c
|
||||
var cIn []string
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "string" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t", "size_t")
|
||||
} else if p.Type == "unsafe.Pointer" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "uintptr" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "int" {
|
||||
cIn = append(cIn, "int")
|
||||
} else if p.Type == "int32" {
|
||||
cIn = append(cIn, "int")
|
||||
} else if p.Type == "int64" {
|
||||
cIn = append(cIn, "long long")
|
||||
} else if p.Type == "uint32" {
|
||||
cIn = append(cIn, "unsigned int")
|
||||
} else if p.Type == "uint64" {
|
||||
cIn = append(cIn, "unsigned long long")
|
||||
} else {
|
||||
cIn = append(cIn, "int")
|
||||
}
|
||||
}
|
||||
|
||||
if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" {
|
||||
if sysname == "select" {
|
||||
// select is a keyword of Go. Its name is
|
||||
// changed to c_select.
|
||||
cExtern += "#define c_select select\n"
|
||||
}
|
||||
// Imports of system calls from libc
|
||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
||||
cIn := strings.Join(cIn, ", ")
|
||||
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
||||
}
|
||||
|
||||
// So file name.
|
||||
if *aix {
|
||||
if modname == "" {
|
||||
modname = "libc.a/shr_64.o"
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
strconvfunc := "C.CString"
|
||||
|
||||
// Go function header.
|
||||
if outps != "" {
|
||||
outps = fmt.Sprintf(" (%s)", outps)
|
||||
}
|
||||
if text != "" {
|
||||
text += "\n"
|
||||
}
|
||||
|
||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
|
||||
|
||||
// Prepare arguments to Syscall.
|
||||
var args []string
|
||||
n := 0
|
||||
argN := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))")
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass nil in that case.
|
||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
|
||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n))
|
||||
n++
|
||||
text += fmt.Sprintf("\tvar _p%d int\n", n)
|
||||
text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.size_t(_p%d)", n))
|
||||
n++
|
||||
} else if p.Type == "int64" && endianness != "" {
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
}
|
||||
n++
|
||||
} else if p.Type == "bool" {
|
||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n)
|
||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n)
|
||||
args = append(args, fmt.Sprintf("_p%d", n))
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
|
||||
} else if p.Type == "unsafe.Pointer" {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
|
||||
} else if p.Type == "int" {
|
||||
if (argN == 2) && ((funct == "readlen") || (funct == "writelen")) {
|
||||
args = append(args, fmt.Sprintf("C.size_t(%s)", p.Name))
|
||||
} else if argN == 0 && funct == "fcntl" {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
} else if p.Type == "int32" {
|
||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
} else if p.Type == "int64" {
|
||||
args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name))
|
||||
} else if p.Type == "uint32" {
|
||||
args = append(args, fmt.Sprintf("C.uint(%s)", p.Name))
|
||||
} else if p.Type == "uint64" {
|
||||
args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name))
|
||||
} else if p.Type == "uintptr" {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
argN++
|
||||
}
|
||||
|
||||
// Actual call.
|
||||
arglist := strings.Join(args, ", ")
|
||||
call := ""
|
||||
if sysname == "exit" {
|
||||
if errvar != "" {
|
||||
call += "er :="
|
||||
} else {
|
||||
call += ""
|
||||
}
|
||||
} else if errvar != "" {
|
||||
call += "r0,er :="
|
||||
} else if retvar != "" {
|
||||
call += "r0,_ :="
|
||||
} else {
|
||||
call += ""
|
||||
}
|
||||
if sysname == "select" {
|
||||
// select is a keyword of Go. Its name is
|
||||
// changed to c_select.
|
||||
call += fmt.Sprintf("C.c_%s(%s)", sysname, arglist)
|
||||
} else {
|
||||
call += fmt.Sprintf("C.%s(%s)", sysname, arglist)
|
||||
}
|
||||
|
||||
// Assign return values.
|
||||
body := ""
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" {
|
||||
reg = "e1"
|
||||
} else {
|
||||
reg = "r0"
|
||||
}
|
||||
if reg != "e1" {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
|
||||
// verify return
|
||||
if sysname != "exit" && errvar != "" {
|
||||
if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil {
|
||||
body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n"
|
||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
||||
body += "\t}\n"
|
||||
} else {
|
||||
body += "\tif (r0 ==-1 && er != nil) {\n"
|
||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
||||
body += "\t}\n"
|
||||
}
|
||||
} else if errvar != "" {
|
||||
body += "\tif (er != nil) {\n"
|
||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
||||
body += "\t}\n"
|
||||
}
|
||||
|
||||
text += fmt.Sprintf("\t%s\n", call)
|
||||
text += body
|
||||
|
||||
text += "\treturn\n"
|
||||
text += "}\n"
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
imp := ""
|
||||
if pack != "unix" {
|
||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
||||
|
||||
}
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, cExtern, imp, text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package %s
|
||||
|
||||
|
||||
%s
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
||||
%s
|
||||
|
||||
%s
|
||||
`
|
614
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go
generated
vendored
Normal file
614
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go
generated
vendored
Normal file
@ -0,0 +1,614 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_aix.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named err.
|
||||
* If go func name needs to be different than its libc name,
|
||||
* or the function is not in libc, name could be specified
|
||||
* at the end, after "=" sign, like
|
||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
|
||||
|
||||
This program will generate three files and handle both gc and gccgo implementation:
|
||||
- zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation)
|
||||
- zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6
|
||||
- zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type.
|
||||
|
||||
The generated code looks like this
|
||||
|
||||
zsyscall_aix_ppc64.go
|
||||
func asyscall(...) (n int, err error) {
|
||||
// Pointer Creation
|
||||
r1, e1 := callasyscall(...)
|
||||
// Type Conversion
|
||||
// Error Handler
|
||||
return
|
||||
}
|
||||
|
||||
zsyscall_aix_ppc64_gc.go
|
||||
//go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o"
|
||||
//go:linkname libc_asyscall libc_asyscall
|
||||
var asyscall syscallFunc
|
||||
|
||||
func callasyscall(...) (r1 uintptr, e1 Errno) {
|
||||
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... )
|
||||
return
|
||||
}
|
||||
|
||||
zsyscall_aix_ppc64_ggcgo.go
|
||||
|
||||
// int asyscall(...)
|
||||
|
||||
import "C"
|
||||
|
||||
func callasyscall(...) (r1 uintptr, e1 Errno) {
|
||||
r1 = uintptr(C.asyscall(...))
|
||||
e1 = syscall.GetErrno()
|
||||
return
|
||||
}
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
aix = flag.Bool("aix", false, "aix")
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall_aix_ppc64.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc64.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
pack := ""
|
||||
// GCCGO
|
||||
textgccgo := ""
|
||||
cExtern := "/*\n#include <stdint.h>\n"
|
||||
// GC
|
||||
textgc := ""
|
||||
dynimports := ""
|
||||
linknames := ""
|
||||
var vars []string
|
||||
// COMMON
|
||||
textcommon := ""
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
||||
pack = p[1]
|
||||
}
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
inps = strings.Join(in, ", ")
|
||||
outps = strings.Join(out, ", ")
|
||||
|
||||
if sysname == "" {
|
||||
sysname = funct
|
||||
}
|
||||
|
||||
onlyCommon := false
|
||||
if funct == "readlen" || funct == "writelen" || funct == "FcntlInt" || funct == "FcntlFlock" {
|
||||
// This function call another syscall which is already implemented.
|
||||
// Therefore, the gc and gccgo part must not be generated.
|
||||
onlyCommon = true
|
||||
}
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
|
||||
textcommon += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
if !onlyCommon {
|
||||
textgccgo += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
textgc += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
}
|
||||
|
||||
// Check if value return, err return available
|
||||
errvar := ""
|
||||
rettype := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
} else {
|
||||
rettype = p.Type
|
||||
}
|
||||
}
|
||||
|
||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
||||
|
||||
// GCCGO Prototype return type
|
||||
cRettype := ""
|
||||
if rettype == "unsafe.Pointer" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "uintptr" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "int" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int32" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int64" {
|
||||
cRettype = "long long"
|
||||
} else if rettype == "uint32" {
|
||||
cRettype = "unsigned int"
|
||||
} else if rettype == "uint64" {
|
||||
cRettype = "unsigned long long"
|
||||
} else {
|
||||
cRettype = "int"
|
||||
}
|
||||
if sysname == "exit" {
|
||||
cRettype = "void"
|
||||
}
|
||||
|
||||
// GCCGO Prototype arguments type
|
||||
var cIn []string
|
||||
for i, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "string" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t", "size_t")
|
||||
} else if p.Type == "unsafe.Pointer" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "uintptr" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "int" {
|
||||
if (i == 0 || i == 2) && funct == "fcntl" {
|
||||
// These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else {
|
||||
cIn = append(cIn, "int")
|
||||
}
|
||||
|
||||
} else if p.Type == "int32" {
|
||||
cIn = append(cIn, "int")
|
||||
} else if p.Type == "int64" {
|
||||
cIn = append(cIn, "long long")
|
||||
} else if p.Type == "uint32" {
|
||||
cIn = append(cIn, "unsigned int")
|
||||
} else if p.Type == "uint64" {
|
||||
cIn = append(cIn, "unsigned long long")
|
||||
} else {
|
||||
cIn = append(cIn, "int")
|
||||
}
|
||||
}
|
||||
|
||||
if !onlyCommon {
|
||||
// GCCGO Prototype Generation
|
||||
// Imports of system calls from libc
|
||||
if sysname == "select" {
|
||||
// select is a keyword of Go. Its name is
|
||||
// changed to c_select.
|
||||
cExtern += "#define c_select select\n"
|
||||
}
|
||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
||||
cIn := strings.Join(cIn, ", ")
|
||||
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
||||
}
|
||||
// GC Library name
|
||||
if modname == "" {
|
||||
modname = "libc.a/shr_64.o"
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
|
||||
os.Exit(1)
|
||||
}
|
||||
sysvarname := fmt.Sprintf("libc_%s", sysname)
|
||||
|
||||
if !onlyCommon {
|
||||
// GC Runtime import of function to allow cross-platform builds.
|
||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname)
|
||||
// GC Link symbol to proc address variable.
|
||||
linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname)
|
||||
// GC Library proc address variable.
|
||||
vars = append(vars, sysvarname)
|
||||
}
|
||||
|
||||
strconvfunc := "BytePtrFromString"
|
||||
strconvtype := "*byte"
|
||||
|
||||
// Go function header.
|
||||
if outps != "" {
|
||||
outps = fmt.Sprintf(" (%s)", outps)
|
||||
}
|
||||
if textcommon != "" {
|
||||
textcommon += "\n"
|
||||
}
|
||||
|
||||
textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
|
||||
|
||||
// Prepare arguments tocall.
|
||||
var argscommon []string // Arguments in the common part
|
||||
var argscall []string // Arguments for call prototype
|
||||
var argsgc []string // Arguments for gc call (with syscall6)
|
||||
var argsgccgo []string // Arguments for gccgo call (with C.name_of_syscall)
|
||||
n := 0
|
||||
argN := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n))
|
||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n))
|
||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass nil in that case.
|
||||
textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
|
||||
textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n))
|
||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n))
|
||||
n++
|
||||
} else if p.Type == "int64" && endianness != "" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n")
|
||||
} else if p.Type == "bool" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n")
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" {
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else if p.Type == "int" {
|
||||
if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) {
|
||||
// These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
|
||||
} else {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
} else if p.Type == "int32" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s int32", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
} else if p.Type == "int64" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s int64", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name))
|
||||
} else if p.Type == "uint32" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name))
|
||||
} else if p.Type == "uint64" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name))
|
||||
} else if p.Type == "uintptr" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else {
|
||||
argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
argN++
|
||||
}
|
||||
nargs := len(argsgc)
|
||||
|
||||
// COMMON function generation
|
||||
argscommonlist := strings.Join(argscommon, ", ")
|
||||
callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist)
|
||||
ret := []string{"_", "_"}
|
||||
body := ""
|
||||
doErrno := false
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" {
|
||||
reg = "e1"
|
||||
ret[1] = reg
|
||||
doErrno = true
|
||||
} else {
|
||||
reg = "r0"
|
||||
ret[0] = reg
|
||||
}
|
||||
if p.Type == "bool" {
|
||||
reg = fmt.Sprintf("%s != 0", reg)
|
||||
}
|
||||
if reg != "e1" {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
if ret[0] == "_" && ret[1] == "_" {
|
||||
textcommon += fmt.Sprintf("\t%s\n", callcommon)
|
||||
} else {
|
||||
textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon)
|
||||
}
|
||||
textcommon += body
|
||||
|
||||
if doErrno {
|
||||
textcommon += "\tif e1 != 0 {\n"
|
||||
textcommon += "\t\terr = errnoErr(e1)\n"
|
||||
textcommon += "\t}\n"
|
||||
}
|
||||
textcommon += "\treturn\n"
|
||||
textcommon += "}\n"
|
||||
|
||||
if onlyCommon {
|
||||
continue
|
||||
}
|
||||
|
||||
// CALL Prototype
|
||||
callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", "))
|
||||
|
||||
// GC function generation
|
||||
asm := "syscall6"
|
||||
if nonblock != nil {
|
||||
asm = "rawSyscall6"
|
||||
}
|
||||
|
||||
if len(argsgc) <= 6 {
|
||||
for len(argsgc) < 6 {
|
||||
argsgc = append(argsgc, "0")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct)
|
||||
os.Exit(1)
|
||||
}
|
||||
argsgclist := strings.Join(argsgc, ", ")
|
||||
callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist)
|
||||
|
||||
textgc += callProto
|
||||
textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc)
|
||||
textgc += "\treturn\n}\n"
|
||||
|
||||
// GCCGO function generation
|
||||
argsgccgolist := strings.Join(argsgccgo, ", ")
|
||||
var callgccgo string
|
||||
if sysname == "select" {
|
||||
// select is a keyword of Go. Its name is
|
||||
// changed to c_select.
|
||||
callgccgo = fmt.Sprintf("C.c_%s(%s)", sysname, argsgccgolist)
|
||||
} else {
|
||||
callgccgo = fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist)
|
||||
}
|
||||
textgccgo += callProto
|
||||
textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo)
|
||||
textgccgo += "\te1 = syscall.GetErrno()\n"
|
||||
textgccgo += "\treturn\n}\n"
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
imp := ""
|
||||
if pack != "unix" {
|
||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
||||
|
||||
}
|
||||
|
||||
// Print zsyscall_aix_ppc64.go
|
||||
err := ioutil.WriteFile("zsyscall_aix_ppc64.go",
|
||||
[]byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)),
|
||||
0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print zsyscall_aix_ppc64_gc.go
|
||||
vardecls := "\t" + strings.Join(vars, ",\n\t")
|
||||
vardecls += " syscallFunc"
|
||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go",
|
||||
[]byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)),
|
||||
0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print zsyscall_aix_ppc64_gccgo.go
|
||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go",
|
||||
[]byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)),
|
||||
0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
const srcTemplate1 = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package %s
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
||||
%s
|
||||
|
||||
%s
|
||||
`
|
||||
const srcTemplate2 = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
// +build !gccgo
|
||||
|
||||
package %s
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
type syscallFunc uintptr
|
||||
|
||||
var (
|
||||
%s
|
||||
)
|
||||
|
||||
// Implemented in runtime/syscall_aix.go.
|
||||
func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||
func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||
|
||||
%s
|
||||
`
|
||||
const srcTemplate3 = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
// +build gccgo
|
||||
|
||||
package %s
|
||||
|
||||
%s
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
|
||||
%s
|
||||
|
||||
%s
|
||||
`
|
335
vendor/golang.org/x/sys/unix/mksyscall_solaris.go
generated
vendored
Normal file
335
vendor/golang.org/x/sys/unix/mksyscall_solaris.go
generated
vendored
Normal file
@ -0,0 +1,335 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_solaris.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named err.
|
||||
* If go func name needs to be different than its libc name,
|
||||
* or the function is not in libc, name could be specified
|
||||
* at the end, after "=" sign, like
|
||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall_solaris.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_solaris.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
pack := ""
|
||||
text := ""
|
||||
dynimports := ""
|
||||
linknames := ""
|
||||
var vars []string
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
||||
pack = p[1]
|
||||
}
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
inps = strings.Join(in, ", ")
|
||||
outps = strings.Join(out, ", ")
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
|
||||
// So file name.
|
||||
if modname == "" {
|
||||
modname = "libc"
|
||||
}
|
||||
|
||||
// System call name.
|
||||
if sysname == "" {
|
||||
sysname = funct
|
||||
}
|
||||
|
||||
// System call pointer variable name.
|
||||
sysvarname := fmt.Sprintf("proc%s", sysname)
|
||||
|
||||
strconvfunc := "BytePtrFromString"
|
||||
strconvtype := "*byte"
|
||||
|
||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
||||
|
||||
// Runtime import of function to allow cross-platform builds.
|
||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"%s.so\"\n", sysname, sysname, modname)
|
||||
// Link symbol to proc address variable.
|
||||
linknames += fmt.Sprintf("//go:linkname %s libc_%s\n", sysvarname, sysname)
|
||||
// Library proc address variable.
|
||||
vars = append(vars, sysvarname)
|
||||
|
||||
// Go function header.
|
||||
outlist := strings.Join(out, ", ")
|
||||
if outlist != "" {
|
||||
outlist = fmt.Sprintf(" (%s)", outlist)
|
||||
}
|
||||
if text != "" {
|
||||
text += "\n"
|
||||
}
|
||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outlist)
|
||||
|
||||
// Check if err return available
|
||||
errvar := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare arguments to Syscall.
|
||||
var args []string
|
||||
n := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))")
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
text += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
text += fmt.Sprintf("\t_p%d, _ = %s(%s)\n", n, strconvfunc, p.Name)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if s := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); s != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass nil in that case.
|
||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, s[1])
|
||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("uintptr(len(%s))", p.Name))
|
||||
n++
|
||||
} else if p.Type == "int64" && endianness != "" {
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
}
|
||||
} else if p.Type == "bool" {
|
||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n)
|
||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n)
|
||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n))
|
||||
n++
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
}
|
||||
nargs := len(args)
|
||||
|
||||
// Determine which form to use; pad args with zeros.
|
||||
asm := "sysvicall6"
|
||||
if nonblock != nil {
|
||||
asm = "rawSysvicall6"
|
||||
}
|
||||
if len(args) <= 6 {
|
||||
for len(args) < 6 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call\n", path)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Actual call.
|
||||
arglist := strings.Join(args, ", ")
|
||||
call := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, arglist)
|
||||
|
||||
// Assign return values.
|
||||
body := ""
|
||||
ret := []string{"_", "_", "_"}
|
||||
doErrno := false
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" {
|
||||
reg = "e1"
|
||||
ret[2] = reg
|
||||
doErrno = true
|
||||
} else {
|
||||
reg = fmt.Sprintf("r%d", i)
|
||||
ret[i] = reg
|
||||
}
|
||||
if p.Type == "bool" {
|
||||
reg = fmt.Sprintf("%d != 0", reg)
|
||||
}
|
||||
if p.Type == "int64" && endianness != "" {
|
||||
// 64-bit number in r1:r0 or r0:r1.
|
||||
if i+2 > len(out) {
|
||||
fmt.Fprintf(os.Stderr, "%s: not enough registers for int64 return\n", path)
|
||||
os.Exit(1)
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1)
|
||||
} else {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i)
|
||||
}
|
||||
ret[i] = fmt.Sprintf("r%d", i)
|
||||
ret[i+1] = fmt.Sprintf("r%d", i+1)
|
||||
}
|
||||
if reg != "e1" {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" {
|
||||
text += fmt.Sprintf("\t%s\n", call)
|
||||
} else {
|
||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call)
|
||||
}
|
||||
text += body
|
||||
|
||||
if doErrno {
|
||||
text += "\tif e1 != 0 {\n"
|
||||
text += "\t\terr = e1\n"
|
||||
text += "\t}\n"
|
||||
}
|
||||
text += "\treturn\n"
|
||||
text += "}\n"
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
imp := ""
|
||||
if pack != "unix" {
|
||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
||||
|
||||
}
|
||||
vardecls := "\t" + strings.Join(vars, ",\n\t")
|
||||
vardecls += " syscallFunc"
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package %s
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
var (
|
||||
%s
|
||||
)
|
||||
|
||||
%s
|
||||
`
|
355
vendor/golang.org/x/sys/unix/mksysctl_openbsd.go
generated
vendored
Normal file
355
vendor/golang.org/x/sys/unix/mksysctl_openbsd.go
generated
vendored
Normal file
@ -0,0 +1,355 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Parse the header files for OpenBSD and generate a Go usable sysctl MIB.
|
||||
//
|
||||
// Build a MIB with each entry being an array containing the level, type and
|
||||
// a hash that will contain additional entries if the current entry is a node.
|
||||
// We then walk this MIB and create a flattened sysctl name to OID hash.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
goos, goarch string
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments.
|
||||
func cmdLine() string {
|
||||
return "go run mksysctl_openbsd.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags.
|
||||
func buildTags() string {
|
||||
return fmt.Sprintf("%s,%s", goarch, goos)
|
||||
}
|
||||
|
||||
// reMatch performs regular expression match and stores the substring slice to value pointed by m.
|
||||
func reMatch(re *regexp.Regexp, str string, m *[]string) bool {
|
||||
*m = re.FindStringSubmatch(str)
|
||||
if *m != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type nodeElement struct {
|
||||
n int
|
||||
t string
|
||||
pE *map[string]nodeElement
|
||||
}
|
||||
|
||||
var (
|
||||
debugEnabled bool
|
||||
mib map[string]nodeElement
|
||||
node *map[string]nodeElement
|
||||
nodeMap map[string]string
|
||||
sysCtl []string
|
||||
)
|
||||
|
||||
var (
|
||||
ctlNames1RE = regexp.MustCompile(`^#define\s+(CTL_NAMES)\s+{`)
|
||||
ctlNames2RE = regexp.MustCompile(`^#define\s+(CTL_(.*)_NAMES)\s+{`)
|
||||
ctlNames3RE = regexp.MustCompile(`^#define\s+((.*)CTL_NAMES)\s+{`)
|
||||
netInetRE = regexp.MustCompile(`^netinet/`)
|
||||
netInet6RE = regexp.MustCompile(`^netinet6/`)
|
||||
netRE = regexp.MustCompile(`^net/`)
|
||||
bracesRE = regexp.MustCompile(`{.*}`)
|
||||
ctlTypeRE = regexp.MustCompile(`{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}`)
|
||||
fsNetKernRE = regexp.MustCompile(`^(fs|net|kern)_`)
|
||||
)
|
||||
|
||||
func debug(s string) {
|
||||
if debugEnabled {
|
||||
fmt.Fprintln(os.Stderr, s)
|
||||
}
|
||||
}
|
||||
|
||||
// Walk the MIB and build a sysctl name to OID mapping.
|
||||
func buildSysctl(pNode *map[string]nodeElement, name string, oid []int) {
|
||||
lNode := pNode // local copy of pointer to node
|
||||
var keys []string
|
||||
for k := range *lNode {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, key := range keys {
|
||||
nodename := name
|
||||
if name != "" {
|
||||
nodename += "."
|
||||
}
|
||||
nodename += key
|
||||
|
||||
nodeoid := append(oid, (*pNode)[key].n)
|
||||
|
||||
if (*pNode)[key].t == `CTLTYPE_NODE` {
|
||||
if _, ok := nodeMap[nodename]; ok {
|
||||
lNode = &mib
|
||||
ctlName := nodeMap[nodename]
|
||||
for _, part := range strings.Split(ctlName, ".") {
|
||||
lNode = ((*lNode)[part]).pE
|
||||
}
|
||||
} else {
|
||||
lNode = (*pNode)[key].pE
|
||||
}
|
||||
buildSysctl(lNode, nodename, nodeoid)
|
||||
} else if (*pNode)[key].t != "" {
|
||||
oidStr := []string{}
|
||||
for j := range nodeoid {
|
||||
oidStr = append(oidStr, fmt.Sprintf("%d", nodeoid[j]))
|
||||
}
|
||||
text := "\t{ \"" + nodename + "\", []_C_int{ " + strings.Join(oidStr, ", ") + " } }, \n"
|
||||
sysCtl = append(sysCtl, text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Get the OS (using GOOS_TARGET if it exist)
|
||||
goos = os.Getenv("GOOS_TARGET")
|
||||
if goos == "" {
|
||||
goos = os.Getenv("GOOS")
|
||||
}
|
||||
// Get the architecture (using GOARCH_TARGET if it exists)
|
||||
goarch = os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
// Check if GOOS and GOARCH environment variables are defined
|
||||
if goarch == "" || goos == "" {
|
||||
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
mib = make(map[string]nodeElement)
|
||||
headers := [...]string{
|
||||
`sys/sysctl.h`,
|
||||
`sys/socket.h`,
|
||||
`sys/tty.h`,
|
||||
`sys/malloc.h`,
|
||||
`sys/mount.h`,
|
||||
`sys/namei.h`,
|
||||
`sys/sem.h`,
|
||||
`sys/shm.h`,
|
||||
`sys/vmmeter.h`,
|
||||
`uvm/uvmexp.h`,
|
||||
`uvm/uvm_param.h`,
|
||||
`uvm/uvm_swap_encrypt.h`,
|
||||
`ddb/db_var.h`,
|
||||
`net/if.h`,
|
||||
`net/if_pfsync.h`,
|
||||
`net/pipex.h`,
|
||||
`netinet/in.h`,
|
||||
`netinet/icmp_var.h`,
|
||||
`netinet/igmp_var.h`,
|
||||
`netinet/ip_ah.h`,
|
||||
`netinet/ip_carp.h`,
|
||||
`netinet/ip_divert.h`,
|
||||
`netinet/ip_esp.h`,
|
||||
`netinet/ip_ether.h`,
|
||||
`netinet/ip_gre.h`,
|
||||
`netinet/ip_ipcomp.h`,
|
||||
`netinet/ip_ipip.h`,
|
||||
`netinet/pim_var.h`,
|
||||
`netinet/tcp_var.h`,
|
||||
`netinet/udp_var.h`,
|
||||
`netinet6/in6.h`,
|
||||
`netinet6/ip6_divert.h`,
|
||||
`netinet6/pim6_var.h`,
|
||||
`netinet/icmp6.h`,
|
||||
`netmpls/mpls.h`,
|
||||
}
|
||||
|
||||
ctls := [...]string{
|
||||
`kern`,
|
||||
`vm`,
|
||||
`fs`,
|
||||
`net`,
|
||||
//debug /* Special handling required */
|
||||
`hw`,
|
||||
//machdep /* Arch specific */
|
||||
`user`,
|
||||
`ddb`,
|
||||
//vfs /* Special handling required */
|
||||
`fs.posix`,
|
||||
`kern.forkstat`,
|
||||
`kern.intrcnt`,
|
||||
`kern.malloc`,
|
||||
`kern.nchstats`,
|
||||
`kern.seminfo`,
|
||||
`kern.shminfo`,
|
||||
`kern.timecounter`,
|
||||
`kern.tty`,
|
||||
`kern.watchdog`,
|
||||
`net.bpf`,
|
||||
`net.ifq`,
|
||||
`net.inet`,
|
||||
`net.inet.ah`,
|
||||
`net.inet.carp`,
|
||||
`net.inet.divert`,
|
||||
`net.inet.esp`,
|
||||
`net.inet.etherip`,
|
||||
`net.inet.gre`,
|
||||
`net.inet.icmp`,
|
||||
`net.inet.igmp`,
|
||||
`net.inet.ip`,
|
||||
`net.inet.ip.ifq`,
|
||||
`net.inet.ipcomp`,
|
||||
`net.inet.ipip`,
|
||||
`net.inet.mobileip`,
|
||||
`net.inet.pfsync`,
|
||||
`net.inet.pim`,
|
||||
`net.inet.tcp`,
|
||||
`net.inet.udp`,
|
||||
`net.inet6`,
|
||||
`net.inet6.divert`,
|
||||
`net.inet6.ip6`,
|
||||
`net.inet6.icmp6`,
|
||||
`net.inet6.pim6`,
|
||||
`net.inet6.tcp6`,
|
||||
`net.inet6.udp6`,
|
||||
`net.mpls`,
|
||||
`net.mpls.ifq`,
|
||||
`net.key`,
|
||||
`net.pflow`,
|
||||
`net.pfsync`,
|
||||
`net.pipex`,
|
||||
`net.rt`,
|
||||
`vm.swapencrypt`,
|
||||
//vfsgenctl /* Special handling required */
|
||||
}
|
||||
|
||||
// Node name "fixups"
|
||||
ctlMap := map[string]string{
|
||||
"ipproto": "net.inet",
|
||||
"net.inet.ipproto": "net.inet",
|
||||
"net.inet6.ipv6proto": "net.inet6",
|
||||
"net.inet6.ipv6": "net.inet6.ip6",
|
||||
"net.inet.icmpv6": "net.inet6.icmp6",
|
||||
"net.inet6.divert6": "net.inet6.divert",
|
||||
"net.inet6.tcp6": "net.inet.tcp",
|
||||
"net.inet6.udp6": "net.inet.udp",
|
||||
"mpls": "net.mpls",
|
||||
"swpenc": "vm.swapencrypt",
|
||||
}
|
||||
|
||||
// Node mappings
|
||||
nodeMap = map[string]string{
|
||||
"net.inet.ip.ifq": "net.ifq",
|
||||
"net.inet.pfsync": "net.pfsync",
|
||||
"net.mpls.ifq": "net.ifq",
|
||||
}
|
||||
|
||||
mCtls := make(map[string]bool)
|
||||
for _, ctl := range ctls {
|
||||
mCtls[ctl] = true
|
||||
}
|
||||
|
||||
for _, header := range headers {
|
||||
debug("Processing " + header)
|
||||
file, err := os.Open(filepath.Join("/usr/include", header))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
var sub []string
|
||||
if reMatch(ctlNames1RE, s.Text(), &sub) ||
|
||||
reMatch(ctlNames2RE, s.Text(), &sub) ||
|
||||
reMatch(ctlNames3RE, s.Text(), &sub) {
|
||||
if sub[1] == `CTL_NAMES` {
|
||||
// Top level.
|
||||
node = &mib
|
||||
} else {
|
||||
// Node.
|
||||
nodename := strings.ToLower(sub[2])
|
||||
ctlName := ""
|
||||
if reMatch(netInetRE, header, &sub) {
|
||||
ctlName = "net.inet." + nodename
|
||||
} else if reMatch(netInet6RE, header, &sub) {
|
||||
ctlName = "net.inet6." + nodename
|
||||
} else if reMatch(netRE, header, &sub) {
|
||||
ctlName = "net." + nodename
|
||||
} else {
|
||||
ctlName = nodename
|
||||
ctlName = fsNetKernRE.ReplaceAllString(ctlName, `$1.`)
|
||||
}
|
||||
|
||||
if val, ok := ctlMap[ctlName]; ok {
|
||||
ctlName = val
|
||||
}
|
||||
if _, ok := mCtls[ctlName]; !ok {
|
||||
debug("Ignoring " + ctlName + "...")
|
||||
continue
|
||||
}
|
||||
|
||||
// Walk down from the top of the MIB.
|
||||
node = &mib
|
||||
for _, part := range strings.Split(ctlName, ".") {
|
||||
if _, ok := (*node)[part]; !ok {
|
||||
debug("Missing node " + part)
|
||||
(*node)[part] = nodeElement{n: 0, t: "", pE: &map[string]nodeElement{}}
|
||||
}
|
||||
node = (*node)[part].pE
|
||||
}
|
||||
}
|
||||
|
||||
// Populate current node with entries.
|
||||
i := -1
|
||||
for !strings.HasPrefix(s.Text(), "}") {
|
||||
s.Scan()
|
||||
if reMatch(bracesRE, s.Text(), &sub) {
|
||||
i++
|
||||
}
|
||||
if !reMatch(ctlTypeRE, s.Text(), &sub) {
|
||||
continue
|
||||
}
|
||||
(*node)[sub[1]] = nodeElement{n: i, t: sub[2], pE: &map[string]nodeElement{}}
|
||||
}
|
||||
}
|
||||
}
|
||||
err = s.Err()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
buildSysctl(&mib, "", []int{})
|
||||
|
||||
sort.Strings(sysCtl)
|
||||
text := strings.Join(sysCtl, "")
|
||||
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package unix
|
||||
|
||||
type mibentry struct {
|
||||
ctlname string
|
||||
ctloid []_C_int
|
||||
}
|
||||
|
||||
var sysctlMib = []mibentry {
|
||||
%s
|
||||
}
|
||||
`
|
190
vendor/golang.org/x/sys/unix/mksysnum.go
generated
vendored
Normal file
190
vendor/golang.org/x/sys/unix/mksysnum.go
generated
vendored
Normal file
@ -0,0 +1,190 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Generate system call table for DragonFly, NetBSD,
|
||||
// FreeBSD, OpenBSD or Darwin from master list
|
||||
// (for example, /usr/src/sys/kern/syscalls.master or
|
||||
// sys/syscall.h).
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
goos, goarch string
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksysnum.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return fmt.Sprintf("%s,%s", goarch, goos)
|
||||
}
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// source string and substring slice for regexp
|
||||
type re struct {
|
||||
str string // source string
|
||||
sub []string // matched sub-string
|
||||
}
|
||||
|
||||
// Match performs regular expression match
|
||||
func (r *re) Match(exp string) bool {
|
||||
r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str)
|
||||
if r.sub != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// fetchFile fetches a text file from URL
|
||||
func fetchFile(URL string) io.Reader {
|
||||
resp, err := http.Get(URL)
|
||||
checkErr(err)
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
checkErr(err)
|
||||
return strings.NewReader(string(body))
|
||||
}
|
||||
|
||||
// readFile reads a text file from path
|
||||
func readFile(path string) io.Reader {
|
||||
file, err := os.Open(os.Args[1])
|
||||
checkErr(err)
|
||||
return file
|
||||
}
|
||||
|
||||
func format(name, num, proto string) string {
|
||||
name = strings.ToUpper(name)
|
||||
// There are multiple entries for enosys and nosys, so comment them out.
|
||||
nm := re{str: name}
|
||||
if nm.Match(`^SYS_E?NOSYS$`) {
|
||||
name = fmt.Sprintf("// %s", name)
|
||||
}
|
||||
if name == `SYS_SYS_EXIT` {
|
||||
name = `SYS_EXIT`
|
||||
}
|
||||
return fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Get the OS (using GOOS_TARGET if it exist)
|
||||
goos = os.Getenv("GOOS_TARGET")
|
||||
if goos == "" {
|
||||
goos = os.Getenv("GOOS")
|
||||
}
|
||||
// Get the architecture (using GOARCH_TARGET if it exists)
|
||||
goarch = os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
// Check if GOOS and GOARCH environment variables are defined
|
||||
if goarch == "" || goos == "" {
|
||||
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
file := strings.TrimSpace(os.Args[1])
|
||||
var syscalls io.Reader
|
||||
if strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "http://") {
|
||||
// Download syscalls.master file
|
||||
syscalls = fetchFile(file)
|
||||
} else {
|
||||
syscalls = readFile(file)
|
||||
}
|
||||
|
||||
var text, line string
|
||||
s := bufio.NewScanner(syscalls)
|
||||
for s.Scan() {
|
||||
t := re{str: line}
|
||||
if t.Match(`^(.*)\\$`) {
|
||||
// Handle continuation
|
||||
line = t.sub[1]
|
||||
line += strings.TrimLeft(s.Text(), " \t")
|
||||
} else {
|
||||
// New line
|
||||
line = s.Text()
|
||||
}
|
||||
t = re{str: line}
|
||||
if t.Match(`\\$`) {
|
||||
continue
|
||||
}
|
||||
t = re{str: line}
|
||||
|
||||
switch goos {
|
||||
case "dragonfly":
|
||||
if t.Match(`^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$`) {
|
||||
num, proto := t.sub[1], t.sub[2]
|
||||
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
||||
text += format(name, num, proto)
|
||||
}
|
||||
case "freebsd":
|
||||
if t.Match(`^([0-9]+)\s+\S+\s+(?:(?:NO)?STD|COMPAT10)\s+({ \S+\s+(\w+).*)$`) {
|
||||
num, proto := t.sub[1], t.sub[2]
|
||||
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
||||
text += format(name, num, proto)
|
||||
}
|
||||
case "openbsd":
|
||||
if t.Match(`^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$`) {
|
||||
num, proto, name := t.sub[1], t.sub[3], t.sub[4]
|
||||
text += format(name, num, proto)
|
||||
}
|
||||
case "netbsd":
|
||||
if t.Match(`^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$`) {
|
||||
num, proto, compat := t.sub[1], t.sub[6], t.sub[8]
|
||||
name := t.sub[7] + "_" + t.sub[9]
|
||||
if t.sub[11] != "" {
|
||||
name = t.sub[7] + "_" + t.sub[11]
|
||||
}
|
||||
name = strings.ToUpper(name)
|
||||
if compat == "" || compat == "13" || compat == "30" || compat == "50" {
|
||||
text += fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
|
||||
}
|
||||
}
|
||||
case "darwin":
|
||||
if t.Match(`^#define\s+SYS_(\w+)\s+([0-9]+)`) {
|
||||
name, num := t.sub[1], t.sub[2]
|
||||
name = strings.ToUpper(name)
|
||||
text += fmt.Sprintf(" SYS_%s = %s;\n", name, num)
|
||||
}
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "unrecognized GOOS=%s\n", goos)
|
||||
os.Exit(1)
|
||||
|
||||
}
|
||||
}
|
||||
err := s.Err()
|
||||
checkErr(err)
|
||||
|
||||
fmt.Printf(template, cmdLine(), buildTags(), text)
|
||||
}
|
||||
|
||||
const template = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package unix
|
||||
|
||||
const(
|
||||
%s)`
|
237
vendor/golang.org/x/sys/unix/types_aix.go
generated
vendored
Normal file
237
vendor/golang.org/x/sys/unix/types_aix.go
generated
vendored
Normal file
@ -0,0 +1,237 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
// +build aix
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See also mkerrors.sh and mkall.sh
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/un.h>
|
||||
#include <utime.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statfs.h>
|
||||
#include <sys/termio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
type off64 C.off64_t
|
||||
type off C.off_t
|
||||
type Mode_t C.mode_t
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
type Timeval32 C.struct_timeval32
|
||||
|
||||
type Timex C.struct_timex
|
||||
|
||||
type Time_t C.time_t
|
||||
|
||||
type Tms C.struct_tms
|
||||
|
||||
type Utimbuf C.struct_utimbuf
|
||||
|
||||
type Timezone C.struct_timezone
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit64
|
||||
|
||||
type Pid_t C.pid_t
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
type dev_t C.dev_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type StatxTimestamp C.struct_statx_timestamp
|
||||
|
||||
type Statx_t C.struct_statx
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
)
|
||||
|
||||
type IfMsgHdr C.struct_if_msghdr
|
||||
|
||||
// Misc
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
type Ustat_t C.struct_ustat
|
||||
|
||||
type Sigset_t C.sigset_t
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Termio C.struct_termio
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
//poll
|
||||
|
||||
type PollFd struct {
|
||||
Fd int32
|
||||
Events uint16
|
||||
Revents uint16
|
||||
}
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
//flock_t
|
||||
|
||||
type Flock_t C.struct_flock64
|
||||
|
||||
// Statfs
|
||||
|
||||
type Fsid_t C.struct_fsid_t
|
||||
type Fsid64_t C.struct_fsid64_t
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
const RNDGETENTCNT = 0x80045200
|
283
vendor/golang.org/x/sys/unix/types_darwin.go
generated
vendored
Normal file
283
vendor/golang.org/x/sys/unix/types_darwin.go
generated
vendored
Normal file
@ -0,0 +1,283 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define __DARWIN_UNIX03 0
|
||||
#define KERNEL
|
||||
#define _DARWIN_USE_64_BIT_INODE
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/message.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
type Timeval32 C.struct_timeval32
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat64
|
||||
|
||||
type Statfs_t C.struct_statfs64
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Fstore_t C.struct_fstore
|
||||
|
||||
type Radvisory_t C.struct_radvisory
|
||||
|
||||
type Fbootstraptransfer_t C.struct_fbootstraptransfer
|
||||
|
||||
type Log2phys_t C.struct_log2phys
|
||||
|
||||
type Fsid C.struct_fsid
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet4Pktinfo C.struct_in_pktinfo
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
)
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr
|
||||
SizeofIfmaMsghdr2 = C.sizeof_struct_ifma_msghdr2
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfmaMsghdr C.struct_ifma_msghdr
|
||||
|
||||
type IfmaMsghdr2 C.struct_ifma_msghdr2
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// uname
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
// Clockinfo
|
||||
|
||||
const SizeofClockinfo = C.sizeof_struct_clockinfo
|
||||
|
||||
type Clockinfo C.struct_clockinfo
|
263
vendor/golang.org/x/sys/unix/types_dragonfly.go
generated
vendored
Normal file
263
vendor/golang.org/x/sys/unix/types_dragonfly.go
generated
vendored
Normal file
@ -0,0 +1,263 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
type Fsid C.struct_fsid
|
||||
|
||||
// File system limits
|
||||
|
||||
const (
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
)
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr
|
||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfmaMsghdr C.struct_ifma_msghdr
|
||||
|
||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// Uname
|
||||
|
||||
type Utsname C.struct_utsname
|
400
vendor/golang.org/x/sys/unix/types_freebsd.go
generated
vendored
Normal file
400
vendor/golang.org/x/sys/unix/types_freebsd.go
generated
vendored
Normal file
@ -0,0 +1,400 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define _WANT_FREEBSD11_STAT 1
|
||||
#define _WANT_FREEBSD11_STATFS 1
|
||||
#define _WANT_FREEBSD11_DIRENT 1
|
||||
#define _WANT_FREEBSD11_KEVENT 1
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
// This structure is a duplicate of if_data on FreeBSD 8-STABLE.
|
||||
// See /usr/include/net/if.h.
|
||||
struct if_data8 {
|
||||
u_char ifi_type;
|
||||
u_char ifi_physical;
|
||||
u_char ifi_addrlen;
|
||||
u_char ifi_hdrlen;
|
||||
u_char ifi_link_state;
|
||||
u_char ifi_spare_char1;
|
||||
u_char ifi_spare_char2;
|
||||
u_char ifi_datalen;
|
||||
u_long ifi_mtu;
|
||||
u_long ifi_metric;
|
||||
u_long ifi_baudrate;
|
||||
u_long ifi_ipackets;
|
||||
u_long ifi_ierrors;
|
||||
u_long ifi_opackets;
|
||||
u_long ifi_oerrors;
|
||||
u_long ifi_collisions;
|
||||
u_long ifi_ibytes;
|
||||
u_long ifi_obytes;
|
||||
u_long ifi_imcasts;
|
||||
u_long ifi_omcasts;
|
||||
u_long ifi_iqdrops;
|
||||
u_long ifi_noproto;
|
||||
u_long ifi_hwassist;
|
||||
// FIXME: these are now unions, so maybe need to change definitions?
|
||||
#undef ifi_epoch
|
||||
time_t ifi_epoch;
|
||||
#undef ifi_lastchange
|
||||
struct timeval ifi_lastchange;
|
||||
};
|
||||
|
||||
// This structure is a duplicate of if_msghdr on FreeBSD 8-STABLE.
|
||||
// See /usr/include/net/if.h.
|
||||
struct if_msghdr8 {
|
||||
u_short ifm_msglen;
|
||||
u_char ifm_version;
|
||||
u_char ifm_type;
|
||||
int ifm_addrs;
|
||||
int ifm_flags;
|
||||
u_short ifm_index;
|
||||
struct if_data8 ifm_data;
|
||||
};
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
const (
|
||||
_statfsVersion = C.STATFS_VERSION
|
||||
_dirblksiz = C.DIRBLKSIZ
|
||||
)
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type stat_freebsd11_t C.struct_freebsd11_stat
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
type statfs_freebsd11_t C.struct_freebsd11_statfs
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
type dirent_freebsd11 C.struct_freebsd11_dirent
|
||||
|
||||
type Fsid C.struct_fsid
|
||||
|
||||
// File system limits
|
||||
|
||||
const (
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Advice to Fadvise
|
||||
|
||||
const (
|
||||
FADV_NORMAL = C.POSIX_FADV_NORMAL
|
||||
FADV_RANDOM = C.POSIX_FADV_RANDOM
|
||||
FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL
|
||||
FADV_WILLNEED = C.POSIX_FADV_WILLNEED
|
||||
FADV_DONTNEED = C.POSIX_FADV_DONTNEED
|
||||
FADV_NOREUSE = C.POSIX_FADV_NOREUSE
|
||||
)
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPMreqn C.struct_ip_mreqn
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_ATTACH = C.PT_ATTACH
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_DETACH = C.PT_DETACH
|
||||
PTRACE_GETFPREGS = C.PT_GETFPREGS
|
||||
PTRACE_GETFSBASE = C.PT_GETFSBASE
|
||||
PTRACE_GETLWPLIST = C.PT_GETLWPLIST
|
||||
PTRACE_GETNUMLWPS = C.PT_GETNUMLWPS
|
||||
PTRACE_GETREGS = C.PT_GETREGS
|
||||
PTRACE_GETXSTATE = C.PT_GETXSTATE
|
||||
PTRACE_IO = C.PT_IO
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
PTRACE_LWPEVENTS = C.PT_LWP_EVENTS
|
||||
PTRACE_LWPINFO = C.PT_LWPINFO
|
||||
PTRACE_SETFPREGS = C.PT_SETFPREGS
|
||||
PTRACE_SETREGS = C.PT_SETREGS
|
||||
PTRACE_SINGLESTEP = C.PT_STEP
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
)
|
||||
|
||||
const (
|
||||
PIOD_READ_D = C.PIOD_READ_D
|
||||
PIOD_WRITE_D = C.PIOD_WRITE_D
|
||||
PIOD_READ_I = C.PIOD_READ_I
|
||||
PIOD_WRITE_I = C.PIOD_WRITE_I
|
||||
)
|
||||
|
||||
const (
|
||||
PL_FLAG_BORN = C.PL_FLAG_BORN
|
||||
PL_FLAG_EXITED = C.PL_FLAG_EXITED
|
||||
PL_FLAG_SI = C.PL_FLAG_SI
|
||||
)
|
||||
|
||||
const (
|
||||
TRAP_BRKPT = C.TRAP_BRKPT
|
||||
TRAP_TRACE = C.TRAP_TRACE
|
||||
)
|
||||
|
||||
type PtraceLwpInfoStruct C.struct_ptrace_lwpinfo
|
||||
|
||||
type __Siginfo C.struct___siginfo
|
||||
|
||||
type Sigset_t C.sigset_t
|
||||
|
||||
type Reg C.struct_reg
|
||||
|
||||
type FpReg C.struct_fpreg
|
||||
|
||||
type PtraceIoDesc C.struct_ptrace_io_desc
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent_freebsd11
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
sizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr8
|
||||
sizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfData = C.sizeof_struct_if_data8
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr
|
||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type ifMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr8
|
||||
|
||||
type ifData C.struct_if_data
|
||||
|
||||
type IfData C.struct_if_data8
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfmaMsghdr C.struct_ifma_msghdr
|
||||
|
||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfZbuf = C.sizeof_struct_bpf_zbuf
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
SizeofBpfZbufHeader = C.sizeof_struct_bpf_zbuf_header
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfZbuf C.struct_bpf_zbuf
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
type BpfZbufHeader C.struct_bpf_zbuf_header
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLINIGNEOF = C.POLLINIGNEOF
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// Capabilities
|
||||
|
||||
type CapRights C.struct_cap_rights
|
||||
|
||||
// Uname
|
||||
|
||||
type Utsname C.struct_utsname
|
290
vendor/golang.org/x/sys/unix/types_netbsd.go
generated
vendored
Normal file
290
vendor/golang.org/x/sys/unix/types_netbsd.go
generated
vendored
Normal file
@ -0,0 +1,290 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
type Fsid C.fsid_t
|
||||
|
||||
// File system limits
|
||||
|
||||
const (
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Advice to Fadvise
|
||||
|
||||
const (
|
||||
FADV_NORMAL = C.POSIX_FADV_NORMAL
|
||||
FADV_RANDOM = C.POSIX_FADV_RANDOM
|
||||
FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL
|
||||
FADV_WILLNEED = C.POSIX_FADV_WILLNEED
|
||||
FADV_DONTNEED = C.POSIX_FADV_DONTNEED
|
||||
FADV_NOREUSE = C.POSIX_FADV_NOREUSE
|
||||
)
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
)
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
type Mclpool C.struct_mclpool
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
type BpfTimeval C.struct_bpf_timeval
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
type Ptmget C.struct_ptmget
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// Sysctl
|
||||
|
||||
type Sysctlnode C.struct_sysctlnode
|
||||
|
||||
// Uname
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
// Clockinfo
|
||||
|
||||
const SizeofClockinfo = C.sizeof_struct_clockinfo
|
||||
|
||||
type Clockinfo C.struct_clockinfo
|
283
vendor/golang.org/x/sys/unix/types_openbsd.go
generated
vendored
Normal file
283
vendor/golang.org/x/sys/unix/types_openbsd.go
generated
vendored
Normal file
@ -0,0 +1,283 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <uvm/uvmexp.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
type Fsid C.fsid_t
|
||||
|
||||
// File system limits
|
||||
|
||||
const (
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
)
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
type Mclpool C.struct_mclpool
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
type BpfTimeval C.struct_bpf_timeval
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// Signal Sets
|
||||
|
||||
type Sigset_t C.sigset_t
|
||||
|
||||
// Uname
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
// Uvmexp
|
||||
|
||||
const SizeofUvmexp = C.sizeof_struct_uvmexp
|
||||
|
||||
type Uvmexp C.struct_uvmexp
|
||||
|
||||
// Clockinfo
|
||||
|
||||
const SizeofClockinfo = C.sizeof_struct_clockinfo
|
||||
|
||||
type Clockinfo C.struct_clockinfo
|
266
vendor/golang.org/x/sys/unix/types_solaris.go
generated
vendored
Normal file
266
vendor/golang.org/x/sys/unix/types_solaris.go
generated
vendored
Normal file
@ -0,0 +1,266 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
// These defines ensure that builds done on newer versions of Solaris are
|
||||
// backwards-compatible with older versions of Solaris and
|
||||
// OpenSolaris-based derivatives.
|
||||
#define __USE_SUNOS_SOCKETS__ // msghdr
|
||||
#define __USE_LEGACY_PROTOTYPES__ // iovec
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <limits.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <termio.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <ustat.h>
|
||||
#include <utime.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
PathMax = C.PATH_MAX
|
||||
MaxHostNameLen = C.MAXHOSTNAMELEN
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
type Timeval32 C.struct_timeval32
|
||||
|
||||
type Tms C.struct_tms
|
||||
|
||||
type Utimbuf C.struct_utimbuf
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
// Filesystems
|
||||
|
||||
type _Fsblkcnt_t C.fsblkcnt_t
|
||||
|
||||
type Statvfs_t C.struct_statvfs
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Misc
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
type Ustat_t C.struct_ustat
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
||||
AT_EACCESS = C.AT_EACCESS
|
||||
)
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfTimeval C.struct_bpf_timeval
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Termio C.struct_termio
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
14
vendor/modules.txt
vendored
14
vendor/modules.txt
vendored
@ -1,6 +1,6 @@
|
||||
# git.rootprojects.org/root/go-gitver/v2 v2.0.2
|
||||
git.rootprojects.org/root/go-gitver/v2
|
||||
git.rootprojects.org/root/go-gitver/v2/gitver
|
||||
# git.rootprojects.org/root/go-gitver v1.1.2
|
||||
git.rootprojects.org/root/go-gitver
|
||||
git.rootprojects.org/root/go-gitver/gitver
|
||||
# github.com/BurntSushi/toml v0.3.1
|
||||
github.com/BurntSushi/toml
|
||||
# github.com/UnnoTed/fileb0x v1.1.3
|
||||
@ -32,8 +32,6 @@ github.com/mattn/go-colorable
|
||||
github.com/mattn/go-isatty
|
||||
# github.com/mattn/go-runewidth v0.0.3
|
||||
github.com/mattn/go-runewidth
|
||||
# github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936
|
||||
github.com/mitchellh/go-ps
|
||||
# github.com/mitchellh/go-wordwrap v1.0.0
|
||||
github.com/mitchellh/go-wordwrap
|
||||
# github.com/nsf/termbox-go v0.0.0-20180819125858-b66b20ab708e
|
||||
@ -45,15 +43,15 @@ github.com/valyala/bytebufferpool
|
||||
# github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4
|
||||
github.com/valyala/fasttemplate
|
||||
# golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b
|
||||
golang.org/x/crypto/acme
|
||||
golang.org/x/crypto/acme/autocert
|
||||
golang.org/x/crypto/acme
|
||||
# golang.org/x/net v0.0.0-20180921000356-2f5d2388922f
|
||||
golang.org/x/net/context
|
||||
golang.org/x/net/webdav
|
||||
golang.org/x/net/context
|
||||
golang.org/x/net/webdav/internal/xml
|
||||
# golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb
|
||||
golang.org/x/sys/unix
|
||||
golang.org/x/sys/windows
|
||||
golang.org/x/sys/windows/registry
|
||||
golang.org/x/sys/unix
|
||||
# gopkg.in/yaml.v2 v2.2.1
|
||||
gopkg.in/yaml.v2
|
||||
|
Loading…
x
Reference in New Issue
Block a user