61442f8880
now lf will start the server in the current directory (which will then Chdir to the user's home directory) to ensure it is always starting as the user intended.
203 lines
3.9 KiB
Go
203 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"runtime/pprof"
|
|
"strconv"
|
|
)
|
|
|
|
var (
|
|
envPath = os.Getenv("PATH")
|
|
envLevel = os.Getenv("LF_LEVEL")
|
|
)
|
|
|
|
var (
|
|
gClientID int
|
|
gHostname string
|
|
gLastDirPath string
|
|
gSelectionPath string
|
|
gSocketProt string
|
|
gSocketPath string
|
|
gLogPath string
|
|
gServerLogPath string
|
|
gSelect string
|
|
gCommand string
|
|
gVersion string
|
|
)
|
|
|
|
func init() {
|
|
h, err := os.Hostname()
|
|
if err != nil {
|
|
log.Printf("hostname: %s", err)
|
|
}
|
|
gHostname = h
|
|
|
|
if envLevel == "" {
|
|
envLevel = "0"
|
|
}
|
|
}
|
|
|
|
func exportEnvVars() {
|
|
os.Setenv("id", strconv.Itoa(gClientID))
|
|
|
|
os.Setenv("OPENER", envOpener)
|
|
os.Setenv("EDITOR", envEditor)
|
|
os.Setenv("PAGER", envPager)
|
|
os.Setenv("SHELL", envShell)
|
|
os.Setenv("TCELL_TRUECOLOR", envTcellTruecolor)
|
|
|
|
level, err := strconv.Atoi(envLevel)
|
|
if err != nil {
|
|
log.Printf("reading lf level: %s", err)
|
|
}
|
|
|
|
level++
|
|
|
|
os.Setenv("LF_LEVEL", strconv.Itoa(level))
|
|
}
|
|
|
|
func startServer() {
|
|
cmd := detachedCommand(os.Args[0], "-server")
|
|
if err := cmd.Start(); err != nil {
|
|
log.Printf("starting server: %s", err)
|
|
}
|
|
}
|
|
|
|
func checkServer() {
|
|
if gSocketProt == "unix" {
|
|
if _, err := os.Stat(gSocketPath); os.IsNotExist(err) {
|
|
startServer()
|
|
} else if _, err := net.Dial(gSocketProt, gSocketPath); err != nil {
|
|
os.Remove(gSocketPath)
|
|
startServer()
|
|
}
|
|
} else {
|
|
if _, err := net.Dial(gSocketProt, gSocketPath); err != nil {
|
|
startServer()
|
|
}
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
showDoc := flag.Bool(
|
|
"doc",
|
|
false,
|
|
"show documentation")
|
|
|
|
showVersion := flag.Bool(
|
|
"version",
|
|
false,
|
|
"show version")
|
|
|
|
remoteCmd := flag.String(
|
|
"remote",
|
|
"",
|
|
"send remote command to server")
|
|
|
|
serverMode := flag.Bool(
|
|
"server",
|
|
false,
|
|
"start server (automatic)")
|
|
|
|
cpuprofile := flag.String(
|
|
"cpuprofile",
|
|
"",
|
|
"path to the file to write the CPU profile")
|
|
|
|
memprofile := flag.String(
|
|
"memprofile",
|
|
"",
|
|
"path to the file to write the memory profile")
|
|
|
|
flag.StringVar(&gLastDirPath,
|
|
"last-dir-path",
|
|
"",
|
|
"path to the file to write the last dir on exit (to use for cd)")
|
|
|
|
flag.StringVar(&gSelectionPath,
|
|
"selection-path",
|
|
"",
|
|
"path to the file to write selected files on open (to use as open file dialog)")
|
|
|
|
flag.StringVar(&gCommand,
|
|
"command",
|
|
"",
|
|
"command to execute on client initialization")
|
|
|
|
flag.Parse()
|
|
|
|
gSocketProt = gDefaultSocketProt
|
|
gSocketPath = gDefaultSocketPath
|
|
|
|
if *cpuprofile != "" {
|
|
f, err := os.Create(*cpuprofile)
|
|
if err != nil {
|
|
log.Fatalf("could not create CPU profile: %s", err)
|
|
}
|
|
if err := pprof.StartCPUProfile(f); err != nil {
|
|
log.Fatalf("could not start CPU profile: %s", err)
|
|
}
|
|
defer pprof.StopCPUProfile()
|
|
}
|
|
|
|
switch {
|
|
case *showDoc:
|
|
fmt.Print(genDocString)
|
|
case *showVersion:
|
|
fmt.Println(gVersion)
|
|
case *remoteCmd != "":
|
|
if err := remote(*remoteCmd); err != nil {
|
|
log.Fatalf("remote command: %s", err)
|
|
}
|
|
case *serverMode:
|
|
os.Chdir(gUser.HomeDir)
|
|
gServerLogPath = filepath.Join(os.TempDir(), fmt.Sprintf("lf.%s.server.log", gUser.Username))
|
|
serve()
|
|
default:
|
|
checkServer()
|
|
|
|
gClientID = 1000
|
|
gLogPath = filepath.Join(os.TempDir(), fmt.Sprintf("lf.%s.%d.log", gUser.Username, gClientID))
|
|
for _, err := os.Stat(gLogPath); !os.IsNotExist(err); _, err = os.Stat(gLogPath) {
|
|
gClientID++
|
|
gLogPath = filepath.Join(os.TempDir(), fmt.Sprintf("lf.%s.%d.log", gUser.Username, gClientID))
|
|
}
|
|
|
|
switch flag.NArg() {
|
|
case 0:
|
|
_, err := os.Getwd()
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
|
os.Exit(2)
|
|
}
|
|
case 1:
|
|
gSelect = flag.Arg(0)
|
|
default:
|
|
fmt.Fprintf(os.Stderr, "only single file or directory is allowed\n")
|
|
os.Exit(2)
|
|
}
|
|
|
|
exportEnvVars()
|
|
|
|
run()
|
|
}
|
|
|
|
if *memprofile != "" {
|
|
f, err := os.Create(*memprofile)
|
|
if err != nil {
|
|
log.Fatal("could not create memory profile: ", err)
|
|
}
|
|
runtime.GC()
|
|
if err := pprof.WriteHeapProfile(f); err != nil {
|
|
log.Fatal("could not write memory profile: ", err)
|
|
}
|
|
f.Close()
|
|
}
|
|
}
|