Exemple #1
0
// StartProcess starts a new process with the program, arguments and attributes
// specified by name, argv and attr.
func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
	sysattr := &syscall.ProcAttr{
		Dir: attr.Dir,
		Env: attr.Env,
	}
	if sysattr.Env == nil {
		sysattr.Env = Environ()
	}
	// Create array of integer (system) fds.
	intfd := make([]int, len(attr.Files))
	for i, f := range attr.Files {
		if f == nil {
			intfd[i] = -1
		} else {
			intfd[i] = f.Fd()
		}
	}
	sysattr.Files = intfd

	pid, h, e := syscall.StartProcess(name, argv, sysattr)
	if iserror(e) {
		return nil, &PathError{"fork/exec", name, Errno(e)}
	}
	return newProcess(pid, h), nil
}
Exemple #2
0
func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
	// If there is no SysProcAttr (ie. no Chroot or changed
	// UID/GID), double-check existence of the directory we want
	// to chdir into.  We can make the error clearer this way.
	if attr != nil && attr.Sys == nil && attr.Dir != "" {
		if _, err := Stat(attr.Dir); err != nil {
			pe := err.(*PathError)
			pe.Op = "chdir"
			return nil, pe
		}
	}

	sysattr := &syscall.ProcAttr{
		Dir: attr.Dir,
		Env: attr.Env,
		Sys: attr.Sys,
	}
	if sysattr.Env == nil {
		sysattr.Env = Environ()
	}
	for _, f := range attr.Files {
		sysattr.Files = append(sysattr.Files, f.Fd())
	}

	pid, h, e := syscall.StartProcess(name, argv, sysattr)
	if e != nil {
		return nil, &PathError{"fork/exec", name, e}
	}
	return newProcess(pid, h), nil
}
func spawnServer(cl libkb.CommandLine) (err error) {

	var files []uintptr
	var cmd string
	var args []string
	var devnull, log *os.File
	var pid int

	defer func() {
		if err != nil {
			if devnull != nil {
				devnull.Close()
			}
			if log != nil {
				log.Close()
			}
		}
	}()

	if devnull, err = os.OpenFile("nul", os.O_RDONLY, 0); err != nil {
		return
	}
	files = append(files, devnull.Fd())

	if G.Env.GetSplitLogOutput() {
		files = append(files, uintptr(1), uintptr(2))
	} else {
		if _, log, err = libkb.OpenLogFile(); err != nil {
			return
		}
		files = append(files, log.Fd(), log.Fd())
	}

	// On 'nix this would include Setsid: true, which means
	// the new process inherits the session/terminal from the parent.
	// This is default on windows and need not be specified.
	attr := syscall.ProcAttr{
		Env:   os.Environ(),
		Files: files,
	}

	cmd, args, err = makeServerCommandLine(cl)
	if err != nil {
		return err
	}

	pid, _, err = syscall.StartProcess(cmd, args, &attr)
	if err != nil {
		err = fmt.Errorf("Error in StartProcess: %s", err)
	} else {
		G.Log.Info("Starting background server with pid=%d", pid)
	}
	return err
}
func (this *Fetcher) startPhantomJSServer(phantomJSPath, fetcherJSPath string) error {
	args := []string{"phantomjs", fetcherJSPath, this.ProxyPort}
	execSpec := &syscall.ProcAttr{
		Env:   os.Environ(),
		Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()},
	}
	pid, handlePtr, execErr := syscall.StartProcess(phantomJSPath, args, execSpec)
	this.phantomJSPid = pid
	this.phantomJSHandlePtr = handlePtr
	return execErr
}
Exemple #5
0
func main() {
	daemon := flag.Bool("daemon", false, "Indicate it's daemon process. Never use it in command line.")
	flag.Parse()

	if *daemon {
		fd, err := syscall.Open("/dev/null", syscall.O_RDWR, 0)

		if err != nil {
			panic(err)
		}

		syscall.Dup2(fd, syscall.Stdin)
		syscall.Dup2(fd, syscall.Stdout)
		syscall.Dup2(fd, syscall.Stderr)

		if fd > syscall.Stderr {
			syscall.Close(fd)
		}
	}

	// start gio as daemon process
	if !*daemon {
		args := append([]string{os.Args[0], "-daemon"}, os.Args[1:]...)
		attr := syscall.ProcAttr{}
		_, _, err := syscall.StartProcess(os.Args[0], args, &attr)

		if err != nil {
			panic(err)
			return
		}
		return
	}

	router := routes.NewRouter()
	for _, function := range functions.Functions {
		router.Get(function.Path, funcwrapper(function.Func))
		router.Post(function.Path, funcwrapper(function.Func))
	}
	s := &http.Server{
		Addr:           ":1234",
		Handler:        router,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	err := s.ListenAndServe()
	if err != nil {
		log.Fatal(err)
	}
}
Exemple #6
0
func spawnServer(g *libkb.GlobalContext, cl libkb.CommandLine, forkType keybase1.ForkType) (pid int, err error) {

	var files []uintptr
	var cmd string
	var args []string
	var devnull *os.File

	defer func() {
		if err != nil && devnull != nil {
			devnull.Close()
		}
	}()

	// Failing to open nul is non-fatal here.
	devnull, err = os.OpenFile("nul", os.O_RDONLY, 0)
	if err != nil {
		G.Log.Warning("Cannot open nul: %v", err)
		// 0 is an invalid handle, but more importantly it will
		// not be passed to DuplicateHandle by Go. This works
		// with Go 1.6, but is hacky. This code path is taken
		// only on systems that are broken to begin with...
		files = append(files, 0, 0, 0)
	} else {
		nullfd := devnull.Fd()
		files = append(files, nullfd, nullfd, nullfd)
	}

	// On 'nix this would include Setsid: true, which means
	// the new process inherits the session/terminal from the parent.
	// This is default on windows and need not be specified.
	attr := syscall.ProcAttr{
		Env:   os.Environ(),
		Files: files,
	}

	cmd, args, err = makeServerCommandLine(g, cl, forkType)
	if err != nil {
		return
	}

	pid, _, err = syscall.StartProcess(cmd, args, &attr)
	if err != nil {
		err = fmt.Errorf("Error in StartProcess: %s", err)
	} else {
		G.Log.Info("Starting background server with pid=%d", pid)
	}
	return
}
Exemple #7
0
func main() {
	argsIndex := 1 // 0 is the name of this program, 1 is either the one to launch or the "wait" option

	if len(os.Args) < 2 {
		log.Fatal("ERROR: no arguments. Use [-wait] programname [arg arg arg]\n")
	}

	// Do this awkward thing so we can pass along the rest of the command line as-is

	doWait := false
	doHide := true
	for i := 1; i < 3 && (i+1) < len(os.Args); i++ {
		if strings.EqualFold(os.Args[argsIndex], "-wait") {
			argsIndex++
			doWait = true
		} else if strings.EqualFold(os.Args[argsIndex], "-show") {
			argsIndex++
			doHide = false
		}
	}

	attr := &syscall.ProcAttr{
		Files: []uintptr{uintptr(syscall.Stdin), uintptr(syscall.Stdout), uintptr(syscall.Stderr)},
		Env:   syscall.Environ(),
		Sys: &syscall.SysProcAttr{
			HideWindow:    doHide,
			CreationFlags: flagCreateNewConsole,
		},
	}
	fmt.Printf("Launching %s with args %v\n", os.Args[argsIndex], os.Args[argsIndex:])
	pid, handle, err := syscall.StartProcess(os.Args[argsIndex], os.Args[argsIndex:], attr)
	fmt.Printf("%v, %v, %v\n", pid, handle, err)
	if doWait {
		p, err := os.FindProcess(pid)
		if err != nil {
			fmt.Printf("Launcher can't find %d\n", pid)
		}

		pstate, err := p.Wait()

		if err == nil && pstate.Success() {
			time.Sleep(100 * time.Millisecond)
		} else {
			fmt.Printf("Unsuccessful wait: Error %v, pstate %v\n", err, *pstate)
		}
	}
}
Exemple #8
0
func StartHttpServe(lis net.Listener, mux http.Handler) {
	// start http serve
	go func() {
		err := http.Serve(lis, mux)
		if err != nil {
			log.Fatal("ListenAndServe: ", err.Error())
		}
	}()

	//received Signal
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGHUP)
	//#WORKER is a new process tag.
	//get the current process args ...
	newArgs := append(os.Args, "#WORKER")
	for {
		sig := <-ch
		//log.Println("Signal received:", sig)
		switch sig {
		case syscall.SIGHUP:
			log.Println("get sighup sighup")
		case syscall.SIGINT:
			log.Println("get SIGINT ,exit!")
			os.Exit(1)
		case syscall.SIGUSR1:
			log.Println("get usr1 signal")
			//close the net
			if err := lis.Close(); err != nil {
				log.Println("Close ERROR ", err)
			}
			log.Println("Close connect!")

			attr := syscall.ProcAttr{
				Env: os.Environ(),
			}
			//start a new same process
			if _, _, err := syscall.StartProcess(os.Args[0], newArgs, &attr); err != nil {
				log.Println(err)
			}
			//exit current process.
			return
		case syscall.SIGUSR2:
			log.Println("usr2 ")
		}
	}
}
func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
	sysattr := &syscall.ProcAttr{
		Dir: attr.Dir,
		Env: attr.Env,
		Sys: attr.Sys,
	}

	for _, f := range attr.Files {
		sysattr.Files = append(sysattr.Files, f.Fd())
	}

	pid, h, e := syscall.StartProcess(name, argv, sysattr)
	if e != nil {
		return nil, &PathError{"fork/exec", name, e}
	}

	return newProcess(pid, h), nil
}
Exemple #10
0
// StartProcess starts a new process with the program, arguments and attributes
// specified by name, argv and attr.
//
// StartProcess is a low-level interface. The exec package provides
// higher-level interfaces.
func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
	sysattr := &syscall.ProcAttr{
		Dir: attr.Dir,
		Env: attr.Env,
		Sys: attr.Sys,
	}
	if sysattr.Env == nil {
		sysattr.Env = Environ()
	}
	for _, f := range attr.Files {
		sysattr.Files = append(sysattr.Files, f.Fd())
	}

	pid, h, e := syscall.StartProcess(name, argv, sysattr)
	if iserror(e) {
		return nil, &PathError{"fork/exec", name, Errno(e)}
	}
	return newProcess(pid, h), nil
}
Exemple #11
0
// StartProcess forks the current process and execs argv0, stopping the
// new process after the exec syscall.  See os.StartProcess for additional
// details.
func StartProcess(argv0 string, argv []string, attr *os.ProcAttr) (Process, os.Error) {
	sysattr := &syscall.ProcAttr{
		Dir: attr.Dir,
		Env: attr.Env,
		Sys: &syscall.SysProcAttr{
			Ptrace: true,
		},
	}
	p := newProcess(-1)

	// Create array of integer (system) fds.
	intfd := make([]int, len(attr.Files))
	for i, f := range attr.Files {
		if f == nil {
			intfd[i] = -1
		} else {
			intfd[i] = f.Fd()
		}
	}
	sysattr.Files = intfd

	// Fork from the monitor thread so we get the right tracer pid.
	err := p.do(func() os.Error {
		pid, _, errno := syscall.StartProcess(argv0, argv, sysattr)
		if errno != 0 {
			return &os.PathError{"fork/exec", argv0, os.Errno(errno)}
		}
		p.pid = pid

		// The process will raise SIGTRAP when it reaches execve.
		_, err := p.newThread(pid, syscall.SIGTRAP, false)
		return err
	})
	if err != nil {
		p.stopMonitor(err)
		return nil, err
	}

	return p, nil
}
Exemple #12
0
func main() {

	// Get a new logger instance
	//log := l4g.NewLogger()

	// Create a default logger that is logging messages of FINE or higher
	log.AddFilter("file", log.FINE, log.NewFileLogWriter(filename, false))
	//log.Close()

	/* Can also specify manually via the following: (these are the defaults) */
	flw := log.NewFileLogWriter(filename, false)
	//flw.SetFormat("[%D %T] [%L] (%S) %M")
	//flw.SetRotate(false)
	//flw.SetRotateSize(0)
	//flw.SetRotateLines(0)
	//flw.SetRotateDaily(false)
	log.AddFilter("file", log.FINE, flw)

	mux := http.NewServeMux()
	staticDirHandler(mux, "/public/", "./public", 0)
	mux.HandleFunc("/", safeHandler(indexHandler))
	mux.HandleFunc("/register", safeHandler(registerHandler))
	mux.HandleFunc("/login", safeHandler(loginHandler))
	mux.HandleFunc("/save", safeHandler(saveHandler))
	mux.HandleFunc("/user_list", safeHandler(userListHandler))

	lis, err := net.Listen("tcp", ":9090")
	check(err)

	go func() {
		http.Serve(lis, mux)
		//err := http.ListenAndServe(":8080", mux)
		if err != nil {
			log.Critical("ListenAndServe: ", err.Error())
		}
	}()

	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGHUP)
	//#WORKER is a new process tag.
	//newArgs := append(os.Args, "#WORKER")
	attr := syscall.ProcAttr{
		Env: os.Environ(),
	}
	for {
		sig := <-ch
		//log.Info("Signal received:", sig)
		switch sig {
		case syscall.SIGHUP:
			log.Info("get sighup sighup")
		case syscall.SIGINT:
			log.Info("get SIGINT ,exit!")
			os.Exit(1)
		case syscall.SIGUSR1:
			log.Info("usr1")
			//close the net
			lis.Close()
			log.Info("close connect")
			if _, _, err := syscall.StartProcess(os.Args[0], os.Args, &attr); err != nil {
				check(err)
			}
			//exit current process.
			return
		case syscall.SIGUSR2:
			log.Info("usr2 ")
		}
	}
}
Exemple #13
0
func main() {
	port := flag.Int("port", 0, "Port to serve http request. By default, the port is the last port you've used.")
	dir := flag.String("dir", "", "Dir served as www root. By default, current dir will be served.")
	alias := flag.String("alias", "", "URL alias to serve. By default, dir name will be used as alias.")
	remove := flag.Bool("remove", false, "Remove current dir so that no one can visit it thru http anymore.")
	list := flag.Bool("list", false, "List all running servers and hosted dirs.")
	worker := flag.Bool("worker", false, "Indicate it's a worker process. It's used to daemonize handyhttpd. Never use it in command line.")
	quit := flag.Bool("quit", false, "Quit server completely.")
	flag.Parse()

	tempdir := os.TempDir()
	file, err := os.OpenFile(tempdir+"/"+HANDY_LOG_FILENAME, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		log.Println("cannot open log file to write. filename:", tempdir+"/"+HANDY_LOG_FILENAME, "err:", err)
		log.Println("print log to stdout now")
		file = os.Stdout
	}

	// worker need to close all std in/out/err
	if *worker {
		fd, err := syscall.Open("/dev/null", syscall.O_RDWR, 0)

		if err != nil {
			fmt.Println("cannot open /dev/null", "err:", err)
			panic(err)
		}

		syscall.Dup2(fd, syscall.Stdin)
		syscall.Dup2(fd, syscall.Stdout)
		syscall.Dup2(fd, syscall.Stderr)

		if fd > syscall.Stderr {
			syscall.Close(fd)
		}
	}

	gLogger = log.New(file, "", log.LstdFlags)
	gLogger.Printf("parsed params. [port: %d] [dir: %s] [alias: %s] [remove: %t] [list: %t] [quit: %t]\n",
		*port, *dir, *alias, *remove, *list, *quit)

	root := *dir
	if root == "" {
		root, _ = os.Getwd()
	}

	pattern := *alias
	if pattern == "" {
		pattern = filepath.Base(root)
	}

	socket := tempdir + "/" + HANDY_SOCK_FILENAME
	l, err := net.Listen("unix", socket)

	// there is a handyhttpd running. notify it with current options.
	if err != nil {
		// hack http client's transport to force it to use unix socket rather than tcp
		client := http.Client{
			Transport: &http.Transport{
				Dial: func(n, addr string) (conn net.Conn, err error) {
					return net.Dial("unix", socket)
				},
			},
		}

		var r *http.Response

		if *list {
			r, err = client.Get("http://localhost/list")
		} else if *quit {
			r, err = client.Get("http://localhost/quit")
		} else {
			var verb string
			if *remove {
				verb = "remove"
			} else {
				verb = "add"
			}

			// format is:
			// GET /?verb=add&alias=abc&dir=/path/to/www/root&port=9696
			r, err = client.Get(
				fmt.Sprintf("http://localhost/?verb=%s&alias=%s&dir=%s&port=%d",
					verb, url.QueryEscape(pattern), url.QueryEscape(root), *port))
		}

		if err != nil {
			gLogger.Println("cannot connect handy server. err:", err)
			return
		}

		if r.StatusCode != 200 {
			gLogger.Println("handy server denies the request. code:", r.StatusCode)
			return
		}

		io.Copy(os.Stdout, r.Body)
		return
	}

	defer l.Close()

	// daemonize handyhttpd
	if !*worker {
		args := append([]string{os.Args[0], "-worker"}, os.Args[1:]...)
		exec := os.Args[0]

		// if exec is called without any path separator, it must be in a PATH dir.
		if !strings.ContainsRune(exec, os.PathSeparator) {
			path := os.Getenv("PATH")
			paths := strings.Split(path, fmt.Sprintf("%c", os.PathListSeparator))

			for _, s := range paths {
				if file, err := os.Stat(s + "/" + exec); err == nil && !file.IsDir() {
					exec = s + "/" + exec
				}
			}
		}

		_, _, err := syscall.StartProcess(exec, args, nil)

		if err != nil {
			fmt.Println("cannot daemonize handyhttpd", "err:", err)
			gLogger.Println("cannot daemonize handyhttpd", "err:", err)
			return
		}

		return
	}

	// there is no running handy, just return
	if *quit {
		gLogger.Println("gracefully exit with command line")
		return
	}

	// as this server is the only running server, nothing to list
	if *list {
		fmt.Println("No server is running")
		return
	}

	parseParams(root, pattern, *port, *remove)

	go func() {
		// handle other server's request
		http.HandleFunc("/list", func(w http.ResponseWriter, r *http.Request) {
			gLogger.Println("listing all ports per request")
			List(w)
		})
		http.HandleFunc("/quit", func(w http.ResponseWriter, r *http.Request) {
			fmt.Fprintln(w, "Handy server is quiting now")

			// gracefully exit
			process, _ := os.FindProcess(os.Getpid())
			process.Signal(syscall.SIGINT)
		})
		http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
			gLogger.Println("handle a verb request. url:", r.URL)
			r.ParseForm()
			verb, verbOk := r.Form["verb"]
			alias, aliasOk := r.Form["alias"]
			dir, dirOk := r.Form["dir"]
			port, portOk := r.Form["port"]

			if !verbOk || !aliasOk || !dirOk || !portOk {
				gLogger.Println("missing required query string params")
				w.WriteHeader(http.StatusBadRequest)
				return
			}

			remove := false
			if verb[0] == "remove" {
				remove = true
			}

			portNumber, _ := strconv.Atoi(port[0])
			if parseParams(dir[0], alias[0], portNumber, remove) {
				fmt.Fprintf(w, "%s dir %s as /%s on port %d\n", verb[0], dir[0], alias[0], LastPort())
			}
		})
		http.Serve(l, nil)
	}()

	defer Stop()
	sig := make(chan os.Signal, 1)
	signal.Notify(sig)

	for {
		s := <-sig
		if s == syscall.SIGKILL || s == syscall.SIGINT || s == syscall.SIGTERM {
			gLogger.Println("gracefully exit with signal", s)
			return
		}
	}
}
Exemple #14
0
func main() {
	var port = flag.Int("port", 11211, "TCP port number to listen on (default: 11211).")
	var daemon = flag.Bool("daemon", false, "Indicate it's daemon process.")
	var daemonized = flag.Bool("daemonized", false, "Indicate it's a daemonized process. Never use it in command line.")
	var logfile = flag.String("logfile", "", "Specify log file, defaults: stderr.")
	var maxconns = flag.Int("maxconns", 1024, "Max simultaneous connections (default: 1024).")
	flag.Parse()

	// Open log file.
	if len(*logfile) > 0 {
		file, err := os.OpenFile(*logfile, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
		if err != nil {
			return
		}
		logger = log.New(file, "", log.LstdFlags)
	} else {
		if *daemon {
			fmt.Println("Need to specify log file when runnning in background.")
			return
		}
		logger = log.New(os.Stderr, "", log.LstdFlags)
	}

	// Daemonize or not.
	if *daemon {
		if *daemonized {
			fd, err := syscall.Open("/dev/null", syscall.O_RDWR, 0)

			if err != nil {
				fmt.Println("cannot open /dev/null", "err:", err)
				panic(err)
			}

			syscall.Dup2(fd, syscall.Stdin)
			syscall.Dup2(fd, syscall.Stdout)
			syscall.Dup2(fd, syscall.Stderr)

			if fd > syscall.Stderr {
				syscall.Close(fd)
			}
		} else {
			// start a new process with "-daemonized" flag
			path, err := exec.LookPath(os.Args[0])
			if err != nil {
				panic(err)
			}
			args := append([]string{path, "-daemonized"}, os.Args[1:]...)
			attr := syscall.ProcAttr{}
			logger.Println("Daemonizing...", args)
			_, _, err = syscall.StartProcess(path, args, &attr)
			if err != nil {
				panic(err)
			}
			return
		}
	}

	// Init semaphore
	sem = make(chan int, *maxconns)
	for i := 0; i < *maxconns; i++ {
		sem <- 1
	}

	// Listing on specified port.
	ls, e := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if e != nil {
		panic(e)
	}
	logger.Printf("Listening on port %d\n", *port)

	// Accepting connections from outside.
	for {
		c, e := ls.Accept()
		if e != nil {
			logger.Printf("Accept error: %v\n", e)
			continue
		}
		serve(c)
	}
}