github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/cmd/snap/cmd_userd.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  // +build !darwin
     3  
     4  /*
     5   * Copyright (C) 2017-2019 Canonical Ltd
     6   *
     7   * This program is free software: you can redistribute it and/or modify
     8   * it under the terms of the GNU General Public License version 3 as
     9   * published by the Free Software Foundation.
    10   *
    11   * This program is distributed in the hope that it will be useful,
    12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14   * GNU General Public License for more details.
    15   *
    16   * You should have received a copy of the GNU General Public License
    17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18   *
    19   */
    20  
    21  package main
    22  
    23  import (
    24  	"fmt"
    25  	"os"
    26  	"os/signal"
    27  	"syscall"
    28  
    29  	"github.com/jessevdk/go-flags"
    30  
    31  	"github.com/snapcore/snapd/i18n"
    32  	"github.com/snapcore/snapd/snapdtool"
    33  	"github.com/snapcore/snapd/usersession/agent"
    34  	"github.com/snapcore/snapd/usersession/autostart"
    35  	"github.com/snapcore/snapd/usersession/userd"
    36  )
    37  
    38  type cmdUserd struct {
    39  	Autostart bool `long:"autostart"`
    40  	Agent     bool `long:"agent"`
    41  }
    42  
    43  var shortUserdHelp = i18n.G("Start the userd service")
    44  var longUserdHelp = i18n.G(`
    45  The userd command starts the snap user session service.
    46  `)
    47  
    48  func init() {
    49  	cmd := addCommand("userd",
    50  		shortUserdHelp,
    51  		longUserdHelp,
    52  		func() flags.Commander {
    53  			return &cmdUserd{}
    54  		}, map[string]string{
    55  			// TRANSLATORS: This should not start with a lowercase letter.
    56  			"autostart": i18n.G("Autostart user applications"),
    57  			// TRANSLATORS: This should not start with a lowercase letter.
    58  			"agent": i18n.G("Run the user session agent"),
    59  		}, nil)
    60  	cmd.hidden = true
    61  }
    62  
    63  func (x *cmdUserd) Execute(args []string) error {
    64  	if len(args) > 0 {
    65  		return ErrExtraArgs
    66  	}
    67  
    68  	if x.Autostart {
    69  		return x.runAutostart()
    70  	}
    71  
    72  	if x.Agent {
    73  		return x.runAgent()
    74  	}
    75  
    76  	return x.runUserd()
    77  }
    78  
    79  var signalNotify = signalNotifyImpl
    80  
    81  func (x *cmdUserd) runUserd() error {
    82  	var userd userd.Userd
    83  	if err := userd.Init(); err != nil {
    84  		return err
    85  	}
    86  	userd.Start()
    87  
    88  	ch, stop := signalNotify(syscall.SIGINT, syscall.SIGTERM)
    89  	defer stop()
    90  
    91  	select {
    92  	case sig := <-ch:
    93  		fmt.Fprintf(Stdout, "Exiting on %s.\n", sig)
    94  	case <-userd.Dying():
    95  		// something called Stop()
    96  	}
    97  
    98  	return userd.Stop()
    99  }
   100  
   101  func (x *cmdUserd) runAgent() error {
   102  	agent, err := agent.New()
   103  	if err != nil {
   104  		return err
   105  	}
   106  	agent.Version = snapdtool.Version
   107  	agent.Start()
   108  
   109  	ch, stop := signalNotify(syscall.SIGINT, syscall.SIGTERM)
   110  	defer stop()
   111  
   112  	select {
   113  	case sig := <-ch:
   114  		fmt.Fprintf(Stdout, "Exiting on %s.\n", sig)
   115  	case <-agent.Dying():
   116  		// something called Stop()
   117  	}
   118  
   119  	return agent.Stop()
   120  }
   121  
   122  func (x *cmdUserd) runAutostart() error {
   123  	if err := autostart.AutostartSessionApps(); err != nil {
   124  		return fmt.Errorf("autostart failed for the following apps:\n%v", err)
   125  	}
   126  	return nil
   127  }
   128  
   129  func signalNotifyImpl(sig ...os.Signal) (ch chan os.Signal, stop func()) {
   130  	ch = make(chan os.Signal, len(sig))
   131  	signal.Notify(ch, sig...)
   132  	stop = func() { signal.Stop(ch) }
   133  	return ch, stop
   134  }