mirror of https://github.com/xSmurf/oz.git
				
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							146 lines
						
					
					
						
							3.0 KiB
						
					
					
				
			
		
		
	
	
							146 lines
						
					
					
						
							3.0 KiB
						
					
					
				package xpra
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"encoding/json"
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"os"
 | 
						|
	"os/exec"
 | 
						|
	"os/user"
 | 
						|
	"path"
 | 
						|
	"strconv"
 | 
						|
	"syscall"
 | 
						|
 | 
						|
	"github.com/subgraph/oz"
 | 
						|
)
 | 
						|
 | 
						|
type Xpra struct {
 | 
						|
	// Server working directory where unix socket is created
 | 
						|
	WorkDir string
 | 
						|
 | 
						|
	Config *oz.XServerConf
 | 
						|
 | 
						|
	// Running xpra process
 | 
						|
	Process *exec.Cmd
 | 
						|
 | 
						|
	// Display number
 | 
						|
	Display uint64
 | 
						|
 | 
						|
	// Arguments passed to xpra command
 | 
						|
	xpraArgs []string
 | 
						|
}
 | 
						|
 | 
						|
var xpraDefaultArgs = []string{
 | 
						|
	"--no-daemon",
 | 
						|
	"--mmap",
 | 
						|
	"--no-sharing",
 | 
						|
	"--bell",
 | 
						|
	"--system-tray",
 | 
						|
	"--xsettings",
 | 
						|
	//"--no-xsettings",
 | 
						|
	"--cursors",
 | 
						|
	"--encoding=rgb",
 | 
						|
}
 | 
						|
 | 
						|
func getDefaultArgs(config *oz.XServerConf) []string {
 | 
						|
	args := []string{}
 | 
						|
	args = append(args, xpraDefaultArgs...)
 | 
						|
	if config.DisableClipboard {
 | 
						|
		args = append(args, "--no-clipboard")
 | 
						|
	} else {
 | 
						|
		args = append(args, "--clipboard")
 | 
						|
	}
 | 
						|
 | 
						|
	switch config.AudioMode {
 | 
						|
	case oz.PROFILE_AUDIO_NONE, "":
 | 
						|
		args = append(args, "--no-microphone", "--no-speaker")
 | 
						|
	case oz.PROFILE_AUDIO_SPEAKER:
 | 
						|
		args = append(args, "--no-microphone", "--speaker")
 | 
						|
	case oz.PROFILE_AUDIO_FULL:
 | 
						|
		args = append(args, "--microphone", "--speaker")
 | 
						|
	}
 | 
						|
 | 
						|
	if config.EnableNotifications {
 | 
						|
		args = append(args, "--notifications")
 | 
						|
	} else {
 | 
						|
		args = append(args, "--no-notifications")
 | 
						|
	}
 | 
						|
 | 
						|
	return args
 | 
						|
}
 | 
						|
 | 
						|
func (x *Xpra) Stop(cred *syscall.Credential) ([]byte, error) {
 | 
						|
	cmd := exec.Command("/usr/bin/xpra",
 | 
						|
		"--socket-dir="+x.WorkDir,
 | 
						|
		"stop",
 | 
						|
		fmt.Sprintf(":%d", x.Display),
 | 
						|
	)
 | 
						|
	cmd.SysProcAttr = &syscall.SysProcAttr{
 | 
						|
		Credential: cred,
 | 
						|
	}
 | 
						|
	cmd.Env = []string{"TMPDIR=" + x.WorkDir}
 | 
						|
	return cmd.Output()
 | 
						|
}
 | 
						|
 | 
						|
func GetPath(u *user.User, name string) string {
 | 
						|
	return path.Join(u.HomeDir, ".Xoz", name)
 | 
						|
}
 | 
						|
 | 
						|
func CreateDir(u *user.User, name string) (string, error) {
 | 
						|
	uid, gid, err := userIds(u)
 | 
						|
	if err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
	dir := GetPath(u, name)
 | 
						|
	if err := createSubdirs(u.HomeDir, uid, gid, 0755, ".Xoz", name); err != nil {
 | 
						|
		return "", fmt.Errorf("failed to create xpra directory (%s): %v", dir, err)
 | 
						|
	}
 | 
						|
	return dir, nil
 | 
						|
}
 | 
						|
 | 
						|
func createSubdirs(base string, uid, gid int, mode os.FileMode, subdirs ...string) error {
 | 
						|
	dir := base
 | 
						|
	for _, sd := range subdirs {
 | 
						|
		dir = path.Join(dir, sd)
 | 
						|
		if err := os.Mkdir(dir, mode); err != nil && !os.IsExist(err) {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		if err := os.Chown(dir, uid, gid); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func userIds(user *user.User) (int, int, error) {
 | 
						|
	uid, err := strconv.Atoi(user.Uid)
 | 
						|
	if err != nil {
 | 
						|
		return -1, -1, errors.New("failed to parse uid from user struct: " + err.Error())
 | 
						|
	}
 | 
						|
	gid, err := strconv.Atoi(user.Gid)
 | 
						|
	if err != nil {
 | 
						|
		return -1, -1, errors.New("failed to parse gid from user struct: " + err.Error())
 | 
						|
	}
 | 
						|
	return uid, gid, nil
 | 
						|
}
 | 
						|
 | 
						|
func writeFakeProfile(cmd *exec.Cmd) error {
 | 
						|
	pi, err := cmd.StdinPipe()
 | 
						|
	if err != nil {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	emptyProfile := new(oz.Profile)
 | 
						|
	emptyProfile.Seccomp.Mode = "blacklist"
 | 
						|
	emptyProfile.Seccomp.Enforce = true
 | 
						|
	jdata, err := json.Marshal(emptyProfile)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	io.Copy(pi, bytes.NewBuffer(jdata))
 | 
						|
	pi.Close()
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 |