mirror of
https://github.com/therootcompany/serviceman.git
synced 2025-04-21 14:50:45 +00:00
Compare commits
45 Commits
Author | SHA1 | Date | |
---|---|---|---|
7c605e5e0b | |||
ab5a6f51b6 | |||
f3ab5471dd | |||
32c71bd698 | |||
8277fa7ac6 | |||
3b6c4bbb7d | |||
1196f1d389 | |||
2824ee4c62 | |||
e7a02191d8 | |||
693e61d7d4 | |||
258623ae44 | |||
8b6479dc95 | |||
3513b64aa7 | |||
b64dbc6ca6 | |||
6c6c0123ed | |||
|
b7989893cd | ||
c84dc517a9 | |||
34ed9cc065 | |||
f03a0755af | |||
cc0176e058 | |||
b3cbca14c6 | |||
6ec2de0602 | |||
76710d58fa | |||
94c00a777d | |||
c78cd82059 | |||
c8453f8d54 | |||
04ee9550ee | |||
a31ba75927 | |||
386a6694e3 | |||
f97f217bc6 | |||
f95897cf30 | |||
40a82f26c4 | |||
389b88331d | |||
8e1bd12df7 | |||
dd25ba0787 | |||
f9631d852a | |||
b74d9f4332 | |||
4c44f70ec3 | |||
58cf28df8e | |||
7035ede0b9 | |||
d610b8cb61 | |||
75ae3eea07 | |||
04e162b20f | |||
2b7148c3ae | |||
00749b3465 |
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,3 +1,10 @@
|
|||||||
|
/serviceman
|
||||||
|
/manager/static/ab0x.go
|
||||||
|
dist
|
||||||
|
xversion.go
|
||||||
|
|
||||||
|
*~
|
||||||
|
.*~
|
||||||
# ---> Go
|
# ---> Go
|
||||||
# Binaries for programs and plugins
|
# Binaries for programs and plugins
|
||||||
*.exe
|
*.exe
|
||||||
|
36
.goreleaser.yml
Normal file
36
.goreleaser.yml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
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:'
|
341
README.md
341
README.md
@ -1,69 +1,114 @@
|
|||||||
# go-serviceman
|
# New, Rewritten Version at New Repo
|
||||||
|
|
||||||
A cross-platform service manager.
|
See <https://github.com/bnnanet/serviceman>.
|
||||||
|
|
||||||
Because debugging launchctl, systemd, etc absolutely sucks!
|
## [serviceman-sh](https://github.com/bnnanet/serviceman)
|
||||||
|
|
||||||
...and I wanted a reasonable way to install [Telebit](https://telebit.io) on Windows.
|
The new version is rewritten in POSIX script.
|
||||||
(see more in the **Why** section below)
|
|
||||||
|
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)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Unprivileged (User Mode) Services
|
- Unprivileged (User Mode) Services with `--user` (_Default_)
|
||||||
- [x] Linux (`sytemctl --user`)
|
- [x] Linux (`sytemctl --user`)
|
||||||
- [x] MacOS (`launchctl`)
|
- [x] MacOS (`launchctl`)
|
||||||
- [x] Windows (`HKEY_CURRENT_USER/.../Run`)
|
- [x] Windows (`HKEY_CURRENT_USER/.../Run`)
|
||||||
- Privileged (System) Services
|
- Privileged (System) Services with `--system` (_Default_ for `root`)
|
||||||
- [x] Linux (`sudo sytemctl`)
|
- [x] Linux (`sudo sytemctl`)
|
||||||
- [x] MacOS (`sudo launchctl`)
|
- [x] MacOS (`sudo launchctl`)
|
||||||
- [ ] Windows (_not yet implemented_)
|
- [ ] Windows (_not yet implemented_)
|
||||||
|
|
||||||
# Table of Contents
|
# Table of Contents
|
||||||
|
|
||||||
- Usage
|
- Usage
|
||||||
- Install
|
- Install
|
||||||
- Examples
|
- Examples
|
||||||
- compiled programs
|
- compiled programs
|
||||||
- scripts
|
- scripts
|
||||||
- bash
|
- bash
|
||||||
- node
|
- node
|
||||||
- python
|
- python
|
||||||
- ruby
|
- ruby
|
||||||
- Logging
|
- PATH
|
||||||
- Debugging
|
- Logging
|
||||||
- Windows
|
- Debugging
|
||||||
- Building
|
- Windows
|
||||||
- Why
|
- Building
|
||||||
- Legal
|
- More Why
|
||||||
|
- Legal
|
||||||
|
|
||||||
# Usage
|
# Usage (DEPRECATED)
|
||||||
|
|
||||||
The basic pattern of usage, and what that might look like:
|
The basic pattern of usage:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
serviceman add [options] [interpreter] <service> -- [service options]
|
sudo serviceman add --name "foobar" [options] [interpreter] <service> [--] [service options]
|
||||||
|
sudo serviceman start <service>
|
||||||
|
sudo serviceman stop <service>
|
||||||
|
sudo serviceman list --all
|
||||||
|
serviceman version
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
And what that might look like:
|
||||||
serviceman add foo.exe
|
|
||||||
|
```bash
|
||||||
|
sudo serviceman add --name "foo" foo.exe -c ./config.json
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
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
|
serviceman add --help
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
# System Services VS User Mode Services
|
||||||
serviceman version
|
|
||||||
```
|
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`.
|
||||||
|
|
||||||
# Install
|
# 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.
|
There are a number of pre-built binaries.
|
||||||
|
|
||||||
If none of them work for you, or you prefer to build from source,
|
If none of them work for you, or you prefer to build from source,
|
||||||
@ -71,14 +116,25 @@ see the instructions for building far down below.
|
|||||||
|
|
||||||
## Downloads
|
## Downloads
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -fsSL "https://rootprojects.org/serviceman/dist/$(uname -s)/$(uname -m)/serviceman" -o serviceman
|
||||||
|
chmod +x ./serviceman
|
||||||
|
```
|
||||||
|
|
||||||
### MacOS
|
### MacOS
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>See download options</summary>
|
||||||
|
|
||||||
MacOS (darwin): [64-bit Download ](https://rootprojects.org/serviceman/dist/darwin/amd64/serviceman)
|
MacOS (darwin): [64-bit Download ](https://rootprojects.org/serviceman/dist/darwin/amd64/serviceman)
|
||||||
|
|
||||||
```
|
```
|
||||||
curl https://rootprojects.org/serviceman/dist/darwin/amd64/serviceman -o serviceman
|
curl https://rootprojects.org/serviceman/dist/darwin/amd64/serviceman -o serviceman
|
||||||
|
chmod +x ./serviceman
|
||||||
```
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
@ -111,6 +167,7 @@ powershell.exe "(New-Object Net.WebClient).DownloadFile('https://rootprojects.or
|
|||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>See download options</summary>
|
<summary>See download options</summary>
|
||||||
|
|
||||||
@ -118,12 +175,14 @@ Linux (64-bit): [Download](https://rootprojects.org/serviceman/dist/linux/amd64/
|
|||||||
|
|
||||||
```
|
```
|
||||||
curl https://rootprojects.org/serviceman/dist/linux/amd64/serviceman -o serviceman
|
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)
|
Linux (32-bit): [Download](https://rootprojects.org/serviceman/dist/linux/386/serviceman)
|
||||||
|
|
||||||
```
|
```
|
||||||
curl https://rootprojects.org/serviceman/dist/linux/386/serviceman -o serviceman
|
curl https://rootprojects.org/serviceman/dist/linux/386/serviceman -o serviceman
|
||||||
|
chmod +x ./serviceman
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
@ -137,24 +196,28 @@ RPi 4 (64-bit armv8): [Download](https://rootprojects.org/serviceman/dist/linux/
|
|||||||
|
|
||||||
```
|
```
|
||||||
curl https://rootprojects.org/serviceman/dist/linux/armv8/serviceman -o serviceman`
|
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)
|
RPi 3 (armv7): [Download](https://rootprojects.org/serviceman/dist/linux/armv7/serviceman)
|
||||||
|
|
||||||
```
|
```
|
||||||
curl https://rootprojects.org/serviceman/dist/linux/armv7/serviceman -o 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)
|
ARMv6: [Download](https://rootprojects.org/serviceman/dist/linux/armv6/serviceman)
|
||||||
|
|
||||||
```
|
```
|
||||||
curl https://rootprojects.org/serviceman/dist/linux/armv6/serviceman -o 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)
|
RPi Zero (armv5): [Download](https://rootprojects.org/serviceman/dist/linux/armv5/serviceman)
|
||||||
|
|
||||||
```
|
```
|
||||||
curl https://rootprojects.org/serviceman/dist/linux/armv5/serviceman -o serviceman
|
curl https://rootprojects.org/serviceman/dist/linux/armv5/serviceman -o serviceman
|
||||||
|
chmod +x ./serviceman
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
@ -165,8 +228,8 @@ curl https://rootprojects.org/serviceman/dist/linux/armv5/serviceman -o servicem
|
|||||||
|
|
||||||
```
|
```
|
||||||
mkdir %userprofile%\bin
|
mkdir %userprofile%\bin
|
||||||
reg add HKEY_CURRENT_USER\Environment /v PATH /d "%PATH%;%userprofile%\bin"
|
|
||||||
move serviceman.exe %userprofile%\bin\serviceman.exe
|
move serviceman.exe %userprofile%\bin\serviceman.exe
|
||||||
|
reg add HKEY_CURRENT_USER\Environment /v PATH /d "%PATH%;%userprofile%\bin"
|
||||||
```
|
```
|
||||||
|
|
||||||
**All Others**
|
**All Others**
|
||||||
@ -177,43 +240,100 @@ sudo mv ./serviceman /usr/local/bin/
|
|||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
|
|
||||||
> **serviceman add** <program> **--** <program options>
|
```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 `--`)
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Compiled Programs</summary>
|
<summary>Compiled Programs</summary>
|
||||||
|
|
||||||
Normally you might your program somewhat like this:
|
Normally you might your program somewhat like this:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
dinglehopper --port 8421
|
gizmo run --port 8421 --config envs/prod.ini
|
||||||
```
|
```
|
||||||
|
|
||||||
Adding a service for that program with `serviceman` would look like this:
|
Adding a service for that program with `serviceman` would look like this:
|
||||||
|
|
||||||
> **serviceman add** dinglehopper **--** --port 8421
|
```bash
|
||||||
|
sudo serviceman add --name "gizmo" gizmo run --port 8421 --config envs/prod.ini
|
||||||
|
```
|
||||||
|
|
||||||
serviceman will find dinglehopper in your PATH.
|
serviceman will find `gizmo` in your PATH and resolve `envs/prod.ini` to its absolute path.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Using with scripts</summary>
|
<summary>Using with scripts</summary>
|
||||||
|
|
||||||
Although your text script may be executable, you'll need to specify the interpreter
|
```bash
|
||||||
in order for `serviceman` to configure the service correctly.
|
|
||||||
|
|
||||||
For example, if you had a bash script that you normally ran like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
./snarfblat.sh --port 8421
|
./snarfblat.sh --port 8421
|
||||||
```
|
```
|
||||||
|
|
||||||
You'd create a system service for it like this:
|
Although your text script may be executable, you'll need to specify the interpreter
|
||||||
|
in order for `serviceman` to configure the service correctly.
|
||||||
|
|
||||||
> serviceman add **bash** ./snarfblat.sh **--** --port 8421
|
This can be done in two ways:
|
||||||
|
|
||||||
`serviceman` will resolve `./snarfblat.sh` correctly because it comes
|
1. Put a **hashbang** in your script, such as `#!/bin/bash`.
|
||||||
before the **--**.
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
Normally you would run the script like this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./imok.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
**Background Information**
|
**Background Information**
|
||||||
|
|
||||||
@ -237,6 +357,8 @@ like this:
|
|||||||
#!/usr/local/bin/node --harmony --inspect
|
#!/usr/local/bin/node --harmony --inspect
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Serviceman understands all 3 of those approaches.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
@ -245,14 +367,37 @@ like this:
|
|||||||
If normally you run your node script something like this:
|
If normally you run your node script something like this:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
node ./demo.js --foo bar --baz
|
pushd ~/my-node-project/
|
||||||
|
npm start
|
||||||
```
|
```
|
||||||
|
|
||||||
Then you would add it as a system service like this:
|
Then you would add it as a system service like this:
|
||||||
|
|
||||||
> **serviceman add** node ./demo.js **--** --foo bar --baz
|
```bash
|
||||||
|
sudo serviceman add npm start
|
||||||
|
```
|
||||||
|
|
||||||
It is important that you specify `node ./demo.js` and not just `./demo.js`
|
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
|
||||||
|
```
|
||||||
|
|
||||||
See **Using with scripts** for more detailed information.
|
See **Using with scripts** for more detailed information.
|
||||||
|
|
||||||
@ -264,14 +409,15 @@ See **Using with scripts** for more detailed information.
|
|||||||
If normally you run your python script something like this:
|
If normally you run your python script something like this:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python ./demo.py --foo bar --baz
|
pushd ~/my-python-project/
|
||||||
|
python ./serve.py --config ./config.ini
|
||||||
```
|
```
|
||||||
|
|
||||||
Then you would add it as a system service like this:
|
Then you would add it as a system service like this:
|
||||||
|
|
||||||
> **serviceman add** python ./demo.py **--** --foo bar --baz
|
```bash
|
||||||
|
sudo serviceman add python ./serve.py --config ./config.ini
|
||||||
It is important that you specify `python ./demo.py` and not just `./demo.py`
|
```
|
||||||
|
|
||||||
See **Using with scripts** for more detailed information.
|
See **Using with scripts** for more detailed information.
|
||||||
|
|
||||||
@ -283,35 +429,65 @@ See **Using with scripts** for more detailed information.
|
|||||||
If normally you run your ruby script something like this:
|
If normally you run your ruby script something like this:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ruby ./demo.rb --foo bar --baz
|
pushd ~/my-ruby-project/
|
||||||
|
ruby ./serve.rb --config ./config.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
Then you would add it as a system service like this:
|
Then you would add it as a system service like this:
|
||||||
|
|
||||||
> **serviceman add** ruby ./demo.rb **--** --foo bar --baz
|
```bash
|
||||||
|
sudo serviceman add ruby ./serve.rb --config ./config.yaml
|
||||||
It is important that you specify `ruby ./demo.rb` and not just `./demo.rb`
|
```
|
||||||
|
|
||||||
See **Using with scripts** for more detailed information.
|
See **Using with scripts** for more detailed information.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## Relative vs Absolute Paths
|
<details>
|
||||||
|
<summary>Setting PATH</summary>
|
||||||
|
|
||||||
Although serviceman can expand the executable's path,
|
You can set the `$PATH` (`%PATH%` on Windows) for your service like this:
|
||||||
if you have any arguments with relative paths
|
|
||||||
you should switch to using absolute paths.
|
|
||||||
|
|
||||||
```
|
```bash
|
||||||
dinglehopper --config ./conf.json
|
sudo serviceman add ./myservice --path "/home/myuser/bin"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Snapshot your actual path like this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo serviceman add ./myservice --path "$PATH"
|
||||||
```
|
```
|
||||||
serviceman add dinglehopper -- --config /Users/me/dinglehopper/conf.json
|
|
||||||
|
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`
|
||||||
|
|
||||||
|
```
|
||||||
|
# Example of a / that isn't a path
|
||||||
|
# (it needs to be escaped with --)
|
||||||
|
sudo serviceman add dinglehopper config/prod -- --category color/blue
|
||||||
```
|
```
|
||||||
|
|
||||||
# Logging
|
# 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
|
When you run `serviceman add` it will either give you an error or
|
||||||
will print out the location where logs will be found.
|
will print out the location where logs will be found.
|
||||||
|
|
||||||
@ -322,14 +498,14 @@ By default it's one of these:
|
|||||||
```
|
```
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
/var/log/<NAME>/var/log/<NAME>.log
|
/opt/<NAME>/var/log/<NAME>.log
|
||||||
```
|
```
|
||||||
|
|
||||||
You set it with one of these:
|
You set it with one of these:
|
||||||
|
|
||||||
- `--logdir <path>` (cli)
|
- `--logdir <path>` (cli)
|
||||||
- `"logdir": "<path>"` (json)
|
- `"logdir": "<path>"` (json)
|
||||||
- `Logdir: "<path>"` (go)
|
- `Logdir: "<path>"` (go)
|
||||||
|
|
||||||
If anything about the logging sucks, tell me... unless they're your logs
|
If anything about the logging sucks, tell me... unless they're your logs
|
||||||
(which they probably are), in which case _you_ should fix them.
|
(which they probably are), in which case _you_ should fix them.
|
||||||
@ -339,6 +515,9 @@ why your app failed to start.
|
|||||||
|
|
||||||
# Debugging
|
# 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
|
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
|
terrible to debug - it's often difficult to find the logs, and nearly impossible
|
||||||
to interpret them, if they exist at all.
|
to interpret them, if they exist at all.
|
||||||
@ -465,7 +644,7 @@ go build -mod=vendor -ldflags "-H=windowsgui" -o serviceman.exe
|
|||||||
go build -mod=vendor -o /usr/local/bin/serviceman
|
go build -mod=vendor -o /usr/local/bin/serviceman
|
||||||
```
|
```
|
||||||
|
|
||||||
# Why
|
# More Why
|
||||||
|
|
||||||
I created this for two reasons:
|
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
|
GOOS=linux GOARCH=arm GOARM=5 go build -mod=vendor -o dist/linux/armv5/${exe} $gocmd
|
||||||
|
|
||||||
echo ""
|
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
|
# https://rootprojects.org/serviceman/dist/windows/amd64/serviceman.exe
|
||||||
|
5
go.mod
5
go.mod
@ -1,10 +1,11 @@
|
|||||||
module git.rootprojects.org/root/go-serviceman
|
module git.rootprojects.org/root/serviceman
|
||||||
|
|
||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.rootprojects.org/root/go-gitver v1.1.2
|
git.rootprojects.org/root/go-gitver/v2 v2.0.2
|
||||||
github.com/UnnoTed/fileb0x v1.1.3
|
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/net v0.0.0-20180921000356-2f5d2388922f
|
||||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb
|
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 v1.1.2 h1:AQhr8ktJyP+X+jFbtLavCi/FQLSmB6xvdG2Nfp+J2JA=
|
git.rootprojects.org/root/go-gitver/v2 v2.0.2 h1:T+Je13wrY1jz4OPJF98HnuCNp6n2Xe2uK6/NNF6a4+0=
|
||||||
git.rootprojects.org/root/go-gitver v1.1.2/go.mod h1:Rj1v3TBhvdaSphFEqMynUYwAz/4f+wY/+syBTvRrmlI=
|
git.rootprojects.org/root/go-gitver/v2 v2.0.2/go.mod h1:ur82M/jZcvr1WWihyVtNEgDBqIjo22o56wcVHeVJFh8=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/UnnoTed/fileb0x v1.1.3 h1:TUfJRey+psXuivBqasgp7Du3iXB4hzjI5UXDl+BCrzE=
|
github.com/UnnoTed/fileb0x v1.1.3 h1:TUfJRey+psXuivBqasgp7Du3iXB4hzjI5UXDl+BCrzE=
|
||||||
@ -26,6 +26,8 @@ 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-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 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
|
||||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
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 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
||||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||||
github.com/nsf/termbox-go v0.0.0-20180819125858-b66b20ab708e h1:fvw0uluMptljaRKSU8459cJ4bmi3qUYyMs5kzpic2fY=
|
github.com/nsf/termbox-go v0.0.0-20180819125858-b66b20ab708e h1:fvw0uluMptljaRKSU8459cJ4bmi3qUYyMs5kzpic2fY=
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
@ -27,6 +28,8 @@
|
|||||||
{{if .User -}}
|
{{if .User -}}
|
||||||
<key>UserName</key>
|
<key>UserName</key>
|
||||||
<string>{{ .User }}</string>
|
<string>{{ .User }}</string>
|
||||||
|
{{end -}}
|
||||||
|
{{if .Group -}}
|
||||||
<key>GroupName</key>
|
<key>GroupName</key>
|
||||||
<string>{{ .Group }}</string>
|
<string>{{ .Group }}</string>
|
||||||
<key>InitGroups</key>
|
<key>InitGroups</key>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# Generated for serviceman. Edit as you wish, but leave this line.
|
||||||
# Pre-req
|
# Pre-req
|
||||||
# sudo mkdir -p {{ .Local }}/opt/{{ .Name }}/ {{ .Local }}/var/log/{{ .Name }}
|
# sudo mkdir -p {{ .Local }}/opt/{{ .Name }}/ {{ .Local }}/var/log/{{ .Name }}
|
||||||
{{ if .System -}}
|
{{ if .System -}}
|
||||||
@ -12,18 +13,20 @@
|
|||||||
# sudo journalctl {{ if not .System -}} --user {{ end -}} -xefu {{ .Name }}
|
# sudo journalctl {{ if not .System -}} --user {{ end -}} -xefu {{ .Name }}
|
||||||
|
|
||||||
[Unit]
|
[Unit]
|
||||||
Description={{ .Title }} - {{ .Desc }}
|
Description={{ .Title }} {{ if .Desc }}- {{ .Desc }}{{ end }}
|
||||||
|
{{ if .URL -}}
|
||||||
Documentation={{ .URL }}
|
Documentation={{ .URL }}
|
||||||
|
{{ end -}}
|
||||||
{{ if .System -}}
|
{{ if .System -}}
|
||||||
After=network-online.target
|
After=network-online.target
|
||||||
Wants=network-online.target systemd-networkd-wait-online.service
|
Wants=network-online.target systemd-networkd-wait-online.service
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
|
{{ end -}}
|
||||||
[Service]
|
[Service]
|
||||||
# Restart on crash (bad signal), but not on 'clean' failure (error exit code)
|
# Restart on crash (bad signal), but not on 'clean' failure (error exit code)
|
||||||
# Allow up to 3 restarts within 10 seconds
|
# Allow up to 3 restarts within 10 seconds
|
||||||
# (it's unlikely that a user or properly-running script will do this)
|
# (it's unlikely that a user or properly-running script will do this)
|
||||||
Restart=on-abnormal
|
Restart=always
|
||||||
StartLimitInterval=10
|
StartLimitInterval=10
|
||||||
StartLimitBurst=3
|
StartLimitBurst=3
|
||||||
|
|
||||||
@ -33,10 +36,13 @@ User={{ .User }}
|
|||||||
Group={{ .Group }}
|
Group={{ .Group }}
|
||||||
|
|
||||||
{{ end -}}
|
{{ end -}}
|
||||||
|
{{- if .Envs }}
|
||||||
|
Environment="{{- range $key, $value := .Envs }}{{ $key }}={{ $value }};{{- end }}"
|
||||||
|
{{- end }}
|
||||||
{{ if .Workdir -}}
|
{{ if .Workdir -}}
|
||||||
WorkingDirectory={{ .Workdir }}
|
WorkingDirectory={{ .Workdir }}
|
||||||
{{ end -}}
|
{{ 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
|
ExecReload=/bin/kill -USR1 $MAINPID
|
||||||
|
|
||||||
{{if .Production -}}
|
{{if .Production -}}
|
||||||
|
@ -7,13 +7,14 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"git.rootprojects.org/root/go-serviceman/service"
|
"git.rootprojects.org/root/serviceman/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Install will do a best-effort attempt to install a start-on-startup
|
// Install will do a best-effort attempt to install a start-on-startup
|
||||||
// user or system service via systemd, launchd, or reg.exe
|
// user or system service via systemd, launchd, or reg.exe
|
||||||
func Install(c *service.Service) error {
|
func Install(c *service.Service) (string, error) {
|
||||||
if "" == c.Exec {
|
if "" == c.Exec {
|
||||||
c.Exec = c.Name
|
c.Exec = c.Name
|
||||||
}
|
}
|
||||||
@ -23,23 +24,35 @@ func Install(c *service.Service) error {
|
|||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "Unrecoverable Error: %s", err)
|
fmt.Fprintf(os.Stderr, "Unrecoverable Error: %s", err)
|
||||||
os.Exit(4)
|
os.Exit(4)
|
||||||
return err
|
return "", err
|
||||||
} else {
|
} else {
|
||||||
c.Home = home
|
c.Home = home
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := install(c)
|
name, err := install(c)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.MkdirAll(c.Logdir, 0755)
|
err = os.MkdirAll(c.Logdir, 0755)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsPrivileged returns true if we suspect that the current user (or process) will be able
|
// IsPrivileged returns true if we suspect that the current user (or process) will be able
|
||||||
@ -57,3 +70,22 @@ func WhereIs(exe string) (string, error) {
|
|||||||
}
|
}
|
||||||
return filepath.Abs(filepath.ToSlash(exepath))
|
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,66 +6,169 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"git.rootprojects.org/root/go-serviceman/manager/static"
|
"git.rootprojects.org/root/serviceman/manager/static"
|
||||||
"git.rootprojects.org/root/go-serviceman/service"
|
"git.rootprojects.org/root/serviceman/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
func install(c *service.Service) error {
|
const (
|
||||||
// Darwin-specific config options
|
srvExt = ".plist"
|
||||||
if c.PrivilegedPorts {
|
srvSysPath = "/Library/LaunchDaemons"
|
||||||
if !c.System {
|
srvUserPath = "Library/LaunchAgents"
|
||||||
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")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check paths first
|
var srvLen int
|
||||||
err := os.MkdirAll(filepath.Dir(plistDir), 0755)
|
|
||||||
|
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)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return 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
|
// Create service file from template
|
||||||
b, err := static.ReadFile("dist/Library/LaunchDaemons/_rdns_.plist.tmpl")
|
b, err := static.ReadFile("dist/Library/LaunchDaemons/_rdns_.plist.tmpl")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
s := string(b)
|
s := string(b)
|
||||||
rw := &bytes.Buffer{}
|
rw := &bytes.Buffer{}
|
||||||
// not sure what the template name does, but whatever
|
// not sure what the template name does, but whatever
|
||||||
tmpl, err := template.New("service").Parse(s)
|
tmpl, err := template.New("service").Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = tmpl.Execute(rw, c)
|
err = tmpl.Execute(rw, c)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the file out
|
// Write the file out
|
||||||
// TODO rdns
|
// TODO rdns
|
||||||
plistName := c.ReverseDNS + ".plist"
|
plistName := c.ReverseDNS + ".plist"
|
||||||
plistPath := filepath.Join(plistDir, plistName)
|
plistPath := filepath.Join(plistDir, plistName)
|
||||||
if err := ioutil.WriteFile(plistPath, rw.Bytes(), 0644); err != nil {
|
if err := ioutil.WriteFile(plistPath, b, 0644); err != nil {
|
||||||
|
return "", fmt.Errorf("Error writing %s: %v", plistPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Errorf("ioutil.WriteFile error: %v", err)
|
// 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
|
||||||
}
|
}
|
||||||
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 nil
|
return "launchd", nil
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,225 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"git.rootprojects.org/root/go-serviceman/manager/static"
|
"git.rootprojects.org/root/serviceman/manager/static"
|
||||||
"git.rootprojects.org/root/go-serviceman/service"
|
"git.rootprojects.org/root/serviceman/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
func install(c *service.Service) error {
|
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) {
|
||||||
// Linux-specific config options
|
// Linux-specific config options
|
||||||
if c.System {
|
if c.System {
|
||||||
if "" == c.User {
|
if "" == c.User {
|
||||||
@ -22,56 +236,4 @@ func install(c *service.Service) error {
|
|||||||
if "" == c.Group {
|
if "" == c.Group {
|
||||||
c.Group = c.User
|
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
|
|
||||||
}
|
}
|
||||||
|
74
manager/install_nixes.go
Normal file
74
manager/install_nixes.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// +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,9 +3,13 @@
|
|||||||
package manager
|
package manager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.rootprojects.org/root/go-serviceman/service"
|
"git.rootprojects.org/root/serviceman/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func Render(c *service.Service) ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func install(c *service.Service) error {
|
func install(c *service.Service) error {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -6,19 +6,32 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.rootprojects.org/root/go-serviceman/service"
|
"git.rootprojects.org/root/serviceman/runner"
|
||||||
|
"git.rootprojects.org/root/serviceman/service"
|
||||||
|
|
||||||
"golang.org/x/sys/windows/registry"
|
"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 nab some goodness from https://github.com/takama/daemon
|
||||||
|
|
||||||
// TODO system service requires elevated privileges
|
// TODO system service requires elevated privileges
|
||||||
// See https://coolaj86.com/articles/golang-and-windows-and-admins-oh-my/
|
// See https://coolaj86.com/articles/golang-and-windows-and-admins-oh-my/
|
||||||
func install(c *service.Service) error {
|
func install(c *service.Service) (string, error) {
|
||||||
/*
|
/*
|
||||||
// LEAVE THIS DOCUMENTATION HERE
|
// LEAVE THIS DOCUMENTATION HERE
|
||||||
reg.exe
|
reg.exe
|
||||||
@ -56,9 +69,12 @@ func install(c *service.Service) error {
|
|||||||
}
|
}
|
||||||
defer k.Close()
|
defer k.Close()
|
||||||
|
|
||||||
|
// Try to stop before trying to copy the file
|
||||||
|
_ = runner.Stop(c)
|
||||||
|
|
||||||
args, err := installServiceman(c)
|
args, err := installServiceman(c)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -85,7 +101,7 @@ func install(c *service.Service) error {
|
|||||||
|
|
||||||
regSZ := fmt.Sprintf(`"%s" %s`, args[0], strings.Join(args[1:], " "))
|
regSZ := fmt.Sprintf(`"%s" %s`, args[0], strings.Join(args[1:], " "))
|
||||||
if len(regSZ) > 260 {
|
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,
|
// In order for a windows gui program to not show a console,
|
||||||
// it has to not output any messages?
|
// it has to not output any messages?
|
||||||
@ -93,24 +109,193 @@ func install(c *service.Service) error {
|
|||||||
//fmt.Println(autorunKey, c.Title, regSZ)
|
//fmt.Println(autorunKey, c.Title, regSZ)
|
||||||
k.SetStringValue(c.Title, regSZ)
|
k.SetStringValue(c.Title, regSZ)
|
||||||
|
|
||||||
return nil
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
// copies self to install path and returns config path
|
// copies self to install path and returns config path
|
||||||
func installServiceman(c *service.Service) ([]string, error) {
|
func installServiceman(c *service.Service) ([]string, error) {
|
||||||
// TODO check version and upgrade or dismiss
|
// TODO check version and upgrade or dismiss
|
||||||
self := os.Args[0]
|
self := os.Args[0]
|
||||||
smdir := `\opt\serviceman`
|
|
||||||
// TODO support service level services (which probably wouldn't need serviceman)
|
args := getRunnerArgs(c)
|
||||||
smdir = filepath.Join(c.Home, ".local", smdir)
|
smbin := args[0]
|
||||||
// for now we'll scope the runner to the name of the application
|
conffile := args[len(args)-1]
|
||||||
smbin := filepath.Join(smdir, `bin\serviceman.`+c.Name+`.exe`)
|
|
||||||
|
|
||||||
if smbin != self {
|
if smbin != self {
|
||||||
err := os.MkdirAll(filepath.Dir(smbin), 0755)
|
err := os.MkdirAll(filepath.Dir(smbin), 0755)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return 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)
|
bin, err := ioutil.ReadFile(self)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -121,26 +306,19 @@ func installServiceman(c *service.Service) ([]string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := json.Marshal(c)
|
b, err := Render(c)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
// this should be impossible, so we'll just panic
|
// this should be impossible, so we'll just panic
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
confpath := filepath.Join(smdir, `etc`)
|
err = os.MkdirAll(filepath.Dir(conffile), 0755)
|
||||||
err = os.MkdirAll(confpath, 0755)
|
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
conffile := filepath.Join(confpath, c.Name+`.json`)
|
|
||||||
err = ioutil.WriteFile(conffile, b, 0640)
|
err = ioutil.WriteFile(conffile, b, 0640)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return []string{
|
return args, nil
|
||||||
smbin,
|
|
||||||
"run",
|
|
||||||
"--config",
|
|
||||||
conffile,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
253
manager/start.go
Normal file
253
manager/start.go
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
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
|
||||||
|
}
|
32
manager/start_stop_test.go
Normal file
32
manager/start_stop_test.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
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
Normal file
1
npm/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
node_modules
|
28
npm/README.md
Normal file
28
npm/README.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# 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
npm/bin/serviceman
Normal file
1
npm/bin/serviceman
Normal file
@ -0,0 +1 @@
|
|||||||
|
# this will be replaced by the postinstall script
|
18
npm/package-lock.json
generated
Normal file
18
npm/package-lock.json
generated
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"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=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
npm/package.json
Normal file
39
npm/package.json
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
269
npm/scripts/fetch-serviceman.js
Executable file
269
npm/scripts/fetch-serviceman.js
Executable file
@ -0,0 +1,269 @@
|
|||||||
|
#!/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,13 +2,17 @@ package runner
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rootprojects.org/root/go-serviceman/service"
|
"git.rootprojects.org/root/serviceman/service"
|
||||||
|
|
||||||
|
ps "github.com/mitchellh/go-ps"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Filled in on init by runner_windows.go
|
// Filled in on init by runner_windows.go
|
||||||
@ -17,7 +21,9 @@ var shellArgs = []string{}
|
|||||||
// Notes on spawning a child process
|
// Notes on spawning a child process
|
||||||
// https://groups.google.com/forum/#!topic/golang-nuts/shST-SDqIp4
|
// https://groups.google.com/forum/#!topic/golang-nuts/shST-SDqIp4
|
||||||
|
|
||||||
func Run(conf *service.Service) {
|
// 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()
|
||||||
originalBackoff := 1 * time.Second
|
originalBackoff := 1 * time.Second
|
||||||
maxBackoff := 1 * time.Minute
|
maxBackoff := 1 * time.Minute
|
||||||
threshold := 5 * time.Second
|
threshold := 5 * time.Second
|
||||||
@ -26,6 +32,17 @@ func Run(conf *service.Service) {
|
|||||||
failures := 0
|
failures := 0
|
||||||
logfile := filepath.Join(conf.Logdir, conf.Name+".log")
|
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
|
binpath := conf.Exec
|
||||||
args := []string{}
|
args := []string{}
|
||||||
if "" != conf.Interpreter {
|
if "" != conf.Interpreter {
|
||||||
@ -61,6 +78,11 @@ func Run(conf *service.Service) {
|
|||||||
if "" != conf.Workdir {
|
if "" != conf.Workdir {
|
||||||
cmd.Dir = 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()
|
err = cmd.Start()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(lf, "[%s] Could not start %q process: %s\n", time.Now(), conf.Name, err)
|
fmt.Fprintf(lf, "[%s] Could not start %q process: %s\n", time.Now(), conf.Name, err)
|
||||||
@ -84,7 +106,7 @@ func Run(conf *service.Service) {
|
|||||||
backoff = originalBackoff
|
backoff = originalBackoff
|
||||||
failures = 0
|
failures = 0
|
||||||
} else {
|
} else {
|
||||||
failures += 1
|
failures++
|
||||||
fmt.Fprintf(lf, "Waiting %s to restart %q (%d consequtive immediate exits)\n", backoff, conf.Name, failures)
|
fmt.Fprintf(lf, "Waiting %s to restart %q (%d consequtive immediate exits)\n", backoff, conf.Name, failures)
|
||||||
time.Sleep(backoff)
|
time.Sleep(backoff)
|
||||||
backoff *= 2
|
backoff *= 2
|
||||||
@ -93,4 +115,125 @@ func Run(conf *service.Service) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,7 +2,19 @@
|
|||||||
|
|
||||||
package runner
|
package runner
|
||||||
|
|
||||||
import "os/exec"
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
func backgroundCmd(cmd *exec.Cmd) {
|
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,10 +1,23 @@
|
|||||||
package runner
|
package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func backgroundCmd(cmd *exec.Cmd) {
|
func backgroundCmd(cmd *exec.Cmd) {
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
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"`
|
MultiuserProtection bool `json:"multiuser_protection,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Normalize(force bool) {
|
func (s *Service) NormalizeWithoutPath() {
|
||||||
if "" == s.Name {
|
if "" == s.Name {
|
||||||
ext := filepath.Ext(s.Exec)
|
ext := filepath.Ext(s.Exec)
|
||||||
base := filepath.Base(s.Exec[:len(s.Exec)-len(ext)])
|
base := filepath.Base(s.Exec[:len(s.Exec)-len(ext)])
|
||||||
@ -93,11 +93,16 @@ func (s *Service) Normalize(force bool) {
|
|||||||
os.Exit(4)
|
os.Exit(4)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
s.Home = home
|
||||||
s.Local = filepath.Join(home, ".local")
|
s.Local = filepath.Join(home, ".local")
|
||||||
s.Logdir = filepath.Join(home, ".local", "share", s.Name, "var", "log")
|
s.Logdir = filepath.Join(home, ".local", "share", s.Name, "var", "log")
|
||||||
} else {
|
} else {
|
||||||
s.Logdir = "/var/log/" + s.Name
|
s.Logdir = "/var/log/" + s.Name
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) Normalize(force bool) {
|
||||||
|
s.NormalizeWithoutPath()
|
||||||
|
|
||||||
// Check to see if Exec exists
|
// Check to see if Exec exists
|
||||||
// /whatever => must exist exactly
|
// /whatever => must exist exactly
|
||||||
@ -111,7 +116,7 @@ func (s *Service) Normalize(force bool) {
|
|||||||
_, err := os.Stat(optpath)
|
_, err := os.Stat(optpath)
|
||||||
if nil == err {
|
if nil == err {
|
||||||
bad = false
|
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
|
s.Exec = optpath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
566
serviceman.go
566
serviceman.go
@ -1,5 +1,6 @@
|
|||||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2
|
||||||
|
|
||||||
|
// main runs the things and does the stuff
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -9,24 +10,49 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"os/user"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
"git.rootprojects.org/root/go-serviceman/manager"
|
"git.rootprojects.org/root/serviceman/manager"
|
||||||
"git.rootprojects.org/root/go-serviceman/runner"
|
"git.rootprojects.org/root/serviceman/runner"
|
||||||
"git.rootprojects.org/root/go-serviceman/service"
|
"git.rootprojects.org/root/serviceman/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
var GitRev = "000000000"
|
var (
|
||||||
var GitVersion = "v0.0.0"
|
// commit refers to the abbreviated commit hash
|
||||||
var GitTimestamp = time.Now().Format(time.RFC3339)
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
func usage() {
|
func usage() {
|
||||||
fmt.Println("Usage: serviceman add ./foo-app -- --foo-arg")
|
fmt.Println("Usage:")
|
||||||
fmt.Println("Usage: serviceman run --config ./foo-app.json")
|
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>")
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
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 {
|
if len(os.Args) < 2 {
|
||||||
fmt.Fprintf(os.Stderr, "Too few arguments: %s\n", strings.Join(os.Args, " "))
|
fmt.Fprintf(os.Stderr, "Too few arguments: %s\n", strings.Join(os.Args, " "))
|
||||||
usage()
|
usage()
|
||||||
@ -37,11 +63,17 @@ func main() {
|
|||||||
os.Args = append(os.Args[:1], os.Args[2:]...)
|
os.Args = append(os.Args[:1], os.Args[2:]...)
|
||||||
switch top {
|
switch top {
|
||||||
case "version":
|
case "version":
|
||||||
fmt.Println(GitVersion, GitTimestamp, GitRev)
|
fmt.Println(ver())
|
||||||
case "add":
|
|
||||||
add()
|
|
||||||
case "run":
|
case "run":
|
||||||
run()
|
run()
|
||||||
|
case "add":
|
||||||
|
add()
|
||||||
|
case "start":
|
||||||
|
start()
|
||||||
|
case "stop":
|
||||||
|
stop()
|
||||||
|
case "list":
|
||||||
|
list()
|
||||||
default:
|
default:
|
||||||
fmt.Fprintf(os.Stderr, "Unknown argument %s\n", top)
|
fmt.Fprintf(os.Stderr, "Unknown argument %s\n", top)
|
||||||
usage()
|
usage()
|
||||||
@ -54,41 +86,268 @@ func add() {
|
|||||||
Restart: true,
|
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
|
force := false
|
||||||
forUser := false
|
forUser := false
|
||||||
forSystem := false
|
forSystem := false
|
||||||
|
dryrun := false
|
||||||
|
pathEnv := ""
|
||||||
flag.StringVar(&conf.Title, "title", "", "a human-friendly name for the service")
|
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.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.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.URL, "url", "", "the documentation on home page of the service")
|
||||||
//flag.StringVar(&conf.Workdir, "workdir", "", "the directory in which the service should be started")
|
flag.StringVar(&conf.Workdir, "workdir", "", "the directory in which the service should be started (if supported)")
|
||||||
flag.StringVar(&conf.ReverseDNS, "rdns", "", "a plist-friendly Reverse DNS name for launchctl (ex: com.example.foo-app)")
|
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(&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(&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.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.User, "username", "", "run the service as this user")
|
||||||
flag.StringVar(&conf.Group, "groupname", "", "run the service as this group")
|
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(&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()
|
flag.Parse()
|
||||||
args = flag.Args()
|
flagargs := flag.Args()
|
||||||
|
|
||||||
|
// You must have something to run, duh
|
||||||
|
n := len(flagargs)
|
||||||
|
if 0 == n {
|
||||||
|
fmt.Println("Usage: serviceman add ./foo-app --foo-arg")
|
||||||
|
os.Exit(2)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if forUser && forSystem {
|
if forUser && forSystem {
|
||||||
fmt.Println("Pfff! You can't --user AND --system! What are you trying to pull?")
|
fmt.Println("Pfff! You can't --user AND --system! What are you trying to pull?")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
return
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
//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)
|
||||||
|
if nil != err {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||||
|
os.Exit(500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
if forUser {
|
||||||
conf.System = false
|
conf.System = false
|
||||||
} else if forSystem {
|
} else if forSystem {
|
||||||
@ -97,44 +356,218 @@ func add() {
|
|||||||
conf.System = manager.IsPrivileged()
|
conf.System = manager.IsPrivileged()
|
||||||
}
|
}
|
||||||
|
|
||||||
n := len(args)
|
// Pretty much just for HomeDir
|
||||||
if 0 == n {
|
conf.NormalizeWithoutPath()
|
||||||
fmt.Println("Usage: serviceman add ./foo-app -- --foo-arg")
|
|
||||||
os.Exit(2)
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
execpath, err := manager.WhereIs(args[0])
|
conf := &service.Service{
|
||||||
if nil != err {
|
Name: args[0],
|
||||||
fmt.Fprintf(os.Stderr, "Error: '%s' could not be found.\n", args[0])
|
Restart: false,
|
||||||
if !force {
|
}
|
||||||
os.Exit(3)
|
if forUser {
|
||||||
return
|
conf.System = false
|
||||||
}
|
} else if forSystem {
|
||||||
|
conf.System = true
|
||||||
} else {
|
} else {
|
||||||
args[0] = execpath
|
conf.System = manager.IsPrivileged()
|
||||||
}
|
}
|
||||||
conf.Exec = args[0]
|
conf.NormalizeWithoutPath()
|
||||||
args = args[1:]
|
|
||||||
|
|
||||||
if n >= 2 {
|
err := manager.Start(conf)
|
||||||
conf.Interpreter = conf.Exec
|
|
||||||
conf.Exec = args[0]
|
|
||||||
conf.Argv = append(args[1:], conf.Argv...)
|
|
||||||
}
|
|
||||||
|
|
||||||
conf.Normalize(force)
|
|
||||||
|
|
||||||
//fmt.Printf("\n%#v\n\n", conf)
|
|
||||||
|
|
||||||
err = manager.Install(conf)
|
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||||
fmt.Fprintf(os.Stderr, "Use 'sudo' to add service as a privileged system service.\n")
|
os.Exit(500)
|
||||||
fmt.Fprintf(os.Stderr, "Use '--user' to add service as an user service.\n")
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Once started, logs will be found at:\n\t%s\n", conf.Logdir)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func run() {
|
func run() {
|
||||||
@ -145,7 +578,7 @@ func run() {
|
|||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if "" == confpath {
|
if "" == confpath {
|
||||||
fmt.Fprintf(os.Stderr, "%s", strings.Join(flag.Args(), " "))
|
fmt.Fprintf(os.Stderr, "%s\n", strings.Join(flag.Args(), " "))
|
||||||
fmt.Fprintf(os.Stderr, "--config /path/to/config.json is required\n")
|
fmt.Fprintf(os.Stderr, "--config /path/to/config.json is required\n")
|
||||||
usage()
|
usage()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -181,7 +614,8 @@ func run() {
|
|||||||
os.Exit(400)
|
os.Exit(400)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Normalize(false)
|
force := false
|
||||||
|
s.Normalize(force)
|
||||||
fmt.Printf("All output will be directed to the logs at:\n\t%s\n", s.Logdir)
|
fmt.Printf("All output will be directed to the logs at:\n\t%s\n", s.Logdir)
|
||||||
err = os.MkdirAll(s.Logdir, 0755)
|
err = os.MkdirAll(s.Logdir, 0755)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
@ -191,23 +625,11 @@ func run() {
|
|||||||
|
|
||||||
if !daemonize {
|
if !daemonize {
|
||||||
//fmt.Fprintf(os.Stdout, "Running %s %s %s\n", s.Interpreter, s.Exec, strings.Join(s.Argv, " "))
|
//fmt.Fprintf(os.Stdout, "Running %s %s %s\n", s.Interpreter, s.Exec, strings.Join(s.Argv, " "))
|
||||||
runner.Run(s)
|
if err := runner.Start(s); nil != err {
|
||||||
|
fmt.Println("Error:", err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(os.Args[0], "run", "--config", confpath)
|
manager.Run(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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
11
serviceman_darwin.go
Normal file
11
serviceman_darwin.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
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)
|
||||||
|
}
|
26
serviceman_linux.go
Normal file
26
serviceman_linux.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
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`)")
|
||||||
|
}
|
||||||
|
}
|
11
serviceman_windows.go
Normal file
11
serviceman_windows.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
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
|
package tools
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "git.rootprojects.org/root/go-gitver"
|
_ "git.rootprojects.org/root/go-gitver/v2"
|
||||||
_ "github.com/UnnoTed/fileb0x"
|
_ "github.com/UnnoTed/fileb0x"
|
||||||
)
|
)
|
||||||
|
3
vendor/git.rootprojects.org/root/go-gitver/go.mod
generated
vendored
3
vendor/git.rootprojects.org/root/go-gitver/go.mod
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
module git.rootprojects.org/root/go-gitver
|
|
||||||
|
|
||||||
go 1.12
|
|
@ -1,6 +1,10 @@
|
|||||||
xversion.go
|
xversion.go
|
||||||
zversion.go
|
zversion.go
|
||||||
|
|
||||||
|
/go-gitver
|
||||||
|
hello
|
||||||
|
examples/*/*.sum
|
||||||
|
|
||||||
# ---> Go
|
# ---> Go
|
||||||
# Binaries for programs and plugins
|
# Binaries for programs and plugins
|
||||||
*.exe
|
*.exe
|
1
vendor/git.rootprojects.org/root/go-gitver/v2/.prettierrc
generated
vendored
Normal file
1
vendor/git.rootprojects.org/root/go-gitver/v2/.prettierrc
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
@ -1,24 +1,79 @@
|
|||||||
# git-version.go
|
# [Go GitVer](https://git.rootprojects.org/root/go-gitver)
|
||||||
|
|
||||||
Use git tags to add semver to your go package.
|
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).
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
Goal: Either use an exact version like v1.0.0
|
Goals:
|
||||||
or translate the git version like v1.0.0-4-g0000000
|
|
||||||
to a semver like v1.0.1-pre4+g0000000
|
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)
|
||||||
|
|
||||||
Fail gracefully when git repo isn't available.
|
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
|
# Demo
|
||||||
|
|
||||||
Generate an `xversion.go` file:
|
Generate an `xversion.go` file:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go run git.rootprojects.org/root/go-gitver
|
go run git.rootprojects.org/root/go-gitver/v2
|
||||||
cat xversion.go
|
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
|
<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
|
generated file's `init()` will come later, and thus take priority, over
|
||||||
most other files.</small>
|
most other files.</small>
|
||||||
@ -26,15 +81,21 @@ most other files.</small>
|
|||||||
See `go-gitver`s self-generated version:
|
See `go-gitver`s self-generated version:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go run git.rootprojects.org/root/go-gitver version
|
go run git.rootprojects.org/root/go-gitver/v2 version
|
||||||
|
```
|
||||||
|
|
||||||
|
```txt
|
||||||
|
6dace8255b52e123297a44629bc32c015add310a
|
||||||
|
v1.1.4-pre2+g6dace82
|
||||||
|
2020-07-16T20:48:15-06:00
|
||||||
```
|
```
|
||||||
|
|
||||||
# QuickStart
|
# QuickStart
|
||||||
|
|
||||||
Add this to the top of your main file:
|
Add this to the top of your main file, so that it runs with `go generate`:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -45,7 +106,7 @@ Add a file that imports go-gitver (for versioning)
|
|||||||
|
|
||||||
package example
|
package example
|
||||||
|
|
||||||
import _ "git.rootprojects.org/root/go-gitver"
|
import _ "git.rootprojects.org/root/go-gitver/v2"
|
||||||
```
|
```
|
||||||
|
|
||||||
Change you build instructions to be something like this:
|
Change you build instructions to be something like this:
|
||||||
@ -56,7 +117,7 @@ go generate -mod=vendor ./...
|
|||||||
go build -mod=vendor -o example cmd/example/*.go
|
go build -mod=vendor -o example cmd/example/*.go
|
||||||
```
|
```
|
||||||
|
|
||||||
You don't have to use `mod vendor`, but I highly recommend it.
|
You don't have to use `-mod=vendor`, but I highly recommend it (just `go mod tidy; go mod vendor` to start).
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
|
|
||||||
@ -77,12 +138,12 @@ GITVER_FAIL=true
|
|||||||
For example:
|
For example:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver --fail
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 --fail
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go run -mod=vendor git.rootprojects.org/root/go-gitver version
|
go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 version
|
||||||
```
|
```
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
@ -91,9 +152,9 @@ See `examples/basic`
|
|||||||
|
|
||||||
1. Create a `tools` package in your project
|
1. Create a `tools` package in your project
|
||||||
2. Guard it against regular builds with `// +build tools`
|
2. Guard it against regular builds with `// +build tools`
|
||||||
3. Include `_ "git.rootprojects.org/root/go-gitver"` in the imports
|
3. Include `_ "git.rootprojects.org/root/go-gitver/v2"` in the imports
|
||||||
4. Declare `var GitRev, GitVersion, GitTimestamp string` in your `package main`
|
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` as well
|
5. Include `//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2` as well
|
||||||
|
|
||||||
`tools/tools.go`:
|
`tools/tools.go`:
|
||||||
|
|
||||||
@ -104,29 +165,29 @@ See `examples/basic`
|
|||||||
package tools
|
package tools
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "git.rootprojects.org/root/go-gitver"
|
_ "git.rootprojects.org/root/go-gitver/v2"
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
`main.go`:
|
`main.go`:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
//go:generate go run git.rootprojects.org/root/go-gitver --fail
|
//go:generate go run git.rootprojects.org/root/go-gitver/v2 --fail
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
GitRev = "0000000"
|
commit = "0000000"
|
||||||
GitVersion = "v0.0.0-pre0+0000000"
|
version = "0.0.0-pre0+0000000"
|
||||||
GitTimestamp = "0000-00-00T00:00:00+0000"
|
date = "0000-00-00T00:00:00+0000"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println(GitRev)
|
fmt.Println(commit)
|
||||||
fmt.Println(GitVersion)
|
fmt.Println(version)
|
||||||
fmt.Println(GitTimestamp)
|
fmt.Println(date)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -134,7 +195,7 @@ If you're using `go mod vendor` (which I highly recommend that you do),
|
|||||||
you'd modify the `go:generate` ever so slightly:
|
you'd modify the `go:generate` ever so slightly:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver --fail
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 --fail
|
||||||
```
|
```
|
||||||
|
|
||||||
The only reason I didn't do that in the example is that I'd be included
|
The only reason I didn't do that in the example is that I'd be included
|
||||||
@ -142,7 +203,7 @@ the repository in itself and that would be... weird.
|
|||||||
|
|
||||||
# Why a tools package?
|
# Why a tools package?
|
||||||
|
|
||||||
> import "git.rootprojects.org/root/go-gitver" is a program, not an importable package
|
> import "git.rootprojects.org/root/go-gitver/v2" 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
|
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`,
|
versions of a command package used for tooling to your `go.mod` with `go mod tidy`,
|
||||||
@ -182,8 +243,8 @@ git rev-parse HEAD
|
|||||||
### cannot find package "."
|
### cannot find package "."
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
package git.rootprojects.org/root/go-gitver: cannot find package "." in:
|
package git.rootprojects.org/root/go-gitver/v2: cannot find package "." in:
|
||||||
/Users/me/go-example/vendor/git.rootprojects.org/root/go-gitver
|
/Users/me/go-example/vendor/git.rootprojects.org/root/go-gitver/v2
|
||||||
cmd/example/example.go:1: running "go": exit status 1
|
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
|
//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@ -6,15 +6,14 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/format"
|
"go/format"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rootprojects.org/root/go-gitver/gitver"
|
"git.rootprojects.org/root/go-gitver/v2/gitver"
|
||||||
)
|
)
|
||||||
|
|
||||||
var GitRev, GitVersion, GitTimestamp string
|
var commit, version, date string
|
||||||
var exitCode int
|
var exitCode int
|
||||||
var verFile = "xversion.go"
|
var verFile = "xversion.go"
|
||||||
|
|
||||||
@ -33,9 +32,9 @@ func main() {
|
|||||||
pkg = args[i+1]
|
pkg = args[i+1]
|
||||||
args[i+1] = ""
|
args[i+1] = ""
|
||||||
} else if "-V" == arg || "version" == arg || "-version" == arg || "--version" == arg {
|
} else if "-V" == arg || "version" == arg || "-version" == arg || "--version" == arg {
|
||||||
fmt.Println(GitRev)
|
fmt.Println(commit)
|
||||||
fmt.Println(GitVersion)
|
fmt.Println(version)
|
||||||
fmt.Println(GitTimestamp)
|
fmt.Println(date)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,8 +44,13 @@ func main() {
|
|||||||
|
|
||||||
v, err := gitver.ExecAndParse()
|
v, err := gitver.ExecAndParse()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
log.Fatalf("Failed to get git version: %s\n", err)
|
fmt.Fprintf(os.Stderr, "Failed to get git version: %s\n", err)
|
||||||
os.Exit(exitCode)
|
if exitCode > 0 {
|
||||||
|
os.Exit(exitCode)
|
||||||
|
}
|
||||||
|
v = &gitver.Versions{
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create or overwrite the go file from template
|
// Create or overwrite the go file from template
|
||||||
@ -55,12 +59,12 @@ func main() {
|
|||||||
Package string
|
Package string
|
||||||
Timestamp string
|
Timestamp string
|
||||||
Version string
|
Version string
|
||||||
GitRev string
|
Commit string
|
||||||
}{
|
}{
|
||||||
Package: pkg,
|
Package: pkg,
|
||||||
Timestamp: v.Timestamp.Format(time.RFC3339),
|
Timestamp: v.Timestamp.Format(time.RFC3339),
|
||||||
Version: v.Version,
|
Version: v.Version,
|
||||||
GitRev: v.Rev,
|
Commit: v.Rev,
|
||||||
}); nil != err {
|
}); nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -89,10 +93,12 @@ var versionTpl = template.Must(template.New("").Parse(`// Code generated by go g
|
|||||||
package {{ .Package }}
|
package {{ .Package }}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
GitRev = "{{ .GitRev }}"
|
{{ if .Commit -}}
|
||||||
{{ if .Version -}}
|
commit = "{{ .Commit }}"
|
||||||
GitVersion = "{{ .Version }}"
|
|
||||||
{{ end -}}
|
{{ end -}}
|
||||||
GitTimestamp = "{{ .Timestamp }}"
|
{{ if .Version -}}
|
||||||
|
version = "{{ .Version }}"
|
||||||
|
{{ end -}}
|
||||||
|
date = "{{ .Timestamp }}"
|
||||||
}
|
}
|
||||||
`))
|
`))
|
@ -21,12 +21,14 @@ func init() {
|
|||||||
gitVer = regexp.MustCompile(`^(v\d+\.\d+)\.(\d+)(-(\d+))?(-(g[0-9a-f]+))?(-(dirty))?`)
|
gitVer = regexp.MustCompile(`^(v\d+\.\d+)\.(\d+)(-(\d+))?(-(g[0-9a-f]+))?(-(dirty))?`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Versions describes the various version properties
|
||||||
type Versions struct {
|
type Versions struct {
|
||||||
Timestamp time.Time
|
Timestamp time.Time
|
||||||
Version string
|
Version string
|
||||||
Rev string
|
Rev string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecAndParse will run git and parse the output
|
||||||
func ExecAndParse() (*Versions, error) {
|
func ExecAndParse() (*Versions, error) {
|
||||||
desc, err := gitDesc()
|
desc, err := gitDesc()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
@ -58,7 +60,7 @@ func gitDesc() (string, error) {
|
|||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
// Don't panic, just carry on
|
// Don't panic, just carry on
|
||||||
//out = []byte("v0.0.0-0-g0000000")
|
//out = []byte("0.0.0-0-g0000000")
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return strings.TrimSpace(string(out)), nil
|
return strings.TrimSpace(string(out)), nil
|
||||||
@ -83,7 +85,7 @@ func gitRev() (string, error) {
|
|||||||
func semVer(desc string) (string, error) {
|
func semVer(desc string) (string, error) {
|
||||||
if exactVer.MatchString(desc) {
|
if exactVer.MatchString(desc) {
|
||||||
// v1.0.0
|
// v1.0.0
|
||||||
return desc, nil
|
return strings.TrimPrefix(desc, "v"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !gitVer.MatchString(desc) {
|
if !gitVer.MatchString(desc) {
|
||||||
@ -122,10 +124,19 @@ func semVer(desc string) (string, error) {
|
|||||||
ver += vers[8]
|
ver += vers[8]
|
||||||
}
|
}
|
||||||
|
|
||||||
return ver, nil
|
return strings.TrimPrefix(ver, "v"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func gitTimestamp(desc string) (time.Time, error) {
|
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{
|
args := []string{
|
||||||
"git",
|
"git",
|
||||||
"show", desc,
|
"show", desc,
|
3
vendor/git.rootprojects.org/root/go-gitver/v2/go.mod
generated
vendored
Normal file
3
vendor/git.rootprojects.org/root/go-gitver/v2/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module git.rootprojects.org/root/go-gitver/v2
|
||||||
|
|
||||||
|
go 1.12
|
2
vendor/git.rootprojects.org/root/go-gitver/v2/go.sum
generated
vendored
Normal file
2
vendor/git.rootprojects.org/root/go-gitver/v2/go.sum
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
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
|
// use recently generated version info as a fallback
|
||||||
// for when git isn't present (i.e. go run <url>)
|
// for when git isn't present (i.e. go run <url>)
|
||||||
func init() {
|
func init() {
|
||||||
GitRev = "0b8c2d86df4bfe32ff4534eec84cd56909c398e9"
|
commit = "37c1fd4b5694fd62c9f0d6ad1df47d938accbeec"
|
||||||
GitVersion = "v1.1.1"
|
version = "2.0.0-pre1-dirty"
|
||||||
GitTimestamp = "2019-06-21T00:18:13-06:00"
|
date = "2020-10-10T16:05:59-06:00"
|
||||||
}
|
}
|
1
vendor/github.com/mitchellh/go-ps/.gitignore
generated
vendored
Normal file
1
vendor/github.com/mitchellh/go-ps/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.vagrant/
|
4
vendor/github.com/mitchellh/go-ps/.travis.yml
generated
vendored
Normal file
4
vendor/github.com/mitchellh/go-ps/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.2.1
|
21
vendor/github.com/mitchellh/go-ps/LICENSE.md
generated
vendored
Normal file
21
vendor/github.com/mitchellh/go-ps/LICENSE.md
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
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
Normal file
34
vendor/github.com/mitchellh/go-ps/README.md
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# 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
Normal file
43
vendor/github.com/mitchellh/go-ps/Vagrantfile
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# -*- 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
Normal file
40
vendor/github.com/mitchellh/go-ps/process.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// 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
Normal file
138
vendor/github.com/mitchellh/go-ps/process_darwin.go
generated
vendored
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
// +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
Normal file
260
vendor/github.com/mitchellh/go-ps/process_freebsd.go
generated
vendored
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
// +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
Normal file
35
vendor/github.com/mitchellh/go-ps/process_linux.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// +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
Normal file
96
vendor/github.com/mitchellh/go-ps/process_solaris.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// +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
Normal file
101
vendor/github.com/mitchellh/go-ps/process_unix.go
generated
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// +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
Normal file
119
vendor/github.com/mitchellh/go-ps/process_windows.go
generated
vendored
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// +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
39
vendor/github.com/nsf/termbox-go/syscalls.go
generated
vendored
@ -1,39 +0,0 @@
|
|||||||
// +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
94
vendor/golang.org/x/net/webdav/litmus_test_server.go
generated
vendored
@ -1,94 +0,0 @@
|
|||||||
// 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
61
vendor/golang.org/x/sys/unix/mkasm_darwin.go
generated
vendored
@ -1,61 +0,0 @@
|
|||||||
// 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
122
vendor/golang.org/x/sys/unix/mkpost.go
generated
vendored
@ -1,122 +0,0 @@
|
|||||||
// 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
407
vendor/golang.org/x/sys/unix/mksyscall.go
generated
vendored
@ -1,407 +0,0 @@
|
|||||||
// 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
415
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go
generated
vendored
@ -1,415 +0,0 @@
|
|||||||
// 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
614
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go
generated
vendored
@ -1,614 +0,0 @@
|
|||||||
// 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
335
vendor/golang.org/x/sys/unix/mksyscall_solaris.go
generated
vendored
@ -1,335 +0,0 @@
|
|||||||
// 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
355
vendor/golang.org/x/sys/unix/mksysctl_openbsd.go
generated
vendored
@ -1,355 +0,0 @@
|
|||||||
// 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
190
vendor/golang.org/x/sys/unix/mksysnum.go
generated
vendored
@ -1,190 +0,0 @@
|
|||||||
// 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
237
vendor/golang.org/x/sys/unix/types_aix.go
generated
vendored
@ -1,237 +0,0 @@
|
|||||||
// 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
283
vendor/golang.org/x/sys/unix/types_darwin.go
generated
vendored
@ -1,283 +0,0 @@
|
|||||||
// 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
263
vendor/golang.org/x/sys/unix/types_dragonfly.go
generated
vendored
@ -1,263 +0,0 @@
|
|||||||
// 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
400
vendor/golang.org/x/sys/unix/types_freebsd.go
generated
vendored
@ -1,400 +0,0 @@
|
|||||||
// 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
290
vendor/golang.org/x/sys/unix/types_netbsd.go
generated
vendored
@ -1,290 +0,0 @@
|
|||||||
// 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
283
vendor/golang.org/x/sys/unix/types_openbsd.go
generated
vendored
@ -1,283 +0,0 @@
|
|||||||
// 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
266
vendor/golang.org/x/sys/unix/types_solaris.go
generated
vendored
@ -1,266 +0,0 @@
|
|||||||
// 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 v1.1.2
|
# git.rootprojects.org/root/go-gitver/v2 v2.0.2
|
||||||
git.rootprojects.org/root/go-gitver
|
git.rootprojects.org/root/go-gitver/v2
|
||||||
git.rootprojects.org/root/go-gitver/gitver
|
git.rootprojects.org/root/go-gitver/v2/gitver
|
||||||
# github.com/BurntSushi/toml v0.3.1
|
# github.com/BurntSushi/toml v0.3.1
|
||||||
github.com/BurntSushi/toml
|
github.com/BurntSushi/toml
|
||||||
# github.com/UnnoTed/fileb0x v1.1.3
|
# github.com/UnnoTed/fileb0x v1.1.3
|
||||||
@ -32,6 +32,8 @@ github.com/mattn/go-colorable
|
|||||||
github.com/mattn/go-isatty
|
github.com/mattn/go-isatty
|
||||||
# github.com/mattn/go-runewidth v0.0.3
|
# github.com/mattn/go-runewidth v0.0.3
|
||||||
github.com/mattn/go-runewidth
|
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 v1.0.0
|
||||||
github.com/mitchellh/go-wordwrap
|
github.com/mitchellh/go-wordwrap
|
||||||
# github.com/nsf/termbox-go v0.0.0-20180819125858-b66b20ab708e
|
# github.com/nsf/termbox-go v0.0.0-20180819125858-b66b20ab708e
|
||||||
@ -43,15 +45,15 @@ github.com/valyala/bytebufferpool
|
|||||||
# github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4
|
# github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4
|
||||||
github.com/valyala/fasttemplate
|
github.com/valyala/fasttemplate
|
||||||
# golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b
|
# golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b
|
||||||
golang.org/x/crypto/acme/autocert
|
|
||||||
golang.org/x/crypto/acme
|
golang.org/x/crypto/acme
|
||||||
|
golang.org/x/crypto/acme/autocert
|
||||||
# golang.org/x/net v0.0.0-20180921000356-2f5d2388922f
|
# golang.org/x/net v0.0.0-20180921000356-2f5d2388922f
|
||||||
golang.org/x/net/webdav
|
|
||||||
golang.org/x/net/context
|
golang.org/x/net/context
|
||||||
|
golang.org/x/net/webdav
|
||||||
golang.org/x/net/webdav/internal/xml
|
golang.org/x/net/webdav/internal/xml
|
||||||
# golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb
|
# golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb
|
||||||
|
golang.org/x/sys/unix
|
||||||
golang.org/x/sys/windows
|
golang.org/x/sys/windows
|
||||||
golang.org/x/sys/windows/registry
|
golang.org/x/sys/windows/registry
|
||||||
golang.org/x/sys/unix
|
|
||||||
# gopkg.in/yaml.v2 v2.2.1
|
# gopkg.in/yaml.v2 v2.2.1
|
||||||
gopkg.in/yaml.v2
|
gopkg.in/yaml.v2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user