Compare commits
30 Commits
stable
...
serviceman
Author | SHA1 | Date |
---|---|---|
AJ ONeal | 38ae4a4a86 | 5 years ago |
AJ ONeal | 7cf8c529dd | 5 years ago |
AJ ONeal | f266559cff | 5 years ago |
AJ ONeal | a4b8a43b32 | 5 years ago |
AJ ONeal | 944731f443 | 5 years ago |
AJ ONeal | b6d4230de4 | 5 years ago |
AJ ONeal | d381c28a0c | 5 years ago |
AJ ONeal | 11b5474d1e | 5 years ago |
AJ ONeal | da440ce000 | 5 years ago |
AJ ONeal | b4b4b68bac | 5 years ago |
AJ ONeal | 33dd835092 | 5 years ago |
AJ ONeal | dafc02201f | 5 years ago |
AJ ONeal | 1c38262641 | 5 years ago |
AJ ONeal | 1f736a71be | 5 years ago |
AJ ONeal | 3ca47d18cd | 5 years ago |
AJ ONeal | c927f0c6c6 | 5 years ago |
AJ ONeal | 8308fe7af8 | 5 years ago |
AJ ONeal | 512e79bbe0 | 5 years ago |
AJ ONeal | b13624444b | 5 years ago |
AJ ONeal | 74230d93e2 | 5 years ago |
AJ ONeal | c40340939a | 5 years ago |
AJ ONeal | 860f852df9 | 5 years ago |
AJ ONeal | b3ddca4ae2 | 5 years ago |
AJ ONeal | d16822b23c | 5 years ago |
AJ ONeal | 7bb71f07ca | 5 years ago |
AJ ONeal | 1e733b6d6d | 5 years ago |
AJ ONeal | c183ebc0b6 | 5 years ago |
AJ ONeal | 308b69da57 | 5 years ago |
AJ ONeal | 0ffa20d8e9 | 5 years ago |
AJ ONeal | 5090134d72 | 5 years ago |
22 changed files with 1984 additions and 1387 deletions
@ -0,0 +1,4 @@ |
|||
# v0.20.8 |
|||
|
|||
- Add CHANGELOG.md |
|||
- Switch to serviceman |
@ -0,0 +1,3 @@ |
|||
#!/usr/bin/env bash |
|||
"$(dirname $(dirname $0))/bin/node" "$(dirname $(dirname $0))/bin/telebit.js" "$@" |
|||
exit $? |
@ -0,0 +1 @@ |
|||
@"%~dp0\..\bin\node" "%~dp0\..\bin\telebit.js" %* |
@ -0,0 +1,756 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"archive/tar" |
|||
"archive/zip" |
|||
"compress/gzip" |
|||
"fmt" |
|||
"io" |
|||
"io/ioutil" |
|||
"log" |
|||
"net/http" |
|||
"os" |
|||
"os/exec" |
|||
"path/filepath" |
|||
"strings" |
|||
) |
|||
|
|||
type pkg struct { |
|||
os string |
|||
arch string |
|||
ext string |
|||
exe string |
|||
} |
|||
|
|||
// ReaderAtCloser is just what it sounds
|
|||
type ReaderAtCloser interface { |
|||
io.ReaderAt |
|||
io.Reader |
|||
io.Closer |
|||
} |
|||
|
|||
func main() { |
|||
nodeArches := map[string]string{ |
|||
"windows": "win", |
|||
"darwin": "darwin", |
|||
"linux": "linux", |
|||
"amd64": "x64", |
|||
"386": "x86", |
|||
"armv7": "armv7l", |
|||
"armv6": "armv6l", |
|||
"arm64": "arm64", |
|||
//"armv8": "arm64",
|
|||
} |
|||
|
|||
pkgs := []pkg{ |
|||
pkg{os: "darwin", arch: "amd64", ext: "tar.gz"}, |
|||
pkg{os: "windows", arch: "amd64", ext: "zip", exe: ".exe"}, |
|||
pkg{os: "windows", arch: "386", ext: "zip", exe: ".exe"}, |
|||
pkg{os: "linux", arch: "amd64", ext: "tar.gz"}, |
|||
//pkg{os: "linux", arch: "armv8", ext: "tar.gz"},
|
|||
pkg{os: "linux", arch: "arm64", ext: "tar.gz"}, |
|||
pkg{os: "linux", arch: "armv7", ext: "tar.gz"}, |
|||
pkg{os: "linux", arch: "armv6", ext: "tar.gz"}, |
|||
} |
|||
|
|||
nodev := "10.16.0" |
|||
release := "stable" |
|||
|
|||
// temp file for the zip
|
|||
// TODO use mktemp
|
|||
f, err := os.OpenFile(fmt.Sprintf("telebit-%s.zip", release), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
|
|||
// get from trusted git source
|
|||
turl := fmt.Sprintf("https://git.rootprojects.org/root/telebit.js/archive/%s.zip", release) |
|||
resp, err := http.Get(turl) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
defer resp.Body.Close() |
|||
if resp.StatusCode >= 300 || resp.StatusCode < 200 { |
|||
log.Fatal("Bad deal on telebit download:", resp.Status) |
|||
} |
|||
|
|||
_, err = io.Copy(f, resp.Body) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
err = f.Sync() |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
|
|||
// Get a copy of all the node modules
|
|||
npmdir := "tmp-package-modules" |
|||
// TODO save bits /*
|
|||
err = os.RemoveAll(npmdir) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
err = os.MkdirAll(npmdir, 0755) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
b, err := ioutil.ReadFile("package.json") |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
err = ioutil.WriteFile(filepath.Join(npmdir, "package.json"), b, 0644) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
nodeExec, err := exec.LookPath("node") |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
npmExec, err := exec.LookPath("npm") |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
cmd := exec.Command(nodeExec, npmExec, "install") |
|||
cmd.Stdin = os.Stdin |
|||
cmd.Stdout = os.Stdout |
|||
cmd.Stderr = os.Stderr |
|||
cmd.Dir = npmdir |
|||
err = cmd.Run() |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
//*/
|
|||
|
|||
for i := range pkgs { |
|||
pkg := pkgs[i] |
|||
|
|||
arch := pkg.arch |
|||
if "arm64" == arch { |
|||
// TODO switch the pathman and serviceman URLs
|
|||
arch = "armv8" |
|||
} |
|||
fmt.Printf("\nOS: %s\nArch: %s\n", pkg.os, arch) |
|||
|
|||
// Create a fresh directory for this telebit release
|
|||
outdir := fmt.Sprintf("telebit-%s-%s-%s", release, pkg.os, pkg.arch) |
|||
fmt.Printf("(clean) Release:%s\n", outdir) |
|||
err := os.RemoveAll(outdir) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
|
|||
nos := nodeArches[pkg.os] |
|||
narch := nodeArches[pkg.arch] |
|||
|
|||
// Grab the node files
|
|||
npath := fmt.Sprintf("node-v%s-%s-%s", nodev, nos, narch) |
|||
nfile := fmt.Sprintf("%s.%s", npath, pkg.ext) |
|||
// TODO check remote filesize anyway as a quick sanity check
|
|||
nurl := fmt.Sprintf("https://nodejs.org/download/release/v%s/%s", nodev, nfile) |
|||
err = download("node package", nurl, nfile, false) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
|
|||
// lay down the node directory first
|
|||
fmt.Printf("Unpacking %s %s\n", nfile, pkg.ext) |
|||
switch pkg.ext { |
|||
case "zip": |
|||
z, err := os.Open(nfile) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
s, err := z.Stat() |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
strip := 1 |
|||
if "windows" == pkg.os { |
|||
// re-nest into "bin" for consistency
|
|||
err = unzip(z, s.Size(), filepath.Join(outdir, "bin"), strip) |
|||
// handle the special case of git bash
|
|||
sh := strings.Join([]string{ |
|||
`#!/usr/bin/env bash`, |
|||
`"$(dirname "$0")/node.exe" "$@"`, |
|||
`exit $?`, |
|||
}, "\n") |
|||
script := filepath.Join(outdir, "bin", "node") |
|||
if err := ioutil.WriteFile(script, []byte(sh), 0755); nil != err { |
|||
panic(err) |
|||
} |
|||
} else { |
|||
err = unzip(z, s.Size(), outdir, strip) |
|||
} |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
case "tar.gz": |
|||
// SAVE ON BITS /*
|
|||
tgz, err := os.Open(nfile) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
defer tgz.Close() |
|||
tarfile, err := gzip.NewReader(tgz) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
// TODOD XXX turn back on
|
|||
strip := 1 |
|||
err = untar(tarfile, outdir, strip) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
//*/
|
|||
default: |
|||
panic(fmt.Errorf("%s", "Liar!!")) |
|||
} |
|||
|
|||
// TODO how to handle node modules?
|
|||
// overlay our stuff on top of the node release package
|
|||
z, err := os.Open(fmt.Sprintf("telebit-%s.zip", release)) |
|||
fmt.Printf("Overlaying %s\n", outdir) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
defer z.Close() |
|||
|
|||
s, err := z.Stat() |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
strip := 1 |
|||
if err := unzip(z, s.Size(), outdir, strip); nil != err { |
|||
panic(err) |
|||
} |
|||
|
|||
pr, pw := io.Pipe() |
|||
go func() { |
|||
tw := tar.NewWriter(pw) |
|||
defer tw.Close() |
|||
//fis, err := ioutil.ReadDir(npmdir)
|
|||
fi, err := os.Stat(npmdir) |
|||
if nil != err { |
|||
panic("stat:" + err.Error()) |
|||
} |
|||
//err = tarDir(tw, npmdir, fis, "")
|
|||
err = tarEntry(tw, "", fi, "") |
|||
if nil != err { |
|||
panic("tarError:" + err.Error()) |
|||
} |
|||
}() |
|||
|
|||
err = untar(pr, outdir, 1) |
|||
if nil != err { |
|||
panic("untarError:" + err.Error()) |
|||
} |
|||
|
|||
// Get pathman for the platform
|
|||
pathmanURL := fmt.Sprintf( |
|||
"https://rootprojects.org/pathman/dist/%s/%s/pathman"+pkg.exe, |
|||
pkg.os, |
|||
arch, |
|||
) |
|||
pathmanFile := filepath.Join(outdir, "node_modules/.bin", "pathman") + pkg.exe |
|||
err = download("pathman", pathmanURL, pathmanFile, true) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
if ".exe" == pkg.exe { |
|||
sh := strings.Join([]string{ |
|||
`#!/usr/bin/env bash`, |
|||
`"$(dirname "$0")/pathman.exe" "$@"`, |
|||
`exit $?`, |
|||
}, "\n") |
|||
script := filepath.Join(outdir, "node_modules/.bin", "pathman") |
|||
if err := ioutil.WriteFile(script, []byte(sh), 0755); nil != err { |
|||
panic(err) |
|||
} |
|||
} |
|||
|
|||
// Get serviceman for the platform
|
|||
servicemanURL := fmt.Sprintf( |
|||
"https://rootprojects.org/serviceman/dist/%s/%s/serviceman"+pkg.exe, |
|||
pkg.os, |
|||
arch, |
|||
) |
|||
servicemanFile := filepath.Join(outdir, "node_modules/.bin", "serviceman") + pkg.exe |
|||
err = download("serviceman", servicemanURL, servicemanFile, true) |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
if ".exe" == pkg.exe { |
|||
sh := strings.Join([]string{ |
|||
`#!/usr/bin/env bash`, |
|||
`"$(dirname "$0")/serviceman.exe" "$@"`, |
|||
`exit $?`, |
|||
}, "\n") |
|||
script := filepath.Join(outdir, "node_modules/.bin", "serviceman") |
|||
if err := ioutil.WriteFile(script, []byte(sh), 0755); nil != err { |
|||
panic(err) |
|||
} |
|||
} |
|||
|
|||
// Write out the packaged deliverable
|
|||
f, err := os.OpenFile(outdir+"."+pkg.ext, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) |
|||
defer f.Close() |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
|
|||
//fis, err := ioutil.ReadDir(npmdir)
|
|||
fi, err := os.Stat(outdir) |
|||
if nil != err { |
|||
panic("stat:" + err.Error()) |
|||
} |
|||
|
|||
switch pkg.ext { |
|||
case "zip": |
|||
err = Zip(f, outdir, "") |
|||
if nil != err { |
|||
panic("zipError:" + err.Error()) |
|||
} |
|||
case "tar.gz": |
|||
// Write out the tar
|
|||
|
|||
zw := gzip.NewWriter(f) |
|||
defer zw.Close() |
|||
tw := tar.NewWriter(zw) |
|||
defer tw.Close() |
|||
|
|||
// TODO create Tar() in go-examples
|
|||
//err = tarDir(tw, outdir, fis, "")
|
|||
err = tarEntry(tw, "", fi, outdir) |
|||
if nil != err { |
|||
panic("tarError:" + err.Error()) |
|||
} |
|||
|
|||
// Explicitly close in the correct order
|
|||
err = tw.Close() |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
err = zw.Close() |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
default: |
|||
panic(fmt.Errorf("%s", "Liar!!")) |
|||
} |
|||
|
|||
err = f.Close() |
|||
if nil != err { |
|||
panic(err) |
|||
} |
|||
fmt.Println("wrote", outdir+"."+pkg.ext) |
|||
|
|||
} |
|||
|
|||
fmt.Printf("Done.\n") |
|||
} |
|||
|
|||
func download(title string, nurl string, nfile string, exec bool) error { |
|||
if _, err := os.Stat(nfile); nil == err { |
|||
return nil |
|||
} |
|||
// doesn't exist, go grab it
|
|||
fmt.Printf("Downloading %s to %s\n", nurl, nfile) |
|||
resp, err := http.Get(nurl) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
if resp.StatusCode >= 300 || resp.StatusCode < 200 { |
|||
log.Fatal("Bad deal on download:", resp.Status) |
|||
} |
|||
defer resp.Body.Close() |
|||
|
|||
// Stream it in locally
|
|||
fmt.Printf("Streaming %s to %s\n", nurl, nfile) |
|||
fmode := os.FileMode(0644) |
|||
if exec { |
|||
fmode = os.FileMode(0755) |
|||
} |
|||
nf, err := os.OpenFile(nfile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, fmode) |
|||
_, err = io.Copy(nf, resp.Body) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
return nf.Sync() |
|||
} |
|||
|
|||
func untar(t io.Reader, outdir string, strip int) error { |
|||
tr := tar.NewReader(t) |
|||
for { |
|||
header, err := tr.Next() |
|||
if err == io.EOF { |
|||
break |
|||
} |
|||
if nil != err { |
|||
return err |
|||
} |
|||
|
|||
fpath := stripPrefix(header.Name, strip) |
|||
fpath = filepath.Join(outdir, fpath) |
|||
switch header.Typeflag { |
|||
case tar.TypeLink: |
|||
// ignore hard links
|
|||
case tar.TypeSymlink: |
|||
//fmt.Println("untarSym:", fpath)
|
|||
// Note: the link itself is always a file, even when it represents a directory
|
|||
lpath := filepath.Join(filepath.Dir(fpath), header.Linkname) |
|||
if !strings.HasPrefix(lpath+string(os.PathSeparator), outdir+string(os.PathSeparator)) { |
|||
return fmt.Errorf("Malicious link path: %s", header.Linkname) |
|||
} |
|||
if err := os.Symlink(header.Linkname, fpath); nil != err { |
|||
return err |
|||
} |
|||
case tar.TypeDir: |
|||
//fmt.Println("untarDir:", fpath)
|
|||
/* |
|||
// TODO
|
|||
if err := os.Lchown(dst); err != nil { |
|||
return err |
|||
} |
|||
*/ |
|||
// gonna use the same perms as were set previously here
|
|||
// should be fine (i.e. we want 755 for execs on *nix)
|
|||
_, err := safeOpen(header.FileInfo(), os.FileMode(header.Mode), fpath, outdir) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
case tar.TypeReg: |
|||
//fmt.Println("untarReg:", fpath)
|
|||
/* |
|||
// TODO
|
|||
if err := os.Lchown(dst); err != nil { |
|||
return err |
|||
} |
|||
*/ |
|||
// gonna use the same perms as were set previously here
|
|||
// should be fine (i.e. we want 755 for execs on *nix)
|
|||
out, err := safeOpen(header.FileInfo(), os.FileMode(header.Mode), fpath, outdir) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
defer out.Close() |
|||
_, err = io.Copy(out, tr) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
err = out.Close() |
|||
if nil != err { |
|||
return err |
|||
} |
|||
default: |
|||
fmt.Printf("[debug] odd type %s (%c)", fpath, header.Typeflag) |
|||
} |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func unzip(z io.ReaderAt, size int64, outdir string, strip int) error { |
|||
zr, err := zip.NewReader(z, size) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
|
|||
for i := range zr.File { |
|||
f := zr.File[i] |
|||
|
|||
fpath := stripPrefix(f.Name, strip) |
|||
fpath = filepath.Join(outdir, fpath) |
|||
out, err := safeOpen(f.FileInfo(), f.Mode(), fpath, outdir) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
if f.FileInfo().IsDir() { |
|||
continue |
|||
} |
|||
// this is actually function scope (not loop scope)
|
|||
defer out.Close() |
|||
|
|||
zf, err := f.Open() |
|||
if nil != err { |
|||
return err |
|||
} |
|||
defer zf.Close() |
|||
|
|||
_, err = io.Copy(out, zf) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
|
|||
// close explicitly within loop scope
|
|||
err = out.Close() |
|||
if nil != err { |
|||
return err |
|||
} |
|||
err = zf.Close() |
|||
if nil != err { |
|||
return err |
|||
} |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func stripPrefix(fpath string, strip int) string { |
|||
// /foo/bar/baz/ => foo/bar/baz
|
|||
// strip 1 => bar/baz
|
|||
fpath = strings.Trim(filepath.ToSlash(fpath), "/") |
|||
parts := []string{} |
|||
if "" != fpath { |
|||
parts = strings.Split(fpath, "/") |
|||
} |
|||
if strip > 0 { |
|||
n := len(parts) |
|||
if strip > n { |
|||
strip = n |
|||
} |
|||
if 0 != len(parts) { |
|||
parts = parts[strip:] |
|||
} |
|||
} |
|||
|
|||
return strings.Join(parts, "/") |
|||
} |
|||
|
|||
// given the path return a file, tell that it's a directory, or error out
|
|||
func safeOpen(fi os.FileInfo, fm os.FileMode, fpath string, outdir string) (io.WriteCloser, error) { |
|||
// Keep it clean
|
|||
// https://github.com/snyk/zip-slip-vulnerability
|
|||
cleanpath, _ := filepath.Abs(filepath.Clean(fpath)) |
|||
cleandest, _ := filepath.Abs(filepath.Clean(outdir)) |
|||
|
|||
// foo/ foo => foo// foo/
|
|||
// foo/ foo/bar.md => foo// foo/bar.md/
|
|||
if !strings.HasPrefix(cleanpath+string(os.PathSeparator), cleandest+string(os.PathSeparator)) { |
|||
return nil, fmt.Errorf("Malicious file path: %s", fpath) |
|||
} |
|||
fpath = cleanpath |
|||
|
|||
if fi.IsDir() { |
|||
err := os.MkdirAll(fpath, fm) |
|||
if nil != err { |
|||
return nil, err |
|||
} |
|||
return nil, err |
|||
} |
|||
|
|||
if err := os.MkdirAll(filepath.Dir(fpath), 0755); nil != err { |
|||
return nil, err |
|||
} |
|||
|
|||
out, err := os.OpenFile(fpath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, fm) |
|||
if nil != err { |
|||
return nil, err |
|||
} |
|||
|
|||
return out, nil |
|||
} |
|||
|
|||
// simpler to tar and untar than to have separate code to copy and to tar
|
|||
func tarDir(tw *tar.Writer, src string, fis []os.FileInfo, trim string) error { |
|||
//fmt.Println("tarDir:", src)
|
|||
for i := range fis { |
|||
fi := fis[i] |
|||
|
|||
//fmt.Println("tarEntry:", src)
|
|||
if err := tarEntry(tw, src, fi, trim); nil != err { |
|||
return err |
|||
} |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func tarEntry(tw *tar.Writer, src string, fi os.FileInfo, trim string) error { |
|||
// gotta get perms
|
|||
/* |
|||
stat, ok := info.Sys().(*syscall.Stat_t) |
|||
if !ok { |
|||
return fmt.Errorf("syscall failed for %q", src) |
|||
} |
|||
// TODO uid, username
|
|||
Uid: int(stat.Uid), |
|||
Gid: int(stat.Gid), |
|||
*/ |
|||
|
|||
src = filepath.Join(src, fi.Name()) |
|||
entryName := strings.TrimPrefix(strings.TrimPrefix(src, trim), "/") |
|||
|
|||
switch fi.Mode() & os.ModeType { |
|||
case os.ModeSymlink: |
|||
//fmt.Println("tarSym:", src)
|
|||
// TODO make sure that this is within the directory
|
|||
targetpath, err := os.Readlink(src) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
|
|||
h, err := tar.FileInfoHeader(fi, targetpath) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
h.Name = entryName |
|||
|
|||
err = tw.WriteHeader(h) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
|
|||
// return to skip chmod
|
|||
return nil |
|||
case os.ModeDir: |
|||
// directories must end in / for go
|
|||
h, err := tar.FileInfoHeader(fi, "") |
|||
if nil != err { |
|||
return err |
|||
} |
|||
h.Name = entryName |
|||
h.Name = strings.TrimPrefix(h.Name+"/", "/") |
|||
|
|||
//fmt.Printf("tarIsDir: %q %q\n", src, h.Name)
|
|||
if "" != h.Name { |
|||
if err := tw.WriteHeader(h); nil != err { |
|||
return err |
|||
} |
|||
} |
|||
|
|||
//fmt.Println("tarReadDir:", src)
|
|||
fis, err := ioutil.ReadDir(src) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
|
|||
return tarDir(tw, src, fis, trim) |
|||
default: |
|||
//fmt.Println("tarDefault:", src)
|
|||
if !fi.Mode().IsRegular() { |
|||
return fmt.Errorf("Unsupported file type: %s", src) |
|||
} |
|||
|
|||
h, err := tar.FileInfoHeader(fi, "") |
|||
if nil != err { |
|||
return err |
|||
} |
|||
h.Name = entryName |
|||
if err := tw.WriteHeader(h); nil != err { |
|||
return err |
|||
} |
|||
|
|||
r, err := os.Open(src) |
|||
defer r.Close() |
|||
if nil != err { |
|||
return err |
|||
} |
|||
|
|||
if _, err := io.Copy(tw, r); nil != err { |
|||
return err |
|||
} |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
// Zip walks `src`, omitting `trim`, writing to `w`
|
|||
func Zip(w io.Writer, src string, trim string) error { |
|||
zw := zip.NewWriter(w) |
|||
defer zw.Close() |
|||
|
|||
return filepath.Walk(src, func(path string, fi os.FileInfo, err error) error { |
|||
// path includes fi.Name() already
|
|||
if nil != err { |
|||
fmt.Println("warning: skipped", path+": ", err) |
|||
return nil |
|||
} |
|||
|
|||
zipOne(zw, path, fi, trim) |
|||
return nil |
|||
}) |
|||
} |
|||
|
|||
func zipOne(zw *zip.Writer, path string, fi os.FileInfo, trim string) error { |
|||
h, err := zip.FileInfoHeader(fi) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
h.Name = strings.TrimPrefix(strings.TrimPrefix(path, trim), string(filepath.Separator)) |
|||
|
|||
if fi.IsDir() { |
|||
//fmt.Printf("directory: %s\n\t%q\n", path, h.Name)
|
|||
return zipDirectory(zw, h) |
|||
} |
|||
|
|||
// Allow zipping a single file
|
|||
if "" == h.Name { |
|||
h.Name = path |
|||
} |
|||
if fi.Mode().IsRegular() { |
|||
//fmt.Printf("file: %s\n\t%q\n", path, h.Name)
|
|||
return zipFile(zw, h, path) |
|||
} |
|||
|
|||
if os.ModeSymlink == (fi.Mode() & os.ModeType) { |
|||
//fmt.Printf("symlink: %s\n\t%q\n", path, h.Name)
|
|||
return zipSymlink(zw, h, path) |
|||
} |
|||
|
|||
fmt.Fprintf(os.Stderr, "skipping: %s\n\t(irregular file type)\n", path) |
|||
return nil |
|||
} |
|||
|
|||
func zipDirectory(zw *zip.Writer, h *zip.FileHeader) error { |
|||
// directories must end in / for go
|
|||
h.Name = strings.TrimPrefix(h.Name+"/", "/") |
|||
|
|||
// skip top-level, trimmed directory
|
|||
if "" == h.Name { |
|||
return nil |
|||
} |
|||
|
|||
if _, err := zw.CreateHeader(h); nil != err { |
|||
return err |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func zipFile(zw *zip.Writer, h *zip.FileHeader, path string) error { |
|||
r, err := os.Open(path) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
defer r.Close() |
|||
|
|||
// Files should be zipped (not dirs, and symlinks... meh)
|
|||
// TODO investigate if files below a certain size shouldn't be deflated
|
|||
h.Method = zip.Deflate |
|||
w, err := zw.CreateHeader(h) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
|
|||
if _, err := io.Copy(w, r); nil != err { |
|||
return err |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func zipSymlink(zw *zip.Writer, h *zip.FileHeader, path string) error { |
|||
w, err := zw.CreateHeader(h) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
|
|||
// TODO make sure that this is within the root directory
|
|||
targetpath, err := os.Readlink(path) |
|||
if nil != err { |
|||
return err |
|||
} |
|||
if _, err := w.Write([]byte(targetpath)); nil != err { |
|||
return err |
|||
} |
|||
|
|||
return nil |
|||
} |
@ -0,0 +1,799 @@ |
|||
{ |
|||
"name": "telebit", |
|||
"version": "0.20.8", |
|||
"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==" |
|||
}, |
|||
"accepts": { |
|||
"version": "1.3.5", |
|||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", |
|||
"integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", |
|||
"requires": { |
|||
"mime-types": "~2.1.18", |
|||
"negotiator": "0.6.1" |
|||
} |
|||
}, |
|||
"acme": { |
|||
"version": "1.3.0", |
|||
"resolved": "https://registry.npmjs.org/acme/-/acme-1.3.0.tgz", |
|||
"integrity": "sha512-Ny8aXnGdtlEVBZLpzNyVp7gff/3zFYrbfbiY93lx5jdrG4BrraA6P8RkRFP7NbFwh1rBgQkdHEsMxTp3f2r8dA==", |
|||
"requires": { |
|||
"acme-v2": "^1.6.0" |
|||
} |
|||
}, |
|||
"acme-dns-01-cli": { |
|||
"version": "3.0.7", |
|||
"resolved": "https://registry.npmjs.org/acme-dns-01-cli/-/acme-dns-01-cli-3.0.7.tgz", |
|||
"integrity": "sha512-Aa4bUpq6ftX1VODiShOetOY5U0tsXY5EV7+fQwme3Q8Y9rjYBArBXHgFCAVKtK1AF+Ev8pIuF6Z42hzMFa73/w==" |
|||
}, |
|||
"acme-v2": { |
|||
"version": "1.8.2", |
|||
"resolved": "https://registry.npmjs.org/acme-v2/-/acme-v2-1.8.2.tgz", |
|||
"integrity": "sha512-uYGA+DuTnA44EsGXE413XnbTotGHCzkucXjMk23QRwGnaGlnr0lNBoYjByyeIVLSzj0W6Y9FqA9h+15+H+ltMw==", |
|||
"requires": { |
|||
"@root/request": "^1.3.11", |
|||
"rsa-compat": "^2.0.8" |
|||
}, |
|||
"dependencies": { |
|||
"@root/request": { |
|||
"version": "1.3.11", |
|||
"resolved": "https://registry.npmjs.org/@root/request/-/request-1.3.11.tgz", |
|||
"integrity": "sha512-3a4Eeghcjsfe6zh7EJ+ni1l8OK9Fz2wL1OjP4UCa0YdvtH39kdXB9RGWuzyNv7dZi0+Ffkc83KfH0WbPMiuJFw==" |
|||
} |
|||
} |
|||
}, |
|||
"argparse": { |
|||
"version": "1.0.10", |
|||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", |
|||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", |
|||
"requires": { |
|||
"sprintf-js": "~1.0.2" |
|||
} |
|||
}, |
|||
"async-limiter": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", |
|||
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" |
|||
}, |
|||
"batch": { |
|||
"version": "0.6.1", |
|||
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", |
|||
"integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" |
|||
}, |
|||
"bluebird": { |
|||
"version": "3.5.1", |
|||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", |
|||
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" |
|||
}, |
|||
"buffer-alloc": { |
|||
"version": "1.2.0", |
|||
"resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", |
|||
"integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", |
|||
"requires": { |
|||
"buffer-alloc-unsafe": "^1.1.0", |
|||
"buffer-fill": "^1.0.0" |
|||
} |
|||
}, |
|||
"buffer-alloc-unsafe": { |
|||
"version": "1.1.0", |
|||
"resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", |
|||
"integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" |
|||
}, |
|||
"buffer-equal-constant-time": { |
|||
"version": "1.0.1", |
|||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", |
|||
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" |
|||
}, |
|||
"buffer-fill": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", |
|||
"integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" |
|||
}, |
|||
"buffer-from": { |
|||
"version": "1.1.0", |
|||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", |
|||
"integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" |
|||
}, |
|||
"cert-info": { |
|||
"version": "1.5.1", |
|||
"resolved": "https://registry.npmjs.org/cert-info/-/cert-info-1.5.1.tgz", |
|||
"integrity": "sha512-eoQC/yAgW3gKTKxjzyClvi+UzuY97YCjcl+lSqbsGIy7HeGaWxCPOQFivhUYm27hgsBMhsJJFya3kGvK6PMIcQ==" |
|||
}, |
|||
"core-util-is": { |
|||
"version": "1.0.2", |
|||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", |
|||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" |
|||
}, |
|||
"csv-parser": { |
|||
"version": "1.12.1", |
|||
"resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-1.12.1.tgz", |
|||
"integrity": "sha512-r45M92nLnGP246ot0Yo5RvbiiMF5Bw/OTIdWJ3OQ4Vbv4hpOeoXVIPxdSmUw+fPJlQOseY+iigJyLSfPMIrddQ==", |
|||
"requires": { |
|||
"buffer-alloc": "^1.1.0", |
|||
"buffer-from": "^1.0.0", |
|||
"generate-function": "^1.0.1", |
|||
"generate-object-property": "^1.0.0", |
|||
"inherits": "^2.0.1", |
|||
"minimist": "^1.2.0", |
|||
"ndjson": "^1.4.0" |
|||
}, |
|||
"dependencies": { |
|||
"minimist": { |
|||
"version": "1.2.0", |
|||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", |
|||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" |
|||
} |
|||
} |
|||
}, |
|||
"debug": { |
|||
"version": "2.6.9", |
|||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", |
|||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", |
|||
"requires": { |
|||
"ms": "2.0.0" |
|||
} |
|||
}, |
|||
"depd": { |
|||
"version": "1.1.2", |
|||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", |
|||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" |
|||
}, |
|||
"destroy": { |
|||
"version": "1.0.4", |
|||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", |
|||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" |
|||
}, |
|||
"ecdsa-sig-formatter": { |
|||
"version": "1.0.11", |
|||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", |
|||
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", |
|||
"requires": { |
|||
"safe-buffer": "^5.0.1" |
|||
} |
|||
}, |
|||
"eckles": { |
|||
"version": "1.4.1", |
|||
"resolved": "https://registry.npmjs.org/eckles/-/eckles-1.4.1.tgz", |
|||
"integrity": "sha512-auWyk/k8oSkVHaD4RxkPadKsLUcIwKgr/h8F7UZEueFDBO7BsE4y+H6IMUDbfqKIFPg/9MxV6KcBdJCmVVcxSA==" |
|||
}, |
|||
"ee-first": { |
|||
"version": "1.1.1", |
|||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", |
|||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" |
|||
}, |
|||
"encodeurl": { |
|||
"version": "1.0.2", |
|||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", |
|||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" |
|||
}, |
|||
"escape-html": { |
|||
"version": "1.0.3", |
|||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", |
|||
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" |
|||
}, |
|||
"esprima": { |
|||
"version": "4.0.1", |
|||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", |
|||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" |
|||
}, |
|||
"etag": { |
|||
"version": "1.8.1", |
|||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", |
|||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" |
|||
}, |
|||
"finalhandler": { |
|||
"version": "1.1.1", |
|||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", |
|||
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", |
|||
"requires": { |
|||
"debug": "2.6.9", |
|||
"encodeurl": "~1.0.2", |
|||
"escape-html": "~1.0.3", |
|||
"on-finished": "~2.3.0", |
|||
"parseurl": "~1.3.2", |
|||
"statuses": "~1.4.0", |
|||
"unpipe": "~1.0.0" |
|||
} |
|||
}, |
|||
"fresh": { |
|||
"version": "0.5.2", |
|||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", |
|||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" |
|||
}, |
|||
"from2": { |
|||
"version": "2.3.0", |
|||
"resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", |
|||
"integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", |
|||
"requires": { |
|||
"inherits": "^2.0.1", |
|||
"readable-stream": "^2.0.0" |
|||
} |
|||
}, |
|||
"generate-function": { |
|||
"version": "1.1.0", |
|||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-1.1.0.tgz", |
|||
"integrity": "sha1-VMIbCAGSsW2Yd3ecW7gWZudyNl8=" |
|||
}, |
|||
"generate-object-property": { |
|||
"version": "1.2.0", |
|||
"resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", |
|||
"integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", |
|||
"requires": { |
|||
"is-property": "^1.0.0" |
|||
} |
|||
}, |
|||
"get-stream": { |
|||
"version": "2.3.1", |
|||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", |
|||
"integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", |
|||
"requires": { |
|||
"object-assign": "^4.0.1", |
|||
"pinkie-promise": "^2.0.0" |
|||
} |
|||
}, |
|||
"greenlock": { |
|||
"version": "2.8.2", |
|||
"resolved": "https://registry.npmjs.org/greenlock/-/greenlock-2.8.2.tgz", |
|||
"integrity": "sha512-pCAYjgVova1ZoUHhuCfIw/3Rs5tE6DK1YF2LI7Cyh15QFBZJNU7pngMvDfeFft3It4WqnHezNgyDWAeV2pWFaw==", |
|||
"requires": { |
|||
"acme": "^1.3.0", |
|||
"acme-dns-01-cli": "^3.0.0", |
|||
"acme-v2": "^1.8.1", |
|||
"cert-info": "^1.5.1", |
|||
"greenlock-store-fs": "^3.0.2", |
|||
"keypairs": "^1.2.14", |
|||
"le-challenge-fs": "^2.0.2", |
|||
"le-sni-auto": "^2.1.9", |
|||
"le-store-certbot": "^2.2.3", |
|||
"rsa-compat": "^2.0.8" |
|||
} |
|||
}, |
|||
"greenlock-store-fs": { |
|||
"version": "3.0.2", |
|||
"resolved": "https://registry.npmjs.org/greenlock-store-fs/-/greenlock-store-fs-3.0.2.tgz", |
|||
"integrity": "sha512-t4So75yKs1+7TqmxD5UKdf+zOQU0/4o0lb2auf5zUcAo7fwwNLOAXyWnnZRL3WuFBUiBGh1qXWleuMua0d3LPg==", |
|||
"requires": { |
|||
"@root/mkdirp": "^1.0.0", |
|||
"safe-replace": "^1.1.0" |
|||
} |
|||
}, |
|||
"http-errors": { |
|||
"version": "1.6.3", |
|||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", |
|||
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", |
|||
"requires": { |
|||
"depd": "~1.1.2", |
|||
"inherits": "2.0.3", |
|||
"setprototypeof": "1.1.0", |
|||
"statuses": ">= 1.4.0 < 2" |
|||
} |
|||
}, |
|||
"inherits": { |
|||
"version": "2.0.3", |
|||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", |
|||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" |
|||
}, |
|||
"into-stream": { |
|||
"version": "2.0.1", |
|||
"resolved": "https://registry.npmjs.org/into-stream/-/into-stream-2.0.1.tgz", |
|||
"integrity": "sha1-25sANpRFPq4JHYpchMwRUHt4HTE=", |
|||
"requires": { |
|||
"from2": "^2.1.1" |
|||
} |
|||
}, |
|||
"is-property": { |
|||
"version": "1.0.2", |
|||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", |
|||
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" |
|||
}, |
|||
"isarray": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", |
|||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" |
|||
}, |
|||
"js-yaml": { |
|||
"version": "3.13.1", |
|||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", |
|||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", |
|||
"requires": { |
|||
"argparse": "^1.0.7", |
|||
"esprima": "^4.0.0" |
|||
} |
|||
}, |
|||
"json-stringify-safe": { |
|||
"version": "5.0.1", |
|||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", |
|||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" |
|||
}, |
|||
"jsonwebtoken": { |
|||
"version": "8.5.1", |
|||
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", |
|||
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", |
|||
"requires": { |
|||
"jws": "^3.2.2", |
|||
"lodash.includes": "^4.3.0", |
|||
"lodash.isboolean": "^3.0.3", |
|||
"lodash.isinteger": "^4.0.4", |
|||
"lodash.isnumber": "^3.0.3", |
|||
"lodash.isplainobject": "^4.0.6", |
|||
"lodash.isstring": "^4.0.1", |
|||
"lodash.once": "^4.0.0", |
|||
"ms": "^2.1.1", |
|||
"semver": "^5.6.0" |
|||
}, |
|||
"dependencies": { |
|||
"ms": { |
|||
"version": "2.1.2", |
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", |
|||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" |
|||
} |
|||
} |
|||
}, |
|||
"jwa": { |
|||
"version": "1.4.1", |
|||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", |
|||
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", |
|||
"requires": { |
|||
"buffer-equal-constant-time": "1.0.1", |
|||
"ecdsa-sig-formatter": "1.0.11", |
|||
"safe-buffer": "^5.0.1" |
|||
} |
|||
}, |
|||
"jws": { |
|||
"version": "3.2.2", |
|||
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", |
|||
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", |
|||
"requires": { |
|||
"jwa": "^1.4.1", |
|||
"safe-buffer": "^5.0.1" |
|||
} |
|||
}, |
|||
"keypairs": { |
|||
"version": "1.2.14", |
|||
"resolved": "https://registry.npmjs.org/keypairs/-/keypairs-1.2.14.tgz", |
|||
"integrity": "sha512-ZoZfZMygyB0QcjSlz7Rh6wT2CJasYEHBPETtmHZEfxuJd7bnsOG5AdtPZqHZBT+hoHvuWCp/4y8VmvTvH0Y9uA==", |
|||
"requires": { |
|||
"eckles": "^1.4.1", |
|||
"rasha": "^1.2.4" |
|||
} |
|||
}, |
|||
"le-challenge-fs": { |
|||
"version": "2.0.9", |
|||
"resolved": "https://registry.npmjs.org/le-challenge-fs/-/le-challenge-fs-2.0.9.tgz", |
|||
"integrity": "sha512-stzI6rxd+aXGxBl87QJKKY/i/wl3uz6EoWzX2xSazJvCPSYBQys1RVNgOcf0SfUQPh6TBCFJFSJkiR4mznb4sg==", |
|||
"requires": { |
|||
"@root/mkdirp": "^1.0.0" |
|||
} |
|||
}, |
|||
"le-sni-auto": { |
|||
"version": "2.1.9", |
|||
"resolved": "https://registry.npmjs.org/le-sni-auto/-/le-sni-auto-2.1.9.tgz", |
|||
"integrity": "sha512-QmQHNwQDi/56GY8+qczFZ06FZbxaeJQjbjEhwwQHhkJ9IHhIQFkPfCT/OyDfLj4gqLIrg5ZX8CemxxVZnLEYfg==" |
|||
}, |
|||
"le-store-certbot": { |
|||
"version": "2.2.3", |
|||
"resolved": "https://registry.npmjs.org/le-store-certbot/-/le-store-certbot-2.2.3.tgz", |
|||
"integrity": "sha512-c4ACR+v+JKMiAOOshLh6gdCKA7wIWR16+mROMLpQjq3rXJ3Vm8FaBHe2H+crT+flP+g7FmciAwUlfOJEJpIuCQ==", |
|||
"requires": { |
|||
"@root/mkdirp": "^1.0.0", |
|||
"pyconf": "^1.1.7", |
|||
"safe-replace": "^1.1.0" |
|||
} |
|||
}, |
|||
"lodash.includes": { |
|||
"version": "4.3.0", |
|||
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", |
|||
"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" |
|||
}, |
|||
"lodash.isboolean": { |
|||
"version": "3.0.3", |
|||
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", |
|||
"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" |
|||
}, |
|||
"lodash.isinteger": { |
|||
"version": "4.0.4", |
|||
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", |
|||
"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" |
|||
}, |
|||
"lodash.isnumber": { |
|||
"version": "3.0.3", |
|||
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", |
|||
"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" |
|||
}, |
|||
"lodash.isplainobject": { |
|||
"version": "4.0.6", |
|||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", |
|||
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" |
|||
}, |
|||
"lodash.isstring": { |
|||
"version": "4.0.1", |
|||
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", |
|||
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" |
|||
}, |
|||
"lodash.once": { |
|||
"version": "4.1.1", |
|||
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", |
|||
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" |
|||
}, |
|||
"mime": { |
|||
"version": "1.4.1", |
|||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", |
|||
"integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" |
|||
}, |
|||
"mime-db": { |
|||
"version": "1.33.0", |
|||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", |
|||
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" |
|||
}, |
|||
"mime-types": { |
|||
"version": "2.1.18", |
|||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", |
|||
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", |
|||
"requires": { |
|||
"mime-db": "~1.33.0" |
|||
} |
|||
}, |
|||
"minimist": { |
|||
"version": "0.0.8", |
|||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", |
|||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" |
|||
}, |
|||
"mkdirp": { |
|||
"version": "0.5.1", |
|||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", |
|||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", |
|||
"requires": { |
|||
"minimist": "0.0.8" |
|||
} |
|||
}, |
|||
"ms": { |
|||
"version": "2.0.0", |
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", |
|||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" |
|||
}, |
|||
"ndjson": { |
|||
"version": "1.5.0", |
|||
"resolved": "https://registry.npmjs.org/ndjson/-/ndjson-1.5.0.tgz", |
|||
"integrity": "sha1-rmA7NrE0vOw0e0UkIrC/mNWDLsg=", |
|||
"requires": { |
|||
"json-stringify-safe": "^5.0.1", |
|||
"minimist": "^1.2.0", |
|||
"split2": "^2.1.0", |
|||
"through2": "^2.0.3" |
|||
}, |
|||
"dependencies": { |
|||
"minimist": { |
|||
"version": "1.2.0", |
|||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", |
|||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" |
|||
} |
|||
} |
|||
}, |
|||
"neat-csv": { |
|||
"version": "2.1.0", |
|||
"resolved": "https://registry.npmjs.org/neat-csv/-/neat-csv-2.1.0.tgz", |
|||
"integrity": "sha1-BvWDYMTDuVW9Rn3cha5FEaOQekw=", |
|||
"requires": { |
|||
"csv-parser": "^1.6.0", |
|||
"get-stream": "^2.1.0", |
|||
"into-stream": "^2.0.0" |
|||
} |
|||
}, |
|||
"negotiator": { |
|||
"version": "0.6.1", |
|||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", |
|||
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" |
|||
}, |
|||
"object-assign": { |
|||
"version": "4.1.1", |
|||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", |
|||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" |
|||
}, |
|||
"on-finished": { |
|||
"version": "2.3.0", |
|||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", |
|||
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", |
|||
"requires": { |
|||
"ee-first": "1.1.1" |
|||
} |
|||
}, |
|||
"parseurl": { |
|||
"version": "1.3.2", |
|||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", |
|||
"integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" |
|||
}, |
|||
"pify": { |
|||
"version": "3.0.0", |
|||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", |
|||
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" |
|||
}, |
|||
"pinkie": { |
|||
"version": "2.0.4", |
|||
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", |
|||
"integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" |
|||
}, |
|||
"pinkie-promise": { |
|||
"version": "2.0.1", |
|||
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", |
|||
"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", |
|||
"requires": { |
|||
"pinkie": "^2.0.0" |
|||
} |
|||
}, |
|||
"process-nextick-args": { |
|||
"version": "2.0.0", |
|||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", |
|||
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" |
|||
}, |
|||
"proxy-packer": { |
|||
"version": "2.0.2", |
|||
"resolved": "https://registry.npmjs.org/proxy-packer/-/proxy-packer-2.0.2.tgz", |
|||
"integrity": "sha512-EQxdOMAYc8zINq9MsV7Vm55hjuNo4eC9z6GlqizCkeE5HldvnOCjsYJnwul+feey6RAJzp34klkD+9+0h2sXLQ==" |
|||
}, |
|||
"ps-list": { |
|||
"version": "5.0.0", |
|||
"resolved": "https://registry.npmjs.org/ps-list/-/ps-list-5.0.0.tgz", |
|||
"integrity": "sha512-EnMjo990nDlzBVoV/m2Vo2+Ja3sO1Ikgo3TcLF2KI1DVW3SYEt8zouS40X4Z/tfULam5R3ig8a/rhmvE3mRq5w==", |
|||
"requires": { |
|||
"pify": "^3.0.0", |
|||
"tasklist": "^3.1.0" |
|||
} |
|||
}, |
|||
"pyconf": { |
|||
"version": "1.1.7", |
|||
"resolved": "https://registry.npmjs.org/pyconf/-/pyconf-1.1.7.tgz", |
|||
"integrity": "sha512-v4clh33m68sjtMsh8XMpjhGWb/MQODAYZ1y7ORG5Qv58UK25OddoB+oXyexgDkK8ttFui/lZm2sQDgA2Ftjfkw==", |
|||
"requires": { |
|||
"safe-replace": "^1.0.2" |
|||
} |
|||
}, |
|||
"range-parser": { |
|||
"version": "1.2.0", |
|||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", |
|||
"integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" |
|||
}, |
|||
"rasha": { |
|||
"version": "1.2.5", |
|||
"resolved": "https://registry.npmjs.org/rasha/-/rasha-1.2.5.tgz", |
|||
"integrity": "sha512-KxtX+/fBk+wM7O3CNgwjSh5elwFilLvqWajhr6wFr2Hd63JnKTTi43Tw+Jb1hxJQWOwoya+NZWR2xztn3hCrTw==" |
|||
}, |
|||
"readable-stream": { |
|||
"version": "2.3.6", |
|||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", |
|||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", |
|||
"requires": { |
|||
"core-util-is": "~1.0.0", |
|||
"inherits": "~2.0.3", |
|||
"isarray": "~1.0.0", |
|||
"process-nextick-args": "~2.0.0", |
|||
"safe-buffer": "~5.1.1", |
|||
"string_decoder": "~1.1.1", |
|||
"util-deprecate": "~1.0.1" |
|||
} |
|||
}, |
|||
"recase": { |
|||
"version": "1.0.4", |
|||
"resolved": "https://registry.npmjs.org/recase/-/recase-1.0.4.tgz", |
|||
"integrity": "sha1-asoF8GFV5u0bY2LmIQUKEdvZ+FE=" |
|||
}, |
|||
"redirect-https": { |
|||
"version": "1.1.5", |
|||
"resolved": "https://registry.npmjs.org/redirect-https/-/redirect-https-1.1.5.tgz", |
|||
"integrity": "sha512-40okBDSPOoK3E8ttlKxG60vBJMmxT+UPS43zrIkWo6QlNrRgvj/jY/trvATXpCN4XpuySdYsQnXxgfB8QBsBHg==", |
|||
"requires": { |
|||
"escape-html": "^1.0.3" |
|||
} |
|||
}, |
|||
"rsa-compat": { |
|||
"version": "2.0.8", |
|||
"resolved": "https://registry.npmjs.org/rsa-compat/-/rsa-compat-2.0.8.tgz", |
|||
"integrity": "sha512-BFiiSEbuxzsVdaxpejbxfX07qs+rtous49Y6mL/zw6YHh9cranDvm2BvBmqT3rso84IsxNlP5BXnuNvm1Wn3Tw==", |
|||
"requires": { |
|||
"keypairs": "^1.2.14" |
|||
} |
|||
}, |
|||
"safe-buffer": { |
|||
"version": "5.1.2", |
|||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", |
|||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" |
|||
}, |
|||
"safe-replace": { |
|||
"version": "1.1.0", |
|||
"resolved": "https://registry.npmjs.org/safe-replace/-/safe-replace-1.1.0.tgz", |
|||
"integrity": "sha512-9/V2E0CDsKs9DWOOwJH7jYpSl9S3N05uyevNjvsnDauBqRowBPOyot1fIvV5N2IuZAbYyvrTXrYFVG0RZInfFw==" |
|||
}, |
|||
"sclient": { |
|||
"version": "1.4.1", |
|||
"resolved": "https://registry.npmjs.org/sclient/-/sclient-1.4.1.tgz", |
|||
"integrity": "sha512-IsSIlWg9MjqknF3YtT6+ewCszAUeZfwLu2bNLSzbqoduc6t73K+zs/L2L5wmmgDL6BapBxqgwqBBchhizxS0JA==" |
|||
}, |
|||
"sec": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/sec/-/sec-1.0.0.tgz", |
|||
"integrity": "sha1-Az1go60g7PLgCUDRT5eCNGV3QzU=" |
|||
}, |
|||
"semver": { |
|||
"version": "5.7.0", |
|||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", |
|||
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" |
|||
}, |
|||
"send": { |
|||
"version": "0.16.2", |
|||
"resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", |
|||
"integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", |
|||
"requires": { |
|||
"debug": "2.6.9", |
|||
"depd": "~1.1.2", |
|||
"destroy": "~1.0.4", |
|||
"encodeurl": "~1.0.2", |
|||
"escape-html": "~1.0.3", |
|||
"etag": "~1.8.1", |
|||
"fresh": "0.5.2", |
|||
"http-errors": "~1.6.2", |
|||
"mime": "1.4.1", |
|||
"ms": "2.0.0", |
|||
"on-finished": "~2.3.0", |
|||
"range-parser": "~1.2.0", |
|||
"statuses": "~1.4.0" |
|||
} |
|||
}, |
|||
"serve-index": { |
|||
"version": "1.9.1", |
|||
"resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", |
|||
"integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", |
|||
"requires": { |
|||
"accepts": "~1.3.4", |
|||
"batch": "0.6.1", |
|||
"debug": "2.6.9", |
|||
"escape-html": "~1.0.3", |
|||
"http-errors": "~1.6.2", |
|||
"mime-types": "~2.1.17", |
|||
"parseurl": "~1.3.2" |
|||
} |
|||
}, |
|||
"serve-static": { |
|||
"version": "1.13.2", |
|||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", |
|||
"integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", |
|||
"requires": { |
|||
"encodeurl": "~1.0.2", |
|||
"escape-html": "~1.0.3", |
|||
"parseurl": "~1.3.2", |
|||
"send": "0.16.2" |
|||
} |
|||
}, |
|||
"serve-tpl-attachment": { |
|||
"version": "1.0.4", |
|||
"resolved": "https://registry.npmjs.org/serve-tpl-attachment/-/serve-tpl-attachment-1.0.4.tgz", |
|||
"integrity": "sha512-lv0t/G/x/Ikk780y+RChulnp42Q3xWStmgU4Yz2HXzO2uE+vJXfG7ntAzffgpuJSY29/arbAaqfEuI/NI5hNnA==", |
|||
"requires": { |
|||
"accepts": "^1.3.5", |
|||
"batch": "^0.6.1", |
|||
"mime-types": "^2.1.19" |
|||
}, |
|||
"dependencies": { |
|||
"mime-db": { |
|||
"version": "1.35.0", |
|||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", |
|||
"integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==" |
|||
}, |
|||
"mime-types": { |
|||
"version": "2.1.19", |
|||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", |
|||
"integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", |
|||
"requires": { |
|||
"mime-db": "~1.35.0" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"setprototypeof": { |
|||
"version": "1.1.0", |
|||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", |
|||
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" |
|||
}, |
|||
"sni": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/sni/-/sni-1.0.0.tgz", |
|||
"integrity": "sha1-b6Qr35d23i43zsYBIua+yD3wBvU=" |
|||
}, |
|||
"socket-pair": { |
|||
"version": "1.0.4", |
|||
"resolved": "https://registry.npmjs.org/socket-pair/-/socket-pair-1.0.4.tgz", |
|||
"integrity": "sha512-OEjlBOVBZpGBDvcjyYwFLZLGwNc8yMewKMirtoaR1WnX/XI2jo8ylsCEH4C6eXmcj5blQisECacN7yc3xlrwAA==", |
|||
"requires": { |
|||
"bluebird": "^3.5.1" |
|||
} |
|||
}, |
|||
"split2": { |
|||
"version": "2.2.0", |
|||
"resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", |
|||
"integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", |
|||
"requires": { |
|||
"through2": "^2.0.2" |
|||
} |
|||
}, |
|||
"sprintf-js": { |
|||
"version": "1.0.3", |
|||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", |
|||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" |
|||
}, |
|||
"statuses": { |
|||
"version": "1.4.0", |
|||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", |
|||
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" |
|||
}, |
|||
"string_decoder": { |
|||
"version": "1.1.1", |
|||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", |
|||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", |
|||
"requires": { |
|||
"safe-buffer": "~5.1.0" |
|||
} |
|||
}, |
|||
"tasklist": { |
|||
"version": "3.1.0", |
|||
"resolved": "https://registry.npmjs.org/tasklist/-/tasklist-3.1.0.tgz", |
|||
"integrity": "sha1-hzqYpORcvez6LC7hiGU1MFfmNpY=", |
|||
"requires": { |
|||
"neat-csv": "^2.1.0", |
|||
"pify": "^2.2.0", |
|||
"sec": "^1.0.0" |
|||
}, |
|||
"dependencies": { |
|||
"pify": { |
|||
"version": "2.3.0", |
|||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", |
|||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" |
|||
} |
|||
} |
|||
}, |
|||
"through2": { |
|||
"version": "2.0.3", |
|||
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", |
|||
"integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", |
|||
"requires": { |
|||
"readable-stream": "^2.1.5", |
|||
"xtend": "~4.0.1" |
|||
} |
|||
}, |
|||
"toml": { |
|||
"version": "0.4.1", |
|||
"resolved": "https://registry.npmjs.org/toml/-/toml-0.4.1.tgz", |
|||
"integrity": "sha1-Iv5QHFe+WpV9o4JcHd5YS7LmL3M=" |
|||
}, |
|||
"unpipe": { |
|||
"version": "1.0.0", |
|||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", |
|||
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" |
|||
}, |
|||
"util-deprecate": { |
|||
"version": "1.0.2", |
|||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", |
|||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" |
|||
}, |
|||
"ws": { |
|||
"version": "6.0.0", |
|||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.0.0.tgz", |
|||
"integrity": "sha512-c2UlYcAZp1VS8AORtpq6y4RJIkJ9dQz18W32SpR/qXGfLDZ2jU4y4wKvvZwqbi7U6gxFQTeE+urMbXU/tsDy4w==", |
|||
"requires": { |
|||
"async-limiter": "~1.0.0" |
|||
} |
|||
}, |
|||
"xtend": { |
|||
"version": "4.0.1", |
|||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", |
|||
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,50 @@ |
|||
'use strict'; |
|||
|
|||
// use pathman and serviceman to make telebit ready
|
|||
|
|||
var spawn = require('child_process').spawn; |
|||
var os = require('os'); |
|||
var path = require('path'); |
|||
var ext = /^win/i.test(os.platform()) ? '.exe' : ''; |
|||
|
|||
function run(bin, args) { |
|||
return new Promise(function(resolve, reject) { |
|||
var runner = spawn(path.join(bin + ext), args, { |
|||
windowsHide: true |
|||
}); |
|||
runner.stdout.on('data', function(chunk) { |
|||
console.info(chunk.toString('utf8')); |
|||
}); |
|||
runner.stderr.on('data', function(chunk) { |
|||
console.error(chunk.toString('utf8')); |
|||
}); |
|||
runner.on('exit', function(code) { |
|||
if (0 !== code) { |
|||
reject( |
|||
new Error("exited with non-zero status code '" + code + "'") |
|||
); |
|||
return; |
|||
} |
|||
resolve({ code: code }); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
run('serviceman', [ |
|||
'add', |
|||
'--name', |
|||
'telebit', |
|||
'--title', |
|||
'Telebit', |
|||
'--rdns', |
|||
'io.telebit.remote.telebit', |
|||
path.resolve(__dirname, '..', 'bin', 'telebit.js'), |
|||
'--', |
|||
'daemon', |
|||
'--config', |
|||
path.join(os.homedir(), '.config/telebit/telebitd.yml') |
|||
]) |
|||
.then(function() {}) |
|||
.catch(function(e) { |
|||
console.error(e.message); |
|||
}); |
@ -0,0 +1,53 @@ |
|||
'use strict'; |
|||
|
|||
// use pathman and serviceman to make telebit ready
|
|||
|
|||
var spawn = require('child_process').spawn; |
|||
var os = require('os'); |
|||
var path = require('path'); |
|||
var ext = /^win/i.test(os.platform()) ? '.exe' : ''; |
|||
|
|||
function run(bin, args) { |
|||
return new Promise(function(resolve, reject) { |
|||
var runner = spawn(path.join(bin + ext), args, { |
|||
windowsHide: true |
|||
}); |
|||
var out = ''; |
|||
runner.stdout.on('data', function(chunk) { |
|||
var txt = chunk.toString('utf8'); |
|||
out += txt; |
|||
}); |
|||
runner.stderr.on('data', function(chunk) { |
|||
var txt = chunk.toString('utf8'); |
|||
out += txt; |
|||
}); |
|||
runner.on('exit', function(code) { |
|||
if ( |
|||
0 !== code && |
|||
!/service matching/.test(out) && |
|||
!/no pid file/.test(out) |
|||
) { |
|||
console.error(out); |
|||
reject( |
|||
new Error("exited with non-zero status code '" + code + "'") |
|||
); |
|||
return; |
|||
} |
|||
resolve({ code: code }); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
var confpath = path.join(os.homedir(), '.config/telebit'); |
|||
require('mkdirp')(confpath, function(err) { |
|||
if (err) { |
|||
console.error("Error creating config path '" + confpath + "':"); |
|||
console.error(err); |
|||
} |
|||
// not having a config is fine
|
|||
}); |
|||
|
|||
run('serviceman', ['stop', 'telebit']).catch(function(e) { |
|||
// TODO ignore
|
|||
console.error(e.message); |
|||
}); |
@ -1,61 +0,0 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>Label</key> |
|||
<string>Telebit Remote</string> |
|||
<key>ProgramArguments</key> |
|||
<array> |
|||
<string>{TELEBIT_NODE}</string> |
|||
<string>{TELEBITD_JS}</string> |
|||
<string>daemon</string> |
|||
<string>--config</string> |
|||
<string>{TELEBITD_CONFIG}</string> |
|||
</array> |
|||
<key>EnvironmentVariables</key> |
|||
<dict> |
|||
<key>TELEBIT_PATH</key> |
|||
<string>{TELEBIT_PATH}</string> |
|||
<key>NODE_PATH</key> |
|||
<string>{NODE_PATH}</string> |
|||
<key>NPM_CONFIG_PREFIX</key> |
|||
<string>{NPM_CONFIG_PREFIX}</string> |
|||
</dict> |
|||
|
|||
<key>UserName</key> |
|||
<string>{TELEBIT_USER}</string> |
|||
<key>GroupName</key> |
|||
<string>{TELEBIT_GROUP}</string> |
|||
<key>InitGroups</key> |
|||
<true/> |
|||
|
|||
<key>RunAtLoad</key> |
|||
<true/> |
|||
<key>KeepAlive</key> |
|||
<true/> |
|||
<!--dict> |
|||
<key>Crashed</key> |
|||
<true/> |
|||
<key>NetworkState</key> |
|||
<true/> |
|||
<key>SuccessfulExit</key> |
|||
<false/> |
|||
</dict--> |
|||
|
|||
<key>SoftResourceLimits</key> |
|||
<dict> |
|||
<key>NumberOfFiles</key> |
|||
<integer>8192</integer> |
|||
</dict> |
|||
<key>HardResourceLimits</key> |
|||
<dict/> |
|||
|
|||
<key>WorkingDirectory</key> |
|||
<string>{TELEBIT_PATH}</string> |
|||
|
|||
<key>StandardErrorPath</key> |
|||
<string>{TELEBIT_LOG_DIR}/telebit.log</string> |
|||
<key>StandardOutPath</key> |
|||
<string>{TELEBIT_LOG_DIR}/telebit.log</string> |
|||
</dict> |
|||
</plist> |
@ -1,2 +0,0 @@ |
|||
#!/bin/bash |
|||
{TELEBIT_NODE} {TELEBIT_JS} "$@" |
@ -1,2 +0,0 @@ |
|||
#!/bin/bash |
|||
{TELEBIT_NODE} {TELEBITD_JS} daemon "$@" |
@ -1,64 +0,0 @@ |
|||
# Pre-req |
|||
# sudo adduser telebit --home {TELEBIT_PATH} |
|||
# sudo mkdir -p {TELEBIT_PATH}/ |
|||
# sudo chown -R {TELEBIT_USER}:{TELEBIT_GROUP} {TELEBIT_PATH}/ |
|||
|
|||
[Unit] |
|||
Description=Telebit Remote |
|||
Documentation=https://git.coolaj86.com/coolaj86/telebit.js/ |
|||
; After=network-online.target |
|||
; Wants=network-online.target systemd-networkd-wait-online.service |
|||
|
|||
[Service] |
|||
# Restart on crash (bad signal), and also on 'clean' failure (error exit code) |
|||
# Allow up to 3 restarts within 10 seconds |
|||
# (it's unlikely that a user or properly-running script will do this) |
|||
Restart=always |
|||
StartLimitInterval=10 |
|||
StartLimitBurst=3 |
|||
|
|||
# User and group the process will run as |
|||
;User={TELEBIT_USER} |
|||
;Group={TELEBIT_GROUP} |
|||
|
|||
WorkingDirectory={TELEBIT_PATH} |
|||
# custom directory cannot be set and will be the place where this exists, not the working directory |
|||
ExecStart={TELEBIT_NODE} {TELEBITD_JS} daemon --config {TELEBITD_CONFIG} |
|||
ExecReload=/bin/kill -USR1 $MAINPID |
|||
|
|||
# Limit the number of file descriptors and processes; see `man systemd.exec` for more limit settings. |
|||
# Unmodified, this is not expected to use more than this. |
|||
;LimitNOFILE=1048576 # no issues yet, but disabled just in case |
|||
;LimitNPROC=64 # doesn't work on some systems |
|||
|
|||
# Use private /tmp and /var/tmp, which are discarded after this stops. |
|||
PrivateTmp=true |
|||
# Use a minimal /dev |
|||
;PrivateDevices=true |
|||
# Hide /home, /root, and /run/user. Nobody will steal your SSH-keys. |
|||
ProtectHome=true |
|||
# Make /usr, /boot, /etc and possibly some more folders read-only. |
|||
ProtectSystem=full |
|||
# ... except for a few because we want a place for config, logs, etc |
|||
# This merely retains r/w access rights, it does not add any new. |
|||
# Must still be writable on the host! |
|||
ReadWriteDirectories={TELEBIT_RW_DIRS} |
|||
|
|||
# Note: in v231 and above ReadWritePaths has been renamed to ReadWriteDirectories |
|||
; ReadWritePaths={TELEBIT_RW_DIRS} |
|||
|
|||
# The following additional security directives only work with systemd v229 or later. |
|||
# They further retrict privileges that can be gained. |
|||
# Note that you may have to add capabilities required by any plugins in use. |
|||
;CapabilityBoundingSet=CAP_NET_BIND_SERVICE |
|||
;AmbientCapabilities=CAP_NET_BIND_SERVICE |
|||
NoNewPrivileges=true |
|||
|
|||
# Caveat: Some features may need additional capabilities. |
|||
# For example an "upload" may need CAP_LEASE |
|||
; CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_LEASE |
|||
; AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_LEASE |
|||
; NoNewPrivileges=true |
|||
|
|||
[Install] |
|||
WantedBy=multi-user.target |
@ -1,70 +0,0 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>Label</key> |
|||
<string>Telebit Remote</string> |
|||
|
|||
<key>ProgramArguments</key> |
|||
<array> |
|||
<string>{TELEBIT_NODE}</string> |
|||
<string>{TELEBITD_JS}</string> |
|||
<string>daemon</string> |
|||
<string>--config</string> |
|||
<string>{TELEBITD_CONFIG}</string> |
|||
</array> |
|||
|
|||
<key>EnvironmentVariables</key> |
|||
<dict> |
|||
<key>TELEBIT_PATH</key> |
|||
<string>{TELEBIT_PATH}</string> |
|||
<key>NODE_PATH</key> |
|||
<string>{NODE_PATH}</string> |
|||
<key>NPM_CONFIG_PREFIX</key> |
|||
<string>{NPM_CONFIG_PREFIX}</string> |
|||
</dict> |
|||
|
|||
<!-- |
|||
:: LaunchDaemon Only :: |
|||
<key>UserName</key> |
|||
<string>{TELEBIT_USER}</string> |
|||
<key>GroupName</key> |
|||
<string>{TELEBIT_GROUP}</string> |
|||
<key>InitGroups</key> |
|||
<true/> |
|||
--> |
|||
|
|||
<key>RunAtLoad</key> |
|||
<true/> |
|||
<key>KeepAlive</key> |
|||
<true/> |
|||
<!-- |
|||
<dict> |
|||
<key>Crashed</key> |
|||
<true/> |
|||
<key>NetworkState</key> |
|||
<true/> |
|||
<key>SuccessfulExit</key> |
|||
<false/> |
|||
</dict> |
|||
--> |
|||
|
|||
<!-- |
|||
<key>SoftResourceLimits</key> |
|||
<dict> |
|||
<key>NumberOfFiles</key> |
|||
<integer>8192</integer> |
|||
</dict> |
|||
<key>HardResourceLimits</key> |
|||
<dict/> |
|||
--> |
|||
|
|||
<key>WorkingDirectory</key> |
|||
<string>{TELEBIT_PATH}</string> |
|||
|
|||
<key>StandardErrorPath</key> |
|||
<string>{TELEBIT_LOG_DIR}/telebit.log</string> |
|||
<key>StandardOutPath</key> |
|||
<string>{TELEBIT_LOG_DIR}/telebit.log</string> |
|||
</dict> |
|||
</plist> |
@ -1,67 +0,0 @@ |
|||
# Pre-req |
|||
# sudo adduser telebit --home {TELEBIT_PATH} |
|||
# sudo mkdir -p {TELEBIT_PATH}/ |
|||
# sudo chown -R {TELEBIT_USER}:{TELEBIT_GROUP} {TELEBIT_PATH}/ |
|||
|
|||
[Unit] |
|||
Description=Telebit Remote |
|||
Documentation=https://git.coolaj86.com/coolaj86/telebit.js/ |
|||
After=network-online.target |
|||
Wants=network-online.target systemd-networkd-wait-online.service |
|||
|
|||
[Service] |
|||
# Restart on crash (bad signal), and also on 'clean' failure (error exit code) |
|||
# Allow up to 3 restarts within 10 seconds |
|||
# (it's unlikely that a user or properly-running script will do this) |
|||
Restart=always |
|||
StartLimitInterval=10 |
|||
StartLimitBurst=3 |
|||
|
|||
# User and group the process will run as |
|||
User={TELEBIT_USER} |
|||
Group={TELEBIT_GROUP} |
|||
|
|||
WorkingDirectory={TELEBIT_PATH} |
|||
# custom directory cannot be set and will be the place where this exists, not the working directory |
|||
ExecStart={TELEBIT_NODE} {TELEBITD_JS} daemon --config {TELEBITD_CONFIG} |
|||
ExecReload=/bin/kill -USR1 $MAINPID |
|||
|
|||
# Limit the number of file descriptors and processes; see `man systemd.exec` for more limit settings. |
|||
# Unmodified, this is not expected to use more than this. |
|||
LimitNOFILE=1048576 |
|||
LimitNPROC=64 |
|||
|
|||
# Use private /tmp and /var/tmp, which are discarded after this stops. |
|||
PrivateTmp=true |
|||
# Use a minimal /dev |
|||
PrivateDevices=true |
|||
# Hide /home, /root, and /run/user. Nobody will steal your SSH-keys. |
|||
ProtectHome=true |
|||
# Make /usr, /boot, /etc and possibly some more folders read-only. |
|||
ProtectSystem=full |
|||
# ... except for a few because we want a place for config, logs, etc |
|||
# This merely retains r/w access rights, it does not add any new. |
|||
# Must still be writable on the host! |
|||
ReadWriteDirectories={TELEBIT_RW_DIRS} |
|||
|
|||
# Note: in v231 and above ReadWritePaths has been renamed to ReadWriteDirectories |
|||
; ReadWritePaths={TELEBIT_RW_DIRS} |
|||
|
|||
# The following additional security directives only work with systemd v229 or later. |
|||
# They further retrict privileges that can be gained. |
|||
# Note that you may have to add capabilities required by any plugins in use. |
|||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE |
|||
AmbientCapabilities=CAP_NET_BIND_SERVICE |
|||
NoNewPrivileges=true |
|||
|
|||
# Caveat: Some features may need additional capabilities. |
|||
# For example an "upload" may need CAP_LEASE |
|||
; CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_LEASE |
|||
; AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_LEASE |
|||
; NoNewPrivileges=true |
|||
|
|||
[Install] |
|||
# For system-level service |
|||
;WantedBy=multi-user.target |
|||
# For userspace service |
|||
WantedBy=default.target |
@ -0,0 +1,14 @@ |
|||
# bash gen-tab.sh >> index.tab |
|||
# |
|||
# version major size sha256 channel os arch url |
|||
# v0.20.8 v0.20 25119710 4128ee6ef3dcc9c754dd1e46d1d68a217707017c223b417d34a6d0e56ab86f1a stable darwin amd64 https://rootprojects.org/telebit/dist/stable/telebit-stable-darwin-amd64.tar.gz |
|||
for x in stable/*; do |
|||
my_os="$(echo $x | cut -d '-' -f 3)" |
|||
my_arch="$(echo $x | cut -d '-' -f 4 | cut -d '.' -f 1)" |
|||
my_version="v0.20.8" |
|||
my_major="v0.20" |
|||
my_chan="stable" |
|||
my_sha256=$(sha256sum -b "$x" | cut -d ' ' -f 1) |
|||
my_size=$(ls -l "$x" | cut -d ' ' -f 5) |
|||
printf "${my_version}\t${my_major}\t${my_size}\t${my_sha256}\t${my_chan}\t${my_os}\t${my_arch}\thttps://rootprojects.org/telebit/dist/$x\n" |
|||
done |
@ -1,448 +0,0 @@ |
|||
'use strict'; |
|||
|
|||
//var fs = require('fs');
|
|||
var os = require('os'); |
|||
var mkdirp = require('mkdirp'); |
|||
var exec = require('child_process').exec; |
|||
var path = require('path'); |
|||
|
|||
var Launcher = module.exports; |
|||
Launcher._killAll = function (fn) { |
|||
var psList = require('ps-list'); |
|||
psList().then(function (procs) { |
|||
procs.forEach(function (proc) { |
|||
if ('node' === proc.name && /\btelebitd\b/i.test(proc.cmd)) { |
|||
console.log(proc); |
|||
process.kill(proc.pid); |
|||
return true; |
|||
} |
|||
}); |
|||
// Two things:
|
|||
// 1) wait to see if the process dies
|
|||
// 2) wait to give time for the socket to connect
|
|||
setTimeout(function () { |
|||
if (fn) { fn(null); return; } |
|||
}, 1.75 * 1000); |
|||
}); |
|||
}; |
|||
Launcher._getError = function getError(err, stderr) { |
|||
if (err) { return err; } |
|||
if (stderr) { |
|||
err = new Error(stderr); |
|||
err.code = 'ELAUNCHER'; |
|||
return err; |
|||
} |
|||
}; |
|||
Launcher._detect = function (things, fn) { |
|||
if (things.launcher) { |
|||
if ('string' === typeof things.launcher) { |
|||
fn(null, things.launcher); |
|||
return; |
|||
} |
|||
if ('function' === typeof things.launcher) { |
|||
things.launcher(things); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
// could have used "command-exists" but I'm trying to stay low-dependency
|
|||
// os.platform(), os.type()
|
|||
if (!/^win/i.test(os.platform())) { |
|||
if (/^darwin/i.test(os.platform())) { |
|||
exec('command -v launchctl', things._execOpts, function (err, stdout, stderr) { |
|||
err = Launcher._getError(err, stderr); |
|||
fn(err, 'launchctl'); |
|||
}); |
|||
} else { |
|||
exec('command -v systemctl', things._execOpts, function (err, stdout, stderr) { |
|||
err = Launcher._getError(err, stderr); |
|||
fn(err, 'systemctl'); |
|||
}); |
|||
} |
|||
} else { |
|||
// https://stackoverflow.com/questions/17908789/how-to-add-an-item-to-registry-to-run-at-startup-without-uac
|
|||
// wininit? regedit? SCM?
|
|||
// REG ADD "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /V "My App" /t REG_SZ /F /D "C:\MyAppPath\MyApp.exe"
|
|||
// https://www.microsoft.com/developerblog/2015/11/09/reading-and-writing-to-the-windows-registry-in-process-from-node-js/
|
|||
// https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg-add
|
|||
// https://social.msdn.microsoft.com/Forums/en-US/5b318f44-281e-4098-8dee-3ba8435fa391/add-registry-key-for-autostart-of-app-in-ice?forum=quebectools
|
|||
// utils.elevate
|
|||
// https://github.com/CatalystCode/windows-registry-node
|
|||
exec('where reg.exe', things._execOpts, function (err, stdout, stderr) { |
|||
//console.log((stdout||'').trim());
|
|||
if (stderr) { |
|||
console.error(stderr); |
|||
} |
|||
fn(err, 'reg.exe'); |
|||
}); |
|||
} |
|||
}; |
|||
Launcher.install = function (things, fn) { |
|||
if (!fn) { fn = function (err) { if (err) { console.error(err); } }; } |
|||
things = things || {}; |
|||
// in some future version we can take this file out
|
|||
// and accept process.env from things
|
|||
var installLauncher = require('./template-launcher'); |
|||
|
|||
// Right now this is just for npm install -g and npx
|
|||
if (things.env) { |
|||
things.env.PATH = things.env.PATH || process.env.PATH; |
|||
} else { |
|||
things.env = process.env; |
|||
} |
|||
things.argv = things.argv || process.argv; |
|||
things._execOpts = { windowsHide: true, env: things.env }; |
|||
var telebitRoot = path.join(__dirname, '../..'); |
|||
var vars = { |
|||
telebitPath: telebitRoot |
|||
, telebitUser: os.userInfo().username |
|||
, telebitGroup: (/^darwin/i.test(os.platform()) ? 'staff' : os.userInfo().username) |
|||
, telebitRwDirs: [ |
|||
telebitRoot |
|||
, path.join(os.homedir(), '.config/telebit') |
|||
, path.join(os.homedir(), '.local/share/telebit') |
|||
] |
|||
, telebitNode: (things.argv[0]||'').replace(/\.exe/i, '') // path.join(telebitRoot, 'bin/node')
|
|||
, telebitBin: path.join(telebitRoot, 'bin/telebit') |
|||
, telebitdBin: path.join(telebitRoot, 'bin/telebitd') |
|||
, telebitJs: path.join(telebitRoot, 'bin/telebit.js') |
|||
, telebitdJs: path.join(telebitRoot, 'bin/telebitd.js') |
|||
, telebitConfig: path.join(os.homedir(), '.config/telebit/telebit.yml') |
|||
, telebitdConfig: path.join(os.homedir(), '.config/telebit/telebitd.yml') |
|||
, TELEBIT_LOG_DIR: path.join(os.homedir(), '.local/share/telebit/var/log') |
|||
, TELEBIT_SOCK_DIR: path.join(os.homedir(), '.local/share/telebit/var/run') |
|||
}; |
|||
vars.telebitBinTpl = path.join(telebitRoot, 'usr/share/dist/bin/telebit.tpl'); |
|||
vars.telebitNpm = path.resolve(vars.telebitNode, '../npm'); |
|||
vars.nodePath = path.resolve(vars.telebitNode, '../../lib/node_modules'); |
|||
vars.npmConfigPrefix = path.resolve(vars.telebitNode, '..', '..'); |
|||
vars.userspace = (!things.telebitUser || (things.telebitUser === os.userInfo().username)) ? true : false; |
|||
if (-1 === vars.telebitRwDirs.indexOf(vars.npmConfigPrefix)) { |
|||
vars.telebitRwDirs.push(vars.npmConfigPrefix); |
|||
} |
|||
vars.telebitRwDirs = vars.telebitRwDirs.join(' '); |
|||
var launchers = { |
|||
'node': function () { |
|||
var fs = require('fs'); |
|||
var spawn = require('child_process').spawn; |
|||
var logpath = path.join(os.homedir(), '.local/share/telebit/var/log'); |
|||
try { |
|||
mkdirp.sync(logpath); |
|||
} catch(e) { |
|||
if (fn) { fn(e); return; } |
|||
return; |
|||
} |
|||
var stdout = fs.openSync(path.join(logpath, 'info.log'), 'a'); |
|||
var stderr = fs.openSync(path.join(logpath, 'error.log'), 'a'); |
|||
|
|||
var killed = 0; |
|||
var err; |
|||
var args = [ |
|||
path.join(telebitRoot, 'bin/telebitd.js') |
|||
, 'daemon' |
|||
, '--config' |
|||
, vars.telebitdConfig |
|||
]; |
|||
var subprocess = spawn( |
|||
vars.telebitNode |
|||
, args |
|||
, { detached: true |
|||
, stdio: [ 'ignore', stdout, stderr ] |
|||
} |
|||
); |
|||
//console.log('[debug]', vars.telebitNode, args.join(' '));
|
|||
subprocess.unref(); |
|||
subprocess.on('error', function (_err) { |
|||
err = _err; |
|||
killed += 1; |
|||
}); |
|||
subprocess.on('exit', function (code, signal) { |
|||
if (!err) { err = new Error('' + code + ' ' + signal + ' failure to launch'); } |
|||
killed += 1; |
|||
}); |
|||
|
|||
// Two things:
|
|||
// 1) wait to see if the process dies
|
|||
// 2) wait to give time for the socket to connect
|
|||
setTimeout(function () { |
|||
if (fn) { fn(err); return; } |
|||
}, 1.75 * 1000); |
|||
return; |
|||
} |
|||
, 'launchctl': function () { |
|||
var launcher = path.join(os.homedir(), 'Library/LaunchAgents/cloud.telebit.remote.plist'); |
|||
try { |
|||
mkdirp.sync(path.join(os.homedir(), 'Library/LaunchAgents')); |
|||
installLauncher.sync({ |
|||
file: { |
|||
tpl: vars.telebitBinTpl |
|||
, launcher: path.join(vars.telebitPath, 'bin/telebit') |
|||
, executable: true |
|||
} |
|||
, vars: vars |
|||
}); |
|||
installLauncher({ |
|||
file: { |
|||
tpl: path.join(vars.telebitPath, 'usr/share/dist/etc/skel/Library/LaunchAgents/cloud.telebit.remote.plist.tpl') |
|||
, launcher: launcher |
|||
} |
|||
, vars: vars |
|||
}); |
|||
var launcherstr = (vars.userspace ? "" : "sudo ") + "launchctl "; |
|||
var execstr = launcherstr + "unload -w " + launcher; |
|||
exec(execstr, things._execOpts, function (/*err, stdout, stderr*/) { |
|||
// we probably only need to skip the stderr (saying that it can't stop something that isn't started)
|
|||
//err = Launcher._getError(err, stderr);
|
|||
//if (err) { fn(err); return; }
|
|||
//console.log((stdout||'').trim());
|
|||
//console.log('unload worked?');
|
|||
execstr = launcherstr + "load -w " + launcher; |
|||
exec(execstr, things._execOpts, function (err, stdout, stderr) { |
|||
err = Launcher._getError(err, stderr); |
|||
if (err) { fn(err); return; } |
|||
//console.log((stdout||'').trim());
|
|||
//console.log('load worked?');
|
|||
setTimeout(function () { |
|||
fn(null); |
|||
}, 1.25 * 1000); |
|||
}); |
|||
}); |
|||
} catch(e) { |
|||
console.error("'" + launcher + "' error:"); |
|||
console.error(e); |
|||
if (fn) { fn(e); return; } |
|||
} |
|||
} |
|||
, 'systemctl': function () { |
|||
var launcher = path.join(os.homedir(), '.config/systemd/user/telebit.service'); |
|||
var launchername = 'telebit.service'; |
|||
try { |
|||
mkdirp.sync(path.join(os.homedir(), '.config/systemd/user')); |
|||
installLauncher({ |
|||
file: { |
|||
tpl: path.join(vars.telebitPath, 'usr/share/dist/etc/skel/.config/systemd/user/telebit.service.tpl') |
|||
, launcher: launcher |
|||
} |
|||
, vars: vars |
|||
}, function () { |
|||
// IMPORTANT
|
|||
// It's a dangerous to go alone, take this:
|
|||
// SYSTEMD_LOG_LEVEL=debug journalctl -xef --user-unit=telebit
|
|||
// (makes debugging systemd issues not "easy" per se, but possible)
|
|||
var launcherstr = (vars.userspace ? "" : "sudo ") + "systemctl " + (vars.userspace ? "--user " : ""); |
|||
var execstr = launcherstr + "daemon-reload"; |
|||
exec(execstr, things._execOpts, function (err, stdout, stderr) { |
|||
err = Launcher._getError(err, stderr); |
|||
if (err) { fn(err); return; } |
|||
//console.log((stdout||'').trim());
|
|||
var execstr = launcherstr + "enable " + launchername; |
|||
exec(execstr, things._execOpts, function (err, stdout, stderr) { |
|||
err = Launcher._getError(err, stderr && !/Created symlink/i.test(stderr) && stderr || ''); |
|||
if (err) { fn(err); return; } |
|||
//console.log((stdout||'').trim());
|
|||
var execstr = launcherstr + "restart " + launchername; |
|||
exec(execstr, things._execOpts, function (err, stdout, stderr) { |
|||
err = Launcher._getError(err, stderr); |
|||
if (err) { fn(err); return; } |
|||
//console.log((stdout||'').trim());
|
|||
setTimeout(function () { |
|||
var execstr = launcherstr + "status " + launchername; |
|||
exec(execstr, things._execOpts, function (err, stdout, stderr) { |
|||
err = Launcher._getError(err, stderr); |
|||
if (err) { fn(err); return; } |
|||
if (!/active.*running/i.test(stdout)) { |
|||
err = new Error("systemd failed to start '" + launchername + "'"); |
|||
} |
|||
if (err) { fn(err); return; } |
|||
//console.log((stdout||'').trim());
|
|||
fn(null); |
|||
}); |
|||
}, 1.25 * 1000); |
|||
}); |
|||
}); |
|||
}); |
|||
}); |
|||
} catch(e) { |
|||
console.error("'" + launcher + "' error:"); |
|||
console.error(e); |
|||
if (fn) { fn(e); return; } |
|||
} |
|||
} |
|||
, 'reg.exe': function () { |
|||
if (!vars.userspace) { |
|||
console.warn("sysetm-level, privileged services are not yet supported on windows"); |
|||
} |
|||
vars.telebitNode += '.exe'; |
|||
var cmd = 'reg.exe add "HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"' |
|||
+ ' /V "Telebit" /t REG_SZ /D ' |
|||
+ '"' + things.argv[0] + ' /c ' // something like C:\\Program Files (x64)\nodejs\node.exe
|
|||
+ [ path.join(__dirname, 'bin/telebitd.js') |
|||
, 'daemon' |
|||
, '--config' |
|||
, path.join(os.homedir(), '.config/telebit/telebitd.yml') |
|||
].join(' ') |
|||
+ '" /F' |
|||
; |
|||
exec(cmd, things._execOpts, function (err, stdout, stderr) { |
|||
err = Launcher._getError(err, stderr); |
|||
if (err) { fn(err); return; } |
|||
// need to start it for the first time ourselves
|
|||
run(null, 'node'); |
|||
}); |
|||
} |
|||
}; |
|||
|
|||
function run(err, launcher) { |
|||
if (err) { |
|||
console.error("No luck with '" + launcher + "', trying a child process instead..."); |
|||
console.error(err); |
|||
launcher = 'node'; |
|||
} |
|||
|
|||
if (launchers[launcher]) { |
|||
// console.log('Launching with launcher ' + launcher);
|
|||
mkdirp.sync(path.join(vars.telebitPath, 'bin')); |
|||
mkdirp.sync(vars.TELEBIT_LOG_DIR); |
|||
mkdirp.sync(vars.TELEBIT_SOCK_DIR); |
|||
launchers[launcher](); |
|||
return; |
|||
} else { |
|||
console.error("No launcher handler for '" + launcher+ "'"); |
|||
} |
|||
} |
|||
|
|||
things._vars = vars; |
|||
things._userspace = vars.userspace; |
|||
Launcher._detect(things, run); |
|||
}; |
|||
Launcher.uninstall = function (things, fn) { |
|||
if (!fn) { fn = function (err) { if (err) { console.error(err); } }; } |
|||
things = things || {}; |
|||
|
|||
// Right now this is just for npm install -g and npx
|
|||
if (things.env) { |
|||
things.env.PATH = things.env.PATH || process.env.PATH; |
|||
} else { |
|||
things.env = process.env; |
|||
} |
|||
things.argv = things.argv || process.argv; |
|||
things._execOpts = { windowsHide: true, env: things.env }; |
|||
var vars = { |
|||
telebitUser: os.userInfo().username |
|||
}; |
|||
vars.userspace = (!things.telebitUser || (things.telebitUser === os.userInfo().username)) ? true : false; |
|||
var launchers = { |
|||
'node': function () { |
|||
Launcher._killAll(fn); |
|||
} |
|||
, 'launchctl': function () { |
|||
var launcher = path.join(os.homedir(), 'Library/LaunchAgents/cloud.telebit.remote.plist'); |
|||
try { |
|||
var launcherstr = (vars.userspace ? "" : "sudo ") + "launchctl "; |
|||
var execstr = launcherstr + "unload -w " + launcher; |
|||
exec(execstr, things._execOpts, function (err, stdout, stderr) { |
|||
// we probably only need to skip the stderr (saying that it can't stop something that isn't started)
|
|||
//err = Launcher._getError(err, stderr);
|
|||
//if (err) { fn(err); return; }
|
|||
//console.log((stdout||'').trim());
|
|||
//console.log('unload worked?');
|
|||
err = Launcher._getError(err, stderr); |
|||
if (err) { fn(err); return; } |
|||
//console.log((stdout||'').trim());
|
|||
//console.log('load worked?');
|
|||
setTimeout(function () { |
|||
fn(null); |
|||
}, 1.25 * 1000); |
|||
}); |
|||
} catch(e) { |
|||
console.error("'" + launcher + "' error (uninstall):"); |
|||
console.error(e); |
|||
if (fn) { fn(e); return; } |
|||
} |
|||
} |
|||
, 'systemctl': function () { |
|||
var launcher = path.join(os.homedir(), '.config/systemd/user/telebit.service'); |
|||
var launchername = 'telebit.service'; |
|||
try { |
|||
mkdirp.sync(path.join(os.homedir(), '.config/systemd/user')); |
|||
// IMPORTANT
|
|||
// It's a dangerous to go alone, take this:
|
|||
// SYSTEMD_LOG_LEVEL=debug journalctl -xef --user-unit=telebit
|
|||
// (makes debugging systemd issues not "easy" per se, but possible)
|
|||
var launcherstr = (vars.userspace ? "" : "sudo ") + "systemctl " + (vars.userspace ? "--user " : ""); |
|||
var execstr = launcherstr + "disable " + launchername; |
|||
exec(execstr, things._execOpts, function (err, stdout, stderr) { |
|||
err = Launcher._getError(err, stderr && !/Removed symlink/i.test(stderr) && stderr || ''); |
|||
if (err) { fn(err); return; } |
|||
//console.log((stdout||'').trim());
|
|||
var execstr = launcherstr + "stop " + launchername; |
|||
exec(execstr, things._execOpts, function (err, stdout, stderr) { |
|||
err = Launcher._getError(err, stderr); |
|||
if (err) { fn(err); return; } |
|||
//console.log((stdout||'').trim());
|
|||
setTimeout(function () { |
|||
var execstr = launcherstr + "status " + launchername; |
|||
exec(execstr, things._execOpts, function (err, stdout, stderr) { |
|||
err = Launcher._getError(err, stderr); |
|||
if (err) { fn(err); return; } |
|||
if (!/inactive.*dead/i.test(stdout)) { |
|||
err = new Error("systemd failed to stop '" + launchername + "'"); |
|||
} |
|||
if (err) { fn(err); return; } |
|||
//console.log((stdout||'').trim());
|
|||
fn(null); |
|||
}); |
|||
}, 1.25 * 1000); |
|||
}); |
|||
}); |
|||
} catch(e) { |
|||
console.error("'" + launcher + "' error:"); |
|||
console.error(e); |
|||
if (fn) { fn(e); return; } |
|||
} |
|||
} |
|||
, 'reg.exe': function () { |
|||
if (!vars.userspace) { |
|||
console.warn("sysetm-level, privileged services are not yet supported on windows"); |
|||
} |
|||
var cmd = 'reg.exe add "HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"' |
|||
+ ' /V "Telebit" /F' |
|||
; |
|||
exec(cmd, things._execOpts, function (err, stdout, stderr) { |
|||
err = Launcher._getError(err, stderr); |
|||
if (err) { fn(err); return; } |
|||
// need to start it for the first time ourselves
|
|||
kill(null, 'node'); |
|||
}); |
|||
} |
|||
}; |
|||
|
|||
function kill(err, launcher) { |
|||
if (err) { |
|||
console.error("No luck with '" + launcher + "', trying a process.kill() instead..."); |
|||
console.error(err); |
|||
launcher = 'node'; |
|||
} |
|||
|
|||
if (launchers[launcher]) { |
|||
launchers[launcher](); |
|||
return; |
|||
} else { |
|||
console.error("No launcher handler (uninstall) for '" + launcher + "'"); |
|||
} |
|||
} |
|||
|
|||
things._vars = vars; |
|||
things._userspace = vars.userspace; |
|||
Launcher._detect(things, kill); |
|||
}; |
|||
|
|||
if (module === require.main) { |
|||
Launcher.install({ |
|||
argv: process.argv |
|||
, env: process.env |
|||
}, function (err) { |
|||
if (err) { console.error(err); return; } |
|||
console.log("Telebit launched, or so it seems."); |
|||
}); |
|||
} |
@ -0,0 +1,14 @@ |
|||
powershell.exe $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest https://rootprojects.org/telebit/dist/stable/telebit-stable-windows-amd64.zip -OutFile telebit.zip |
|||
mkdir %SYSTEMPROFILE%\.local\opt\ |
|||
|
|||
del /F /Q /S %SYSTEMPROFILE%\.local\opt\telebit-stable-windows-amd64 > NUL |
|||
rmdir /Q /S %SYSTEMPROFILE%\.local\opt\telebit-stable-windows-amd64 |
|||
powershell.exe Expand-Archive -Force .\telebit.zip %SYSTEMPROFILE%\.local\opt\ |
|||
|
|||
%SYSTEMPROFILE%\.local\opt\telebit-stable-windows-amd64\bin\serviceman.exe stop telebit |
|||
|
|||
del /F /Q /S %SYSTEMPROFILE%\.local\opt\telebit\* > NUL |
|||
rmdir /Q /S %SYSTEMPROFILE%\.local\opt\telebit |
|||
move %SYSTEMPROFILE%\.local\opt\telebit-stable-windows-amd64 %SYSTEMPROFILE%\.local\opt\telebit |
|||
%SYSTEMPROFILE%\.local\opt\telebit\bin\serviceman.exe add --name telebit %SYSTEMPROFILE%\.local\opt\telebit\bin\node %SYSTEMPROFILE%\.local\opt\telebit\bin\telebitd.js |
|||
%SYSTEMPROFILE%\.local\opt\telebit\bin\pathman.exe add %SYSTEMPROFILE%\.local\opt\telebit\bin |
@ -1,574 +1,41 @@ |
|||
#!/bin/bash |
|||
#<pre><code> |
|||
|
|||
# What does this do.. and why? |
|||
# (and why is it so complicated?) |
|||
# |
|||
# What this does |
|||
# |
|||
# 1. Sets some vars and asks some questions |
|||
# 2. Installs everything into a single place |
|||
# (inculding deps like node.js, with the correct version) |
|||
# 3. Depending on OS, creates a user for the service |
|||
# 4. Depending on OS, register with system launcher |
|||
# |
|||
# Why |
|||
# |
|||
# So that you can get a fully configured, running product, |
|||
# with zero manual configuration in a matter of seconds - |
|||
# and have an uninstall that's just as easy. |
|||
# |
|||
# Why so complicated? |
|||
# |
|||
# To support nuance differences between various versions of |
|||
# Linux, macOS, and Android, including whether it's being |
|||
# installed with user privileges, as root, wit a system user |
|||
# system daemon launcher, etc. Also, this is designed to be |
|||
# reusable with many apps and services, so it's very variabled... |
|||
# This downloads the telebit zip (Windows) or tarball (Mac, Linux), |
|||
# unpacks it, and then completes the installation |
|||
|
|||
set -e |
|||
set -u |
|||
|
|||
### http_bash exported by get.sh |
|||
|
|||
TELEBIT_DEBUG=${TELEBIT_DEBUG:-} |
|||
|
|||
# NOTE: On OS X logname works from a pipe, but on Linux it does not |
|||
my_logname=$(who am i </dev/tty | awk '{print $1}') |
|||
#my_logname=${my_logname:-$(logname)} |
|||
#my_logname=${my_logname:-$SUDO_USER} |
|||
if [ -n "$my_logname" ] && [ "$my_logname" != "$(id -u -n)" ]; then |
|||
echo "WARNING:" |
|||
echo " You are logged in as '$(logname)' but acting as '$(id -u -n)'." |
|||
echo " If the installation is not successful please log in as '$(id -u -n)' directly." |
|||
sleep 3 |
|||
fi |
|||
|
|||
if [ -n "${TELEBIT_DEBUG:-}" ]; then |
|||
echo 'TELEBIT_DEBUG='${TELEBIT_DEBUG} |
|||
fi |
|||
if [ -n "${TELEBIT_PATH:-}" ]; then |
|||
echo 'TELEBIT_PATH='${TELEBIT_PATH} |
|||
fi |
|||
if [ -n "${TELEBIT_USERSPACE:-}" ]; then |
|||
echo 'TELEBIT_USERSPACE='${TELEBIT_USERSPACE} |
|||
fi |
|||
if [ -n "${TELEBIT_USER:-}" ]; then |
|||
echo 'TELEBIT_USER='${TELEBIT_USER} |
|||
fi |
|||
if [ -n "${TELEBIT_GROUP:-}" ]; then |
|||
echo 'TELEBIT_GROUP='${TELEBIT_GROUP} |
|||
fi |
|||
TELEBIT_VERSION=${TELEBIT_VERSION:-master} |
|||
TELEBIT_USERSPACE=${TELEBIT_USERSPACE:-no} |
|||
my_email=${1:-} |
|||
my_relay=${2:-} |
|||
my_servernames=${3:-} |
|||
my_secret=${4:-} |
|||
|
|||
cur_user="$(id -u -n)" |
|||
TELEBIT_USER="${TELEBIT_USER:-$cur_user}" |
|||
|
|||
cur_group="$(id -g -n)" |
|||
TELEBIT_GROUP="${TELEBIT_GROUP:-$cur_group}" |
|||
|
|||
my_app_pkg_name="cloud.telebit.remote" |
|||
my_app="telebit" |
|||
my_daemon="telebitd" |
|||
my_bin="telebit.js" |
|||
my_name="Telebit Remote" |
|||
my_repo="telebit.js" |
|||
my_root=${my_root:-} # todo better install script |
|||
soft_sudo_cmd="sudo" |
|||
soft_sudo_cmde="sudo " |
|||
exec 3<>/dev/tty |
|||
read_cmd="read -u 3" |
|||
# TODO detect if rsync is available and use rsync -a (more portable) |
|||
rsync_cmd="cp -pPR" |
|||
|
|||
set +e |
|||
my_edit=$(basename "${EDITOR:-}") |
|||
if [ -z "$my_edit" ]; then |
|||
my_edit=$(basename "$(type -p edit)") |
|||
fi |
|||
if [ -z "$my_edit" ]; then |
|||
my_edit=$(basename "$(type -p nano)") |
|||
fi |
|||
if [ -z "$my_edit" ]; then |
|||
my_edit=$(basename "$(type -p vim)") |
|||
fi |
|||
if [ -z "$my_edit" ]; then |
|||
my_edit=$(basename "$(type -p vi)") |
|||
fi |
|||
if [ -z "$my_edit" ]; then |
|||
my_edit="nano" |
|||
fi |
|||
set -e |
|||
|
|||
if [ "root" == $(whoami) ] || [ 0 == $(id -u) ]; then |
|||
soft_sudo_cmd=" " |
|||
soft_sudo_cmde="" |
|||
fi |
|||
|
|||
echo "" |
|||
|
|||
TELEBIT_REAL_PATH=${TELEBIT_PATH:-} |
|||
|
|||
if [ $(id -u) -ne 0 ] && [ "$TELEBIT_USER" == "$cur_user" ]; then |
|||
TELEBIT_USERSPACE="yes" |
|||
if [ -z "${TELEBIT_REAL_PATH:-}" ]; then |
|||
TELEBIT_REAL_PATH=$HOME/Applications/$my_app |
|||
fi |
|||
else |
|||
TELEBIT_USERSPACE="no" |
|||
if [ -z "${TELEBIT_REAL_PATH:-}" ]; then |
|||
TELEBIT_REAL_PATH=/opt/$my_app |
|||
fi |
|||
fi |
|||
TELEBIT_PATH="$TELEBIT_REAL_PATH" |
|||
TELEBIT_TMP="$TELEBIT_REAL_PATH" |
|||
# this works slightly differently between bsd (macOS) and gnu mktemp |
|||
# bsd requires the Xes for templates while GNU uses them literally |
|||
my_tmp="$(mktemp -d -t telebit.XXXXXXXX)" |
|||
#TELEBIT_TMP="$my_tmp/telebit" |
|||
|
|||
echo "Installing $my_name to '$TELEBIT_REAL_PATH'" |
|||
# v10.2+ has much needed networking fixes, but breaks ursa. |
|||
# v9.x has severe networking bugs. |
|||
# v8.x has working ursa, but requires tls workarounds" |
|||
# v10.13 seems to work for me locally (new greenlock) |
|||
NODEJS_VER="${NODEJS_VER:-v10.13}" |
|||
export NODEJS_VER |
|||
export NODE_PATH="$TELEBIT_TMP/lib/node_modules" |
|||
export NPM_CONFIG_PREFIX="$TELEBIT_TMP" |
|||
# this comes last for security |
|||
export PATH="$PATH:$TELEBIT_REAL_PATH/bin" |
|||
sleep 0.25 |
|||
real_sudo_cmd=$soft_sudo_cmd |
|||
real_sudo_cmde=$soft_sudo_cmde |
|||
|
|||
set +e |
|||
mkdir -p $my_tmp "$TELEBIT_REAL_PATH" "$TELEBIT_REAL_PATH/etc" "$TELEBIT_REAL_PATH/var/log" 2>/dev/null && \ |
|||
chown -R $(id -u -n):$(id -g -n) $my_tmp "$TELEBIT_REAL_PATH" 2>/dev/null |
|||
if [ $? -eq 0 ]; then |
|||
soft_sudo_cmd=" " |
|||
soft_sudo_cmde="" |
|||
else |
|||
$soft_sudo_cmd mkdir -p $my_tmp "$TELEBIT_REAL_PATH" "$TELEBIT_REAL_PATH/etc" "$TELEBIT_REAL_PATH/var/log" |
|||
$soft_sudo_cmd chown -R $(id -u -n):$(id -g -n) $my_tmp "$TELEBIT_REAL_PATH" |
|||
fi |
|||
set -e |
|||
|
|||
|
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " - installing node.js runtime to '$TELEBIT_REAL_PATH'..." |
|||
http_bash https://git.coolaj86.com/coolaj86/node-installer.sh/raw/branch/master/install.sh --no-dev-deps |
|||
else |
|||
echo -n "." |
|||
#bash -c 'while true; do echo -n "."; sleep 2; done' 2>/dev/null & |
|||
#_my_pid=$! |
|||
http_bash https://git.coolaj86.com/coolaj86/node-installer.sh/raw/branch/master/install.sh --no-dev-deps >/dev/null 2>/dev/null |
|||
#kill $_my_pid >/dev/null 2>/dev/null |
|||
fi |
|||
|
|||
# |
|||
# TODO create "upgrade" script and run that instead |
|||
# |
|||
|
|||
my_node="$TELEBIT_REAL_PATH/bin/node" |
|||
tmp_node="$TELEBIT_TMP/bin/node" |
|||
my_npm="$my_node $TELEBIT_TMP/bin/npm" |
|||
tmp_npm="$tmp_node $TELEBIT_TMP/bin/npm" |
|||
|
|||
#https://git.coolaj86.com/coolaj86/telebit.js.git |
|||
#https://git.coolaj86.com/coolaj86/telebit.js/archive/:tree:.tar.gz |
|||
#https://git.coolaj86.com/coolaj86/telebit.js/archive/:tree:.zip |
|||
set +e |
|||
my_unzip=$(type -p unzip) |
|||
my_tar=$(type -p tar) |
|||
# TODO extract to temporary directory, configure, copy etc, replace |
|||
if [ -n "$my_unzip" ]; then |
|||
rm -f $my_tmp/$my_app-$TELEBIT_VERSION.zip |
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " - installing telebit zip to '$TELEBIT_REAL_PATH'" |
|||
fi |
|||
echo -n "." |
|||
#bash -c 'while true; do echo -n "."; sleep 2; done' 2>/dev/null & |
|||
#_my_pid=$! |
|||
http_get https://git.coolaj86.com/coolaj86/$my_repo/archive/$TELEBIT_VERSION.zip $my_tmp/$my_app-$TELEBIT_VERSION.zip |
|||
#kill $_my_pid >/dev/null 2>/dev/null |
|||
# -o means overwrite, and there is no option to strip |
|||
$my_unzip -o $my_tmp/$my_app-$TELEBIT_VERSION.zip -d $my_tmp/ >/dev/null |
|||
$rsync_cmd $my_tmp/$my_repo/* $TELEBIT_TMP/ > /dev/null |
|||
rm -rf $my_tmp/$my_repo |
|||
elif [ -n "$my_tar" ]; then |
|||
rm -f $my_tmp/$my_app-$TELEBIT_VERSION.tar.gz |
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " - installing telebit tar.gz to '$TELEBIT_REAL_PATH'" |
|||
fi |
|||
echo -n "." |
|||
#bash -c 'while true; do echo -n "."; sleep 2; done' 2>/dev/null & |
|||
#_my_pid=$! |
|||
http_get https://git.coolaj86.com/coolaj86/$my_repo/archive/$TELEBIT_VERSION.tar.gz $my_tmp/$my_app-$TELEBIT_VERSION.tar.gz |
|||
#kill $_my_pid >/dev/null 2>/dev/null |
|||
$my_tar -xzf $my_tmp/$my_app-$TELEBIT_VERSION.tar.gz --strip 1 -C $TELEBIT_TMP/ >/dev/null |
|||
else |
|||
echo "Neither tar nor unzip found. Abort." |
|||
exit 13 |
|||
fi |
|||
set -e |
|||
|
|||
# |
|||
# TODO create slim packages that contain all the deps on each os and cpu |
|||
# |
|||
pushd $TELEBIT_TMP >/dev/null |
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " - installing telebit npm dependencies to '$TELEBIT_REAL_PATH'..." |
|||
### http_get, http_bash, archiver, and archive_ext are exported by get.sh |
|||
|
|||
mkdir -p $HOME/Downloads |
|||
my_tmp="$(mktemp -d -t telebit.XXXX)" |
|||
http_get "https://rootprojects.org/telebit/dist/index.tab" "$my_tmp/index.tab" |
|||
latest=$(grep $TELEBIT_RELEASE $my_tmp/index.tab | grep $TELEBIT_OS | grep $TELEBIT_ARCH | head -n 1 | cut -f 1) |
|||
major=$(grep $TELEBIT_RELEASE $my_tmp/index.tab | grep $TELEBIT_OS | grep $TELEBIT_ARCH | head -n 1 | cut -f 2) |
|||
size=$(grep $TELEBIT_RELEASE $my_tmp/index.tab | grep $TELEBIT_OS | grep $TELEBIT_ARCH | head -n 1 | cut -f 3) |
|||
#latest=$(grep $TELEBIT_RELEASE $my_tmp/index.tab | grep $TELEBIT_OS | grep $TELEBIT_ARCH | head -n 1 | cut -f 1) |
|||
my_dir="telebit-$latest-$TELEBIT_OS-$TELEBIT_ARCH" |
|||
my_file="$my_dir.$archive_ext" |
|||
if [ -f "$HOME/Downloads/$my_file" ]; then |
|||
my_size=$(($(wc -c < "$HOME/Downloads/$my_file"))) |
|||
if [ "$my_size" -eq "$size" ]; then |
|||
echo "File exists in ~/Downloads, skipping download" |
|||
else |
|||
echo -n "." |
|||
echo "Removing corrupt download '~/Downloads/$my_file'" |
|||
rm -f "$HOME/Downloads/$my_file" |
|||
fi |
|||
set +e |
|||
$tmp_npm install >/dev/null 2>/dev/null & |
|||
tmp_npm_pid=$! |
|||
while [ -n "$tmp_npm_pid" ]; do |
|||
sleep 2 |
|||
echo -n "." |
|||
kill -s 0 $tmp_npm_pid >/dev/null 2>/dev/null || tmp_npm_pid="" |
|||
done |
|||
set -e |
|||
echo -n "." |
|||
$tmp_npm install >/dev/null 2>/dev/null |
|||
# ursa is now an entirely optional dependency for key generation |
|||
# but very much needed on ARM devices |
|||
$tmp_npm install ursa >/dev/null 2>/dev/null || true |
|||
popd >/dev/null |
|||
|
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " - configuring telebit..." |
|||
echo "" |
|||
fi |
|||
|
|||
############################################### |
|||
# |
|||
# TODO convert to node script |
|||
# |
|||
# Now that node is installed and the telebit |
|||
# packeage is downloaded, everything can be |
|||
# run from node, except things requiring sudo |
|||
# |
|||
############################################### |
|||
|
|||
# telebit remote |
|||
echo '#!/bin/bash' > "$TELEBIT_TMP/bin/$my_app" |
|||
echo "$my_node $TELEBIT_REAL_PATH/bin/$my_bin "'"$@"' >> "$TELEBIT_TMP/bin/$my_app" |
|||
chmod a+x "$TELEBIT_TMP/bin/$my_app" |
|||
|
|||
# telebit daemon |
|||
echo '#!/bin/bash' > "$TELEBIT_TMP/bin/$my_daemon" |
|||
echo "$my_node $TELEBIT_REAL_PATH/bin/$my_daemon.js daemon "'"$@"' >> "$TELEBIT_TMP/bin/$my_daemon" |
|||
chmod a+x "$TELEBIT_TMP/bin/$my_daemon" |
|||
|
|||
# Create uninstall script based on the install script variables |
|||
cat << EOF > $TELEBIT_TMP/bin/${my_app}_uninstall |
|||
#!/bin/bash |
|||
set -x |
|||
if [ "$(type -p launchctl)" ]; then |
|||
sudo launchctl unload -w /Library/LaunchDaemons/${my_app_pkg_name}.plist |
|||
sudo rm -f /Library/LaunchDaemons/${my_app_pkg_name}.plist |
|||
|
|||
launchctl unload -w $HOME/Library/LaunchAgents/${my_app_pkg_name}.plist |
|||
rm -f $HOME/Library/LaunchAgents/${my_app_pkg_name}.plist |
|||
fi |
|||
if [ "$(type -p systemctl)" ]; then |
|||
systemctl --user disable $my_app >/dev/null |
|||
systemctl --user stop $my_app |
|||
rm -f $HOME/.config/systemd/user/$my_app.service |
|||
|
|||
sudo systemctl disable $my_app >/dev/null |
|||
sudo systemctl stop $my_app |
|||
sudo rm -f /etc/systemd/system/$my_app.service |
|||
fi |
|||
sudo rm -rf $TELEBIT_REAL_PATH /usr/local/bin/$my_app |
|||
sudo rm -rf $TELEBIT_REAL_PATH /usr/local/bin/$my_daemon |
|||
rm -rf $HOME/.config/$my_app $HOME/.local/share/$my_app |
|||
EOF |
|||
chmod a+x $TELEBIT_TMP/bin/${my_app}_uninstall |
|||
|
|||
#set +e |
|||
#if type -p setcap >/dev/null 2>&1; then |
|||
# #echo "Setting permissions to allow $my_app to run on port 80 and port 443 without sudo or root" |
|||
# echo " > ${real_sudo_cmde}setcap cap_net_bind_service=+ep $TELEBIT_REAL_PATH/bin/node" |
|||
# $real_sudo_cmd setcap cap_net_bind_service=+ep $TELEBIT_REAL_PATH/bin/node |
|||
#fi |
|||
#set -e |
|||
|
|||
my_skip="" |
|||
set +e |
|||
# TODO for macOS https://apple.stackexchange.com/questions/286749/how-to-add-a-user-from-the-command-line-in-macos |
|||
# TODO do stuff for groups too |
|||
# TODO add ending $ |
|||
if type -p dscl >/dev/null 2>/dev/null; then |
|||
if [ -n "$(dscl . list /users | grep ^$TELEBIT_USER)" ] && [ -n "$(dscl . list /groups | grep ^$TELEBIT_GROUP)" ]; then |
|||
my_skip="yes" |
|||
fi |
|||
elif [ -n "$(cat $my_root/etc/passwd | grep $TELEBIT_USER)" ] && [ -n "$(cat $my_root/etc/group | grep $TELEBIT_GROUP)" ]; then |
|||
my_skip="yes" |
|||
fi |
|||
|
|||
if [ -z "$my_skip" ]; then |
|||
if type -p adduser >/dev/null 2>/dev/null; then |
|||
$real_sudo_cmd adduser --home $TELEBIT_REAL_PATH --gecos '' --disabled-password $TELEBIT_USER >/dev/null 2>&1 |
|||
#TELEBIT_USER=$my_app_name |
|||
TELEBIT_GROUP=$TELEBIT_USER |
|||
elif [ -n "$(cat /etc/passwd | grep www-data:)" ]; then |
|||
# Linux (Ubuntu) |
|||
TELEBIT_USER=www-data |
|||
TELEBIT_GROUP=www-data |
|||
elif [ -n "$(cat /etc/passwd | grep _www:)" ]; then |
|||
# Mac |
|||
TELEBIT_USER=_www |
|||
TELEBIT_GROUP=_www |
|||
else |
|||
# Unsure |
|||
TELEBIT_USER=$(id -u -n) # $(whoami) |
|||
TELEBIT_GROUP=$(id -g -n) |
|||
fi |
|||
fi |
|||
set -e |
|||
|
|||
export TELEBIT_USER |
|||
export TELEBIT_GROUP |
|||
export TELEBIT_PATH |
|||
export TELEBIT_CONFIG=$HOME/.config/$my_app/$my_app.yml |
|||
# TODO check both expected sock paths in client by default |
|||
if [ "yes" == "$TELEBIT_USERSPACE" ]; then |
|||
TELEBIT_TMP_CONFIGD=$HOME/.config/$my_app/$my_daemon.yml |
|||
TELEBITD_CONFIG=$HOME/.config/$my_app/$my_daemon.yml |
|||
TELEBIT_LOG_DIR=${TELEBIT_LOG_DIR:-$HOME/.local/share/$my_app/var/log/} |
|||
TELEBIT_SOCK_DIR=${TELEBIT_SOCK_DIR:-$HOME/.local/share/$my_app/var/run/} |
|||
TELEBIT_SOCK=${TELEBIT_SOCK:-$HOME/.local/share/$my_app/var/run/$my_app.sock} |
|||
else |
|||
TELEBIT_TMP_CONFIGD=$TELEBIT_TMP/etc/$my_daemon.yml |
|||
TELEBITD_CONFIG=$TELEBIT_REAL_PATH/etc/$my_daemon.yml |
|||
TELEBIT_LOG_DIR=${TELEBIT_LOG_DIR:-$TELEBIT_REAL_PATH/var/log/} |
|||
TELEBIT_SOCK_DIR=${TELEBIT_SOCK_DIR:-$TELEBIT_REAL_PATH/var/run/} |
|||
TELEBIT_SOCK=${TELEBIT_SOCK:-$TELEBIT_REAL_PATH/var/run/$my_app.sock} |
|||
fi |
|||
export TELEBITD_CONFIG |
|||
export TELEBIT_SOCK |
|||
export TELEBIT_NODE=$TELEBIT_REAL_PATH/bin/node |
|||
export TELEBIT_NPM=$TELEBIT_REAL_PATH/bin/npm |
|||
export TELEBIT_BIN=$TELEBIT_REAL_PATH/bin/telebit |
|||
export TELEBITD_BIN=$TELEBIT_REAL_PATH/bin/telebitd |
|||
export TELEBIT_JS=$TELEBIT_REAL_PATH/bin/telebit.js |
|||
export TELEBITD_JS=$TELEBIT_REAL_PATH/bin/telebitd.js |
|||
export TELEBIT_LOG_DIR |
|||
export TELEBIT_SOCK_DIR |
|||
export NODE_PATH="$TELEBIT_REAL_PATH/lib/node_modules" |
|||
export NPM_CONFIG_PREFIX="$TELEBIT_REAL_PATH" |
|||
|
|||
$my_node $TELEBIT_TMP/usr/share/template-launcher.js |
|||
|
|||
# TODO don't create this in TMP_PATH if it exists in TELEBIT_REAL_PATH |
|||
mkdir -p "$(dirname $TELEBIT_TMP_CONFIGD)" |
|||
if [ ! -e "$TELEBITD_CONFIG" ]; then |
|||
|
|||
echo "sock: $TELEBIT_SOCK" >> "$TELEBIT_TMP_CONFIGD" |
|||
echo "root: $TELEBIT_REAL_PATH" >> "$TELEBIT_TMP_CONFIGD" |
|||
cat $TELEBIT_REAL_PATH/usr/share/$my_daemon.tpl.yml >> "$TELEBIT_TMP_CONFIGD" |
|||
|
|||
fi |
|||
|
|||
mkdir -p "$(dirname $TELEBIT_CONFIG)" |
|||
if [ ! -e "$TELEBIT_CONFIG" ]; then |
|||
|
|||
echo "sock: $TELEBIT_SOCK" >> "$TELEBIT_CONFIG" |
|||
|
|||
fi |
|||
|
|||
|
|||
|
|||
# TODO |
|||
# Backup final directory, if it exists |
|||
# Move everything over to final directory |
|||
# Restore config files, if they exist |
|||
# rewrite system service file with real variables |
|||
|
|||
# This should only affect non-USERSPACE installs |
|||
#echo "${soft_sudo_cmde}chown -R $TELEBIT_USER '$TELEBIT_REAL_PATH' |
|||
$soft_sudo_cmd mkdir -p $TELEBIT_LOG_DIR |
|||
$soft_sudo_cmd mkdir -p $TELEBIT_SOCK_DIR |
|||
$soft_sudo_cmd chown -R $TELEBIT_USER "$TELEBIT_REAL_PATH" |
|||
|
|||
# $HOME/.config/systemd/user/ |
|||
# %h/.config/telebit/telebit.yml |
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " - adding $my_app as a system service" |
|||
fi |
|||
# TODO detect with type -p |
|||
my_system_launcher="" |
|||
my_app_launchd_service="" |
|||
if [ -d "/Library/LaunchDaemons" ]; then |
|||
my_system_launcher="launchd" |
|||
my_sudo_cmde="$real_sudo_cmde" |
|||
my_sudo_cmd="$real_sudo_cmd" |
|||
|
|||
|
|||
if [ "yes" == "$TELEBIT_USERSPACE" ]; then |
|||
my_app_launchd_service_skel="etc/skel/Library/LaunchAgents/${my_app_pkg_name}.plist" |
|||
my_app_launchd_service="$HOME/Library/LaunchAgents/${my_app_pkg_name}.plist" |
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " > $rsync_cmd $TELEBIT_REAL_PATH/usr/share/dist/$my_app_launchd_service $my_app_launchd_service" |
|||
fi |
|||
mkdir -p $HOME/Library/LaunchAgents |
|||
$rsync_cmd "$TELEBIT_REAL_PATH/usr/share/dist/$my_app_launchd_service_skel" "$my_app_launchd_service" |
|||
|
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " > chown $(id -u -n):$(id -g -n) $my_app_launchd_service" |
|||
fi |
|||
chown $(id -u -n):$(id -g -n) "$my_app_launchd_service" |
|||
my_sudo_cmd="" |
|||
my_sudo_cmde="" |
|||
|
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " > launchctl unload -w $my_app_launchd_service >/dev/null 2>/dev/null" |
|||
fi |
|||
launchctl unload -w "$my_app_launchd_service" >/dev/null 2>/dev/null |
|||
else |
|||
my_app_launchd_service_skel="usr/share/dist/Library/LaunchDaemons/${my_app_pkg_name}.plist" |
|||
my_app_launchd_service="$my_root/Library/LaunchDaemons/${my_app_pkg_name}.plist" |
|||
echo " > ${real_sudo_cmde}$rsync_cmd $TELEBIT_REAL_PATH/usr/share/dist/$my_app_launchd_service $my_app_launchd_service" |
|||
$real_sudo_cmd $rsync_cmd "$TELEBIT_REAL_PATH/usr/share/dist/$my_app_launchd_service_skel" "$my_app_launchd_service" |
|||
|
|||
echo " > ${real_sudo_cmde}chown root:wheel $my_app_launchd_service" |
|||
$real_sudo_cmd chown root:wheel "$my_app_launchd_service" |
|||
|
|||
echo " > ${real_sudo_cmde}launchctl unload -w $my_app_launchd_service >/dev/null 2>/dev/null" |
|||
$real_sudo_cmd launchctl unload -w "$my_app_launchd_service" >/dev/null 2>/dev/null |
|||
fi |
|||
|
|||
elif [ -d "$my_root/etc/systemd/system" ]; then |
|||
my_system_launcher="systemd" |
|||
|
|||
if [ "yes" == "$TELEBIT_USERSPACE" ]; then |
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " > $rsync_cmd $TELEBIT_REAL_PATH/usr/share/dist/etc/skel/.config/systemd/user/$my_app.service $HOME/.config/systemd/user/$my_app.service" |
|||
fi |
|||
mkdir -p $HOME/.config/systemd/user |
|||
$rsync_cmd "$TELEBIT_REAL_PATH/usr/share/dist/etc/skel/.config/systemd/user/$my_app.service" "$HOME/.config/systemd/user/$my_app.service" |
|||
else |
|||
echo " > ${real_sudo_cmde}$rsync_cmd $TELEBIT_REAL_PATH/usr/share/dist/etc/systemd/system/$my_app.service /etc/systemd/system/$my_app.service" |
|||
$real_sudo_cmd $rsync_cmd "$TELEBIT_REAL_PATH/usr/share/dist/etc/systemd/system/$my_app.service" "/etc/systemd/system/$my_app.service" |
|||
fi |
|||
fi |
|||
|
|||
sleep 1 |
|||
|
|||
############################### |
|||
# Actually Launch the Service # |
|||
############################### |
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
if [ ! -f "$HOME/Downloads/$my_file" ]; then |
|||
echo "Downloading from https://rootprojects.org/telebit/dist/$major/$my_file ..." |
|||
sleep 0.3 |
|||
http_get "https://rootprojects.org/telebit/dist/$major/$my_file" "$HOME/Downloads/$my_file" |
|||
echo "Saved to '$HOME/Downloads/$my_file' ..." |
|||
echo "" |
|||
sleep 0.3 |
|||
fi |
|||
if [ "launchd" == "$my_system_launcher" ]; then |
|||
|
|||
if [ "yes" == "$TELEBIT_USERSPACE" ]; then |
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " > launchctl load -w $my_app_launchd_service" |
|||
else |
|||
echo -n "." |
|||
fi |
|||
launchctl load -w "$my_app_launchd_service" |
|||
else |
|||
echo " > ${real_sudo_cmde}launchctl load -w $my_app_launchd_service" |
|||
$real_sudo_cmd launchctl load -w "$my_app_launchd_service" |
|||
fi |
|||
sleep 2; # give it time to start |
|||
|
|||
elif [ "systemd" == "$my_system_launcher" ]; then |
|||
|
|||
if [ "yes" == "$TELEBIT_USERSPACE" ]; then |
|||
# https://wiki.archlinux.org/index.php/Systemd/User |
|||
# sudo loginctl enable-linger username |
|||
|
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " > systemctl --user enable $my_app" |
|||
else |
|||
echo -n "." |
|||
fi |
|||
set +e |
|||
if systemctl --user daemon-reload; then |
|||
# enable also puts success output to stderr... why? |
|||
systemctl --user enable $my_app >/dev/null 2>/dev/null |
|||
#echo " > systemctl --user enable systemd-tmpfiles-setup.service systemd-tmpfiles-clean.timer" |
|||
#systemctl --user enable systemd-tmpfiles-setup.service systemd-tmpfiles-clean.timer |
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " > systemctl --user start $my_app" |
|||
fi |
|||
systemctl --user stop $my_app >/dev/null 2>/dev/null |
|||
systemctl --user start $my_app >/dev/null |
|||
|
|||
sleep 2; # give it time to start |
|||
_is_running=$(systemctl --user status --no-pager $my_app 2>/dev/null | grep "active.*running") |
|||
if [ -z "$_is_running" ]; then |
|||
echo "Something went wrong:" |
|||
systemctl --user status --no-pager $my_app |
|||
fi |
|||
else |
|||
echo "libpam-systemd is missing, which is required on Linux to register Telebit with the user launcher." |
|||
echo "sudo apt-get install -y libpam-systemd" |
|||
sudo apt-get install -y libpam-systemd |
|||
fi |
|||
set -e |
|||
echo -n "." |
|||
else |
|||
|
|||
$real_sudo_cmd systemctl daemon-reload |
|||
echo " > ${real_sudo_cmde}systemctl enable $my_app" |
|||
$real_sudo_cmd systemctl enable $my_app >/dev/null |
|||
echo " > ${real_sudo_cmde}systemctl start $my_app" |
|||
$real_sudo_cmd systemctl daemon-reload |
|||
$real_sudo_cmd systemctl restart $my_app |
|||
sleep 2; # give it time to start |
|||
$real_sudo_cmd systemctl status --no-pager $my_app |
|||
fi |
|||
|
|||
else |
|||
|
|||
echo "Run the service manually (we couldn't detect your system service to do that automatically):" |
|||
echo "" |
|||
echo " $TELEBITD_BIN --config $TELEBITD_CONFIG" |
|||
echo " ~/$my_app --config $TELEBIT_CONFIG" |
|||
|
|||
fi |
|||
|
|||
# NOTE: ln -sf *should* replace an existing link... but sometimes it doesn't, hence rm -f |
|||
if [ "yes" == "$TELEBIT_USERSPACE" ]; then |
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " > ${real_sudo_cmde}ln -sf $TELEBIT_REAL_PATH/bin/$my_app /usr/local/bin/$my_app" |
|||
fi |
|||
rm -f /usr/local/bin/$my_app 2>/dev/null || true |
|||
ln -sf $TELEBIT_REAL_PATH/bin/$my_app /usr/local/bin/$my_app 2>/dev/null || true |
|||
else |
|||
echo " > ${real_sudo_cmde}ln -sf $TELEBIT_REAL_PATH/bin/$my_app /usr/local/bin/$my_app" |
|||
rm -f /usr/local/bin/$my_app 2>/dev/null || \ |
|||
$real_sudo_cmd rm -f /usr/local/bin/$my_app |
|||
ln -sf $TELEBIT_REAL_PATH/bin/$my_app /usr/local/bin/$my_app 2>/dev/null || \ |
|||
$real_sudo_cmd ln -sf $TELEBIT_REAL_PATH/bin/$my_app /usr/local/bin/$my_app |
|||
# telebitd |
|||
echo " > ${real_sudo_cmde}ln -sf $TELEBIT_REAL_PATH/bin/$my_daemon /usr/local/bin/$my_daemon" |
|||
rm -f $TELEBIT_REAL_PATH/bin/$my_daemon || $real_sudo_cmd rm -f $TELEBIT_REAL_PATH/bin/$my_daemon |
|||
ln -sf $TELEBIT_REAL_PATH/bin/$my_daemon /usr/local/bin/$my_daemon || \ |
|||
$real_sudo_cmd ln -sf $TELEBIT_REAL_PATH/bin/$my_daemon /usr/local/bin/$my_daemon |
|||
fi |
|||
rm -f $HOME/$my_app; ln -s $TELEBIT_REAL_PATH/bin/$my_app $HOME/ |
|||
|
|||
|
|||
if [ -n "${TELEBIT_DEBUG}" ]; then |
|||
echo " > telebit init --tty" |
|||
echo "" |
|||
fi |
|||
sleep 0.25 |
|||
|
|||
echo "" |
|||
$TELEBIT_REAL_PATH/bin/node $TELEBIT_REAL_PATH/bin/telebit.js init --tty |
|||
echo "Unpacking and installing Telebit ..." |
|||
unarchiver $my_file $my_tmp |
|||
pushd $my_tmp/$my_dir |
|||
bash ./setup.sh |
|||
|
@ -1,5 +0,0 @@ |
|||
#agree_tos: true # agree to the Telebit, Greenlock, and Let's Encrypt TOSes |
|||
community_member: true # receive infrequent relevant updates |
|||
telemetry: true # contribute to project telemetric data |
|||
newsletter: false # contribute to project telemetric data |
|||
ssh_auto: false # forward ssh-looking packets, from any connection, to port 22 |
@ -1,97 +0,0 @@ |
|||
'use strict'; |
|||
|
|||
var path = require('path'); |
|||
var fs = require('fs'); |
|||
var os = require('os'); |
|||
|
|||
module.exports = function (opts, fn) { |
|||
// TODO make async version
|
|||
try { |
|||
module.exports.sync(opts); |
|||
} catch(e) { |
|||
if (fn) { fn(e); } |
|||
} |
|||
|
|||
if (fn) { fn(null); } |
|||
}; |
|||
module.exports.sync = function (opts) { |
|||
var f = opts.file; |
|||
var vars = opts.vars; |
|||
var text = fs.readFileSync(f.tpl, 'utf8') |
|||
.replace(/{TELEBIT_PATH}/g, vars.telebitPath || '{TELEBIT_PATH}') |
|||
.replace(/{TELEBIT_NODE}/g, vars.telebitNode || '{TELEBIT_NODE}') |
|||
.replace(/{NODE_PATH}/g, vars.nodePath || '{NODE_PATH}') |
|||
.replace(/{NPM_CONFIG_PREFIX}/g, vars.npmConfigPrefix || '{NPM_CONFIG_PREFIX}') |
|||
.replace(/{TELEBIT_NPM}/g, vars.telebitNpm || '{TELEBIT_NPM}') |
|||
.replace(/{TELEBIT_BIN}/g, vars.telebitBin || '{TELEBIT_BIN}') |
|||
.replace(/{TELEBITD_BIN}/g, vars.telebitdBin || '{TELEBITD_BIN}') |
|||
.replace(/{TELEBIT_JS}/g, vars.telebitJs || '{TELEBIT_JS}') |
|||
.replace(/{TELEBITD_JS}/g, vars.telebitdJs || '{TELEBITD_JS}') |
|||
.replace(/{TELEBIT_USER}/g, vars.telebitUser || '{TELEBIT_USER}') |
|||
.replace(/{TELEBIT_GROUP}/g, vars.telebitGroup || '{TELEBIT_GROUP}') |
|||
.replace(/{TELEBIT_RW_DIRS}/g, vars.telebitRwDirs || '{TELEBIT_RW_DIRS}') |
|||
.replace(/{TELEBIT_CONFIG}/g, vars.telebitConfig || '{TELEBIT_CONFIG}') |
|||
.replace(/{TELEBITD_CONFIG}/g, vars.telebitdConfig || '{TELEBITD_CONFIG}') |
|||
.replace(/{TELEBIT_LOG_DIR}/g, vars.TELEBIT_LOG_DIR || '{TELEBIT_LOG_DIR}') |
|||
.replace(/{TELEBIT_SOCK_DIR}/g, vars.TELEBIT_LOG_DIR || '{TELEBIT_SOCK_DIR}') |
|||
; |
|||
fs.writeFileSync(f.launcher, text, 'utf8'); |
|||
if (f.executable && !/^win/i.test(os.platform())) { |
|||
// TODO not sure if chmod works on windows
|
|||
fs.chmodSync(f.launcher, parseInt('755', 8)); |
|||
} |
|||
}; |
|||
|
|||
function run() { |
|||
var files = [ |
|||
{ tpl: (process.env.TELEBIT_SERVICE_TPL || path.join(__dirname, 'dist/etc/systemd/system/telebit.service.tpl')) |
|||
, launcher: (process.env.TELEBIT_SERVICE || path.join(__dirname, 'dist/etc/systemd/system/telebit.service')) |
|||
} |
|||
, { tpl: (process.env.TELEBIT_USER_SERVICE_TPL || path.join(__dirname, 'dist/etc/skel/.config/systemd/user/telebit.service.tpl')) |
|||
, launcher: (process.env.TELEBIT_USER_SERVICE || path.join(__dirname, 'dist/etc/skel/.config/systemd/user/telebit.service')) |
|||
} |
|||
, { tpl: (process.env.TELEBIT_PLIST_TPL || path.join(__dirname, 'dist/Library/LaunchDaemons/cloud.telebit.remote.plist.tpl')) |
|||
, launcher: (process.env.TELEBIT_PLIST || path.join(__dirname, 'dist/Library/LaunchDaemons/cloud.telebit.remote.plist')) |
|||
} |
|||
, { tpl: (process.env.TELEBIT_USER_PLIST_TPL || path.join(__dirname, 'dist/etc/skel/Library/LaunchAgents/cloud.telebit.remote.plist.tpl')) |
|||
, launcher: (process.env.TELEBIT_USER_PLIST || path.join(__dirname, 'dist/etc/skel/Library/LaunchAgents/cloud.telebit.remote.plist')) |
|||
} |
|||
]; |
|||
|
|||
files.forEach(function (f) { |
|||
var telebitRoot = path.resolve(__dirname, '../..'); |
|||
var vars = { |
|||
telebitPath: process.env.TELEBIT_PATH || telebitRoot |
|||
, telebitNode: process.env.TELEBIT_NODE || process.argv[0] || path.resolve(telebitRoot, 'bin/node') |
|||
, telebitBin: process.env.TELEBIT_BIN || path.resolve(telebitRoot, 'bin/telebit') |
|||
, telebitdBin: process.env.TELEBITD_BIN || path.resolve(telebitRoot, 'bin/telebitd') |
|||
, telebitJs: process.env.TELEBIT_JS || path.resolve(telebitRoot, 'bin/telebit.js') |
|||
, telebitdJs: process.env.TELEBITD_JS || path.resolve(telebitRoot, 'bin/telebitd.js') |
|||
, telebitRwDirs: [ |
|||
(process.env.TELEBIT_PATH || path.resolve(__dirname, '../..')) |
|||
, path.join(os.homedir(), '.config/telebit') |
|||
, path.join(os.homedir(), '.local/share/telebit') |
|||
] |
|||
, telebitUser: process.env.TELEBIT_USER || os.userInfo().username |
|||
, telebitGroup: process.env.TELEBIT_GROUP || ('darwin' === os.platform() ? 'staff' : os.userInfo().username) |
|||
, telebitConfig: process.env.TELEBIT_CONFIG || path.join(os.homedir(), '.config/telebit/telebit.yml') |
|||
, telebitdConfig: process.env.TELEBITD_CONFIG || path.join(os.homedir(), '.config/telebit/telebitd.yml') |
|||
, TELEBIT_LOG_DIR: process.env.TELEBIT_LOG_DIR || path.join(os.homedir(), '.local/share/telebit/var/log') |
|||
}; |
|||
vars.telebitNpm = process.env.TELEBIT_NPM || path.resolve(vars.telebitNode, '../npm'); |
|||
vars.nodePath = process.env.NODE_PATH || path.resolve(vars.telebitNode, '../../lib/node_modules'); |
|||
vars.npmConfigPrefix = process.env.NPM_CONFIG_PREFIX || path.resolve(vars.telebitNode, '..', '..'); |
|||
if (-1 === vars.telebitRwDirs.indexOf(vars.npmConfigPrefix)) { |
|||
vars.telebitRwDirs.push(vars.npmConfigPrefix); |
|||
} |
|||
vars.telebitRwDirs = vars.telebitRwDirs.join(' '); |
|||
module.exports({ |
|||
file: f |
|||
, vars: vars |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
if (module === require.main) { |
|||
run(); |
|||
} |
Loading…
Reference in new issue