Full Code of dnschneid/crouton for AI

master 59e36db17c54 cached
165 files
608.4 KB
177.5k tokens
167 symbols
1 requests
Download .txt
Showing preview only (648K chars total). Download the full file or copy to clipboard to get everything.
Repository: dnschneid/crouton
Branch: master
Commit: 59e36db17c54
Files: 165
Total size: 608.4 KB

Directory structure:
gitextract_imr3a977/

├── .github/
│   ├── CONTRIBUTING.md
│   └── ISSUE_TEMPLATE.md
├── .gitignore
├── AUTHORS
├── CONTRIBUTORS
├── LICENSE
├── Makefile
├── README.md
├── README.zh.md
├── build/
│   ├── CONTRIBUTORS.sed
│   ├── genversion.sh
│   ├── release.sh
│   └── wrapper.sh
├── chroot-bin/
│   ├── brightness
│   ├── crouton-noroot
│   ├── crouton-unity-autostart
│   ├── croutonclip
│   ├── croutoncycle
│   ├── croutonfindnacl
│   ├── croutonnotify
│   ├── croutonpowerd
│   ├── croutontriggerd
│   ├── croutonurlhandler
│   ├── croutonversion
│   ├── croutonxinitrc-wrapper
│   ├── gnome-session-wrapper
│   ├── host-dbus
│   ├── host-wayland
│   ├── setres
│   ├── startgnome
│   ├── startunity
│   ├── volume
│   ├── xinit
│   └── xiwi
├── chroot-etc/
│   ├── kodi-cycle.py
│   ├── kodi-keyboard.xml
│   ├── pulseaudio-default.pa
│   ├── unity-autostart.desktop
│   ├── unity-profiled
│   ├── xbindkeysrc.scm
│   ├── xiwi.conf
│   ├── xorg-dummy.conf
│   ├── xorg-intel-sna.conf
│   ├── xserverrc
│   ├── xserverrc-local.example
│   ├── xserverrc-xiwi
│   └── xserverrc-xorg
├── host-bin/
│   ├── crash_reporter_wrapper
│   ├── edit-chroot
│   ├── enter-chroot
│   ├── mount-chroot
│   ├── startcli
│   ├── starte17
│   ├── startgnome
│   ├── startkde
│   ├── startkodi
│   ├── startlxde
│   ├── startunity
│   ├── startxfce4
│   ├── startxiwi
│   └── unmount-chroot
├── host-ext/
│   ├── .gitignore
│   ├── crouton/
│   │   ├── background.html
│   │   ├── background.js
│   │   ├── first.html
│   │   ├── kiwi.nmf
│   │   ├── manifest.json
│   │   ├── popup.html
│   │   ├── popup.js
│   │   ├── window.html
│   │   └── window.js
│   ├── gencrx.sh
│   └── nacl_src/
│       ├── .gitignore
│       ├── Makefile
│       ├── keycode_converter.h
│       └── kiwi.cc
├── installer/
│   ├── .gitattributes
│   ├── crouton
│   ├── debian/
│   │   ├── defaults
│   │   └── releases
│   ├── functions
│   ├── kali/
│   │   ├── defaults
│   │   └── releases
│   ├── main.sh
│   ├── prepare.sh
│   └── ubuntu/
│       ├── ar
│       ├── bootstrap
│       ├── defaults
│       ├── getrelease.sh
│       ├── pkgdetails
│       ├── prepare
│       └── releases
├── src/
│   ├── fbserver-proto.h
│   ├── fbserver.c
│   ├── findnacld.c
│   ├── freon.c
│   ├── vtmonitor.c
│   ├── websocket.c
│   ├── websocket.h
│   └── xi2event.c
├── targets/
│   ├── audio
│   ├── chrome
│   ├── chrome-beta
│   ├── chrome-common
│   ├── chrome-dev
│   ├── chromium
│   ├── cli-extra
│   ├── common
│   ├── core
│   ├── e17
│   ├── extension
│   ├── gnome
│   ├── gnome-desktop
│   ├── gtk-extra
│   ├── kde
│   ├── kde-desktop
│   ├── keyboard
│   ├── kodi
│   ├── lxde
│   ├── lxde-desktop
│   ├── post-common
│   ├── touch
│   ├── unity
│   ├── unity-desktop
│   ├── x11
│   ├── x11-common
│   ├── xbmc
│   ├── xfce
│   ├── xfce-desktop
│   ├── xiwi
│   └── xorg
└── test/
    ├── autotest_control.template
    ├── daemon.sh
    ├── genreport.sh
    ├── reports/
    │   ├── 00-all.sh
    │   ├── 35-xorg.sh
    │   └── w0-common.sh
    ├── run.sh
    └── tests/
        ├── 00-tester
        ├── 10-basic
        ├── 11-32-on-64
        ├── 12-edit-chroot
        ├── 14-background
        ├── 15-media
        ├── 16-targetsfile
        ├── 17-encryption
        ├── 18-upgrade
        ├── 20-logind
        ├── 30-audio
        ├── 35-xorg
        ├── 37-xiwi
        ├── w0-common
        ├── w1-e17
        ├── w2-gnome
        ├── w2d-gnome-desktop
        ├── w3-kde
        ├── w3d-kde-desktop
        ├── w4-lxde
        ├── w4d-lxde-desktop
        ├── w5-unity
        ├── w5d-unity-desktop
        ├── w6-kodi
        ├── w7-xfce
        ├── w7d-xfce-desktop
        └── x0-alltargets

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/CONTRIBUTING.md
================================================
## For users who want to report an issue
Please read [this wiki page]
(https://github.com/dnschneid/crouton/wiki/Common-issues-and-reporting)
for instructions on reporting an issue.

## For contributors
Please read [this
section](https://github.com/dnschneid/crouton#i-want-to-be-a-contributor)
of the README and the following relevant sections first.


================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
```
Please paste the output of the following command here: sudo edit-chroot -all
```

#### Please describe your issue:


#### If known, describe the steps to reproduce the issue:


================================================
FILE: .gitignore
================================================
*.tar.*
.*.swp
.*.tmp
nacl_sdk/
/crouton*
/test/run
/releases/


================================================
FILE: AUTHORS
================================================
Google, Inc


================================================
FILE: CONTRIBUTORS
================================================
Aaron Zauner
Alex Bennée
Alfred Suleymanov
Alfriadox
Alireza Ghasemi
Andrew Kanner
Aron Griffis
Aurelien Lourot
Avi Zajac
Blaine Bublitz
Braden Farmer
brannon
brmbrmcar
Bryce Thorup
Chris Galle
Christopher Mårtensson
Chris Varga
Chuan Ji
Corey Garst
Daniel Haber
David Reveman
David Schneider
Dennis Lockhart
dimonf
dumpweed
Eugene Y. Q. Shen
George Shank
Icecream95
Igor Bukanov
JackMacWindows
Jake Waksbaum
Javi Merino
jessaustin
Jim Tittsler
Johan Lorentzon
John Tantalo
joshua stein
Justin Frankel
Justin Guy
Kenny Strawn
Kerwin Hui
Lef Ioannidis
Magnus Nyberg
Masaki Muranaka
Maurice van Kruchten
Micah Lee
Michael Mattioli
Michael Moss
Michael Orr
Mike Kasick
Mikito Takada
Miles Whittaker
Neal McBurnett
Nevada Romsdahl
Nicolas Boichat
Pete Baldridge
Phillip Pearson
Rich Murphey
Ricky Brent
Ryan Fowler
Samuel Dionne-Riel
Simon Podhajsky
Stephen Barber
Steve Desmond
Steven Maude
Steven Merrill
Ted Matsumura
Tobbe Lundberg
Tom Dunlap
Tony Xue
William Kong
William Ransohoff
William W. Wu
Yang Wang
Yu-Hsi Chiang
Yuri Pole
Yushin Washio
zguithues
Zopolis4


================================================
FILE: LICENSE
================================================
// Copyright (c) 2016 The crouton Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: Makefile
================================================
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

TARGET = crouton
EXTTARGET = crouton.zip
LIBS = src/freon.c
LIBSTARGETS = $(patsubst src/%.c, crouton%.so, $(LIBS))
SRCTARGETS = $(patsubst src/%.c,crouton%,$(filter-out $(LIBS),$(wildcard src/*.c)))
CONTRIBUTORS = CONTRIBUTORS
WRAPPER = build/wrapper.sh
SCRIPTS_NOSYM := \
	$(wildcard host-bin/*) \
	$(wildcard installer/*.sh) installer/functions \
	$(wildcard installer/*/*) \
	$(wildcard src/*) \
	$(wildcard targets/*)
SCRIPTS := \
	$(wildcard chroot-bin/*) \
	$(wildcard chroot-etc/*)
EXTPEXE = host-ext/crouton/kiwi.pexe
EXTPEXESOURCES = $(wildcard host-ext/nacl_src/*.h) \
				 $(wildcard host-ext/nacl_src/*.cc)
EXTSOURCES = $(wildcard host-ext/crouton/*)
BOOTSTRAPS := $(wildcard installer/*/bootstrap)
BUILDDIR = crouton.build
GENVERSION = build/genversion.sh
CONTRIBUTORSSED = build/CONTRIBUTORS.sed
RELEASE = build/release.sh
VERSION = 1
TARPARAMS ?= -j

CFLAGS=-g -Wall -Werror -Wno-error=unused-function -Os

croutonfbserver_LIBS = -lX11 -lXdamage -lXext -lXfixes -lXtst
croutonxi2event_LIBS = -lX11 -lXi
croutonfreon.so_LIBS = -ldl -ldrm -I/usr/include/libdrm

croutonwebsocket_DEPS = src/websocket.h
croutonfbserver_DEPS = src/websocket.h

ifeq ($(wildcard .git/HEAD),)
    GITHEAD :=
else
    GITHEADFILE := .git/refs/heads/$(shell cut -d/ -f3 '.git/HEAD')
    ifeq ($(wildcard $(GITHEADFILE)),)
        GITHEAD := .git/HEAD
    else
        GITHEAD := .git/HEAD .git/refs/heads/$(shell cut -d/ -f3 '.git/HEAD')
    endif
endif

$(TARGET): $(WRAPPER) $(BUILDDIR) $(GENVERSION) $(GITHEAD) Makefile
	{ \
		sed -e "s/\$$TARPARAMS/$(TARPARAMS)/" \
			-e "s/VERSION=.*/VERSION='$(shell $(GENVERSION) $(VERSION))'/" \
			$(WRAPPER) \
		&& (cd $(BUILDDIR) && tar --owner=root --group=root -c $(TARPARAMS) *)\
		&& chmod +x /dev/stdout \
	;} > $(TARGET) || ! rm -f $(TARGET)

$(BUILDDIR): $(SCRIPTS) $(SCRIPTS_NOSYM) Makefile
	rm -rf $(BUILDDIR) && mkdir -p $(BUILDDIR) \
	&& cp -at $(BUILDDIR) --parents $(SCRIPTS) \
	&& cp -Lprt $(BUILDDIR) --parents $(SCRIPTS_NOSYM) \
	&& for bootstrap in $(BOOTSTRAPS); do \
		tmp=$(BUILDDIR); \
		[ -h "$$bootstrap" ] && continue; \
		echo "Preparing bootstrap dependencies for $$bootstrap" >&2; \
		tmp=$(BUILDDIR) sh -e "$$bootstrap" \
			|| ! rm -rf $(BUILDDIR) || exit 1; \
	done

$(EXTTARGET): $(EXTSOURCES) Makefile
	rm -f $(EXTTARGET) && zip -q --junk-paths $(EXTTARGET) $(EXTSOURCES)

$(EXTPEXE): $(EXTPEXESOURCES)
	$(MAKE) -C host-ext/nacl_src

$(SRCTARGETS): $(patsubst crouton%,src/%.c,$@) $($@_DEPS) Makefile
	gcc $(CFLAGS) $(patsubst crouton%,src/%.c,$@) $($@_LIBS) -o $@

$(LIBSTARGETS): $(patsubst crouton%.so,src/%.c,$@) $($@_DEPS) Makefile
	gcc $(CFLAGS) -shared -fPIC $(patsubst crouton%.so,src/%.c,$@) $($@_LIBS) -o $@

extension: $(EXTTARGET)

$(CONTRIBUTORS): $(GITHEAD) $(CONTRIBUTORSSED)
	git shortlog -s | sed -f $(CONTRIBUTORSSED) | sort -uf > $(CONTRIBUTORS)

contributors: $(CONTRIBUTORS)

release: $(CONTRIBUTORS) $(TARGET) $(RELEASE)
	[ ! -d .git ] || git status | grep -q 'working [a-z]* clean' || \
		{ echo "There are uncommitted changes. Aborting!" 1>&2; exit 2; }
	$(RELEASE) $(TARGET)

force-release: $(CONTRIBUTORS) $(TARGET) $(RELEASE)
	$(RELEASE) -f $(TARGET)

all: $(TARGET) $(SRCTARGETS) $(LIBSTARGETS) $(EXTTARGET)

clean:
	rm -f $(TARGET) $(EXTTARGET) $(SRCTARGETS) $(LIBSTARGETS)
	rm -rf $(BUILDDIR)

.PHONY: all clean contributors extension release force-release


================================================
FILE: README.md
================================================
# crouton: Chromium OS Universal Chroot Environment

crouton is a set of scripts that bundle up into an easy-to-use,
Chromium OS-centric chroot generator. Ubuntu, Debian, and Kali are supported
(using debootstrap behind the scenes), but "Chromium OS Debian and Ubuntu (plus
one distro) EOL'd Chroot Environment" doesn't acronymize as well (crodupodece is
admittedly pretty fun to say, though).

### 🪦 crouton is now end-of-life 🪦

All good things must come to an end, and considering
 * Chromium OS's introduction of increasingly strict shell safeguards,
 * the [change in cras's build tools](https://github.com/dnschneid/crouton/issues/4958),
 * the [removal of manifest v2 extensions](https://github.com/dnschneid/crouton/pull/5094),
 * the [removal of PNaCl, breaking xiwi](https://github.com/dnschneid/crouton/issues/5130),
 * oh, and Chromium OS being replaced by Android

there's really not much to gain from continued development. Put another way, the
proverbial mixed salad is just about out of tasty crunchy bits, and the
remaining morsels have gone a bit stale. And for some reason someone's about to
swap all the lettuce out for onion rings? Point is, it's time to stop mixing
dressings. Unless it's ranch, I guess, since that goes with just about anything.
But this is crouton, not some Ready-for-Android Native Chroot Host, alas.

Anyway, this means that:
 * The repo is now locked, and no further changes will be considered.
 * Eventually someone will want the latest Ubuntu added to the release list. See
   [this commit](https://github.com/dnschneid/crouton/commit/6d80f57b91c39d10b29fde861aac5a2b5b9b3910)
   for an example of how to do it on your own copy.
 * Sometime around July 2025, the GitHub project will be archived, making the
   issue tracker, discussions, and wiki read-only.
 * For the safety of users and stability of crouton's functionality for those on
   EOL devices, offers to take over the dnschneid/crouton repo or extension will
   be declined, and requests to change link destinations will be rejected.

If you have an EOL device, though, crouton is still a great match for you!
 * Chromium OS version 110 and earlier, everything should work! Breathe new life
   into your old devices!!
 * Starting 111, crouton can't compile cras, so audio devices cannot be shared
   with Chromium OS
 * Starting 117, sudo in crosh is disabled and you'll need to use VT-2
 * Starting 133 (139 for enterprise devices), manifest v2 is disabled and you
   won't be able to run the extension (easy switching, clipboard sync, xiwi)
 * Also starting 133 (139 for enterprise devices), pnacl is disabled, so even if
   you somehow got the extension working, xiwi won't function
 * Beyond that, it's anybody's guess as to what will break

## Moving right along...

:warning: **Steps to install crouton have changed!**  :warning:

Chromium OS has introduced several security features over the years that impede
the installation and usage of crouton. If your device is no longer receiving
updates, the steps below will likely work for you. However, if you are still
having trouble, please try the [community-maintained instructions](https://github.com/dnschneid/crouton/wiki/Updated-Installation-Instructions-for-Crouton).

In addition, goo.gl is going away! That means the goo.gl/fd3zc you know and love
has been replaced with [git.io/JZEs0](https://git.io/JZEs0). That's a zero at
the end, if you were wondering. Both just point to
[github](https://raw.githubusercontent.com/dnschneid/crouton/master/installer/crouton),
so you can always just memorize the full link instead, which (fun fact) does not
include any numbers at all!

## "crouton"...an acronym?

It stands for _ChRomium Os Universal chrooT envirONment_
...or something like that. Do capitals really matter if caps-lock has been
(mostly) banished, and the keycaps are all lower-case?

Moving on...


## Who's this for?

Anyone who wants to run straight Linux on their Chromium OS device, and doesn't
care about physical security. You're also better off having some knowledge of
Linux tools and the command line in case things go funny, but it's not strictly
necessary.


## What's a chroot?

Like virtualization, chroots provide the guest OS with their own, segregated
file system to run in, allowing applications to run in a different binary
environment from the host OS. Unlike virtualization, you are *not* booting a
second OS; instead, the guest OS is running using the Chromium OS system. The
benefit to this is that there is zero speed penalty since everything is run
natively, and you aren't wasting RAM to boot two OSes at the same time. The
downside is that you must be running the correct chroot for your hardware, the
software must be compatible with Chromium OS's kernel, and machine resources are
inextricably tied between the host Chromium OS and the guest OS. What this means
is that while the chroot cannot directly access files outside of its view, it
*can* access all of your hardware devices, including the entire contents of
memory. A root exploit in your guest OS will essentially have unfettered access
to the rest of Chromium OS.

...but hey, you can run [TuxRacer](https://en.wikipedia.org/wiki/Tux_Racer)!


### What about dem crostinis though?

[Crostini](https://chromium.googlesource.com/chromiumos/docs/+/HEAD/containers_and_vms.md)
is an official project within Chromium OS to bring the Linux shell and apps to
the platform *in verified mode* with clean integration, multi-layered security,
and all the polish you expect from Chromium OS proper.

That means compared to crouton, Crostini has official support, competent
engineers, and code that looks a little less like ramen.  crouton, in its
defense, has wider device compatibility, enables direct hardware access, and is
named after an objectively tastier bread-based food item.

There's a solid community on [Reddit](https://www.reddit.com/r/Crostini/) if
you'd like to try Crostini out.  If it works for you -- great!  No hard
feelings.  If in the end you decide that crouton suits you better, read on!

Note: you can't get the best of both worlds by installing crouton inside of
Crostini.  The technology (and life itself) just doesn't work that way.  Not to
mention a crouton Crostini would look ridiculous and be impossible to eat
without getting bits everywhere.


## Prerequisites

You need a device running Chromium OS that has been switched to developer mode.

For instructions on how to do that, go to [this Chromium OS wiki page](https://www.chromium.org/chromium-os/developer-information-for-chrome-os-devices),
click on your device model and follow the steps in the *Entering Developer Mode*
section.

Note that developer mode, in its default configuration, is *completely
insecure*, so don't expect a password in your chroot to keep anyone from your
data. crouton does support encrypting chroots, but the encryption is only as
strong as the quality of your passphrase. Consider this your warning.

It's also highly recommended that you install the [crouton extension](https://chromewebstore.google.com/detail/crouton-integration/gcpneefbbnfalgjniomfjknbcgkbijom),
which, when combined with the `extension` or `xiwi` targets, provides much 
improved integration with Chromium OS.

That's it! Surprised?


## Usage

crouton is a powerful tool, and there are a *lot* of features, but basic usage
is as simple as possible by design.

If you're just here to use crouton, you can grab the latest release from
[https://git.io/JZEs0](https://git.io/JZEs0). Download it, pop open a
shell (Ctrl+Alt+T, type `shell` and hit enter), make the installer executable
with `sudo install -Dt /usr/local/bin -m 755 ~/Downloads/crouton`, then launch
it with `sudo crouton` to see the help text. See the "examples" section for some
usage examples.

If you're modifying crouton, you'll probably want to clone or download the repo
into a subdirectory of `/usr/local` and then either run `installer/main.sh`
directly, or use `make` to build your very own `crouton`. You can also download
the latest release, install it as above and run `crouton -x` to extract out the
juicy scripts contained within, but you'll be missing build-time stuff like the
Makefile. You also need to remember to place the unbundled scripts somewhere in
`/usr/local` in order to be able to execute them.

crouton uses the concept of "targets" to decide what to install. While you will
have apt-get in your chroot, some targets may need minor hacks to avoid issues
when running in the chrooted environment. As such, if you expect to want
something that is fulfilled by a target, install that target when you make the
chroot and you'll have an easier time.  Don't worry if you forget to include a
target; you can always update the chroot later and add it. You can see the list
of available targets by running `crouton -t help`.

Once you've set up your chroot, you can easily enter it using the
newly-installed `enter-chroot` command, or one of the target-specific
start\* commands. Ta-da! That was easy.


## Examples

### The easy way (assuming you want an Ubuntu LTS with Xfce)

  1. Download `crouton`
  2. Open a shell (Ctrl+Alt+T, type `shell` and hit enter)
  3. Copy the installer to an executable location by running
     `sudo install -Dt /usr/local/bin -m 755 ~/Downloads/crouton`
  4. Now that it's executable, run the installer itself: `sudo crouton -t xfce`
  5. Wait patiently and answer the prompts like a good person.
  6. Done! You can jump straight to your Xfce session by running
     `sudo enter-chroot startxfce4` or, as a special shortcut, `sudo startxfce4`
  7. Cycle through Chromium OS and your running graphical chroots using
     Ctrl+Alt+Shift+Back and Ctrl+Alt+Shift+Forward.
  8. Exit the chroot by logging out of Xfce.

### With encryption!

  1. Add the `-e` parameter when you run crouton to create an encrypted chroot
     or encrypt a non-encrypted chroot.
  2. You can get some extra protection on your chroot by storing the decryption
     key separately from the place the chroot is stored. Use the `-k` parameter
     to specify a file or directory to store the keys in (such as a USB drive or
     SD card) when you create the chroot. Beware that if you lose this file,
     your chroot will not be decryptable. That's kind of the point, of course.

### Hey now, Ubuntu 16.04 is pretty old; I'm young and hip

  1. The `-r` parameter specifies which distro release you want to use.
  2. Run `crouton -r list` to list the recognized releases and which distros
     they belong to.

### Wasteful redundancies are wasteful: one clipboard, one browser, one window

  1. Install the [crouton extension](https://chromewebstore.google.com/detail/crouton-integration/gcpneefbbnfalgjniomfjknbcgkbijom)
     into Chromium OS.
  2. Add the `extension` or `xiwi` version to your chroot.
  3. Try some copy-pasta, or uninstall all your web browsers from the chroot.

*Installing the extension and its target gives you synchronized clipboards, the
option of using Chromium OS to handle URLs, and allows chroots to create
graphical sessions as Chromium OS windows.*

### I don't always use Linux, but when I do, I use CLI

  1. You can save a chunk of space by ditching X and just installing
     command-line tools using `-t core` or `-t cli-extra`
  2. Enter the chroot in as many crosh shells as you want simultaneously using
     `sudo enter-chroot`
  3. Use the [Crosh Window](https://chromewebstore.google.com/detail/crosh-window/nhbmpbdladcchdhkemlojfjdknjadhmh)
     extension to keep Chromium OS from eating standard keyboard shortcuts.
  4. If you installed cli-extra, `startcli` will launch a new VT right into the
     chroot.

### A new version of crouton came out; my chroot is therefore obsolete and sad

  1. Exit the chroot if you have it open.
  2. If you haven't already, download `crouton`, and copy it so it works:
     `sudo install -Dt /usr/local/bin -m 755 ~/Downloads/crouton`
  3. Update your chroot with `sudo crouton -u -n chrootname`. It will update
     all installed targets.

### I want to open my desktop in a window or a tab but I don't have the 'xiwi' target/xmethod.

  1. Add 'xiwi' or any other target to an existing chroot with the `-u` option:
     `sudo crouton -t xiwi -u -n chrootname`

  This will also make 'xiwi' the default xmethod.

  2. If you want to keep the 'xorg' xmethod as the default then pick it first:
     `sudo sh crouton -t xorg,xiwi -u -n chrootname`

### A backup a day keeps the price-gouging data restoration services away

  1. `sudo edit-chroot -b chrootname` backs up your chroot to a timestamped
     tarball in the current directory. Chroots are named either via the `-n`
     parameter when created or by the release name if -n was not specified.
  2. `sudo edit-chroot -r chrootname` restores the chroot from the most recent
     timestamped tarball. You can explicitly specify the tarball with `-f`
  3. If your machine is new, powerwashed, or held upside-down and shaken, you
     can use the crouton installer to restore a chroot and relevant scripts:
     `sudo crouton -f mybackup.tar.gz`

*Unlike with Chromium OS, the data in your chroot isn't synced to the cloud.*

### This chroot's name/location/password/existence sucks. How to fix?

  1. Check out the `edit-chroot` command; it likely does what you need it to do.
  2. If you set a Chromium OS root password, you can change it with
     `sudo chromeos-setdevpasswd`
  3. You can change the password inside your chroot with `passwd`

### I want to install the chroot to another location

  1. Use `-p` to specify the directory in which to install the chroot and
     scripts. Be sure to quote or escape spaces.
  2. When entering the chroot for the first time each boot, you will first need
     to ensure the place you've installed the scripts is in a place that allows
     executables to run. Determine the mountpoint by running
     `df --output=target /path/to/enter-chroot`, then mark the mount exec with
     `sudo mount -o remount,exec /path/to/mountpoint`.
  3. You can then launch the chroot by specifying the full path of any of the
     enter-chroot or start* scripts (i.e. `sudo /path/to/enter-chroot`), or use
     the `-c` parameter to explicitly specify the chroots directory.

*If for some reason you have to run the installer without touching the local
disk, you can (for the time being) run
`curl -fL https://git.io/JZEs0 | sudo sh -s -- options_for_crouton_installer`.
Note that this will definitely break in the near future, so don't depend on it.*

### Downloading bootstrap files over and over again is a waste of time

  1. Download `crouton`
  2. Open a shell (Ctrl+Alt+T, type `shell` and hit enter)
  3. Copy the installer to an executable location by running
     `sudo install -Dt /usr/local/bin -m 755 ~/Downloads/crouton`
  4. Now that it's executable, use the installer to build a bootstrap tarball:
     `sudo crouton -d -f ~/Downloads/mybootstrap.tar.bz2`
  5. Include the `-r` parameter if you want to specify for which release to
     prepare a bootstrap.
  6. You can then create chroots using the tarball by running
     `sudo crouton -f ~/Downloads/mybootstrap.tar.bz2`. Make sure you also
     specify the target environment with `-t`.

*This is the quickest way to create multiple chroots at once, since you won't
have to determine and download the bootstrap files every time.*

### Targets are cool. Abusing them for fun and profit is even cooler

  1. You can make your own target files (start by copying one of the existing
     ones) and then use them with any version of crouton via the `-T` parameter.

*This is great for automating common tasks when creating chroots.*

### Help! I've created a monster that must be slain!

  1. The delete-chroot command is your sword, shield, and only true friend.
     `sudo delete-chroot evilchroot`
  2. It's actually just a shortcut to `sudo edit-chroot -d evilchroot`, which I
     suppose makes it a bit of a deceptive Swiss Army knife friend...still good?


## Tips

  * Chroots are cheap! Create multiple ones using `-n`, break them, then make
    new, better ones!
  * You can change the distro mirror from the default by using `-m`
  * Want to use a proxy? `-P` lets you specify one (or disable it).
  * A script is installed in your chroot called `brightness`. You can assign
    this to keyboard shortcuts to adjust the brightness of the screen (e.g.
    `brightness up`) or keyboard (e.g. `brightness k down`).
  * Multiple monitors will work fine in the chroot, but you may have to switch
    to Chromium OS and back to enable them.
  * You can make commands run in the background so that you can close the
    terminal. This is particularly useful for desktop environments: try running
    `sudo startxfce4 -b`
  * Want to disable Chromium OS's power management? Run `croutonpowerd -i`
  * Only want power management disabled for the duration of a command?
    `croutonpowerd -i command and arguments` will automatically stop inhibiting
    power management when the command exits.
  * Have a Pixel or two or 4.352 million? `-t touch` improves touch support.
  * Want to share some files and/or folders between Chromium OS and your chroot?
    Check out the `/etc/crouton/shares` file, or read all about it in the wiki.
  * Want more tips? Check the [wiki](https://github.com/dnschneid/crouton/wiki).


## Issues?

Running another OS in a chroot is a pretty messy technique (although it's hidden
behind very pretty scripts), and while these scripts are relatively mature,
Chromium OS is changing all the time so problems are not surprising. Check the
issue tracker and file a bug if your issue isn't there. When filing a new bug,
include the output of `croutonversion` run from inside the chroot or, if you
cannot mount your chroot, include the output of `cat /etc/lsb-release` from Crosh.


## I want to be a Contributor!

That's great!  But before your code can be merged, you'll need to have signed
the [Individual Contributor License Agreement](https://cla.developers.google.com/clas/new?kind=KIND_INDIVIDUAL&domain=DOMAIN_GOOGLE).
Don't worry, it only takes a minute and you'll definitely get to keep your
firstborn, probably.  If you've already signed it for contributing to Chromium
or Chromium OS, you're already done.

If you don't know what to do with your time as an official Contributor, keep in
mind that crouton is maintenance-only and will only be accepting a limited amount
of changes.  That having been said, here's some suggestions:

  * Really like a certain desktop environment? Fork crouton, add the target, and
    let people know in the discussions area.
  * Is your distro underrepresented? Want to contribute to the elusive and
    mythical beast known as "croagh"? Fork crouton, add the distro, and people
    will come.
  * Discovered a bug lurking within the scripts, or a papercut that bothers you
    just enough to make you want to actually do something about it? You guessed
    it: fork crouton, fix everything, and create a pull request.
  * Are most bugs too high-level for you to defeat? Grind up some
    [EXP](https://en.wikipedia.org/wiki/Experience_point) by using
    your fork to eat [pie](https://github.com/dnschneid/crouton/labels/pie).


## Are there other, non-Contributory ways I can help?

Yes!


## But how?

There's a way For Everyone to help!

  * Something broken? File a bug! Bonus points if you try to fix it. It helps if
    you provide the output of `croutonversion` (or the output of
    `cat /etc/lsb-release` from Crosh) when you submit the bug.
  * Look through [open issues](https://github.com/dnschneid/crouton/issues?state=open)
    and see if there's a topic or application you happen to have experience
    with. And then, preferably, share that experience with others.
  * Find issues that need [wiki entries](https://github.com/dnschneid/crouton/issues?labels=needswiki&state=open,closed)
    and add the relevant info to the [wiki](https://github.com/dnschneid/crouton/wiki).
    Or just add things to/improve things in the wiki in general, but do try to
    keep it relevant and organized.
  * Really like a certain desktop environment, but not up for coding? Open or
    comment on a bug with steps to get things working well.


## License

crouton (including this eloquently-written README) is copyright © 2016 The
crouton Authors. All rights reserved. Use of the source code included here is
governed by a BSD-style license that can be found in the LICENSE file in the
source tree.


================================================
FILE: README.zh.md
================================================
# Crouton中文版教程

> 基于crouton项目README的英文版进行汉化,部分内容没有进行汉化,建议有能力者优先阅读英文版本。

## 简介

​	Chroot是Chromium OS Universal Chroot Environment 的简写,是一系列脚本的合集,利用Linux的Chroot,在Chromebook上同时运行Chrome OS和某个Linux发行版。

## Chroot介绍

​	Chroot命令用来在指定的根目录下运行指令。Chroot的这种功能可以为第二系统提供一个隔离的文件系统,就像虚拟化一样,但是第二系统实际上仍然在主系统的文件系统下面工作,在进程和网络层面,chroot并没有进行隔离。

​	至于详细的内容,为什么不去问问[百度搜索](https://www.baidu.com/s?wd=chroot)?

## 进入正题

### 环境

- **良好的**网络环境
- 进入**开发者模式**的Chromebook,相关操作请进入[这个页面](https://www.chromium.org/chromium-os/developer-information-for-chrome-os-devices)(英文页面),点击对应的设备型号,按照*Entering Developer Mode*章节的步骤进行
- 强烈建议安装[Crouton插件](https://chromewebstore.google.com/detail/crouton-integration/gcpneefbbnfalgjniomfjknbcgkbijom),配合`extension`或者`xiwi`目标,可以提高第二系统与Chrome OS之间的交互体验

### 用法

1. 你需要从[这里](https://git.io/JZEs0)下载Crouton脚本。~~什么?下不下来?关我什么事~~

2. 然后打开shell(`ctrl+alt+T`,在打开的窗口中输入`shell`,然后回车)。

3. 输入`sudo install -Dt /usr/local/bin -m 755 ~/Downloads/crouton`,这一步是将下载下来的脚本安装到`/usr/local/bin`这个可执行目录里面。

4. `sudo crouton`可以查看帮助,本教程**示例**部分会有一些命令使用举例。

   如果你想对Crouton稍作修改,可以将本项目下载到`/usr/local`,直接运行`installer/main.sh`或者使用`make`进行编译。你也可以按上述四步安装crouton后,使用`crouton -x`将包含的脚本解压,不过那样的话你需要自己编写编译所需的文件,以及记住脚本所在的位置。

   Crouton使用“目标”('targets')来决定安装什么。可用的目标可以运行`crouton -t help`来查看。

   安装之后,可以输入`enter-chroot`,或者由你选择的安装目标所决定的 start* 命令。具体的命令,安装完成后终端会有介绍(英文)。  

## 示例

**简单示例(安装Ubuntu LTS,使用Xfce桌面环境)**

1. 下载Crouton
2. 打开shell(`ctrl+alt+T`,在打开的窗口中输入`shell`,然后回车)。
3. 输入`sudo install -Dt /usr/local/bin -m 755 ~/Downloads/crouton`
4. `sudo crouton -t xfce`
5. 等吧,可以喝杯星巴克
6. 安装完成后,使用`sudo enter-chroot startxfce4`,或者`sudo startxfce4`运行chroot,会自动跳至Xfce
7. 登出/注销(logout)Xfce来退出chroot,**在Xfce里点击关机是没有用的**。

**加密**

1. 运行crouton是可以添加`-e`参数来创建一个加密的chroot环境,或者加密一个未加密的chroot环境
2. 使用`-k`参数来指定储存密钥的路径

**想用别的系统?**

1. `-r`参数可以指定你想要使用的发行版和版本代号
2. `crouton -r list`可以查看支持的发行版和版本代号(英文)

**说好的“更好的交互体验”?**

1. 在Chrome OS安装[Crouton插件](https://chromewebstore.google.com/detail/crouton-integration/gcpneefbbnfalgjniomfjknbcgkbijom)

2. 在chroot环境中添加`extension`或者`xiwi`目标

   这样可以同步chroot环境和主系统的剪贴板,允许chroot环境的程序在Chrome OS界面中窗口化运行。

**只使用命令行**

1. 指定安装目标时可以只使用`-t core`或者`-t cli-extra`
2. 使用`sudo enter-chroot`进入chroot环境
3. 使用[Crosh Window插件](https://chromewebstore.google.com/detail/crosh-window/nhbmpbdladcchdhkemlojfjdknjadhmh),防止chroot命令行环境导致的快捷键失效

**升级chroot环境**

​	使用`sudo crouton -u -n chrootname`来升级chroot环境中的系统。

**安装后想添加一些安装目标?**

​	使用`-u`参数来添加安装目标。

​	比如,添加`xiwi`目标:`sudo crouton -t xiwi -u -n chrootname`

​	上述命令会让xiwi成为默认的[X窗口方法](https://baike.baidu.com/item/X%E7%AA%97%E5%8F%A3/1471357?fr=aladdin)(原默认方法为xorg),如果想让X窗口方法继续保持默认:

​	`sudo crouton -t xorg,xiwi -u -n chrootname`

**备份**

​	`sudo edit-chroot -b chrootname`会在命令运行目录下生成chroot环境的tar格式的备份文件(带备份时间戳),Chroot环境的名字可以在安装时由`-n`参数指定,未指定时默认为所安装的Linux发行版版本代号(例如,默认的Ubuntu 16.04LTS版本代号为xenial)

​	`sudo edit-chroot -r chrootname`默认恢复最近一次的备份文件。可以用`-r`参数指定恢复文件

​	对全新或者重置过的电脑,可以使用Crouton的恢复命令:`sudo crouton -f mybackup.tar.gz`

**更改安装位置**

​	`-p`参数可指定chroot的安装位置。

​	每次启动电脑后第一次启动chroot,请确定chroot的安装位置是可执行(executable)的:

	1. 确定挂载点:`df --output=target /path/to/enterchroot`
 	2. 使挂载点可读写:`sudo mount -o remount,exec /path/to/mountpoint`

**删除Chroot环境**

​	`sudo delete-chroot chrootname`

## 使用提醒

- 使用`-n`来指定Chroot环境的名字,可以创建多个chroot环境
- 使用`-m`参数更改镜像源
- `-P`参数开启/关闭Chroot环境的代理,仅支持http/https
- chroot内置`brightness`脚本,可以:
  - 调节屏幕亮度(比如,在chroot内运行`brightness up`)
  - 调节背光键盘亮度(比如,在chroot内运行:`brightness k down`)
- 使用多屏可能需要先切换到Chrome OS界面,然后再切换回来
- 运行命令添加`-b`参数可以让chroot在后台运行,比如:`sudo startxfce4 -b`
- `croutonpowerd -i`可以关闭Chrome OS的电源管理
- `croutonpowerd -i command and arguments`可以指定在chroot执行某些命令时关闭Chrome OS的电源管理
- `touch`安装目标可以改善触摸屏设备的使用体验
- 本项目Wiki中有关于文件共享的介绍
- [Wiki](https://github.com/dnschneid/crouton/wiki)中也有更多其他提示(英文)


================================================
FILE: build/CONTRIBUTORS.sed
================================================
s/^[ \t0-9]*//
s/^DennisL.*$/Dennis Lockhart/
s/^drinkcat$/Nicolas Boichat/
s/^divx118$/Maurice van Kruchten/
s/^haberda$/Daniel Haber/
s/^tedm$/Ted Matsumura/
s/^magnus$/Magnus Nyberg/
s/^eyqs$/Eugene Y. Q. Shen/
/^nromsdahl$/d
/^root$/d
/^ttk153$/d
/^lnxsrt$/d
/\?/d


================================================
FILE: build/genversion.sh
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Outputs a version string with the specified prefix.

if [ "$#" != 1 ]; then
    echo "Usage: ${0##*/} VERSION" 1>&2
    exit 1
fi

source=''

# Get the branch from git
git="`dirname "$0"`/../.git"
if [ -f "$git/HEAD" ]; then
    source="`cut -d/ -f3 "$git/HEAD"`"
    if [ -n "$source" ]; then
        if [ -f "$git/refs/heads/$source" ]; then
            source="$source:`head -c 8 "$git/refs/heads/$source"`"
        else
            source="${source%"${source#????????}"}"
        fi
        source="~$source"
    fi
fi

VERSION="$1-%Y%m%d%H%M%S$source"

exec date "+$VERSION"


================================================
FILE: build/release.sh
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

# Generates a release in the releases/ directory (which should be a checkout of
# the releases branch of the same repo) and pushes it.

USAGE="Usage: ${0##*/} [-f] bundle [..]
    -f  Hard-reset the releases branch in case of unpushed releases."
FORCE=''

# CD into the repo's root directory
dir="`readlink -f -- "$0"`"
cd "${dir%/*}/.."

# Import common functions
. installer/functions 

if [ "$1" = '-f' ]; then
    FORCE=y
    shift
fi

if [ "$#" = 0 ]; then
    error 2 "$USAGE"
fi

# Check the releases directory and update, or create it if necessary
if [ -d releases/.git ]; then
    if ! grep -q 'releases$' releases/.git/HEAD; then
        error 1 'releases/ is not in the releases branch.'
    fi
    if ! awk "/'releases'/{print \$1}" releases/.git/FETCH_HEAD | \
            diff -q releases/.git/refs/heads/releases - >/dev/null; then
        echo 'releases/ is ahead of or not up-to-date with remote' 1>&2
        if [ -z "$FORCE" ]; then
            exit 1
        fi
    fi
    git -C releases fetch origin releases
    git -C releases reset --hard origin/releases
elif [ -e releases ]; then
    error 1 "releases/ is not a git repo"
else
    url="`git remote -v | awk '$1=="origin" && $3=="(fetch)" {print $2}'`"
    git clone --single-branch --branch releases --reference . "$url" releases
fi

# Apply the releases
for bundle in "$@"; do
    bundle="${bundle##*/}"
    if [ ! -f "$bundle" ]; then
        error 1 "$bundle bundle does not exist"
    fi
    version="`sh "$bundle" -V`"
    if [ "$version" = "${version#crouton*:}" ]; then
        error 1 "$bundle bundle is invalid"
    fi
    branch="${version#*~}"
    branch="${branch%:*}"
    dest="${branch#master}"
    dest="crouton${dest:+-}$dest"
    # Compare the current release to avoid duplicates
    if [ -f "releases/$dest" ] && \
            sh "releases/$dest" -V | grep -q "${version#*~}"; then
        echo "Release already current: `sh "$bundle" -V`"
        continue
    fi
    # Copy it in and make a commit
    cp -fv "$bundle" "releases/$dest"
    git -C releases add "$dest"
    git -C releases commit -m "$version"
done

# Push the resulting releases
git -C releases push origin releases
git -C releases fetch origin releases

exit 0


================================================
FILE: build/wrapper.sh
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file of the source repository, which has been replicated
# below for convenience of distribution:
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#    * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#    * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#    * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# This is a wrapped tarball. This script untars itself to a temporary directory
# and then runs installer/main.sh with the parameters passed to it.
# You can pass -x [directory] to extract the contents somewhere.

set -e

VERSION='git'

# Minimum Chromium OS version is R45 stable
CROS_MIN_VERS=7262

if [ "$1" = '-x' -a "$#" -le 2 ]; then
    # Extract to the specified directory.
    SCRIPTDIR="${2:-"${0##*/}.unbundled"}"
    mkdir -p "$SCRIPTDIR"
else
    # Make a temporary directory and auto-remove it when the script ends.
    SCRIPTDIR='/tmp'
    # If we're running from a directory in /tmp, make the temporary directory a
    # subdirectory of it.
    if [ "${0#/tmp/}" != "$0" ]; then
        SCRIPTDIR="${0%/*}"
    fi
    SCRIPTDIR="`mktemp -d --tmpdir="$SCRIPTDIR" "${0##*/}.XXX"`"
    TRAP="rm -rf --one-file-system '$SCRIPTDIR';$TRAP"
    trap "$TRAP" INT HUP 0
fi

# Extract this file after the ### line
# TARPARAMS will be set by the Makefile to match the compression method.
line="`awk '/^###/ { print FNR+1; exit 0; }' "$0"`"
tail -n "+$line" "$0" | tar -x $TARPARAMS -C "$SCRIPTDIR"

# Exit here if we're just extracting
if [ -z "$TRAP" ]; then
    exit
fi

# See if we want to just run a script from the bundle
if [ "$1" = '-X' ]; then
    script="$SCRIPTDIR/$2"
    if [ ! -f "$script" ]; then
        cd "$SCRIPTDIR"
        echo "USAGE: ${0##*/} -X DIR/SCRIPT [ARGS]
Runs a script directly from the bundle. Valid DIR/SCRIPT combos:" 1>&2
        ls chroot-bin/* host-bin/* 1>&2
        if [ -n "$2" ]; then
            echo 1>&2
            echo "Invalid script '$2'" 1>&2
        fi
        exit 2
    fi
    shift 2
    # If this script was called with '-x' or '-v', pass that on
    SETOPTIONS="-e"
    if set -o | grep -q '^xtrace.*on$'; then
        SETOPTIONS="$SETOPTIONS -x"
    fi
    if set -o | grep -q '^verbose.*on$'; then
        SETOPTIONS="$SETOPTIONS -v"
    fi
    sh $SETOPTIONS "$script" "$@"
    exit "$?"
fi

# Execute the main script inline. It will use SCRIPTDIR to find what it needs.
. "$SCRIPTDIR/installer/main.sh"

exit
### end of script; tarball follows


================================================
FILE: chroot-bin/brightness
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# A shortcut script to control device brightness.
# Usage:
#    brightness [b|k] [up|down|# [instant]]

# Choose the device
device='Screen'
nokbd=''
case "$1" in
k*) device='Keyboard'
    nokbd='echo "Command not supported with keyboard backlight." 1>&2; exit 1' 
    shift;;
b*) shift;;
esac

# Handle user command
print=''
postcmd=''
case "$1" in
u*) precmd='Increase';;
d*) precmd='Decrease';;
[0-9]*) eval $nokbd;
    precmd='Set'; postcmd="Percent double:$1 int32:${2:-"1"}${2:+"2"}";;
*) eval $nokbd; precmd='Get'; postcmd='Percent'; print='--print-reply';;
esac

host-dbus dbus-send --system --dest=org.chromium.PowerManager \
          --type=method_call $print /org/chromium/PowerManager \
          org.chromium.PowerManager.${precmd}${device}Brightness${postcmd} | {
    read -r junk
    read -r double percent
    if [ -n "$print" ]; then
        echo "${percent%.*}"
    fi
}

exit 0


================================================
FILE: chroot-bin/crouton-noroot
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Wrapper for scripts that shouldn't be launched as root.
# Symlink to launch the application with the same name in /usr/bin/
# Launch directly with a parameter to launch that executable
# Launch directly with a blank or - first parameter and a word to just check and
# exit with an exit code, printing out the second parameter as the app name.

APPLICATION="${0##*/}"
if [ "$APPLICATION" = 'crouton-noroot' ]; then
    if [ -z "$1" -o "$1" = '-' -o "$1" = '--' ]; then
        APPLICATION=''
    else
        APPLICATION="$1"
        shift
    fi
else
    APPLICATION="/usr/bin/$APPLICATION"
fi

if [ "$USER" = root -o "$UID" = 0 ]; then
    app="${APPLICATION:-"$2"}"
    echo "Do not launch ${app##*/} as root inside the chroot." 1>&2
    exit 2
elif [ -z "$APPLICATION" ]; then
    exit 0
fi

exec "$APPLICATION" "$@"


================================================
FILE: chroot-bin/crouton-unity-autostart
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Helper script for launching services normally managed by upstart.
# Called during session's XDG autostart.

RELEASE="`/usr/local/bin/croutonversion -r`"

# Run the exec line from an Upstart conf file. Right now this assumes no space
# in the path and no arguments.
execfromconf() {
    local exec_cmd="`awk '/^exec/{print $2; exit}' "$1"`"
    if [ -x "$exec_cmd" ]; then
        "$exec_cmd" &
    fi
}

# Upstart launches unity on utopic+, and this needs to be started before
# any dependent services.
if [ "$RELEASE" = 'xenial' ]; then
    PATH="$PATH":/sbin /usr/bin/unity &
fi

# Launch window-stack-bridge for Unity HUD support, and unity-panel-service for
# indicators.
if [ "$RELEASE" != 'precise' ]; then
    services="unity-panel-service window-stack-bridge"
    for service in $services; do
        conf_file=/usr/share/upstart/sessions/"$service".conf
        execfromconf "$conf_file"
    done
fi

# If on trusty or later, indicators also need to be started.
if [ "$RELEASE" = 'trusty' -o "$RELEASE" = 'xenial' ]; then
    for conf_file in /usr/share/upstart/sessions/*.conf; do
        if grep -q '^start on.* indicator-services-start' "$conf_file"; then
            execfromconf "$conf_file"
        fi
    done
fi


================================================
FILE: chroot-bin/croutonclip
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Synchronizes clipboard between X displays, making use of crouton's WebSocket
# server and Chromium extension to synchronize the clipboard with Chromium OS

VERBOSE=''

. "`dirname "$0"`/../installer/functions"

# rundisplay :X cmd ...
# Run a command on the specified display
rundisplay() {
    local disp="$1"
    shift
    DISPLAY="$disp" "$@"
}

copyclip() {
    next="$1"

    # Do not copy if next is empty (display cannot be detected), or
    # if current == next. Also set current=$next if $current is empty
    if [ -z "$next" -o "${current:="$next"}" = "$next" ]; then
        if [ -n "$VERBOSE" ]; then
            echo "==Current: $current==Next: $next==" 1>&2
        fi
        return 0
    fi

    if [ -n "$VERBOSE" ]; then
        echo ">>Current: $current>>" 1>&2
    fi

    # Copy clipboard content from the current display
    {
        if [ "$current" = 'cros' ]; then
            echo -n 'R' | websocketcommand
        else
            # Check if display is still running
            if rundisplay "$current" xdpyinfo >/dev/null 2>&1; then
                echo -n 'R'
                rundisplay "$current" xsel -ob
            else
                echo -n "EUnable to open display '$current'."
            fi
        fi
    } | (
        STATUS="`head -c 1`"
        if [ "$STATUS" != 'R' ]; then
            echo -n "croutonwebsocket error: " >&2
            cat >&2
            # Stop here (the clipboard content is lost in this case)
            exit 0
        fi

        # Paste clipboard content to the next display
        if [ "$next" = 'cros' ]; then
            STATUS="`(echo -n 'W'; cat) | websocketcommand`"
            if [ "$STATUS" != 'WOK' ]; then
                # Write failed, skip Chromium OS (do not update $current)
                echo -n "croutonwebsocket error: $STATUS" >&2
                exit 1
            fi
        else
            # Do not override content if it "looks" the same
            # (we might have rich text or other content in the clipboard)
            cliptmp="`mktemp "croutonclip.XXX" --tmpdir=/tmp`"
            trap "rm -f '$cliptmp'" 0
            cat > $cliptmp

            if ! rundisplay "$next" xsel -ob \
                    | diff -q - "$cliptmp" > /dev/null; then
                rundisplay "$next" xsel -ib < "$cliptmp"
            fi
        fi
    ) && current="$next"

    if [ -n "$VERBOSE" ]; then
        echo "<<Next: $current<<" 1>&2
    fi
}

# Wait for the websocket server to get connected to the extension
# Timeout after 10 seconds (twice crouton extension retry period)
waitwebsocket() {
    timeout=10
    while [ $timeout -gt 0 ]; do
        if [ -n "$VERBOSE" ]; then
            echo "Ping..." 1>&2
        fi

        # Prepare and send a ping message
        MSG="PING$$$timeout"
        STATUS="`echo -n "$MSG" | websocketcommand`"
        if [ "$STATUS" = "$MSG" ]; then
            if [ -n "$VERBOSE" ]; then
                echo "OK!" 1>&2
            fi
            return 0
        fi

        if [ -n "$VERBOSE" ]; then
            echo "$STATUS" 1>&2
        fi

        sleep 1
        timeout=$(($timeout-1))
    done
    echo "Timeout waiting for extension to connect." >&2
}

# Assume current display is Chromium OS: avoid race as we may not be able to
# detect the first VT/window change.
current='cros'

mkdir -m 775 -p "$CROUTONLOCKDIR"
exec 3>>"$CROUTONLOCKDIR/clip"
chmod -Rf g+rwX "$CROUTONLOCKDIR" || true
chgrp -Rf crouton "$CROUTONLOCKDIR" || true
if ! flock -n 3; then
    echo "Another instance of croutonclip running, waiting..."
    flock 3
fi

addtrap "echo -n > '$CROUTONLOCKDIR/clip' 2>/dev/null"

(
    # This subshell handles USR1 signals from croutoncycle.
    # It prints a line when it receives a signal, or on VT change (we are able
    # to filter out duplicate notifications).

    # Start croutonwebsocket here to give "wait" something to wait for
    croutonwebsocket &
    addtrap "kill $! 2>/dev/null"

    waitwebsocket

    # Update on VT change (if user types Ctrl-Alt instead of Ctrl-Alt-Shift)
    if hash croutonvtmonitor 2>/dev/null; then
       croutonvtmonitor &
       addtrap "kill $! 2>/dev/null"
    fi

    trap "echo 'USR1'" USR1

    # Set the PID of this subshell after the trap is in place
    sh -c 'echo -n "$PPID"' > "$CROUTONLOCKDIR/clip"

    # Force an update when started.
    echo "Force"

    # Wait until all the children have terminated (gets interrupted on signal,
    # which gives handlers a chance to run)
    while ! wait; do
        :
    done
) | (
    # Do not hold the lock in this subshell and children (especially xsel)
    exec 3>/dev/null
    while read -r line; do
        display="`croutoncycle display`"
        copyclip "$display"
    done
)

exit 1


================================================
FILE: chroot-bin/croutoncycle
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

. "$(dirname "$0")/../installer/functions"

USAGE="${0##*/} next|prev|cros|list|#
Cycles through running graphical chroots.
    next: switch to the next display
    prev: switch to the previous display
    cros: switch directly to Chromium OS
    list: list all of the active displays and the associated chroot name
    #: switch to the nth item in the list, zero-indexed
    :#: switch directly to the chroot owning the specified display number"

# Undocumented:
#   display: return display associated with current window
#            (used from croutonclip):
#     - cros: Chromium OS
#     - :0: Chromium OS X11 display (non-aura window)
#     - :1-9: chroot displays
#   s<num>: informs of a Chromium OS window change (called from extension):
#     - cros: any Chromium OS window
#     - :1-9: kiwi window: X11 display number
#   force [command]: Force switching display, even if it does not appear
#                    to be necessary.

force=''
if [ "${1#[Ff]}" != "$1" ]; then
    force='y'
    shift
fi

case "$1" in
[Ll]*) cmd='l';;
[Dd]*) cmd='d';;
[Cc]*) cmd='0';;
[Pp]*) cmd='p';;
[Nn]*) cmd='n';;
[Ss]*) cmd='s' disp="${1#s}";;
:*) cmd="${1%%.*}"; cmd=":$((${cmd#:}))";;
[0-9]*) cmd="$(($1))";;
*) error 2 "$USAGE";;
esac

# Returns the chroot name of an X11 display specified in $1 on stdout
getname() {
    local name='Unknown'
    if [ "$1" = 'cros' ]; then
        if [ -r '/var/host/lsb-release' ]; then
            name="$(awk -F= '/_RELEASE_NAME=/{print $2}' \
                            '/var/host/lsb-release')"
        fi
    else
        local crname="$(DISPLAY=":${1#:}" xprop -root CROUTON_NAME 2>/dev/null)"
        if [ "${crname%\"}" != "$crname" ]; then
            crname="${crname%\"}"
            name="${crname#*\"}"
        fi
    fi
    echo "$name"
}

# Only let one instance run at a time to avoid nasty race conditions
# Make sure to release this before running websocket commands
mkdir -m 775 -p "$CROUTONLOCKDIR"
exec 3>"$CROUTONLOCKDIR/cycle"
chmod -Rf g+rwX "$CROUTONLOCKDIR" || true
chgrp -Rf crouton "$CROUTONLOCKDIR" || true
flock 3

# set display command from extension
if [ "$cmd" = 's' ]; then
    echo "$disp" > "$CRIATDISPLAY"
    if [ -s "$CROUTONLOCKDIR/clip" ]; then
        kill -USR1 "$(cat "$CROUTONLOCKDIR/clip")" || true
    fi
    exit 0
fi

# Ensure environment sanity
export XAUTHORITY=''

# Set to y if there is any xiwi instance running
xiwiactive=''

# Prepare display list for easier looping
displist='cros'
for disp in /tmp/.X*-lock; do
    disp="${disp#*X}"
    disp=":${disp%-lock}"
    # Only add VT-based and xiwi-based chroots here (that excludes Xephyr)
    if [ "$disp" = ':0' ]; then
        continue
    elif DISPLAY="$disp" xprop -root 'XFree86_VT' 2>/dev/null \
            | grep -q 'INTEGER'; then
        displist="$displist $disp"
    elif DISPLAY="$disp" xprop -root 'CROUTON_XMETHOD' 2>/dev/null \
            | grep -q '= "xiwi'; then
        displist="$displist $disp"
        xiwiactive='y'
    fi
done

# Set to the freon display owner if freon is used
freonowner=''
if [ ! -f "/sys/class/tty/tty0/active" ]; then
    if [ -f "$CROUTONLOCKDIR/display" ]; then
        read -r freonowner < "$CROUTONLOCKDIR/display"
    fi
    freonowner="${freonowner:-0}"
    tty=''
else
    tty="$(cat '/sys/class/tty/tty0/active')"
fi

# Determine current display
if [ "$freonowner" = 0 -o "$tty" = 'tty1' ]; then
    # In Chromium OS or xiwi chroot
    curdisp='cros'
    if [ -n "$xiwiactive" -a -s "$CRIATDISPLAY" ]; then
        kiwidisp="$(cat "$CRIATDISPLAY")"
        if [ "${kiwidisp#:[0-9]}" != "$kiwidisp" ]; then
            curdisp="$kiwidisp"
        fi
    fi
elif [ -z "$freonowner" ]; then
    # Poll the displays to figure out which one owns this VT
    curdisp="$tty"
    for disp in $displist; do
        if [ "$disp" = 'cros' ]; then
            continue
        fi
        if DISPLAY="$disp" xprop -root 'XFree86_VT' 2>/dev/null \
                | grep -q " ${tty#tty}\$"; then
            curdisp="$disp"
            break
        fi
    done
else
    # Match the pid to the current freon owner
    for lockfile in /tmp/.X*-lock; do
        if grep -q "\\<$freonowner$" "$lockfile"; then
            curdisp="${lockfile#*X}"
            curdisp=":${curdisp%%-*}"
        fi
    done
fi

# List the displays if requested
if [ "$cmd" = 'l' -o "$cmd" = 'd' ]; then
    for disp in $displist; do
        active=' '
        if [ "$disp" = "$curdisp" ]; then
            active='*'
            if [ "$cmd" = 'd' ]; then
                echo "$disp"
                exit 0
            fi
        fi

        if [ "$cmd" = 'l' ]; then
            echo -n "$disp$active "
            getname "$disp"
        fi
    done
    exit 0
fi

# Determine the target display
if [ -n "${cmd#[pn]}" ]; then
    if [ "${cmd#:}" != "$cmd" ]; then
        destdisp="$cmd"
    else
        i=0
        destdisp=''
        for disp in $displist; do
            if [ "$i" -eq "$cmd" ]; then
                destdisp="$disp"
                break
            fi
            i="$((i+1))"
        done
        if [ -z "$destdisp" ]; then
            error 2 "Display number out of range."
        fi
    fi
elif [ "$cmd" = 'p' ]; then
    destdisp="${displist##* }"
    for disp in $displist; do
        if [ "$disp" = "$curdisp" ]; then
            break
        fi
        destdisp="$disp"
    done
elif [ "$cmd" = 'n' ]; then
    destdisp=''
    for disp in $displist; do
        if [ -n "$destdisp" ]; then
            destdisp="$disp"
            break
        elif [ "$disp" = "$curdisp" ]; then
            destdisp="${displist%% *}"
        fi
    done
    if [ -z "$destdisp" ]; then
        destdisp="${displist%% *}"
    fi
else
    error 3 "Bad command $cmd."
fi

# No-op on no-op
if [ "$destdisp" = "$curdisp" -a -z "$force" ]; then
    exit 0
fi

# Determine if the target display is on a VT
if [ "${destdisp#:}" = "$destdisp" ]; then
    if [ "$destdisp" != 'cros' ]; then
        error 3 "Bad destination display $destdisp."
    fi
    if [ -z "$freonowner" ]; then
        export DISPLAY=":0"
        export XAUTHORITY='/var/host/Xauthority'
        if [ "$tty" != 'tty1' ]; then
            sudo -n chvt 1
            sleep .1
        fi
    elif [ "${freonowner:-0}" != 0 ]; then
        kill -USR1 "$freonowner"
    fi

    if [ -n "$xiwiactive" ]; then
        # Release the croutoncycle lock
        exec 3>&-
        STATUS="$(echo -n "Xcros" | websocketcommand)"
        if [ "$STATUS" != 'XOK' ]; then
            error 1 "${STATUS#?}"
        fi
    fi
else
    export DISPLAY="$destdisp"
    xmethod="$(xprop -root 'CROUTON_XMETHOD' 2>/dev/null \
               | sed -n 's/^.*\"\(.*\)\"/\1/p')"
    if [ "${xmethod%%-*}" = 'xiwi' ]; then
        if [ -z "$freonowner" -a "$tty" != 'tty1' ]; then
            sudo -n chvt 1
            sleep .1
        elif [ "${freonowner:-0}" != 0 ]; then
            kill -USR1 "$freonowner"
        fi
        # Release the croutoncycle lock
        exec 3>&-
        STATUS="$(echo -n "X${destdisp} ${xmethod#*-}" | websocketcommand)"
        if [ "$STATUS" != 'XOK' ]; then
            error 1 "${STATUS#?}"
        fi
    elif [ -z "$freonowner" ]; then
        dest="$(xprop -root 'XFree86_VT' 2>/dev/null)"
        dest="${dest##* }"
        if [ "${dest#[1-9]}" = "$dest" ]; then
            dest='1'
        fi
        # When the destination we are changing to is using fbdev driver in X, we
        # need first a change to vt 2, else only the session switches and the
        # display will be stuck on the old vt.
        sudo -n chvt 2
        sudo -n chvt "$dest"
    else
        dest="/tmp/.X${destdisp#:}-lock"
        if [ -f "$dest" ]; then
            # Trigger the target before releasing the current owner
            kill -USR1 "$(cat "/tmp/.X${destdisp#:}-lock")"
        fi
        if [ "${freonowner:-0}" != 0 ]; then
            kill -USR1 "$freonowner"
        fi
    fi
fi

if [ -s "$CROUTONLOCKDIR/clip" ]; then
    kill -USR1 "$(cat "$CROUTONLOCKDIR/clip")" || true
fi

# Wait a flip and then refresh the display for good measure
if [ -n "$DISPLAY" ] && hash xrefresh 2>/dev/null; then
    sleep .1
    xrefresh
fi

exit 0


================================================
FILE: chroot-bin/croutonfindnacl
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# croutonfindnacl address signature ["pids"]
#
# This script is used by croutonfbserver to find the nacl_helper process it is
# connected to, and, in particular, the file descriptor corresponding to the shm
# memory that the nacl_helper process shares with Chromium.
#
# - address:   NaCl-space address of the shared memory (hexadecimal). We assume
#              that the NaCl/hardware memory mapping conserves the address,
#              possibly with a prefix in the MSBs.
# - signature: random 8 byte pattern (hexadecimal, machine byte order) that is
#              written at the beginning of the shared buffer by the NaCl
#              application. The first 8 bytes of each candidate buffer is read,
#              guaranteeing that the correct buffer is returned.
# - pids:      (normally ununsed, defaults to all processes named "nacl_helper")
#              Space-separated list of PIDs to scan for.
#
# On success, prints "pid:filename" and exits with code 0.
# On error (shm not found, invalid parameters), exits with code >0.

set -e

VERBOSE=

if [ "$#" -lt 2 -o "$#" -gt 3 ]; then
    echo "Invalid parameters"
    exit 2
fi

ADDRESS="$1"
PATTERN="$2"
PIDS="${3:-"`pgrep nacl_helper`"}"

MATCH=""

# Iterate over all NaCl helper processes
for pid in $PIDS; do
    [ -n "$VERBOSE" ] && echo "pid:$pid" 1>&2
    # Find candidate mappings
    file="`awk '$1 ~ /^[0-9a-f]*'"$ADDRESS"'-/ && $2 == "rw-s" \
             && $6 ~ /\/shm\/\.(com\.google\.Chrome|org\.chromium\.Chromium)/ \
                   { print $6 }
    ' "/proc/$pid/maps"`"
    [ -n "$VERBOSE" ] && echo "file:$file" 1>&2
    if [ -z "$file" ]; then
        continue
    fi

    # Iterate over mappings, and check signature
    for fd in "/proc/$pid/fd"/*; do
        link="$(readlink -- "$fd" || true)"
        link="${link% (deleted)}"
        if [ "$link" = "$file" ]; then
            # Check if signature matches
            pattern="`od -An -t x1 -N8 "$fd" | tr -d ' '`"
            [ -n "$VERBOSE" ] && echo "FD:$fd ($pattern)" 1>&2
            if [ "$pattern" = "$PATTERN" ]; then
                # Second match? This should never happen
                if [ -n "$MATCH" ]; then
                    echo -n "-1:ambiguous"
                    exit 1
                fi
                MATCH="$pid:$fd"
            fi
        fi
    done
done

if [ -n "$MATCH" ]; then
    echo -n "$MATCH"
    exit 0
else
    echo -n "-1:no match"
    exit 1
fi


================================================
FILE: chroot-bin/croutonnotify
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

USAGE="${0##*/} -j
${0##*/} -t title [-m message] [-d] [-i icon] [-I id]
Raises a notification in Chromium OS (requires crouton extension).

When -j is specified, reads JSON data from stdin, in the format required
by chrome.notifications API, with 2 additional fields, \"crouton_id\" and
\"crouton_display\", corresponding respectively to the notification id, and the
display to switch to when the notification is clicked (croutoncycle parameter).

Otherwise, constructs a \"basic\" notification with the requested fields.

Options:
    -j       Read JSON data from stdin (see example below)
    -t       Title to display (chrome.notifications field: \"title\")
    -m       Message to display (chrome.notifications field: \"message\")
    -d       Switch to display in environment variable DISPLAY ($DISPLAY) when
             the notification is clicked. Default: Do not switch display.
    -i       Small icon to display on the left of the notification
             (chrome.notifications field: \"iconUrl\")
    -I       ID to pass to chrome.notifications.create: only the last
             notification with a given ID is shown.
             Default: Display a new notification.

Example JSON data:
"'{
  "type": "basic",
  "title": "Primary Title",
  "message": "Primary message to display",
  "crouton_display": ":1",
  "iconUrl": "data:image/png;base64,<base64 encoded png data>"
}'

. "$(dirname "$0")/../installer/functions"

SWITCHDISPLAY=""
MESSAGE=""
TITLE=""
ID=""
ICON=""
JSON=""

# Process arguments
while getopts 'di:I:jm:t:' f; do
    case "$f" in
    d) SWITCHDISPLAY="$DISPLAY";;
    i) ICON="$OPTARG";;
    I) ID="$OPTARG";;
    j) JSON="y";;
    m) MESSAGE="$OPTARG";;
    t) TITLE="$OPTARG";;
    \?) error 2 "$USAGE";;
    esac
done

# No extra parameters, -j precludes other parameters, and at least title
# must be specified (or -j)
if [ "$#" != "$((OPTIND-1))" ] ||
        [ "$JSON" = 'y' -a -n "$SWITCHDISPLAY$ICON$ID$MESSAGE$TITLE" ] ||
        [ -z "$JSON$TITLE" ]; then
    error 2 "$USAGE"
fi

if [ -n "$ICON" ] && [ ! -r "$ICON" -o ! -f "$ICON" ]; then
    error 2 "Cannot open $ICON."
fi

# Escape json string (backslash and double quotes)
json_escape() {
    echo -n "$1" | sed -e 's/\\/\\u005C/g;s/"/\\u0022/g;2~1s/^/\\u000A/;' \
                 | tr -d '\n'
}

STATUS="$({
    echo -n "N"
    if [ -z "$JSON" ]; then
        echo -n '{
            "type": "basic",
            "title": "'"$(json_escape "$TITLE")"'",
            "message": "'"$(json_escape "$MESSAGE")"'",
            "crouton_display": "'"$(json_escape "$SWITCHDISPLAY")"'",
            "crouton_id": "'"$(json_escape "$ID")"'"'
        if [ -n "$ICON" ]; then
            ext="${ICON##*.}"
            if grep -Iq '<svg' "$ICON"; then
                ext='svg+xml'
            fi
            echo -n ', "iconUrl": "data:image/'"${ext:-png}"';base64,'
            base64 -w 0 "$ICON"
            echo '"'
        fi
        echo -n '}'
    else
        cat
    fi
} | websocketcommand)"

if [ "$STATUS" != 'NOK' ]; then
    error 1 "${STATUS#?}"
fi


================================================
FILE: chroot-bin/croutonpowerd
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

USAGE="${0##*/} -p|--poke|-deactivate|--daemon
${0##*/} -i|--inhibit [command [params ...]]
Interfaces with Chromium OS's powerd to prevent the system from suspending.

Passes parameters to the appropriate command if called as xscreensaver-command
or gnome-screensaver-command.

Options:
    -i --inhibit           Inhibits powerd for the duration of the command, or
                           forever if no command is specified.
    -p --poke -deactivate  Pings powerd to prevent activation.
    --suspend              Switches to Chromium OS and triggers a suspend.
    --daemon               Enters daemon mode where idleness and screensaver
                           inhibition are passed on to Chromium OS's powerd."

INHIBITSLEEP='30'
DAEMONSLEEP='15'

# Common functions
. "`dirname "$0"`/../installer/functions"

# Check if we need to pass through to another command
EXEC="${0##*/}"
case "$EXEC" in
gnome-screensaver-command|xscreensaver-command) EXEC="/usr/bin/$EXEC";;
*) EXEC='';;
esac

# Check what command we need to run, or immediately pass through if unrecognized
case "$1" in
-i|--inhibit) CMD='i';;
-p|--poke|-deactivate) CMD='p';;
--suspend) CMD='s';;
--daemon) CMD='d';;
*)  if [ -z "$EXEC" ]; then
        echo "$USAGE" 1>&2
        exit 2
    fi
    exec "$EXEC" "$@";;
esac

hostdbus=''
if hash host-dbus 2>/dev/null; then
    hostdbus='host-dbus'
fi

pingpowerd() {
    $hostdbus dbus-send --system --dest=org.chromium.PowerManager \
                        --type=method_call /org/chromium/PowerManager \
                        org.chromium.PowerManager.HandleUserActivity \
                        int32:0 || true
}

if [ "$CMD" = 'p' ]; then
    # Ping
    pingpowerd
    exec "${EXEC:-"true"}" "$@"
elif [ "$CMD" = 'i' ]; then
    # Inhibit
    while pingpowerd; do
        sleep "$INHIBITSLEEP"
    done &
    pid=$!
    addtrap "kill '$pid' 2>/dev/null"
    if [ -n "$EXEC" ]; then
        "$EXEC" "$@"
    elif [ -n "$2" ]; then
        shift
        "$@"
    else
        wait $pid
    fi
elif [ -n "$EXEC" ]; then
    exec "$EXEC" "$@"
elif [ "$CMD" = 's' ]; then
    if hash croutoncycle 2>/dev/null; then
        croutoncycle cros
    fi
    $hostdbus dbus-send --system --dest=org.chromium.PowerManager \
                        --type=method_call /org/chromium/PowerManager \
                        org.chromium.PowerManager.RequestSuspend || true
elif [ "$CMD" = 'd' ]; then
    if [ -z "$DISPLAY" ]; then
        error 1 'Cannot launch daemon: $DISPLAY not specified.'
    fi

    # Daemon
    xdgs='/usr/bin/xdg-screensaver'
    xi2pid=''

    # Send pings to powerd at regular intervals, if the user is active (i.e.
    # there are input events), or if the screensaver is disabled.
    # For performance reason, we probably do not want to monitor every single
    # X input events. Therefore, we start a subshell that pings powerd upon
    # receiving a single event, then quits.
    # Every $DAEMONSLEEP seconds we check if that subshell if alive, and
    # restart it if necessary. This means that we miss events during up to 
    # $DAEMONSLEEP seconds, and, if powerd timeout is X seconds, then the
    # screen may already dim after X-DAEMONSLEEP seconds of inactivity. This is
    # not noticeable if DAEMONSLEEP is much smaller than X (usually, X=300s).

    while sleep "$DAEMONSLEEP"; do
        if [ "`"$xdgs" status 2>/dev/null`" = 'disabled' ]; then
            # Screensaver disabled: ping
            pingpowerd
        elif [ -z "$xi2pid" ] || ! kill -0 "$xi2pid" 2>/dev/null; then
            # croutonxi2event subshell is not running

            if [ -n "$xi2pid" ]; then
                # Fail if return status from process != 0: wait returns the exit
                # status of the child, and this shell exits on error (-e)
                wait $xi2pid
            fi

            # Wait for input event, then ping immediately
            ( croutonxi2event -1 >/dev/null 2>&1 && pingpowerd ) &
            xi2pid=$!
        fi
    done
fi

exit 0


================================================
FILE: chroot-bin/croutontriggerd
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Monitors keyboard events for the crouton switch command.

. "`dirname "$0"`/../installer/functions"

# hexdump output format variables
if getconf LONG_BIT | grep -q 32; then
    HEXDUMP_FMT='2/4 "%u 0 " " " 2/2 "%u " " " 1/4 "%u " "\n"'
else
    HEXDUMP_FMT='4/4 "%u " " " 2/2 "%u " " " 1/4 "%u " "\n"'
fi
SECONDS_LO='$1'
SECONDS_HI='$2'
USECONDS_LO='$3'
USECONDS_HI='$4'
TYPE='$5'
KEY='$6'
STATE='$7'

# constants
TYPE_EV_KEY=1
STATE_DOWN=1
STATE_UP=0
KEY_LEFTCTRL=29
KEY_LEFTALT=56
KEY_LEFTSHIFT=42
KEY_RIGHTCTRL=97
KEY_RIGHTALT=100
KEY_RIGHTSHIFT=54
KEY_F1=59
KEY_F2=60

EVENT_DEV_POLL=15

# Only one at a time. xbindkeys lockfile is for legacy compatibility
mkdir -m 775 -p "$CROUTONLOCKDIR"
exec 3>>"$CROUTONLOCKDIR/xbindkeys"
chmod -Rf g+rwX "$CROUTONLOCKDIR" || true
chgrp -Rf crouton "$CROUTONLOCKDIR" || true
if ! flock -n 3; then
    echo "Another instance of ${0##*/} running, waiting..."
    flock 3
fi

# Reset event variables to handle strange environments
unset `set | grep -o '^event[0-9]*'` 2>/dev/null || true

# Poll for new event files and dump the output
while :; do
    # Clean up old hexdumps and start new ones
    for event in `set | grep -o '^event[0-9]*'` /dev/input/event*; do
        # Check if the event file is already monitored
        eval "pid=\"\${${event##*/}:-0}\""
        if [ "$pid" != 0 ]; then
            # Check if it's still running
            if kill -0 "$pid" 2>/dev/null; then
                continue
            fi
            wait "$pid" || true
        fi
        # Clean up old variables
        if [ "${event#/}" = "$event" ]; then
            unset "$event"
        else
            # Read in the event files and split into input_event fields
            stdbuf -oL hexdump -e "$HEXDUMP_FMT" "$event" &
            eval "${event##*/}='$!'"
        fi
    done
    # Avoid picking up the event variable
    unset event
    # Kill all event daemons
    pids="`set | sed -n 's/^event[0-9]*=.\(.*\).$/\1/p' | tr '\n' ' '`"
    settrap "kill $pids 2>/dev/null;"
    # Wait for next poll
    sleep "$EVENT_DEV_POLL"
done | unbuffered_awk "
    function update() {
        c = lc || rc; s = ls || rs; a = la || ra
        if (!cmd && c && s && a && p) {
            cmd = \"p\"
        } else if (!cmd && c && s && a && n) {
            cmd = \"n\"
        } else if (cmd && !c && !s && !a && !p && !n) {
            system(\"/usr/local/bin/croutoncycle \" cmd)
            cmd = \"\"
        }
    }
    $TYPE == $TYPE_EV_KEY && $KEY == $KEY_LEFTCTRL   { lc = $STATE; update() }
    $TYPE == $TYPE_EV_KEY && $KEY == $KEY_LEFTSHIFT  { ls = $STATE; update() }
    $TYPE == $TYPE_EV_KEY && $KEY == $KEY_LEFTALT    { la = $STATE; update() }
    $TYPE == $TYPE_EV_KEY && $KEY == $KEY_RIGHTCTRL  { rc = $STATE; update() }
    $TYPE == $TYPE_EV_KEY && $KEY == $KEY_RIGHTSHIFT { rs = $STATE; update() }
    $TYPE == $TYPE_EV_KEY && $KEY == $KEY_RIGHTALT   { ra = $STATE; update() }
    $TYPE == $TYPE_EV_KEY && $KEY == $KEY_F1         {  p = $STATE; update() }
    $TYPE == $TYPE_EV_KEY && $KEY == $KEY_F2         {  n = $STATE; update() }
"


================================================
FILE: chroot-bin/croutonurlhandler
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

NEWTABPAGE='chrome://newtab'
USAGE="${0##*/} [-n] [URL]
Open an URL in Chromium OS (requires crouton extension).
If no URL is specified, opens $NEWTABPAGE instead.
Switches back to Chromium OS unless -n is specified."

. "`dirname "$0"`/../installer/functions"

noswitch=''
if [ "$1" = '-n' ]; then
    noswitch='y'
    shift
fi

if [ -z "$*" ]; then
    set -- "$NEWTABPAGE"
elif [ "$1" = '-h' -o "$1" = '--help' ]; then
    error 0 "$USAGE"
fi

STATUS="`echo -n U"$*" | websocketcommand`"

if [ "$STATUS" != 'UOK' ]; then
    error 1 "${STATUS#?}"
fi

if [ -z "$noswitch" ]; then
    croutoncycle cros
fi


================================================
FILE: chroot-bin/croutonversion
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

VERSION='unknown'
RELEASE='unknown'
ARCH='unknown'

APPLICATION="${0##*/}"
CHANGES=''
DOWNLOAD=''
UPDATES=''

BRANCH="${VERSION##*~}"
BRANCH="${BRANCH%%:*}"
COMMIT="${VERSION##*:}"
CHANGESURL="https://github.com/dnschneid/crouton/compare/$COMMIT..."
INSTALLER="crouton-$BRANCH"
INSTALLER="${INSTALLER%-master}"
CROUTONURL="https://github.com/dnschneid/crouton/raw/releases/$INSTALLER"
DEST="$HOME/Downloads/$INSTALLER"

USAGE="$APPLICATION [options]

Reports the version of crouton installed, checks if updates are available,
and/or launches a changelog.

If no options are specified, outputs crouton version information to STDOUT.

Options:
    -a       Prints the architecture of this chroot to stdout.
    -c       Launches a browser to view the list of changes.
             If -u is specified, only launches if a newer version exists.
    -d       Downloads the latest version of crouton to the location specified.
             If -u is specified, only downloads if the version is newer.
    -f FILE  Changes the destination of the downloaded crouton.
             Default: $DEST
    -h       Prints out usage.
    -r       Prints the release of this chroot to stdout.
    -u       Checks for updates, and prints out the updated version number."


# Function to exit with exit code $1, spitting out message $@ to stderr
error() {
    local ecode="$1"
    shift
    echo "$*" 1>&2
    exit "$ecode"
}

# Process arguments
while getopts 'acdf:ru' f; do
    case "$f" in
    a) echo "$ARCH"; exit 0;;
    c) CHANGES='y';;
    d) DOWNLOAD='y';;
    f) DEST="$OPTARG";;
    r) echo "$RELEASE"; exit 0;;
    u) UPDATES='y';;
    \?) error 2 "$USAGE";;
    esac
done

# No extra parameters
if [ "$#" != "$((OPTIND-1))" ]; then
    error 2 "$USAGE"
fi

# Print out version if nothing else specified
if [ -z "$CHANGES$DOWNLOAD$UPDATES" ]; then
    echo "crouton: version $VERSION"
    echo "release: $RELEASE"
    echo "architecture: $ARCH"
    xmethodfile='/etc/crouton/xmethod'
    if [ -r "$xmethodfile" ]; then
        echo "xmethod: `cat "$xmethodfile"`"
    fi
    targetfile='/etc/crouton/targets'
    if [ -r "$targetfile" ]; then
        echo "targets: `sed 's/^,//' "$targetfile"`"
    fi
    hostrel='/var/host/lsb-release'
    if [ -r "$hostrel" ]; then
        host="`awk -F= '/_RELEASE_DESCRIPTION=/{print $2}' "$hostrel"`"
    fi
    echo "host: version ${host:-unknown}"
    echo "kernel: $(uname -a)"
    freon="yes"
    if [ -f /sys/class/tty/tty0/active ]; then
        freon="no"
    fi
    echo "freon: $freon"
    exit 0
fi

# Print out version to stderr for info
echo "crouton: version $VERSION" 1>&2

latest=''
tmpdir=''
if [ -n "$UPDATES$DOWNLOAD" ]; then
    tmpdir="`mktemp -d --tmpdir=/tmp crouton.XXX`"
    trap "rm -rf --one-file-system '$tmpdir'" INT HUP 0
    echo "Retrieving latest version of $INSTALLER" 1>&2
    if ! wget "$CROUTONURL" -O "$tmpdir/$INSTALLER" 2>"$tmpdir/log"; then
        cat "$tmpdir/log" 1>&2
        echo "Failed to retrieve latest version of $INSTALLER" 1>&2
        exit 1
    fi
    latest="`awk -F"'" '/^VERSION=/{print $2;exit}' "$tmpdir/$INSTALLER"`"
fi

# Print out latest version number if requested
if [ -n "$UPDATES" ]; then
    echo "latest: version $latest"
elif [ -n "$latest" ]; then
    echo "latest: version $latest" 1>&2
fi

# Save latest version if requested
if [ -n "$DOWNLOAD" -a "$VERSION" != "$latest" ]; then
    echo "Saving latest version to $DEST" 1>&2
    mv -f "$tmpdir/$INSTALLER" "$DEST"
fi

# Launch changelog if requested
if [ -n "$CHANGES" -a "$VERSION" != "$latest" ]; then
    # Check if changelogs are available from this version / to this branch
    if ! wget "$CHANGESURL$BRANCH" -O/dev/full 2>&1 | grep -q '404 Not Found'; then
        CHANGESURL="$CHANGESURL$BRANCH"
    elif ! wget "${CHANGESURL}master" -O/dev/full 2>&1 | grep -q '404 Not Found'; then
        CHANGESURL="${CHANGESURL}master"
    else
        # Fall back on the main commit log
        CHANGESURL='https://github.com/dnschneid/crouton/commits/'
    fi
    # One of these will probably work...
    for x in exo-open gnome-open kde-open xdg-open \
             sensible-browser x-www-browser www-browser; do
        if hash "$x" 2>/dev/null; then
            browser="$x"
            break
        fi
    done
    if [ -z "$browser" ]; then
        error 2 "No browser found to view $CHANGESURL"
    fi
    # Launch the webpage
    if ! "$browser" "$CHANGESURL"; then
        error 1 "Failed to launch browser to view $CHANGESURL"
    fi
fi

exit 0


================================================
FILE: chroot-bin/croutonxinitrc-wrapper
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# xinitrc wrapper for crouton:
#  1. Runs crouton-specific commands
#  2. Runs the provided client (emulating xinit behaviour)
#  3. Runs crouton-specific commands before the server is destroyed

cmd=''
extraargs=''
binary=''
ret=0

# This part is a translation of what is found in xorg's xinit.c

if [ -z "$1" ] || [ "${1#[/.]}" = "$1" ]; then
    # No client parameter: find .xinitrc if possible, run xterm otherwise
    required=''

    if [ -n "$XINITRC" ]; then
        cmd="$XINITRC"
        required='y'
    elif [ -n "$HOME" ]; then
        cmd="$HOME/.xinitrc"
    fi

    if [ ! -e "$cmd" ]; then
        if [ -n "$required" ]; then
            echo "Warning, no client init file \"$cmd\"" 1>&2
        fi

        # If no client is given, use default command
        cmd="xterm"
        extraargs="-geometry +1+1 -n login"
        # Make sure xterm is executed directly: let sh resolve the path
        binary='y'
    fi
else
    cmd="$1"
    shift
fi

# Run crouton-specific commands:

# Show chroot specifics for troubleshooting
croutonversion 1>&2

if [ -z "$XMETHOD" ]; then
    if [ -f '/etc/crouton/xmethod' ]; then
        read -r XMETHOD _ < /etc/crouton/xmethod
        export XMETHOD
    else
        echo 'X11 backend not set.' 1>&2
        exit 1
    fi
fi
xmethodtype="${XMETHOD%%-*}"
xmethodargs="${XMETHOD#*-}"

# Record the name of the chroot in the root window properties
if [ -f '/etc/crouton/name' ] && hash xprop 2>/dev/null; then
    xprop -root -f CROUTON_NAME 8s -set CROUTON_NAME "`cat '/etc/crouton/name'`"
fi

# Record the crouton XMETHOD in the root window properties
xprop -root -f CROUTON_XMETHOD 8s -set CROUTON_XMETHOD "$XMETHOD"

# Launch the powerd poker daemon
croutonpowerd --daemon &

# Launch the clipboard synchronization daemon
if hash croutonclip 2>/dev/null; then
    croutonclip &
fi

# Launch system-wide trigger daemon
croutontriggerd &


# Apply the Chromebook keyboard map. Not needed for non-Freon xiwi.
if [ "$xmethodtype" != 'xiwi' -o ! -f "/sys/class/tty/tty0/active" ]; then
    # Apply the Chromebook keyboard map if installed.
    if [ -f '/usr/share/X11/xkb/compat/chromebook' ]; then
        setxkbmap -model chromebook
    fi
fi

# Input-related stuff is not needed for kiwi
if [ "$xmethodtype" != "xiwi" ]; then

    # Launch X-server-local key binding daemon
    xbindkeys -fg /etc/crouton/xbindkeysrc.scm

    # Launch touchegg if it is requested.
    toucheggconf='/etc/touchegg.conf'
    if [ -f "$toucheggconf" ]; then
        mkdir -p "$HOME/.config/touchegg"
        ln -sf "$toucheggconf" "$HOME/.config/touchegg/"
        touchegg 2>/dev/null &
    fi

    # Configure trackpad settings if needed
    if synclient >/dev/null 2>&1; then
        # Elan trackpads usually like these settings
        if grep -q 'Elan Touchpad' /sys/class/input/event*/device/name; then
            SYNCLIENT="FingerLow=1 FingerHigh=5 $SYNCLIENT"
        fi
        # Other special cases
        case "`awk -F= '/_RELEASE_BOARD=/{print $2}' '/var/host/lsb-release'`" in
            butterfly*|eve*|falco*)
                SYNCLIENT="FingerLow=1 FingerHigh=5 $SYNCLIENT";;
            parrot*|peppy*|wolf*)
                SYNCLIENT="FingerLow=5 FingerHigh=10 $SYNCLIENT";;
        esac
        if [ -n "$SYNCLIENT" ]; then
            synclient $SYNCLIENT
        fi
    fi
fi

# Crouton-in-a-tab: Start fbserver and launch display
if [ "$xmethodtype" = 'xiwi' ]; then
    # The extension sends evdev key codes: fix the keyboard mapping rules
    setxkbmap -rules evdev
    # Reapply xkb map: This fixes autorepeat mask in "xset q"
    xkbcomp "$DISPLAY" - | xkbcomp - "$DISPLAY" 2>/dev/null

    # Set resolution to a default 1024x768, this is important so that the DPI
    # looks reasonable when the WM/DE start.
    setres 1024 768 > /dev/null
    croutonfbserver "$DISPLAY" &

    try=1
    while ! croutoncycle force "$DISPLAY"; do
        echo "Cannot connect to extension, retrying..."
        if [ "$try" -ge 10 ]; then
            echo "\
Unable to start display, make sure the crouton extension is installed
and enabled, and up to date. Download from:
  https://chromewebstore.google.com/detail/crouton-integration/gcpneefbbnfalgjniomfjknbcgkbijom" 1>&2
            ret=1
            break
        fi
        sleep 1
        try="$((try+1))"
    done
    if [ "$ret" -eq 0 ]; then
        echo "Connected to extension, launched crouton in a window." 1>&2
    fi
fi

if [ "$xmethodtype" = "xorg" ]; then
    # Since Chromium 56.0.2923.0, Chromium tries to switch off the display when
    # switching VT (crbug.com/655770). For some unclear reason, running xrandr
    # forces the display to be back on, and this is not needed ever again
    # when switching VTs.
    # The loop tries to work around a race that is more likely on xenial
    try=1
    while xrandr --auto 2>&1 | grep . 1>&2; do
        echo "Kicking xrandr again" 1>&2
        if [ "$try" -ge 10 ]; then
            break
        fi
        sleep 1
        try="$((try+1))"
    done
fi

# Only run if no error occured before (e.g. cannot connect to extension)
if [ "$ret" -eq 0 ]; then
    # Shell is the leader of a process group, so signals sent to this process
    # are propagated to its children. We ignore signals in this process, but the
    # child handles them and exits. We use a no-op handler, as "" causes the
    # signal to be ignored in children as well (see NOTES in "man 2 sigaction"
    # for details). This process then runs exit commands, and terminates.
    trap "true" HUP INT TERM

    # Run the client itself if it is executable, otherwise run it in a shell.
    if [ -n "$binary" -o -x "$cmd" ]; then
        "$cmd" $extraargs "$@" || ret=$?
    else
        /bin/sh "$cmd" $extraargs "$@" || ret=$?
    fi

    trap - HUP INT TERM
fi

# Run crouton-specific commands before the server exits:

echo "Running exit commands..." 1>&2

exit "$ret"


================================================
FILE: chroot-bin/gnome-session-wrapper
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Provides a wrapper around gnome-session to allow gnome-session based
# desktop environments to work with crouton nicely

USAGE="${0##*/} [session]
A wrapper around gnome-session that can be passed to xinit.
Provide the session type in the DESKTOP_SESSION variable, 
or as an optional session argument.

Examples:
(launch GNOME from crosh with session in DESKTOP_SESSION)
DESKTOP_SESSION=gnome xinit /etc/X11/xinit/xinitrc ${0##*/}

(launch Unity from an xterm with session as an argument)
${0##*/} ubuntu"

export DESKTOP_SESSION="${DESKTOP_SESSION:-"$1"}"
export XDG_SESSION_TYPE="${XDG_SESSION_TYPE:-"x11"}"
export XDG_SESSION_CLASS="user"

SESSION='gnome-session'
CINNAMON_SESSION='cinnamon-session'

if [ -z "$DESKTOP_SESSION" ]; then
    echo "$USAGE" 1>&2
    exit 2
fi

# Cinnamon 2.0 and later uses its own fork of gnome-session
if [ "${DESKTOP_SESSION#cinnamon}" != "$DESKTOP_SESSION" ] && \
        hash "$CINNAMON_SESSION" 2>/dev/null; then
    SESSION="$CINNAMON_SESSION"
fi

SESSION_FILE="/usr/share/$SESSION/sessions/$DESKTOP_SESSION.session"
XDG_CURRENT_DESKTOP="$(awk -F "=" '/DesktopName/ {print $2}' "$SESSION_FILE")"
if [ -n "$XDG_CURRENT_DESKTOP" ]; then
    XDG_SESSION_DESKTOP="$XDG_CURRENT_DESKTOP"
    export XDG_CURRENT_DESKTOP XDG_SESSION_DESKTOP
fi

if [ -z "$DISPLAY" ]; then
    exec xinit /etc/X11/xinit/xinitrc "$0"
else
    exec "$SESSION" --session="$DESKTOP_SESSION"
fi


================================================
FILE: chroot-bin/host-dbus
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Either runs the specified command with the environment set to use the host's
# system dbus instance, or prints out the environment changes required.

export DBUS_SYSTEM_BUS_ADDRESS='unix:path=/var/host/dbus/system_bus_socket'
if [ "$#" = 0 ]; then
    echo "export DBUS_SYSTEM_BUS_ADDRESS='$DBUS_SYSTEM_BUS_ADDRESS'"
else
    exec "$@"
fi


================================================
FILE: chroot-bin/host-wayland
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Either runs the specified command with the environment set to use the host's
# wayland server, or prints out the environment changes required.

# If wayland-0 socket does not exit, no Chromium OS wayland server exist
if [ ! -S "/var/run/chrome/wayland-0" ]; then
    err="No Chromium OS Wayland server is available."
    if [ "$#" = 0 ]; then
        echo "echo '$err' 1>&2"
    else
        echo "$err" 1>&2
        exit 1
    fi
else
    export XDG_RUNTIME_DIR='/var/run/chrome'
    if [ "$#" = 0 ]; then
        echo "export XDG_RUNTIME_DIR='$XDG_RUNTIME_DIR'"
    else
        exec "$@"
    fi
fi


================================================
FILE: chroot-bin/setres
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Changes the resolution of the current display.
# If XMETHOD is xiwi, tries to create a new exact resolution, and change mode
# to that. If that fails (e.g. non-patched xorg-dummy), take the closest,
# smaller, available resolution in xrandr, and if no smaller resolution is
# available, pick the closest one.
# If XMETHOD is anything else, set a resolution from cvt output.
# In all cases, outputs the applied resolution.

set -e

if [ "$#" -lt 2 -o "$#" -gt 4 ]; then
    echo "USAGE: ${0##*/} x y [r [output]]" 1>&2
    exit 2
fi
x="$1"
y="$2"
r="${3:-60}"
o="${4}"
if [ -z "$o" ]; then
    o="`xrandr -q | awk 'x{print $1;exit}/^Screen 0/{x=1}'`"
fi

xmethod="`xprop -root 'CROUTON_XMETHOD' | sed -n 's/^.*\"\(.*\)\"/\1/p'`"

if [ "${xmethod%%-*}" != "xiwi" ]; then
    cvt "$x" "$y" "$r" | {
        read -r _
        read -r _ mode data
        mode="${mode#\"}"
        mode="${mode%\"}"
        xrandr --newmode "$mode" $data 2>/dev/null || true
        xrandr --addmode "$o" "$mode"
        xrandr --output "$o" --mode "$mode"
        echo "$mode"
    }
    exit 0
fi

# Replace mode $2 in output $1, with new data $3..$#
# Deletes the mode if $3 is not provided
replacemode() {
    local o="$1"
    local mode="$2"
    shift 2
    xrandr --delmode "$o" "$mode" 2>/dev/null || true
    xrandr --rmmode "$mode" 2>/dev/null || true
    if [ "$#" -gt 0 ]; then
        xrandr --newmode "$mode" "$@"
        xrandr --addmode "$o" "$mode"
    fi
}

# Try to change to arbitrary resolution
mhz="$((r*x*y/1000000))"
name="kiwi_${x}x${y}_${r}"

# Try to switch mode, if it already exists.
if xrandr --output "$o" --mode "$name" 2>/dev/null; then
    echo "${x}x${y}_${r}"
    exit 0
fi

# Add the new mode
xrandr --newmode "$name" $mhz $x $x $x $x $y $y $y $y
xrandr --addmode "$o" "$name"

# The next line fails on non-patched xorg-dummy
if xrandr --output "$o" --mode "$name"; then
    # Success: remove old modes
    others="`xrandr | sed -n 's/^.*\(kiwi[0-9x_]*\)[^*]*$/\1/p'`"
    for othername in $others; do
        xrandr --delmode "$o" "$othername" 2>/dev/null || true
        xrandr --rmmode "$othername" 2>/dev/null || true
    done
    echo "${x}x${y}_${r}"
    exit 0
else
    # Delete the new mode
    xrandr --delmode "$o" "$name" 2>/dev/null || true
    xrandr --rmmode "$name" 2>/dev/null || true
fi

# Probably xorg-dummy got overwritten. Recommend an update.
echo "Failed to set custom resolution. Update your chroot and try again." 1>&2
exit 1


================================================
FILE: chroot-bin/startgnome
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Launches GNOME; automatically falls back to gnome-panel

exec crouton-noroot gnome-session-wrapper gnome


================================================
FILE: chroot-bin/startunity
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Launches Unity; will fall back to Unity-2D on supported releases

# Ensure global app menus work.
export UBUNTU_MENUPROXY=1
export GTK_MODULES="unity-gtk-module"

exec crouton-noroot gnome-session-wrapper ubuntu


================================================
FILE: chroot-bin/volume
================================================
#!/bin/sh
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# This script uses amixer to present an interface similar to the brightness
# script for crouton.

set -e
set -u

DEFAULT_VOLUME_DELTA=5

APPLICATION="${0##*/}"
USAGE="$APPLICATION [set] [0-100]
$APPLICATION up|down [0-100]
$APPLICATION mute [set|unset|toggle]
$APPLICATION get [all|volume|mute]

This script changes the volume of the current output
device, as would changing it with the shortcut keys or
with the GUI in Chrome OS.

Shortcut invocations:
    $APPLICATION up     increases by $DEFAULT_VOLUME_DELTA
    $APPLICATION down   decreases by $DEFAULT_VOLUME_DELTA
    $APPLICATION mute   sets muted
    $APPLICATION 0-100  sets volume to given value
    $APPLICATION get    shortcut for get all
"
# The control which controls the current output.
ALSA_CONTROL="Master"

# Tiny sugar coating around amixer for common parameters.
_amixer() {
    amixer -Dcras "$@"
}
amixer_get_value() {
    # $1 is the control name to get the value for
    _amixer cget "name=$1" | sed -n \
        -e "/[[:space:]]\+:/s/.*=//p"
    #       ^              ^      ^ Print the line.
    #       ^              ^ Replace everything before the equal sign.
    #       ^ Search for the line with spaces and a colon (the value).
}

get_volume() {
    amixer_get_value "$ALSA_CONTROL Playback Volume"
}

set_volume() {
    local volume="$1"
    _amixer -q sset $ALSA_CONTROL "$volume"
}

get_is_muted() {
    # Get the alsa state of the control.
    local state="$(amixer_get_value "$ALSA_CONTROL Playback Switch")"

    # Muted is off (control is off)
    if [ "$state" = "on" ]; then
        # Is not muted, so is_muted is false
        return 1
    else
        # Is muted, so is_muted is true
        return 0
    fi
}

get_is_muted_as_text() {
    if get_is_muted; then
        echo "yes"
    else
        echo "no"
    fi
}

toggle_mute() {
    _amixer -q sset $ALSA_CONTROL toggle
}

mute() {
    _amixer -q sset $ALSA_CONTROL mute
}
unmute() {
    _amixer -q sset $ALSA_CONTROL unmute
}

relative_volume() {
    local delta="$1"

    # Check that this is integer-ish enough.
    if ! [ "$delta" -eq "$delta" ] 2>/dev/null; then
        error_help "Error: $APPLICATION <up|down> needs a number [0-100]"
        exit 1
    fi

    if get_is_muted; then
        if [ "$delta" -lt 0 ]; then
            set_volume 0
        fi
        unmute
    else
        # Is the volume going down or up?
        if [ "$delta" -lt 0 ]; then
            # Going down, we strip the leading minus sign,
            # And suffix the minus sign.
            set_volume "${delta#*-}-"
        else
            # Only suffix the plus sign.
            set_volume "${delta}+"
        fi
    fi
}

print_help() {
    echo "$USAGE"
}
error_help() {
    # Prints an error message and the usage to stderr
    [ $# -gt 0 ] && echo "$@" 1>&2
    print_help 1>&2
}

# Do a sanity check with amixer.
# An out of date crouton chroot might exhibit problems like:
#     amixer: Control cras element read error: Input/output error
# We cannot do it in _amixer since it's executed in a subshell and its value is
# used as a substitution.
if ! _amixer > /dev/null 2>&1; then
    echo "Failed to communicate with the audio server. Please update your chroot." 1>&2
    exit 2
fi

if [ $# -lt 1 ]; then
    error_help "Error: $APPLICATION needs at least a command."
    exit 1
fi

cmd="$1"
shift

case "$cmd" in
h*|-h*|--help)
    print_help
    ;;
up)
    relative_volume "${1:-$DEFAULT_VOLUME_DELTA}"
    ;;
down)
    relative_volume "-${1:-$DEFAULT_VOLUME_DELTA}"
    ;;
mute)
    action="${1-set}"
    case "$action" in
    toggle) toggle_mute ;;
    set) mute ;;
    unset) unmute ;;
    *)
        error_help "Invalid action: $action for mute."
        exit 1
        ;;
    esac
    ;;
set|[0-9]|[0-9][0-9]|100)
    amount="$cmd"
    # First, check that we received a value to set the volume to.
    if [ $# -eq 0 ] && [ "$cmd" = "set" ]; then
        error_help "Error: $APPLICATION set needs an amount to set."
        exit 1
    fi
    # The value /could/ have been a parameter or the command itself.
    if [ $# -gt 0 ]; then
        amount="$1"
        shift
    fi
    # Check that this is integer-ish enough.
    if ! [ "$amount" -eq "$amount" ] 2>/dev/null; then
        error_help "Error: $APPLICATION set needs a number [0-100]"
        exit 1
    fi
    set_volume "$amount"
    ;;
get)
    action="${1-all}"
    case "$action" in
    mute) get_is_muted_as_text ;;
    volume) get_volume ;;
    all)
        echo "Volume: $(get_volume)"
        echo "Muted: $(get_is_muted_as_text)"
        ;;
    *)
        error_help "Invalid action: $action for get."
        exit 1
        ;;
    esac
    ;;
*)
    error_help "Error: Unkown command $cmd"
    exit 1
    ;;
esac


================================================
FILE: chroot-bin/xinit
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Adds a :# to the xinit command line, where # is the first available display
# number. Also adds the -- to the command line and references the global
# xserverrc if it isn't already there.  By putting this in /usr/local/bin, PATH
# will prefer it and scripts that call xinit will automagically work.

xserverrc='/etc/X11/xinit/xserverrc'
dash='--'
for arg in "$@"; do
    if [ -z "$dash" ]; then
        # Check if there's a xserverrc specified.
        if [ "${arg#/}" != "$arg" ]; then
            xserverrc=''
        fi
        break
    elif [ "$arg" = '--' ]; then
        dash=
    fi
done

# Never use display :0 (confusing if aura does not use X11)
disp=1
while [ -f "/tmp/.X$disp-lock" ]; do
    disp=$((disp+1))
done

# If possible, switch to VT1 to avoid strangeness when launching from VT2
chvt 1 2>/dev/null || true

exec /usr/bin/xinit /usr/local/bin/croutonxinitrc-wrapper "$@" $dash $xserverrc ":$disp"


================================================
FILE: chroot-bin/xiwi
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Runs the specified X11 application in its own X server in Chromium OS.

USAGE="Usage: ${0##*/} [-f] [-F|-T] APPLICATION [PARAMETERS ...]
Launches a windowed session in Chromium OS for any graphical application.
Applications launched in this way show in independent windows or tabs.
All parameters are passed to the specified application.

By default, the app is launched in a window.

Options:
    -F          Launch the APPLICATION full-screen.
    -T          Launch the APPLICATION in a tab.
    -f          Prevent ${0##*/} from quitting automatically. (see NOTE below)

NOTE:
${0##*/} will normally close when the application returns. Some gui applications
fork before or during normal operation, which can confuse ${0##*/} and cause it to
quit prematurely. If your application does not have a parameter that prevents
it from forking, and crouton is unable to automatically detect the fork, you can
use -f to prevent ${0##*/} from quitting automatically.
${0##*/} will quit if you close the Chromium OS window when nothing is displayed.

A default window manager will full-screen all windows, unless APPLICATION begins
with 'start' or is 'xinit'. You can cycle through multiple windows inside the
application via Ctrl-Alt-Tab/Ctrl-Alt-Shift-Tab, or close them via
Ctrl-Alt-Shift-Escape.  If APPLICATION begins with 'start' but you still want to
use the default window manager, specify the full path of the application."

. "`dirname "$0"`/../installer/functions"
xiwicmd="`readlink -f -- "$0"`"
OPTSTRING='FfTt'

if [ "$#" = 0 ]; then
    error 2 "$USAGE"
elif [ "$1" = '/' ]; then
    shift 1
    foreground=''
    while getopts "$OPTSTRING" f; do
        case "$f" in
        f) foreground='y';;
        t|T|F) :;;
        \?) error 2 "$USAGE";;
        esac
    done
    shift "$((OPTIND-1))"
    xsetroot -cursor_name left_ptr
    if [ "$1" != 'xinit' -a "${1#start}" = "$1" ]; then
        i3 -c "/etc/crouton/xiwi.conf" &
        # Wait for i3 to launch
        xprop -spy -root | grep -q _NET_ACTIVE_WINDOW
        # Launch the window title monitoring daemon
        # _NET_ACTIVE_WINDOW is more reliable than _NET_CLIENT_LIST_STACKING for
        # keeping track of the topmost window.
        xprop -spy -notype -root 0i ' $0\n' '_NET_ACTIVE_WINDOW' 2>/dev/null | {
            name="`cat /etc/crouton/name`"
            monpid=''
            monwid=''
            while read _ wid; do
                if [ "$wid" = "$monwid" ]; then
                    continue
                fi
                if [ -n "$monpid" ]; then
                    kill "$monpid" 2>/dev/null
                fi
                monwid="$wid"
                (xprop -spy -notype -id "$wid" 'WM_NAME' 2>/dev/null || echo) \
                    | while read _ title; do
                        title="${title%\"}"
                        xprop -root -f CROUTON_NAME 8s -set CROUTON_NAME \
                            "$name/$1${title:+": "}${title#*\"}"
                        {
                            echo -n 'C'
                            croutoncycle l
                        } | websocketcommand >/dev/null
                    done &
                monpid="$!"
            done
            if [ -n "$monpid" ]; then
                kill "$monpid" 2>/dev/null
            fi
        } &
        # Launch user init scripts
        if [ -f "$HOME/.xiwirc" ]; then
            /bin/sh "$HOME/.xiwirc" || true
        fi
    fi
    starttime="$(date +%s)"
    "$@"
    endtime="$(date +%s)"
    if [ -n "$foreground" -o "$(($endtime-$starttime))" -le 2 ]; then
        xprop -spy -notype -root 0i ' $0\n' 'CROUTON_CONNECTED' \
            | while read _ connected; do
                if [ "$connected" != 0 ]; then
                    continue
                fi
                # _NET_CLIENT_LIST_STACKING is more reliable than
                # _NET_ACTIVE_WINDOW for detecting when no windows exist
                if ! xprop -notype -root '_NET_CLIENT_LIST_STACKING' \
                            | grep -q '0x'; then
                    kill "$$"
                    break
                fi
            done
    fi
else
    export XMETHOD='xiwi-window'
    while getopts "$OPTSTRING" f; do
        case "$f" in
        f) :;;
        F) export XMETHOD='xiwi-fullscreen';;
        t|T) export XMETHOD='xiwi-tab';;
        \?) error 2 "$USAGE";;
        esac
    done
    eval "exe=\"\$$OPTIND\""
    if ! hash "$exe" 2>/dev/null; then
        error 2 "${0##*/}: $exe: not found"
    fi
    exec /usr/local/bin/xinit "$xiwicmd" / "$@"
fi


================================================
FILE: chroot-etc/kodi-cycle.py
================================================
#!/usr/bin/env python
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Python script to call croutoncycle. This is needed to let the 
# hotkeys ctr-shift-alt F1/F2 work when kodi is in fullscreen.
import subprocess
import sys

if len(sys.argv) == 2 and sys.argv[1] in ("prev", "next"):
  exitcode = subprocess.call(["/usr/local/bin/croutoncycle", sys.argv[1]])
else:
  sys.stderr.write("Usage: %s prev|next\n" % str(sys.argv[0]))
  exitcode = 2
sys.exit(exitcode)


================================================
FILE: chroot-etc/kodi-keyboard.xml
================================================
<!-- Copyright (c) 2016 The crouton Authors. All rights reserved.           -->
<!-- Use of this source code is governed by a BSD-style license that can be -->
<!-- found in the LICENSE file.                                             -->
<!--                                                                        -->
<!-- Keymappings kodi for ctr-shift-alt F1/F2 to switch between chroots     -->
<keymap>
  <global>
    <keyboard>
     <f1 mod="ctrl,alt,shift">RunScript(/etc/crouton/kodi-cycle.py,prev)</f1>
     <f2 mod="ctrl,alt,shift">RunScript(/etc/crouton/kodi-cycle.py,next)</f2>
   </keyboard>
  </global>
</keymap>


================================================
FILE: chroot-etc/pulseaudio-default.pa
================================================
#!/usr/bin/pulseaudio -nF
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Include default configuration first
.include /etc/pulse/default.pa

# Forward audio to Chromium OS audio server
load-module module-alsa-sink device=cras sink_name=cras-sink
load-module module-alsa-source device=cras source_name=cras-source
set-default-sink cras-sink
set-default-source cras-source


================================================
FILE: chroot-etc/unity-autostart.desktop
================================================
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

[Desktop Entry]
Type=Application
Name=crouton autostart script for Unity
Exec=/usr/local/bin/crouton-unity-autostart
OnlyShowIn=Unity;
NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=true


================================================
FILE: chroot-etc/unity-profiled
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Helper script for Unity called at user login.
# Right now this just sets up .desktop files in the user's autostart
# directory to override global autostart.

RELEASE="`/usr/local/bin/croutonversion -r`"

# unity-settings-daemon should run instead of gnome-settings-daemon in trusty
if [ "$RELEASE" = 'trusty' -o "$RELEASE" = 'xenial' ]; then
    autostartdir="$HOME/.config/autostart"
    mkdir -p "$autostartdir"
    cat > "$autostartdir"/gnome-settings-daemon.desktop <<EOF
[Desktop Entry]
OnlyShowIn=GNOME;
EOF

fi


================================================
FILE: chroot-etc/xbindkeysrc.scm
================================================
;; Copyright (c) 2016 The crouton Authors. All rights reserved.
;; Use of this source code is governed by a BSD-style license that can be
;; found in the LICENSE file.

;; Run xbindkeys -dg for some example configuration file with explanation

; Cycle chroots. On most systems, this is handled by croutontriggerd.
; On freon, we have to do it ourselves since we currently grab the event device.
(if (access? "/sys/class/tty/tty0/active" F_OK) (begin
    (xbindkey '(control shift alt F1) "")
    (xbindkey '(control shift alt F2) "")
) (begin
    (xbindkey '(control shift alt F1) "xte 'keyup F1'; croutoncycle prev")
    (xbindkey '(control shift alt F2) "xte 'keyup F2'; croutoncycle next")
))

; Extra bindings that must only be activated in chroot X11
(if (not (string-null? (getenv "XMETHOD")))
    (begin
        ; Brightness control
        (xbindkey '(XF86MonBrightnessDown) "brightness down")
        (xbindkey '(XF86MonBrightnessUp) "brightness up")

        ; Load ~/.xbindkeysrc.scm for customization if the current user has one
        (let ((usercfg (string-append (getenv "HOME") "/.xbindkeysrc.scm")))
            (if (access? usercfg F_OK) (load usercfg))
        )
    )
)


================================================
FILE: chroot-etc/xiwi.conf
================================================
# i3 config file (v4)
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Style
new_window none
new_float normal
workspace_layout tabbed
font pango:Sans 8

# Colors                border  backgr. text    indicator
client.focused          #8E8E8F #EAEAEB #000000 #8E8E8F
client.focused_inactive #8E8E8F #CACACB #525252 #8E8E8F
client.unfocused        #8E8E8F #CACACB #525252 #8E8E8F
client.urgent           #FF8E8E #FFCACB #520000 #FF8E8E
client.background       #C3C3C4

# Interaction
focus_follows_mouse no
bindsym Mod1+Shift+Control+Escape kill
floating_modifier Mod1
bindsym Mod1+Tab focus right
bindsym Mod1+Shift+Tab focus left
bindsym Mod1+Control+Tab focus right
bindsym Mod1+Shift+Control+Tab focus left
bindsym --release button2 kill


================================================
FILE: chroot-etc/xorg-dummy.conf
================================================
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

Section "Monitor"
    Identifier "Monitor0"
    HorizSync 5.0-1000.0
    VertRefresh 5.0-200.0
EndSection

Section "Device"
    Identifier "Card0"
    Driver "dummy"
    # Enough memory for 4096x2048
    VideoRam 32768
EndSection

Section "Screen"
    DefaultDepth 24
    Identifier "Screen0"
    Device "Card0"
    Monitor "Monitor0"
    SubSection "Display"
        Depth 24
        Modes "1024x768"
    EndSubSection
EndSection

Section "ServerLayout"
    Identifier "Layout0"
    Screen "Screen0"
EndSection

Section "ServerFlags"
    Option "AutoAddDevices" "false"
    Option "AutoAddGPU" "false"
    Option "DontVTSwitch" "true"
    Option "AllowMouseOpenFail" "true"
    Option "PciForceNone" "true"
    Option "AutoEnableDevices" "false"
EndSection


================================================
FILE: chroot-etc/xorg-intel-sna.conf
================================================
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# On Intel platforms with FBC enabled, in order to see anything we need to use
# the SNA driver with the TearFree option.
Section "Device"
   Identifier "Intel Graphics SNA+TearFree"
   Driver     "intel"
   Option     "AccelMethod" "sna"
   Option     "TearFree"    "true"
EndSection


================================================
FILE: chroot-etc/xserverrc
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

if [ -z "$XMETHOD" ]; then
    if [ -f '/etc/crouton/xmethod' ]; then
        read -r XMETHOD _ < /etc/crouton/xmethod
    else
        echo 'X11 backend not set.' 1>&2
        exit 1
    fi
fi

xserverrc="/etc/crouton/xserverrc-${XMETHOD%%-*}"
if [ "${XMETHOD##*/}" != "$XMETHOD" -o ! -f "$xserverrc" ]; then
    echo "Invalid X11 backend '$XMETHOD'" 1>&2
    exit 2
fi

. "$xserverrc"


================================================
FILE: chroot-etc/xserverrc-local.example
================================================
#!/bin/sh
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Sample script to customize X server invocation. To activate copy it to
# /etc/crouton/xserverrc-local
#
# The file is sourced before invoking the X server with the variable
# XMETHOD set to xiwi, or xorg and the variable XARGS containing the
# command line arguments that will be passed to the server.
#
# Uncoment if fonts look too big on machines with 1366x768 11.6" screen
#XARGS="$XARGS -dpi 135x135"


================================================
FILE: chroot-etc/xserverrc-xiwi
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

logfile="/tmp/Xorg.crouton.$$.log"
for arg in "$@"; do
    disp="`echo "$arg" | sed -n 's/^\:\([0-9]*\)$/\1/p'`"
    if [ -n "$disp" ]; then
        logfile="/tmp/Xorg.crouton.$disp.log"
    fi
done

if [ "${XMETHOD%%-*}" != 'xiwi' ]; then
    export XMETHOD='xiwi'
fi
XARGS="-nolisten tcp -config xorg-dummy.conf -logfile $logfile"
if [ -f /etc/crouton/xserverrc-local ]; then
    . /etc/crouton/xserverrc-local
fi

exec /usr/bin/Xorg $XARGS "$@"


================================================
FILE: chroot-etc/xserverrc-xorg
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

if [ "${XMETHOD%%-*}" != 'xorg' ]; then
    export XMETHOD='xorg'
fi
XARGS='-nolisten tcp'
if [ -f /etc/crouton/xserverrc-local ]; then
    . /etc/crouton/xserverrc-local
fi

X=/usr/bin/X

# Handle Freon systems
if [ ! -f "/sys/class/tty/tty0/active" ]; then
    # We won't be able to launch properly if running from frecon
    ppid="$$"
    while [ -n "$ppid" -a "$ppid" -ne 1 ]; do
        ppid="`ps -p "$ppid" -o 'ppid=' 2>/dev/null | sed 's/ //g'`"
        if ps -p "$ppid" -o 'comm=' | grep -q '^frecon$'; then
            echo 'Xorg X11 servers cannot be launched from Frecon.' 1>&2
            echo 'Return to Chromium OS and use crosh to launch X.' 1>&2
            exit 2
        fi
    done
    # Prepare lock file
    mkdir -p '/tmp/crouton-lock'
    touch '/tmp/crouton-lock/display'
    chmod -Rf g+rwX '/tmp/crouton-lock'
    chgrp -Rf crouton '/tmp/crouton-lock'
    # Freon necessitates the preload hack for X to coexist
    X=/usr/bin/Xorg
    logfile="/tmp/Xorg.crouton.$$.log"
    for arg in "$@"; do
        disp="`echo "$arg" | sed -n 's/^\:\([0-9]*\)$/\1/p'`"
        if [ -n "$disp" ]; then
            logfile="/tmp/Xorg.crouton.$disp.log"
        fi
    done
    XARGS="$XARGS -logfile $logfile"
    export LD_PRELOAD="/usr/local/lib/croutonfreon.so:$LD_PRELOAD"
fi

exec "$X" $XARGS "$@"


================================================
FILE: host-bin/crash_reporter_wrapper
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# When launched from the kernel, PATH is not set and stderr is closed
if [ ! -t 0 ]; then
    exec 2>/var/log/crash_reporter_wrapper.log
    export PATH='/bin:/sbin:/usr/bin:/usr/sbin'
fi

APPLICATION="${0##*/}"
CORE_PATTERN_PARAMS='%p %s %u %g %e %h %t %E'
CORE_PATTERN_PARAMS_COUNT=8
CORE_PATTERN="|`readlink -f -- "$0"` $CORE_PATTERN_PARAMS"
CORE_PATTERN_FILE='/var/run/crw/core_pattern'
CORE_PATTERN_PROC='/proc/sys/kernel/core_pattern'
DEFAULT_CHROOT_PATTERN=''
IDEAL_LOCATION='/var/run/crw/crw'

USAGE="$APPLICATION register
$APPLICATION $CORE_PATTERN_PARAMS

Handles system core dumps, passing the dump through to Chromium OS's
crash_reporter or processing it as the chroot requests, depending on what
namespace the process belongs to.

The first form should be run as root, and sets $CORE_PATTERN_PROC
to use this script as the core dump pipe program.

The second form is expected to be called by the kernel upon program crash, via
the core_pattern set with the first form. The script checks if the crashing
PID's root has an /etc/crouton/core_pattern and uses that to emulate the
kernel's handling of the core_pattern proc entry."


# Outputs a parameter by core_pattern name (e.g. %p prints out the expanded $1)
# If the parameter doesn't exist, outputs an error to stderr and returns $1
# $1: the parameter name, either in the form of "%p" or just "p"
# $2+: must be "$@"
get_parameter() {
    local param="%${1#%}" param_names="$CORE_PATTERN_PARAMS "
    if [ "$param" = '%%' ]; then
        echo -n '%'
        return
    elif [ "$param" = '%c' ]; then
        echo -n "$core_limit"
        return
    fi
    shift
    while [ "$param" != "${param_names%% *}" ]; do
        param_names="${param_names#* }"
        if [ -z "$param_names" ]; then
            echo "$param not provided for core_pattern" 1>&2
            echo -n "$param"
            return
        fi
        shift
    done
    echo -n "$1"
}

# Takes the specified string and expands included parameters
# Outputs result to stdout
# $1: the string to expand and escape
# $2+: must be "$@"
expand_parameters() {
    local unexpanded="$1%" remain param
    shift
    while [ -n "$unexpanded" ]; do
        param="${unexpanded%%%*}"
        echo -n "$param"
        remain="${unexpanded#*%?}"
        if [ "$remain" = "$unexpanded" ]; then
            break
        fi
        param="${unexpanded#"$param"}"
        param="${param%"$remain"}"
        unexpanded="$remain"
        get_parameter "$param" "$@"
    done
}

# Takes stdin and escapes it to be safe within single-quotes
# Outputs result to stdout
# Converts ' to '\''
escape() {
    sed "s/'/'\\\\\\''/g"
}


if [ "$#" != 1 -a "$#" != "$CORE_PATTERN_PARAMS_COUNT" ]; then
    echo "$USAGE" 1>&2
    exit 2
fi

if [ "$#" = 1 -a "$1" != 'register' ]; then
    echo "$USAGE" 1>&2
    exit 2
fi

if [ "${UID:-0}" != 0 -o "${USER:-root}" != 'root' ]; then
    echo "$APPLICATION must be run as root." 1>&2
    exit 2
fi

if [ "$#" = 1 ]; then
    # Always register the script from /var/run for safety
    if [ "$0" != "$IDEAL_LOCATION" ]; then
        dir="${IDEAL_LOCATION%/*}"
        if ! mountpoint "$dir" >/dev/null 2>/dev/null; then
            mkdir -p "$dir"
            mount -t tmpfs \
                  -o 'rw,nosuid,nodev,exec,noatime,mode=700,size=128K' \
                  tmpfs "$dir"
        fi
        cp -fT "$0" "$IDEAL_LOCATION"
        chmod 500 "$IDEAL_LOCATION"
        exec "$IDEAL_LOCATION" "$@"
    fi
    # Store Chromium OS's core pattern for passthrough usage
    if [ ! -f "$CORE_PATTERN_FILE" ]; then
        cat "$CORE_PATTERN_PROC" > "$CORE_PATTERN_FILE"
    fi
    # Register ourselves as the coredump handler
    echo "$CORE_PATTERN" > "$CORE_PATTERN_PROC"
    exit 0
fi

# It's a core dump! See CORE(5) for details in emulating core_pattern.
pattern=''

# $1 is the pid of the process. Check the process's root for etc/crouton
pid="$1"
root="/proc/$pid/root"
cwd="/proc/$pid/cwd"
croutondir="$root/etc/crouton"
if [ -d "$croutondir" ]; then
    # Looks like a chroot (or a very weird rootfs, but that's unlikely)
    # Grab the chroot's pattern or use the default if the file doesn't exist
    if [ -f "$croutondir/core_pattern" ]; then
        # File exists; first non-empty, non-comment line is the core_pattern
        pattern="`awk '/^[^#]/ { print $0; exit }' "$croutondir/core_pattern"`"
    else
        pattern="$DEFAULT_CHROOT_PATTERN"
    fi
else
    # Probably a Chromium process. Grab the backed-up core pattern.
    if [ -f "$CORE_PATTERN_FILE" ]; then
        pattern="`cat "$CORE_PATTERN_FILE"`"
    else
        echo "$APPLICATION was not properly registered as the core_pattern." 1>&2
        echo "You must register using '$0 register'" 1>&2
        exit 2
    fi
fi

# If the pattern is empty, just exit.
if [ -z "$pattern" ]; then
    exit 0
fi

# Remove the pipe character so we can play with the path generically
ispipe=''
if [ "${pattern#|}" != "$pattern" ]; then
    ispipe='y'
    pattern="${pattern#|}"
    # Pipe paths must be absolute
    if [ "${pattern#/}" = "$pattern" ]; then
        echo "core_pattern '|$pattern' is not absolute" 1>&2
        exit 2
    fi
fi

# Get the core size limit for the process
core_limit="`awk '/^Max core file size/ {
                printf ($5=="unlimited") ? -1 : $5; exit
            }' "/proc/$pid/limits"`"

# Prepare the file to operate on
if [ -z "$ispipe" ]; then
    # Don't bother if core file size limit is 0
    if [ "$core_limit" = 0 ]; then
        exit 0
    fi
    # If this is not a pipe, we need to expand the %'s here.
    file="`expand_parameters "$pattern" "$@"`"
else
    # For pipes, path is anything up to a space
    file="${pattern%% *}"
    pattern="${pattern#"$file"}"
fi

# Fix up the path to be working directory-relative
if [ "${file#/}" = "$file" ]; then
    file="$cwd/$file"
fi

# Canonicalize within the chroot and escape the filename to work within quotes
file="`chroot "$root" readlink -m -- "/${file%/*}"`/${file##*/}"
file="`echo -n "$file" | escape`"

# Prepare the command to run inside the chroot as the appropriate user
if [ -z "$ispipe" ]; then
    cmd="
        if [ -e '$file' -a ! -f '$file' ] || [ -h '$file' ]; then
            echo \"Not overwriting '$file'; it is not a regular file\" 1>&2
        elif [ -f '$file' ] && [ \"\`stat -c '%h' '$file'\`\" != 1 ]; then
            echo \"Not overwriting '$file'; it is multiply linked\" 1>&2
        elif [ '$core_limit' = -1 ] && cat > '$file'; then
            exit 0
        elif [ '$core_limit' != -1 ] && head -c '$core_limit' > '$file'; then
            exit 0
        fi
        exit 1
    "
    username="`chroot "$root" ps -ouser= -p "$pid"`"
else
    # Finally need to expand the parameters here
    cmd="exec '$file'"
    params="$pattern "
    while [ -n "$params" ]; do
        param="${params%% *}"
        params="${params#* }"
        if [ -n "$param" ]; then
            cmd="$cmd '`expand_parameters "$param" "$@" | escape`'"
        fi
    done
    username='root'
fi

# Run the generated command within the appropriate chroot
exec chroot "$root" su -s '/bin/sh' -c "$cmd" - "$username"


================================================
FILE: host-bin/edit-chroot
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

APPLICATION="${0##*/}"
ALLCHROOTS=''
BACKUP=''
BINDIR="`dirname "\`readlink -f -- "$0"\`"`"
CHROOTS="`readlink -m -- "$BINDIR/../chroots"`"
DELETE=''
ENCRYPT=''
KEYFILE=''
LISTDETAILS=''
MOVE=''
COPY=''
NEEDS_UNMOUNT=''
RESTORE=''
SPLIT=''
TARBALL=''
YES=''
YESPARAM=''

USAGE="$APPLICATION [options] name [...]

Edits a chroot.

Options:
    -a          Operates on all chroots in $CHROOTS.
                If no other operation is specified, prints out the names of the chroots.
    -c CHROOTS  Directory the chroots are in. Default: $CHROOTS
    -b          Backs up the chroot to a tarball. Compression format is chosen
                based on the tarball extension. Backups always take place before
                other actions on a given chroot.
    -d          Deletes the chroot. Assumed if run as delete-chroot.
    -e          If the chroot is not encrypted, encrypt it.
                If it is encrypted, change the encryption passphrase.
    -f TARBALL  When used with -b, overrides the default tarball to back up to.
                If unspecified, assumes NAME-yyyymmdd-hhmm.tar[.gz], where .gz
                is included for unencrypted chroots, and not for encrypted ones.
                When used with -r, specifies the tarball to restore from.
                If TARBALL is a directory, automatic naming is still used.
                If multiple chroots are specified, TARBALL must be a directory.
    -k KEYFILE  File or directory to store the (encrypted) encryption keys in.
                If unspecified, the keys will be stored in the chroot if doing a
                first encryption, or left in place on existing chroots.
                If specified, keyfile will be moved. Specify a dash - as the
                KEYFILE to move the key back into the chroot.
                If multiple chroots are specified, KEYFILE must either be -
                or a directory.
    -l          Prints out croutonversion details on the chroot, if available.
                Specify twice to prompt and unlock encrypted chroots as necessary.
    -m DEST     Moves a chroot. Specify a new name to keep it in the same
                directory, or an absolute path to move it entirely.
                DEST can be a directory, in which case it must end in a slash.
                If multiple chroots are specified, DEST must be a directory.
                If you are moving a chroot to a SD card/USB drive, make sure the
                storage is formatted to ext2/3/4.
    -C DEST     Like -m, but copies instead of moves.
    -r          Restores a chroot from a tarball. The tarball path can be
                specified with -f or detected from name. If both are specified,
                restores to that name instead of the one in the tarball.
                Will not overwrite a chroot when restoring unless -r is
                specified twice.
    -s SPLIT    Force a backup archive to be split into SPLIT-sized chunks.
                SPLIT is specified in megabytes (1048576 bytes), and cannot be
                smaller than 10.
                FAT32 filesystems are split by default to fit within 4GB.
    -y          Do all actions without confirmation."

# Common functions
. "$BINDIR/../installer/functions"

# Process arguments
getopts_string='abc:C:def:k:lm:rs:y'
while getopts_nextarg; do
    case "$getopts_var" in
    a) ALLCHROOTS='y';;
    b) BACKUP='y'; NEEDS_UNMOUNT='y';;
    c) CHROOTS="`readlink -m -- "$getopts_arg"`";;
    C) COPY="$getopts_arg"; NEEDS_UNMOUNT='y';;
    d) DELETE='y'; NEEDS_UNMOUNT='y';;
    e) ENCRYPT='y'; NEEDS_UNMOUNT='y';;
    f) TARBALL="$getopts_arg";;
    k) KEYFILE="$getopts_arg";;
    l) LISTDETAILS=$(($LISTDETAILS+1));;
    m) MOVE="$getopts_arg"; NEEDS_UNMOUNT='y';;
    r) RESTORE=$(($RESTORE+1)); NEEDS_UNMOUNT='y';;
    s) SPLIT="$getopts_arg";;
    y) YES='a'; YESPARAM='-y';;
    \?) error 2 "$USAGE";;
    esac
done

# If the executable name is delete*, assume DELETE.
if [ "${APPLICATION#delete}" != "$APPLICATION" ]; then
    DELETE='y'
    NEEDS_UNMOUNT='y'
fi

# At least one command must be specified
if [ -z "$ALLCHROOTS$BACKUP$DELETE$ENCRYPT$KEYFILE$LISTDETAILS$MOVE$COPY$RESTORE" ]; then
    error 2 "$USAGE"
fi

# Need at least one chroot listed if not using -r with -f or -a.
if [ $# = 0 ] && ! [ -n "$RESTORE" -a -n "$TARBALL" -o -n "$ALLCHROOTS" ]; then
    error 2 "$USAGE"
fi

# Cannot specify a chroot and -a.
if [ $# -gt 0 -a -n "$ALLCHROOTS" ]; then
    error 2 "$USAGE"
fi

# -f without -r or -b doesn't make sense
if [ -n "$TARBALL" -a -z "$BACKUP$RESTORE" ]; then
    error 2 "$USAGE"
fi

# Cannot specify both backup and restore.
if [ -n "$BACKUP" -a -n "$RESTORE" ]; then
    error 2 "$USAGE"
fi

# Cannot specify both copy and move.
if [ -n "$COPY" -a -n "$MOVE" ]; then
    error 2 "$USAGE"
fi

# Cannot specify delete with anything else.
if [ -n "$DELETE" -a -n "$BACKUP$ENCRYPT$KEYFILE$MOVE$COPY$RESTORE" ]; then
    error 2 "$USAGE"
fi

# Make sure SPLIT is reasonable
if [ -n "$SPLIT" ] && [ "$SPLIT" -lt 10 -o -z "$BACKUP" ]; then
    error 2 "$USAGE"
fi

# If we specified -a option, bring in all chroots.
if [ -n "$ALLCHROOTS" ]; then
    if [ ! -d "$CHROOTS" ]; then
        error 1 "$CHROOTS not found."
    fi
    for crname in "$CHROOTS"/*; do
        if [ -d "$crname" ]; then
            set -- "$@" "${crname##*/}"
        fi
    done
    if [ $# = 0 ]; then
        error 1 "No chroots found in $CHROOTS"
    fi
fi

# If TARBALL is unspecified and we're in /, put the tarball in ~/Downloads
if [ -n "$BACKUP$RESTORE" -a -z "$TARBALL" -a "$PWD" = '/' \
        -a -d '/home/chronos/user/Downloads' ]; then
    TARBALL="/home/chronos/user/Downloads/"
fi

# If multiple chroots are listed, KEYFILE and MOVE and COPY must be empty or directories.
if [ $# -gt 1 -a -f "$KEYFILE" -a "$KEYFILE" != '-' ]; then
    error 2 "Multiple chroots specified, but $KEYFILE is not a directory."
elif [ $# -gt 1 -a -n "$MOVE" -a "${MOVE%/}" = "$MOVE" ]; then
    error 2 "Multiple chroots specified, but $MOVE is not a directory."
elif [ $# -gt 1 -a -n "$COPY" -a "${COPY%/}" = "$COPY" ]; then
    error 2 "Multiple chroots specified, but $COPY is not a directory."
elif [ $# -gt 1 -a -f "$TARBALL" ]; then
    error 2 "Multiple chroots specified, but $TARBALL is not a directory."
fi

# Don't allow moving to non-ext filesystems (but don't check if just renaming)
if [ -n "$MOVE" -a "${MOVE#*/}" != "$MOVE" ] && \
        df -T "`getmountpoint "$MOVE"`" | awk '$2~"^ext"{exit 1}'; then
    error 2 "Chroots can only be moved to ext filesystems."
fi

# Don't allow copying to non-ext filesystems (but don't check if in same directory)
if [ -n "$COPY" -a "${COPY#*/}" != "$COPY" ] && \
        df -T "`getmountpoint "$COPY"`" | awk '$2~"^ext"{exit 1}'; then
    error 2 "Chroots can only be copied to ext filesystems."
fi

# Don't allow restoring to non-ext filesystems
if [ -n "$RESTORE" ] && \
        df -T "`getmountpoint "$CHROOTS"`" | awk '$2~"^ext"{exit 1}'; then
    error 2 "Chroots can only be restored to ext filesystems."
fi

# Don't allow backing up to tmpfs filesystems
if [ -n "$BACKUP" ] && ! df -T "`getmountpoint "${TARBALL:-.}"`" \
                            | awk '$2=="tmpfs"{exit 1}'; then
    error 2 "Chroots cannot be backed up to temporary filesystems."
fi

# We need to run as root
if [ "$USER" != root -a "$UID" != 0 ]; then
    error 2 "$APPLICATION must be run as root."
fi

# Strongly advise against moving a keyfile to a tmpfs path
if [ "${KEYFILE:--}" != '-' ] && \
        ! df -T "`getmountpoint "$KEYFILE"`" | awk '$2=="tmpfs"{exit 1}'; then
    echo -n '\
Moving a keyfile to a temporary filesystem is a really good way to permanently
lose access to your chroot. If you still want to do this, wait for 15 seconds.
Otherwise: HIT CTRL-C RIGHT NOW > ' 1>&2
    sleep 15
    echo \
'...okay. Be sure to put the keyfile somewhere safe before you reboot.' 1>&2
fi

# If we're restoring and specified a tarball and no name, detect the name.
if [ -n "$RESTORE" -a -n "$TARBALL" -a $# = 0 ]; then
    echo 'Detecting chroot name...' 1>&2
    label="`tar --test-label -f "$TARBALL" 2>/dev/null`"
    if [ -n "$label" ]; then
        if [ "${label#crouton:backup}" = "$label" ]; then
            error 2 "$TARBALL doesn't appear to be a valid crouton backup."
        fi
        NAME="${label#*-}"
    else
        # Old backups just use the first folder name
        NAME="`tar -tf "$TARBALL" 2>/dev/null | head -n 1`"
        NAME="${NAME%%/*}"
    fi
    if [ -z "$NAME" ]; then
        error 2 "$TARBALL doesn't appear to be a valid tarball."
    fi
    set -- "$NAME"
fi

# Make sure that all names are valid chroot names.
# For anything but restore, make sure all chroots exist before doing anything.
for NAME in "$@"; do
    if ! validate_name "$NAME"; then
        error 2 "Invalid chroot name '$NAME'."
    fi

    if [ -z "$RESTORE" ]; then
        CHROOT="$CHROOTS/$NAME"

        # Check for existence
        if [ ! -d "$CHROOT" ]; then
            extra=''
            if [ "${NAME#-}" != "$NAME" ]; then
                extra="
Please specify all options before chroot names."
            fi
            error 2 "$CHROOT not found.$extra"
        fi
    fi
done

# Display all chroot names if using -a without any other operations.
if [ -n "$ALLCHROOTS" -a -z "$BACKUP$DELETE$ENCRYPT$KEYFILE$LISTDETAILS$MOVE$COPY$RESTORE" ]; then
    echo "$@"
    exit 0
fi

# If TARBALL ends in a slash or we're restoring multiple chroots, make directory
if [ -n "$TARBALL" ] && \
        [ $# -ge 2 -o -d "$TARBALL" -o "${TARBALL%/}" != "$TARBALL" ]; then
    TARBALL="${TARBALL%/}/"
    mkdir -p "$TARBALL"
fi

# Avoid kernel panics due to slow I/O
disablehungtask

# Make sure we always exit with echo on the tty.
addtrap "stty echo 2>/dev/null"

# Prints out a fancy spinner that updates every time a line is fed in, unless
# the output is not to a tty, in which case it just prints a new line.
# $1: number of lines between each update of the spinner
# $2...: Command to be run
# Erases the line each time, so it will always be at position 0.
# Either expect this and put text later in the line, or give this its own line.
spinner() {
    local spin="$1"
    shift
    if [ -t 2 ]; then
        # Keep track of the exit status of the piped command
        local ret="`(("$@" || echo "$?" 1>&3) | mawk -Winteractive '
            BEGIN {
                printf "\r"
            }
            {
                y = (y+1) % '"$spin"'
                if (y == 0) {
                    x = (x+1) % 4
                    printf substr("\|/-", x+1, 1) "\r"
                }
            }' 1>&2) 3>&1`"
        if [ -n "$ret" ]; then
            return "$ret"
        fi
    else
        echo 1>&2
        "$@" 1>/dev/null
    fi
}

# Process each chroot
for NAME in "$@"; do
    # Double check $NAME (better paranoid than sorry)
    if ! validate_name "$NAME"; then
        error 2 "Invalid chroot name '$NAME'."
    fi
    CHROOT="$CHROOTS/$NAME"

    # Check for existence and unmount/delete the chroot.
    if [ -d "$CHROOT" ]; then
        if [ -n "$LISTDETAILS" ]; then
            getversion='y'
            echo "name: $NAME"
            if [ -f "$CHROOT/.ecryptfs" ]; then
                if [ ! -d "/var/run/crouton/$CHROOT" \
                        -a "$LISTDETAILS" -gt 1 ]; then
                    sh "$BINDIR/mount-chroot" -c "$CHROOTS" -- "$NAME" || true
                fi
                if mountpoint -q "/var/run/crouton/$CHROOT"; then
                    echo "encrypted: yes, unlocked"
                else
                    echo "encrypted: yes, locked"
                    getversion='n'
                fi
            else
                echo "encrypted: no"
            fi
            if [ "$getversion" = 'y' ]; then
                CROUTON_NO_UNMOUNT=1 sh "$BINDIR/enter-chroot" \
                    -c "$CHROOTS" -n "$NAME" -x /usr/local/bin/croutonversion \
                    || true
            fi
        fi
        if [ "$RESTORE" = 1 ]; then
            error 2 "$CHROOT already exists! Specify a second -r to overwrite it (dangerous)."
        elif [ -n "$RESTORE" ]; then
            EXISTS='y'
        elif ! sh -e "$BINDIR/unmount-chroot" $YESPARAM \
                    -c "$CHROOTS" -- "$NAME"; then
            if [ -n "$NEEDS_UNMOUNT" ]; then
                exit 1
            fi
        fi
    elif [ -n "$RESTORE" ]; then
        EXISTS=''
    else
        # This should have been caught earlier
        error 2 "$CHROOT not found."
    fi

    # Delete the chroot?
    if [ -n "$DELETE" ]; then
        # Confirm deletion
        if [ "${YES#[Aa]}" = "$YES" ]; then
            echo -n "Delete $CHROOT? [a/y/N] " 1>&2
            if [ -n "$CROUTON_EDIT_RESPONSE" ]; then
                YES="$CROUTON_EDIT_RESPONSE"
                echo "$YES" 1>&2
            else
                read -r YES
            fi
            if [ "${YES#[AaYy]}" = "$YES" ]; then
                 error 2 "Aborting deletion of $CHROOT"
            fi
        fi
        # Delete the chroot
        echo -n "  Deleting $CHROOT..." 1>&2
        spinner 1000 rm -rvf --one-file-system "$CHROOT"
        echo "Finished deleting $CHROOT" 1>&2
        continue
    fi

    # Backup the chroot
    if [ -n "$BACKUP" ]; then
        dest="$TARBALL"
        date="`date '+%Y%m%d-%H%M'`"
        if [ -z "$dest" -o -d "$TARBALL" ]; then
            dest="$TARBALL$NAME-$date.tar"
            # Only compress if it's not encrypted (it'd be a waste of time)
            if [ ! -f "$CHROOT/.ecryptfs" ]; then
                dest="$dest.gz"
            fi
        fi
        # If we're writing to a fat32 filesystem, split the file at 4GB chunks
        if ! df -T "`getmountpoint "$dest"`" | awk '$2~"^v?fat"{exit 1}'; then
            SPLIT="${SPLIT:-4095}"
        fi
        if [ -n "$SPLIT" ]; then
            tardest="`mktemp -d --tmpdir=/tmp 'crouton-backup.XXX'`"
            addtrap "rm -rf '$tardest'"
            tardest="$tardest/pipe.${dest##*/}"
            mkfifo -m 600 "$tardest"
            split -b "${SPLIT}m" -a 4 "$tardest" "$dest.part-" &
            splitpid="$!"
        else
            tardest="$dest"
            splitpid=''
        fi
        echo -n "  Backing up $CHROOT to $(readlink -m -- "$dest")..." 1>&2
        addtrap "echo 'Deleting partial archive.' 1>&2; \
                 kill '$splitpid' 2>/dev/null; rm -f '$dest' '$dest.part-'*"
        ret=0
        spinner 1 tar --checkpoint=100 --checkpoint-action=exec=echo \
            --one-file-system -V "crouton:backup.${date%-*}${date#*-}-$NAME" \
            -caf "$tardest" -C "$CHROOTS" "$NAME" || ret="$?"
        if [ -n "$SPLIT" ]; then
            wait "$splitpid" || ret="$?"
            mv -f "$dest.part-aaaa" "$dest" || ret="$?"
        fi
        if [ "$ret" -ne 0 ]; then
            echo "Unable to backup $CHROOT." 1>&2
            exit "$ret"
        fi
        # Make sure filesystem is sync'ed
        sync
        undotrap
        echo "Finished backing up $CHROOT to $dest" 1>&2
    fi

    # Restore the chroot
    if [ -n "$RESTORE" ]; then
        src="$TARBALL"
        if [ -z "$src" -o -d "$TARBALL" ]; then
            src=''
            file="$TARBALL$NAME"
            # Search for the alphabetically last tarball with src.
            # Dated tarballs take precedence over undated tarballs.
            for file in "$file."* "$file-"*; do
                if [ "${file%.part-[a-z][a-z][a-z][a-z]}" != "$file" \
                        -o ! -f "$file" ]; then
                    continue
                fi
                # Confirm it's a tarball
                if ! tar --test-label -f "$file" >/dev/null 2>&1; then
                    continue
                fi
                # Since * alphabetizes, always keep the last one
                src="$file"
            done
            if [ -z "$src" ]; then
                error 2 "Unable to find a tarball for $NAME. You can specify one with -f."
            fi
            echo "Found $src for restoring $NAME." 1>&2
        elif ! tar --test-label -f "$src" >/dev/null 2>&1; then
            error 2 "$src doesn't appear to be a valid tarball."
        fi
        if [ -n "$EXISTS" ]; then
            echo "WARNING: $CHROOT already exists. Deleting it before restoring." 1>&2
            echo "Press Control-C to abort; restoration will continue in 5 seconds." 1>&2
            sleep 5
            sh -e "$BINDIR/edit-chroot" -d -y -c "$CHROOTS" "$NAME"
        fi
        echo -n "  Restoring $src to $CHROOT..." 1>&2
        mkdir -p "$CHROOT"
        if [ -f "$src.part-aaab" ]; then
            # Detect the type of compression before sending it through a fifo
            for tarparam in -z -j -J -Z --no-auto-compress fail; do
                if [ "$tarparam" = 'fail' ]; then
                    error 2 "Unable to detect compression method of $src"
                elif tar $tarparam --test-label -f "$src" >/dev/null 2>&1; then
                    break
                fi
            done
            # Don't let tar get tripped up by cat's incomplete writes
            tarparam="$tarparam -B"
            tarsrc="`mktemp -d --tmpdir=/tmp 'crouton-restore.XXX'`"
            addtrap "rm -rf '$tarsrc'"
            tarsrc="$tarsrc/pipe"
            mkfifo -m 600 "$tarsrc"
            cat "$src" "$src.part"* >> "$tarsrc" &
            catpid="$!"
            addtrap "kill '$catpid' 2>/dev/null"
        else
            tarsrc="$src"
            tarparam='-a'
            catpid=''
        fi
        spinner 1 tar --checkpoint=200 --checkpoint-action=exec=echo $tarparam \
            --one-file-system -xf "$tarsrc" -C "$CHROOT" --strip-components=1
        if [ -n "$catpid" ]; then
            wait "$catpid"
        fi
        # Make sure filesystem is sync'ed
        sync
        echo "Finished restoring $src to $CHROOT" 1>&2
    fi

    # Update the keyfile
    if [ -n "$KEYFILE" ]; then
        newkeyfile="$KEYFILE"
        # Find the current keyfile
        oldkeyfile="$CHROOT/.ecryptfs"
        if [ -f "$oldkeyfile" ]; then
            header="`head -n1 "$oldkeyfile"`"
            if [ -n "$header" ]; then
                oldkeyfile="$header"
            fi
        fi
        if [ "$newkeyfile" = '-' ]; then
            newkeyfile="$CHROOT/.ecryptfs"
        fi
        if [ "${newkeyfile#/}" = "$newkeyfile" ]; then
            newkeyfile="$PWD/$newkeyfile"
        fi
        if [ -d "$newkeyfile" -o "${newkeyfile%/}" != "$newkeyfile" ]; then
            newkeyfile="${newkeyfile%/}/$NAME"
        fi
        oldkeyfile="`readlink -m -- "$oldkeyfile"`"
        keyfilecanon="`readlink -m -- "$newkeyfile"`"
        if [ ! -f "$oldkeyfile" ]; then
            # If there is no old keyfile, make sure we've requested encryption.
            if [ -z "$ENCRYPT" ]; then
                error 1 "Old key file not found"
            fi
        elif [ "$oldkeyfile" != "$keyfilecanon" ]; then
            chrootecryptfsfile="`readlink -m -- "$CHROOT/.ecryptfs"`"
            # Don't clobber a file already there
            if [ -e "$newkeyfile" -a "$newkeyfile" != "$chrootecryptfsfile" ]; then
                error 1 "Encryption key file $newkeyfile already exists. Refusing to overwrite!"
            fi
            # Write the new keyfile before removing the old.
            if ! mkdir -p "`dirname "$newkeyfile"`"; then
                error 1 "Unable to create directory for $newkeyfile"
            fi
            echo "Moving key file from $oldkeyfile to $newkeyfile" 1>&2
            (echo; tail -n+2 "$oldkeyfile") > "$newkeyfile"
            # Remove old keyfile before writing .ecryptfs, as it may be the same
            rm -f "$oldkeyfile"
            if [ "$chrootecryptfsfile" != "$newkeyfile" ]; then
                echo "$newkeyfile" > "$CHROOT/.ecryptfs"
            fi
        elif [ -z "$ENCRYPT$MOVE" ]; then
            echo "Keyfile is already located at $newkeyfile" 1>&2
        fi
    fi

    # Encrypt/rewrap the chroot
    if [ -n "$ENCRYPT" ]; then
        # Use mount-chroot to do the heavy lifting
        unmount="sh -e '$BINDIR/unmount-chroot' -y -c '$CHROOTS' -- '$NAME'"
        addtrap "$unmount"
        if [ -n "$KEYFILE" ]; then
            sh -e "$BINDIR/mount-chroot" -ee -k "$KEYFILE" -c "$CHROOTS" -- "$NAME"
        else
            sh -e "$BINDIR/mount-chroot" -ee -c "$CHROOTS" -- "$NAME"
        fi
        undotrap
        eval "$unmount"
    fi

    # Move the chroot if requested
    if [ -n "$MOVE" ]; then
        target="$MOVE"
        if [ "${target##*/}" = "$target" ]; then
            # No slashes in the path. Assume renaming.
            if ! validate_name "$target"; then
                error 2 "Invalid target chroot name '$target'."
            fi
            target="$CHROOTS/$target"
        elif [ "${target%/}" != "$target" ]; then
            # Ends in a slash; append name.
            target="$target$NAME"
        fi
        if [ -e "$target" ]; then
            # Can't tell if the destination is a directory or a chroot that
            # already exists; be safe and assume it was a mistake.
            error 2 "$target already exists"
        fi
        # Check if we're changing filesystems, because we should cp+rm for
        # safety. We don't do this when encrypting a chroot (see mount-chroot),
        # because that would require 2x the space on one device. When switching
        # filesystems like this, however, that isn't a concern.
        if [ "`getmountpoint "$target"`" != "`getmountpoint "$CHROOT"`" ]; then
            echo "Moving $CHROOT across filesystems to $target" 1>&2
            echo 'This will take a while.' 1>&2
            echo "If the operation gets interrupted, you can safely delete $target" 1>&2
            # Confirm long operation
            if [ "${YES#[Aa]}" = "$YES" ]; then
                echo -n "Are you sure you want to continue? [a/y/N] " 1>&2
                if [ -n "$CROUTON_EDIT_RESPONSE" ]; then
                    YES="$CROUTON_EDIT_RESPONSE"
                    echo "$YES" 1>&2
                else
                    read -r YES
                fi
                if [ "${YES#[AaYy]}" = "$YES" ]; then
                     error 2 "Aborting move of $CHROOT"
                fi
            fi
            if ! mkdir -p "`dirname "$target"`"; then
                error 1 "Unable to create directory for $target"
            fi
            echo -n "  Copying to $target..." 1>&2
            spinner 200 cp -av --one-file-system "$CHROOT" "$target"
            echo "Finished copying to $target" 1>&2
            echo -n "  Deleting old $CHROOT..." 1>&2
            spinner 1000 rm -rfv --one-file-system "$CHROOT"
            echo "Finished deleting old $CHROOT" 1>&2
        else
            if ! mkdir -p "`dirname "$target"`"; then
                error 1 "Unable to create directory for $target"
            fi
            echo "Moving $CHROOT to $target" 1>&2
            mv "$CHROOT" "$target"
        fi
    fi

    # Copy the chroot if requested
    if [ -n "$COPY" ]; then
        target="$COPY"
        if [ "${target##*/}" = "$target" ]; then
            # No slashes in the path. Assume same directory.
            if ! validate_name "$target"; then
                error 2 "Invalid target chroot name '$target'."
            fi
            target="$CHROOTS/$target"
        elif [ "${target%/}" != "$target" ]; then
            # Ends in a slash; append name.
            target="$target$NAME"
        fi
        if [ -e "$target" ]; then
            # Can't tell if the destination is a directory or a chroot that
            # already exists; be safe and assume it was a mistake.
            error 2 "$target already exists"
        fi
        if ! mkdir -p "`dirname "$target"`"; then
            error 1 "Unable to create directory for $target"
        fi
        echo "Copying $CHROOT to $target" 1>&2
        spinner 200 cp -av --one-file-system "$CHROOT" "$target"
    fi
done

exit 0


================================================
FILE: host-bin/enter-chroot
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

APPLICATION="${0##*/}"
BACKGROUND=''
BINDIR="`dirname "\`readlink -f -- "$0"\`"`"
CHROOTS="`readlink -m -- "$BINDIR/../chroots"`"
KEYFILE=''
LOGIN=''
NAME=''
TARGET=''
USERNAME='1000'
TMPXMETHOD=''
NOLOGIN=''
SETUPSCRIPT='/prepare.sh'

USAGE="$APPLICATION [options] [command [args...]]

Enters an installed Debian-based chroot for running alongside Chromium OS.

By default, it will log into the primary user on the first chroot found.
You can specify a command and parameters to run instead of an interactive shell.

Options:
    -b          Fork and run the specified command silently in the background.
    -c CHROOTS  Directory the chroots are in. Default: $CHROOTS
    -l          Make the command part of a login. Parameters are passed directly
                to the chroot command, and a call to su is appended.
    -k KEYFILE  Override the auto-detected encryption key location.
    -n NAME     Name of the chroot to enter. Default: first one found in CHROOTS
    -t TARGET   Only enter the chroot if it contains the specified TARGET.
    -u USERNAME Username (or UID) to log into. Default: 1000 (the primary user)
    -X XMETHOD  Override the auto-detected XMETHOD for this session.
    -x          Does not log in, but directly executes the command instead.
                Note that the environment will be empty (sans TERM).
                Specify -x a second time to run the $SETUPSCRIPT script."

# Common functions
. "$BINDIR/../installer/functions"

# Safely launch a command ($*) via /bin/sh within the chroot as the root user.
chrootcmd() {
    # env may be overridden when running in the background; don't let it fork.
    local ret=0 oldtrap="$TRAP"
    TRAP=''
    env -i chroot "$CHROOT" su -s '/bin/sh' -c "$*" - root || ret=$?
    local pid="$!"
    # $pid might not be set if env has not been redefined yet
    if [ -n "$BACKGROUND" ] && [ -n "$pid" ]; then
        wait "$pid" || ret=$?
    fi
    TRAP="$oldtrap"
    return "$ret"
}

# Process arguments
prevoptind=1
while getopts 'bc:k:ln:t:u:X:x' f; do
    # Disallow empty string as option argument
    if [ "$((OPTIND-prevoptind))" = 2 -a -z "$OPTARG" ]; then
        error 2 "$USAGE"
    fi
    prevoptind="$OPTIND"
    case "$f" in
    b) BACKGROUND='y';;
    c) CHROOTS="`readlink -m -- "$OPTARG"`";;
    k) KEYFILE="$OPTARG";;
    l) LOGIN='y';;
    n) NAME="$OPTARG";;
    t) TARGET="$OPTARG";;
    u) USERNAME="$OPTARG";;
    X) TMPXMETHOD="$OPTARG";;
    x) NOLOGIN="$((NOLOGIN+1))"
       [ "$NOLOGIN" -gt 2 ] && NOLOGIN=2;;
    \?) error 2 "$USAGE";;
    esac
done
shift "$((OPTIND-1))"

# Shift away empty string as first argument (used in start* scripts to mark
# the end of user-specified parameters)
if [ "$#" -ge 1 -a -z "$1" ]; then
    shift
fi

# We need to run as root
if [ "$USER" != root -a "$UID" != 0 ]; then
    error 2 "$APPLICATION must be run as root."
fi

# We need a command if we specified to run in the background
if [ -n "$BACKGROUND" -a $# = 0 ]; then
    error 2 "A command must be specified in order to run in the background."
fi

# If -x is specified twice, our command is the setup script.
if [ "$NOLOGIN" = 2 ]; then
    if [ $# != 0 ]; then
        error 2 "A command cannot be specified with -xx."
    fi
    if [ -n "$BACKGROUND" ]; then
        error 2 "Cannot run the setup script in the background."
    fi
    set -- "$SETUPSCRIPT"
fi

# Select the first chroot available if one hasn't been specified
if [ -z "$NAME" ]; then
    haschroots=''
    for CHROOT in "$CHROOTS"/*; do
        if [ ! -d "$CHROOT/etc" -a ! -f "$CHROOT/.ecryptfs" ]; then
            continue
        fi
        haschroots='y'
        if [ -n "$TARGET" ]; then
            if ! grep -q "^$TARGET$" "$CHROOT/.crouton-targets" 2>/dev/null; then
                continue
            fi
        fi
        NAME="${CHROOT##*/}"
        break
    done
    if [ -z "$haschroots" ]; then
        error 1 "No chroots found in $CHROOTS"
    fi
    if [ -z "$NAME" ]; then
        error 1 "No chroots with target '$TARGET' found in $CHROOTS"
    fi
elif [ -n "$TARGET" ]; then
    if ! grep -q "^$TARGET$" "$CHROOTS/$NAME/.crouton-targets" 2>/dev/null; then
        error 1 "$CHROOTS/$NAME does not contain target '$TARGET'"
    fi
fi

# Check to ensure that the XMETHOD requested has been installed
if [ -n "$TMPXMETHOD" ]; then
    if ! grep -q "^${TMPXMETHOD%%-*}$" "$CHROOTS/$NAME/.crouton-targets"; then
        error 1 "$CHROOTS/$NAME does not contain XMETHOD '${TMPXMETHOD%%-*}'"
    fi
fi

# Avoid kernel panics due to slow I/O
disablehungtask

# Allow X server running as normal user to set/drop DRM master
drm_relax_file="/sys/kernel/debug/dri/drm_master_relax"
if [ -f "$drm_relax_file" ]; then
    echo 'Y' > "$drm_relax_file"
fi

# Make sure we always exit with echo on the tty.
addtrap "stty echo 2>/dev/null"

# Mount the chroot and update our CHROOT path
CHROOTSRC="$CHROOTS/$NAME"
if [ -n "$KEYFILE" ]; then
    CHROOT="`sh -e "$BINDIR/mount-chroot" \
                                     -k "$KEYFILE" -p -c "$CHROOTS" -- "$NAME"`"
else
    CHROOT="`sh -e "$BINDIR/mount-chroot" -p -c "$CHROOTS" -- "$NAME"`"
fi

if [ "$NOLOGIN" != 2 ]; then
    echo "Entering $CHROOTSRC..." 1>&2
fi

# In disk full situations, mount-chroot can be empty. Good time to check sanity.
if [ -z "$CHROOT" ]; then
    error 1 'Something is wrong with the crouton install. Please make sure you have
sufficient space available, then re-install the chroot and try again.'
fi

# Register the crash_reporter_wrapper to properly handle coredumps
if [ -f "$BINDIR/crash_reporter_wrapper" ]; then
    if ! sh -e "$BINDIR/crash_reporter_wrapper" register; then
        echo 'WARNING: Unable to register core dump handler.' 1>&2
    fi
fi

if [ -z "$CROUTON_NO_UNMOUNT" ]; then
    # Auto-unmount everything below and including the chroot upon exit
    addtrap "sh -e '$BINDIR/unmount-chroot' -yc '$CHROOTS' -- '$NAME'"
fi

# If our root is on an external disk we need to ensure USB device persistence is
# enabled otherwise we will lose the file-system after a suspend event.
if [ "${CHROOTSRC#/media}" != "$CHROOTSRC" ]; then
    for usbp in /sys/bus/usb/devices/*/power/persist; do
        if [ -e "$usbp" ]; then
            echo 1 > "$usbp"
        fi
    done
fi

# Offer to run the setup script if it exists and yet we're logging in.
if [ -z "$NOLOGIN" -a -f "$CHROOT$SETUPSCRIPT" ]; then
    echo 'A chroot setup script still exists inside the chroot.' 1>&2
    echo 'The chroot may not be fully set up.' 1>&2
    response=''
    # A finished setup script will have permissions 500
    if [ "`stat -c '%a' "$CHROOT$SETUPSCRIPT"`" != '500' ]; then
        echo 'However, it appears the setup script is invalid.' 1>&2
        response='d'
    fi
    if [ -t 0 -a -z "$response" ]; then
        echo -n 'Would you like to finish the setup? [Y/n/d] ' 1>&2
        read -r response
    fi
    if [ -z "$response" -o "${response#[Yy]}" != "$response" ]; then
        echo 'Preparing chroot environment...' 1>&2
        if CROUTON_NO_UNMOUNT=1 sh -e "$BINDIR/enter-chroot" \
                -c "$CHROOTS" -n "$NAME" -xx; then
            echo 'Setup completed. Entering chroot...' 1>&2
            response=''
        else
            echo 'The chroot setup script may be broken. Your chroot is not fully configured.' 1>&2
            response='d'
        fi
    fi
    if [ "${response#[Dd]}" != "$response" ]; then
        echo 'Removing the chroot setup script. You may want to update your chroot again.' 1>&2
        rm -f "$CHROOT$SETUPSCRIPT"
    elif [ -n "$response" ]; then
        echo 'Skipping setup. You will be prompted again next time.' 1>&2
    fi
fi

# Resolve USERNAME if it is a UID (and we're logging in)
passwd="$CHROOT/etc/passwd"
if [ -z "$NOLOGIN" ]; then
    if [ ! -r "$passwd" ]; then
        error 1 "$CHROOTSRC doesn't appear to be a valid chroot."
    fi
    case "$USERNAME" in
    ''|*[!0-9]*)
        # Make sure the username exists
        if ! grep -q "^$USERNAME:" "$passwd"; then
            error 1 "User $USERNAME not found in $NAME"
        fi;;
     *)
        # Resolve the UID
        uid="$USERNAME"
        USERNAME="`awk -F: '$3=='"$uid"'{print $1; exit}' "$passwd"`"
        if [ -z "$USERNAME" ]; then
            error 1 "UID $uid not found in $NAME"
        fi
    esac
    # Detect the home directory and shell for the user
    CHROOTHOME="`awk -F: '$1=="'"$USERNAME"'"{print $6; exit}' "$passwd"`"
    CHROOTSHELL="`awk -F: '$1=="'"$USERNAME"'"{print $NF; exit}' "$passwd"`"
else
    CHROOTSHELL='/bin/sh'
fi

# Save the chroot name to the chroot
echo "$NAME" > "$CHROOT/etc/crouton/name"

# Ensure $CHROOT/var/host exists.
mkdir -p "$CHROOT/var/host"

# Copy in the current Chromium OS version for reference
cp -f '/etc/lsb-release' "$CHROOT/var/host/"

# Copy CRAS version into the chroot
cras_test_client --version 2>/dev/null > "$CHROOT/var/host/cras-version" || true

# Copy the latest Xauthority into the chroot
if [ -f "${XAUTHORITY:=/home/chronos/.Xauthority}" ]; then
    cp -f "$XAUTHORITY" "$CHROOT/var/host/Xauthority"
    chmod 444 "$CHROOT/var/host/Xauthority"
    # Be backwards-compatible, just in case
    if [ -f "$CHROOT/etc/X11/host-Xauthority" ]; then
        ln -sfT '/var/host/Xauthority' "$CHROOT/etc/X11/host-Xauthority"
    fi
fi

# Prepare chroot filesystem
# Soft-link resolv.conf so that updates are automatically propagated
ln -sfT '/var/host/shill/resolv.conf' "$CHROOT/etc/resolv.conf"

# Sanity check of the timezone setting
localtime="$CHROOT/etc/localtime"
hostlocaltime='/var/host/timezone/localtime'
if [ -h "$localtime" ] && [ "`readlink -- "$localtime"`" = "$hostlocaltime" ]; then
    timezone="`readlink -m -- /var/lib/timezone/localtime || true`"
    if [ -z "$timezone" -o ! -e "$CHROOT$LOCALTIME" ]; then
        echo "\
WARNING: the timezone selected in Chromium OS does not exist inside the chroot.
To set the chroot's timezone, run the following: sudo dpkg-reconfigure tzdata" 1>&2
    else
        # Set /etc/timezone in chroot - fixes the clock in Unity
        echo "${timezone#/usr/share/zoneinfo/}" > "$CHROOT/etc/timezone"
    fi
fi

# Follows and fixes dangerous symlinks, returning the canonicalized path.
fixabslinks() {
    local p="$CHROOT/$1" c
    # Follow and fix dangerous absolute symlinks
    while c="`readlink -m -- "$p"`" && [ "$c" != "$p" ]; do
        p="$CHROOT${c#"$CHROOT"}"
    done
    echo "$p"
}

# Bind-mounts $1 into $CHROOT/${2:-"$1"} if $2 is not already mounted
# If $3 is specified, remounts with the specified options.
# If $1 starts with a -, it's considered options to the bind mount, and the rest
# of the parameters are shifted.
bindmount() {
    bindopts=''
    if [ "${1#"-"}" != "$1" ]; then
        bindopts="$1"
        shift
    fi
    local target="`fixabslinks "${2:-"$1"}"`"
    if mountpoint -q "$target"; then
        return 0
    fi
    mkdir -p "$target"
    mount --bind $bindopts "$1" "$target"
    mount -i -o 'remount,symfollow' "$target" 2>/dev/null || true
    if [ -n "$3" ]; then
        mount -i -o "remount,$3" "$target"
    fi
}

# Creates a tmpfs mount at $CHROOT/$1 with options $2 if not already mounted
tmpfsmount() {
    local target="`fixabslinks "$1"`"
    if mountpoint -q "$target"; then
        return 0
    fi
    mkdir -p "$target"
    mount -i -t tmpfs -o "rw${2:+,}$2" tmpfs "$target"
    mount -i -o 'remount,symfollow' "$target" 2>/dev/null || true
}

# If /var/run isn't mounted, we know the chroot hasn't been started yet.
if mountpoint -q "`fixabslinks '/var/run'`"; then
    firstrun=''
else
    firstrun='y'
fi

bindmount /dev
bindmount /dev/pts
bindmount /dev/shm
bindmount /tmp /tmp exec
bindmount /proc
tmpfsmount /var/run 'noexec,nosuid,mode=0755,size=10%'
tmpfsmount /var/run/lock 'noexec,nosuid,nodev,size=5120k'
bindmount /var/run/dbus /var/host/dbus
bindmount /var/run/shill /var/host/shill
bindmount /var/lib/timezone /var/host/timezone
for m in /lib/modules/*; do
    if [ -d "$m" ]; then
        bindmount '-o ro' "$m"
    fi
done

# Add a shm symlink to our new /var/run
ln -sfT /dev/shm "`fixabslinks '/var/run'`/shm"

# Setup udev control directory in the chroot
# Chromium OS >=6092 uses /run/udev, older versions /dev/.udev
if [ -d /var/run/udev ]; then
    bindmount /var/run/udev /var/host/udev
    ln -sfT /var/host/udev "`fixabslinks '/var/run'`/udev"
else
    # Add a /run/udev symlink for later versions of udev in chroot
    ln -sfT /dev/.udev "`fixabslinks '/var/run'`/udev"
fi

if [ -d /var/run/cras ]; then
    bindmount /var/run/cras /var/host/cras
    # Add a /var/host/cras symlink for CRAS clients
    ln -sfT /var/host/cras "$(fixabslinks '/var/run')/cras"
else
    echo "\
WARNING: CRAS not running in Chromium OS. Audio forwarding will not work." 1>&2
fi

if [ -d /var/run/chrome ]; then
    bindmount /var/run/chrome /var/host/chrome
    # Add a /var/host/chrome symlink for display clients
    ln -sfT /var/host/chrome "$(fixabslinks '/var/run')/chrome"
else
    echo "\
WARNING: Chrome not running in Chromium OS. Display forwarding will not work." 1>&2
fi

# Bind-mount /media, specifically the removable directory
destmedia="`fixabslinks '/var/host/media'`"
if ! mountpoint -q "$destmedia"; then
    mount --make-shared /media
    mkdir -p "$destmedia" "$CHROOT/media"
    ln -sfT "/var/host/media/removable" "$CHROOT/media/removable"
    mount --rbind /media "$destmedia"
fi

# Provide a default /etc/crouton/shares file
shares="`fixabslinks '/etc/crouton/shares'`"
if [ -e "$shares" -a ! -f "$shares" ]; then
    echo "Not mounting shares: /etc/crouton/shares is not a file." 1>&2
elif [ ! -f "$shares" ]; then
    cat > "$shares" <<EOF
# Defines directories to map into the chroot from the host.
# Order is important: be sure to mount directories before you mount
# subdirectories of those mounts.
# The only directories that can be mapped from outside of the chroot are
# subdirectories of the following locations:
#  myfiles: ~/MyFiles
#  downloads: ~/Downloads
#  shared: /mnt/stateful_partition/crouton/shared
#  encrypted: ~/crouton/shared
# Inside the chroot, any absolute or user-relative path (~/x or ~user/x) is OK.
# Syntax is as follows:
#  HOSTDIR CHROOTDIR [OPTIONS]
# Directory names can have spaces (if quoted), but no quote characters or
# relative path elements (..'s).
# Options can be any options to mount. If unspecified, "exec" is assumed.

# Examples:
#  Share a home directory encrypted by the current user's unsynced profile
#   encrypted/home ~
#  Share an unencrypted directory between chroots.
#   shared/home ~/Share
#  Absolute directories on the chroot side work too
#   shared/bin /usr/local/bin exec,suid
#  Share a noexec path that has spaces, and a specific user home directory
#   "encrypted/stupid example" "~omg/Why are you even doing this?" noexec

# Share the downloads folder of the current user's profile
downloads ~/Downloads
EOF
fi
# Bind-mount the stuff in $CHROOT/etc/crouton/shares, unless NOLOGIN is set
if [ -z "$NOLOGIN" -a -f "$shares" ]; then
    localmyfiles='/home/chronos/user/MyFiles'
    if [ ! -d "$localmyfiles" ]; then
        localmyfiles=''
    fi
    localdownloads='/home/chronos/user/Downloads'
    if [ ! -d "$localdownloads" ]; then
        localdownloads=''
    fi
    localencrypted='/home/chronos/user/crouton/shared'
    if [ ! -d "/home/chronos/user" ]; then
        localencrypted=''
    fi
    localshare='/mnt/stateful_partition/crouton/shared'
    # Parse file and split into three lines: src, dest, options
    awk '
        BEGIN {
            PARAMMATCH = "^[ \t]*(\"[^\"]+\"|[^ \t\"]+)([ \t]"
        }
        function strip(s) {
            if (index(s, "\"")) {
                sub("[ \t]*\"", "", s)
                sub("\"[ \t]*", "", s)
            } else {
                gsub("[ \t]", "", s)
            }
            return s
        }
        $1 ~ /^#/ { next }
        match($0, PARAMMATCH ")") {
            dest = substr($0, RLENGTH+1)
            src = strip(substr($0, 1, RLENGTH))
            if (match(dest, PARAMMATCH "|$)")) {
                opts = strip(substr(dest, RLENGTH+1))
                dest = strip(substr(dest, 1, RLENGTH))
                if (src && dest ~ "^[/~]" && opts ~ "^[a-z,]*$") {
                    # Ensure that they end in slashes
                    if (src !~ "/$")
                        src = src "/"
                    if (dest !~ "/$")
                        dest = dest "/"
                    # .. path elements are not allowed
                    if (src !~ "/../" && dest !~ "/../") {
                        print src
                        print dest
                        print opts
                        next
                    }
                }
            }
        }
        /./ {
            print "error"
            print "Invalid syntax in /etc/crouton/shares on line " NR ":\n  " \
                  $0
        }
    ' "$shares" | while read -r src && read -r dest && read -r opts; do
        line="\n  \"$src\" \"$dest\" $opts"
        # Expand src
        case "${src%%/*}" in
            myfile|myfiles)
                if [ -z "$localmyfiles" ]; then
                    echo "Not mounting share (no Chromium OS user):$line" 1>&2
                    continue
                fi
                src="$localmyfiles/${src#*/}";;
            download|downloads)
                if [ -z "$localdownloads" ]; then
                    echo "Not mounting share (no Chromium OS user):$line" 1>&2
                    continue
                fi
                src="$localdownloads/${src#*/}";;
            encrypt|encrypted)
                if [ -z "$localencrypted" ]; then
                    echo "Not mounting share (no Chromium OS user):$line" 1>&2
                    continue
                fi
                src="$localencrypted/${src#*/}";;
            share|shares|shared)
                src="$localshare/${src#*/}";;
            error)
                # Print the error message from awk script.
                echo "$dest" 1>&2
                echo "$opts" 1>&2
                continue;;
            *)
                echo "Invalid share:$line" 1>&2
                continue;;
        esac
        # Expand dest for homedirs
        if [ "${dest#"~"}" != "$dest" ]; then
            destuser="${dest%%/*}"
            if [ "$destuser" = '~' ]; then
                if [ -z "$CHROOTHOME" ]; then
                    echo "Not mounting share (no chroot user):$line" 1>&2
                    continue
                fi
                dest="$CHROOTHOME/${dest#*/}"
            else
                dest="/home/${destuser#"~"}/${dest#*/}"
            fi
        fi
        # Do the bindmount
        mkdir -m 700 -p "$src"
        if ! bindmount "$src" "$dest" "${opts:-exec}"; then
            echo "Failed to mount share:$line" 1>&2
        fi
    done
fi

# Bind-mount /sys recursively, making it a slave in the chroot
if ! mountpoint -q "$CHROOT/sys"; then
    mkdir -p "$CHROOT/sys"
    mount --make-rshared /sys
    mount --rbind /sys "$CHROOT/sys"
    mount --make-rslave "$CHROOT/sys"
    # Unmount selinux in the chroot, make a fake entry to set enforce=0
    if mountpoint -q "$CHROOT/sys/fs/selinux"; then
        umount "$CHROOT/sys/fs/selinux"
        mount -t tmpfs none "$CHROOT/sys/fs/selinux"
        echo 0 > "$CHROOT/sys/fs/selinux/enforce"
        mount -o remount,ro "$CHROOT/sys/fs/selinux"
    fi
fi

# Modify chroot's /sys/class/drm and /dev/dri to avoid vgem/mfgsys
varrundrm="$(fixabslinks '/var/run/drm')"
varrundri="$(fixabslinks '/var/run/dri')"
sysclassdrm="$(fixabslinks '/sys/class/drm')"
devdri="$(fixabslinks '/dev/dri')"
if [ ! -d "$varrundrm" -a -d "$sysclassdrm" -a -d "$devdri" ]; then
    cp -Ta "$sysclassdrm" "$varrundrm"
    cp -Ta "$devdri" "$varrundri"
    for f in "$varrundrm"/*; do
        if [ -h "$f" ] && readlink -- "$f" | grep -qF -e /vgem/ -e mfgsys; then
            rm -f "$f" "$varrundri/${f##*/}"
        fi
    done
    # Scanning of /dev/dri is done sequentially, so make sure there's a card0
    for f in "$varrundri/card"*; do
        [ -e "$varrundri/card0" ] || mv -f "$f" "$varrundri/card0"
    done
    mount --bind "$varrundrm" "$sysclassdrm"
    mount --bind "$varrundri" "$devdri"
fi

# Get croutonversion variables
croutonversion="$CHROOT/usr/local/bin/croutonversion"
CHROOTRELEASE="unknown"
if [ -x "$croutonversion" ]; then
    CHROOTRELEASE="`"$croutonversion" -r 2>/dev/null || echo "$CHROOTRELEASE"`"
fi

# For test machines with low entropy, bind mount /dev/urandom to /dev/random
if [ -n "$CROUTON_WEAK_RANDOM" ]; then
    mount --bind "$CHROOT/dev/urandom" "$CHROOT/dev/random"
fi

# Fix group numbers for critical groups to match Chromium OS. This is necessary
# so that users have access to shared hardware, such as video and audio.
gfile="$CHROOT/etc/group"
if [ -f "$gfile" ]; then
    for group in audio:hwaudio cras:audio cdrom chronos-access:crouton \
                 devbroker-access dialout disk floppy i2c input lp serial \
                 tape tty usb:plugdev uucp video wayland; do
        hostgroup="${group%:*}"
        chrootgroup="${group#*:}"
        gid="$(awk -F: '$1=="'"$hostgroup"'"{print $3; exit}' '/etc/group')"
        curgid="$(awk -F: '$1=="'"$chrootgroup"'"{print $3; exit}' "$gfile")"
        if [ -z "$gid" ]; then
            if [ -z "$curgid" ]; then
                echo "Creating unassociated $chrootgroup group..." 1>&2
                chrootcmd groupadd --system "$chrootgroup"
            fi
            continue
        fi
        if [ "$gid" = "$curgid" ]; then
            continue
        elif [ -z "$curgid" ]; then
            echo "Creating $chrootgroup group with GID $gid..." 1>&2
            groupcmd=groupadd
        else
            echo "Changing $chrootgroup GID from $curgid to $gid..." 1>&2
            groupcmd=groupmod
        fi
        move="`awk -F: '$3=='"$gid"'{print $1; exit}' "$gfile"`"
        if [ -n "$move" ]; then
            ngid="$gid"
            while grep -q ":$ngid:" "$gfile"; do
                ngid="$((ngid+1))"
            done
            echo "Moving $move GID from $gid to $ngid..." 1>&2
            chrootcmd groupmod -g "$ngid" "$move"
        fi
        chrootcmd "$groupcmd" -g "$gid" "$chrootgroup"
    done
fi

# To run silently, we override the env command to launch a background process,
# and move the trap code to happen there.
if [ -n "$BACKGROUND" ]; then
    env() {
        # Shuffle FDs around to preserve stdin
        { (
            trap '' INT HUP
            trap "$TRAP" 0
            exec 0<&9 9<&-
            [ -t 0 ] && exec < /dev/null
            [ -t 1 ] && exec > /dev/null
            [ -t 2 ] && exec 2>&1
            /usr/bin/env "$@"
        ) & } 9<&0
    }
fi

ret=0

# Launch the system dbus unless we are entering a basic shell.
if [ "$NOLOGIN" != 1 ] && grep -q '^root:' "$passwd" 2>/dev/null; then
    # Try to detect the dbus user by parsing its configuration file
    # If it fails, or if the user does not exist, `id -un '$dbususer'`
    # will fail, and we fallback on a default user name ("messagebus")
    dbususer="`echo "cat /busconfig/user/text()" \
        | xmllint --shell "$CHROOT/etc/dbus-1/system.conf" 2>/dev/null \
        | grep '^[a-z][-a-z0-9_]*$' || true`"
    chrootcmd "
        if ! hash dbus-daemon 2>/dev/null; then
            exit 0
        fi
        dbususer='$dbususer'"'
        pidfile="/var/run/dbus/pid"
        if [ -f "$pidfile" ]; then
            if grep -q "^dbus-daemon" "/proc/`cat "$pidfile"`/cmdline" \
                    2>/dev/null; then
                exit 0
            fi
            rm -f "$pidfile"
        fi
        mkdir -p /var/run/dbus
        dbususer="`id -un "$dbususer" 2>/dev/null || echo "messagebus"`"
        dbusgrp="`id -gn "$dbususer" 2>/dev/null || echo "messagebus"`"
        chown "$dbususer:$dbusgrp" /var/run/dbus
        exec dbus-daemon --system --fork' || ret=$?
    if [ "$ret" != 0 ]; then
        echo "WARNING: starting chroot system dbus daemon failed with code $ret" 1>&2
        ret=0
    fi

    # Launch systemd-logind if available and not already running
    # Whitelisted for saucy and trusty
    systemd_dir="`fixabslinks '/run/systemd'`"
    if [ -x "$CHROOT/lib/systemd/systemd-logind" ] && \
            [ ! -d "$systemd_dir" ] && \
            [ "$CHROOTRELEASE" = 'saucy' -o "$CHROOTRELEASE" = 'trusty' ]; then
        # Every piece of systemd code ever assumes that this directory exists
        mkdir -p "$systemd_dir"

        # Create systemd cgroup if necessary
        if ! mountpoint -q "$CHROOT/sys/fs/cgroup/systemd"; then
            mkdir -p "$CHROOT/sys/fs/cgroup/systemd"
            mount -t cgroup -o nosuid,noexec,nodev,none,name=systemd systemd \
                  "$CHROOT/sys/fs/cgroup/systemd"
        fi
        # systemd-logind doesn't fork
        chrootcmd "/lib/systemd/systemd-logind >/dev/null 2>&1 </dev/null &"
    fi

    chrootcmd "/usr/local/bin/croutonfindnacld >/dev/null 2>&1 </dev/null &"
fi

# Start the chroot and any specified command
if [ -n "$NOLOGIN" ]; then
    env -i TERM="$TERM" chroot "$CHROOT" "$@" || ret=$?
    # Handle the return value when running the setup script.
    if [ "$NOLOGIN" = 2 ]; then
        # If it succeeded yet still exists, run it again.
        if [ "$ret" = 0 -a -f "$CHROOT$SETUPSCRIPT" ]; then
            sh -e "$BINDIR/unmount-chroot" -yxc "$CHROOTS" -- "$NAME"
            # We don't need to return from this.
            exec sh -e "$BINDIR/enter-chroot" -c "$CHROOTS" -n "$NAME" -xx
        elif [ "$ret" != 0 ]; then
            error "$ret" 'Failed to complete chroot setup.'
        fi
    fi
else
    # Check and run rc.local
    if [ -n "$firstrun" -a -x "$CHROOT/etc/rc.local" ]; then
        ( sleep 10; echo "Still running chroot's rc.local..." 2>&1 ) &
        noticepid="$!"
        addtrap "kill '$noticepid' 2>/dev/null"
        chrootcmd 'exec /etc/rc.local >/dev/null 2>/dev/null </dev/null' \
            || ret=$?
        undotrap
        kill "$noticepid" 2>/dev/null || true
        wait "$noticepid" || true
        if [ "$ret" != 0 ]; then
            echo "WARNING: /etc/rc.local failed with code $ret" 1>&2
            ret=0
        fi
    fi

    if [ $# = 0 -o -n "$LOGIN" ]; then
        env -i TERM="$TERM" chroot "$CHROOT" "$@" su - "$USERNAME" || ret=$?
    else
        # Escape out the command
        cmd="export SHELL='$CHROOTSHELL';"
        if [ -n "$TMPXMETHOD" ]; then
            cmd="$cmd export XMETHOD='$TMPXMETHOD';"
        fi
        for param in "$@"; do
            cmd="$cmd'`echo -n "$param" | sed "s/'/'\\\\\\''/g"`' "
        done
        env -i TERM="$TERM" chroot "$CHROOT" \
            su -s '/bin/sh' -c "$cmd" - "$USERNAME" \
            || ret=$?
    fi
fi

# We don't want to trap for this proccess if we're running in the background
if [ -n "$BACKGROUND" ]; then
    settrap ''
fi

# Cleanup all happens in the exit trap
exit $ret


================================================
FILE: host-bin/mount-chroot
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

APPLICATION="${0##*/}"
BINDIR="`dirname "\`readlink -f -- "$0"\`"`"
CHROOTS="`readlink -m -- "$BINDIR/../chroots"`"
CREATE=''
ENCRYPT=''
KEYFILE=''
PRINT=''
ROOT="`readlink -m -- '/var/run/crouton'`"
MOUNTOPTS='rw,dev,exec,suid'
METRICSDIR='/run/metrics/external/crouton'

USAGE="$APPLICATION [options] name [...]

Mounts one or more chroots into a root-only subdirectory of $ROOT

Options:
    -c CHROOTS  Directory the chroots are in. Default: $CHROOTS
    -e          If the chroot is not encrypted, encrypt it.
                If specified twice, prompt to change the encryption passphrase.
    -k KEYFILE  File or directory to store the (encrypted) encryption keys in.
                If unspecified, the keys will be stored in the chroot if doing a
                first encryption, or auto-detected on existing chroots.
    -n          Create the chroot if it doesn't exist.
    -p          Prints out the path to the mounted directory on stdout."

# Common functions
. "$BINDIR/../installer/functions"

# Process arguments
getopts_string='c:ek:np'
while getopts_nextarg; do
    case "$getopts_var" in
    c) CHROOTS="`readlink -m -- "$getopts_arg"`";;
    e) ENCRYPT="$((ENCRYPT+1))";;
    k) KEYFILE="$getopts_arg";;
    n) CREATE='y';;
    p) PRINT='y';;
    \?) error 2 "$USAGE";;
    esac
done

# Need at least one chroot listed
if [ $# = 0 ]; then
    error 2 "$USAGE"
fi

# We need to run as root
if [ "$USER" != root -a "$UID" != 0 ]; then
    error 2 "$APPLICATION must be run as root."
fi

# Make sure we always exit with echo on the tty.
addtrap "stty echo 2>/dev/null"

# Whitelists a directory for symlink and other hardening
whitelist() {
    # As of 67, symlinks and fifos are blocked in stateful partitions.
    # Add exceptions for this chroot.
    local sec='/sys/kernel/security' mounted=''
    if mountpoint -q "$sec"; then
        mounted=y
    elif ! mount -n -t securityfs -o nodev,noexec,nosuid securityfs "$sec"; then
        return
    fi
    # Ensure it's mounted rw
    if ! mount -o remount,rw "$sec"; then
        echo "Failed to make inode security policies writeable" >&2
        return 1
    fi
    policies="$sec/chromiumos/inode_security_policies"
    if [ -d "$policies" ]; then
        # Touch allow_symlink first to avoid kernel crash on chromeos-5.15 R126.
        printf "$CHROOT" > "$policies/allow_symlink"
        printf "$CHROOT" > "$policies/allow_fifo"
    fi
    if [ -z "$mounted" ]; then
        umount "$sec"
    fi
}

# Function to prompt the user for a passphrase. Sets $passphrase.
promptNewPassphrase() {
    echo_tty -n "Choose an encryption passphrase for $NAME: "
    [ -t 0 ] && stty -echo
    while [ -z "$passphrase" ]; do
        read -r passphrase
        if [ -z "$passphrase" ]; then
            echo_tty ''
            echo_tty -n 'You must specify a passphrase: '
            continue
        fi
        echo_tty ''
        echo_tty -n 'Please confirm your passphrase: '
        read -r confirmation
        if [ "$confirmation" != "$passphrase" ]; then
            passphrase=''
            echo_tty ''
            echo_tty -n 'Passphrases do not match; try again: '
        fi
        confirmation=''
    done
    [ -t 0 ] && stty echo
    echo_tty ''
}

# Mount each chroot
for NAME in "$@"; do
    if ! validate_name "$NAME"; then
        error 2 "Invalid chroot name '$NAME'."
    fi

    # Check for existence
    CHROOT="$CHROOTS/$NAME"
    movesrc=''
    if [ -d "$CHROOT" ]; then
        if [ -f "$CHROOT/.ecryptfs" -o -n "$ENCRYPT" ]; then
            if [ -z "$ENCRYPT" ]; then
                ENCRYPT=0
            fi
            # Check for non-encrypted files that we may need to move
            for file in "$CHROOT/"*; do
                if [ "${file#*/ECRYPTFS_FNEK_ENCRYPTED}" = "$file" ]; then
                    movesrc="$CHROOT"
                    break
                fi
            done
        fi
    elif [ -z "$CREATE" ]; then
        error 1 "$CHROOT not found."
    else
        mkdir -p "$CHROOT"
    fi

    CHROOTSRC="$CHROOT"
    CHROOT="$ROOT/${CHROOT#/}"

    # Ensure there's a root-only folder for the bind-mounted chroot
    mkdir -p -m 0700 "$CHROOT"
    chown root:root "$ROOT"
    chmod 700 "$ROOT"

    # Extraordinarily vague usage stat; see https://crbug.com/989219
    if [ -z "${CROUTON_DISABLE_STATS-}" -a -d "${METRICSDIR%/*}" ]; then
        mkdir -p -m 0777 "$METRICSDIR"
        chown root:root "$METRICSDIR"
        chmod 777 "$METRICSDIR"
        touch "$METRICSDIR/crouton-started"
    fi || true

    if [ -n "$PRINT" ]; then
        echo "$CHROOT"
    fi

    # Check if we actually need to mount
    if ! mountpoint -q "$CHROOT"; then
        if [ -z "$ENCRYPT" ]; then
            mount --bind "$CHROOTSRC" "$CHROOT"
            mount -i -o "remount,$MOUNTOPTS" "$CHROOT"
            mount -i -o 'remount,symfollow' "$CHROOT" 2>/dev/null || true
            mount --make-private "$CHROOT"
            whitelist "$CHROOT"
            continue
        fi

        # We must be on a terminal, unless we already have a password in env.
        if [ ! -t 0 -a -z "$CROUTON_PASSPHRASE$CROUTON_NEW_PASSPHRASE" ]; then
            error 2 'STDIN is not a terminal; cannot request passwords.'
        fi

        # Ensure that there's a root password set before decrypting the chroot,
        # unless the passphrase was specified via env, which isn't secure anyway
        if [ ! -f '/mnt/stateful_partition/etc/devmode.passwd' ]; then
            echo_tty \
'You must have a root password in Chromium OS to mount encrypted chroots.'
            if [ -z "$CROUTON_PASSPHRASE$CROUTON_NEW_PASSPHRASE" ]; then
                while ! chromeos-setdevpasswd; do :; done
            fi
        fi

        # Detect the key file
        if [ -z "$KEYFILE" ]; then
            KEYFILE="$CHROOTSRC/.ecryptfs"
            if [ -f "$KEYFILE" ]; then
                header="`head -n1 "$KEYFILE"`"
                if [ -n "$header" ]; then
                    KEYFILE="$header"
                fi
            fi
        elif [ "${KEYFILE#/}" = "$KEYFILE" ]; then
            KEYFILE="$PWD/$KEYFILE"
        fi
        if [ -d "$KEYFILE" -o "${KEYFILE%/}" != "$KEYFILE" ]; then
            KEYFILE="${KEYFILE%/}/$NAME"
        fi
        if ! mkdir -p "`dirname "$KEYFILE"`"; then
            error 1 "Unable to create directory for $KEYFILE"
        fi

        # If we just created it, choose and create the keyfile.
        passphrase="${CROUTON_PASSPHRASE:-"$CROUTON_NEW_PASSPHRASE"}"
        if [ ! -f "$CHROOTSRC/.ecryptfs" ]; then
            if [ -e "$KEYFILE" ]; then
                error 1 "Encryption key file $KEYFILE already exists. Refusing to overwrite!"
            fi

            promptNewPassphrase

            if [ -z "$CROUTON_WEAK_RANDOM" ]; then
                random="/dev/random"
                echo 'Generating keys (move the mouse to generate entropy)...' 1>&2
            else
                random="/dev/urandom"
                echo 'Generating keys from /dev/urandom...' 1>&2
            fi
            key="`hexdump -v -n32 -e'32/1 "%02x"' "$random"`"
            fnek="`hexdump -v -n32 -e'32/1 "%02x"' "$random"`"
            echo 'done' 1>&2

            # Create key file
            wrappedkey="`mktemp`"
            wrappedfnek="`mktemp`"
            addtrap "rm -f '$wrappedkey' '$wrappedfnek'"
            echo -n "$key
$passphrase" | ecryptfs-wrap-passphrase "$wrappedkey" -
            echo -n "$fnek
$passphrase" | ecryptfs-wrap-passphrase "$wrappedfnek" -
            unset key fnek
            echo | cat - "$wrappedkey" "$wrappedfnek" > "$KEYFILE"
            if [ ! -f "$CHROOTSRC/.ecryptfs" ]; then
                echo "$KEYFILE" > "$CHROOTSRC/.ecryptfs"
            fi
        elif [ ! -f "$KEYFILE" ]; then
            error 1 "Unable to find encryption key file $KEYFILE"
        else
            echo_tty -n "Enter encryption passphrase for $NAME: "
            [ -t 0 ] && stty -echo
            if [ -z "$passphrase" ]; then
                read -r passphrase
            fi
            [ -t 0 ] && stty echo
            echo_tty ''

            wrappedkey="`mktemp`"
            wrappedfnek="`mktemp`"
            addtrap "rm -f '$wrappedkey' '$wrappedfnek'"

            # Extract wrapped keys from keyfile
            wrappedtotal="$(($(wc -c < "$KEYFILE") - $(head -n 1 "$KEYFILE" | wc -c)))"
            wrappedsize="$((wrappedtotal / 2))"
            tail -c "$wrappedtotal" "$KEYFILE" | head -c "$wrappedsize" > "$wrappedkey"
            tail -c "$wrappedsize" "$KEYFILE" > "$wrappedfnek"

            # Change the passphrase if requested
            if [ "${ENCRYPT:-0}" -ge 2 ]; then
                oldpassphrase="$passphrase"
                passphrase="$CROUTON_NEW_PASSPHRASE"
                promptNewPassphrase

                echo "Applying passphrase change" 1>&2
                echo -n "$oldpassphrase
$passphrase" | ecryptfs-rewrap-passphrase "$wrappedkey" -
                echo -n "$oldpassphrase
$passphrase" | ecryptfs-rewrap-passphrase "$wrappedfnek" -
                echo | cat - "$wrappedkey" "$wrappedfnek" > "$KEYFILE"

                unset oldpassphrase
            fi
        fi

        # Add keys to keychain and extract
        keysig="`echo -n "$passphrase" \
            | ecryptfs-unwrap-passphrase "$wrappedkey" - 2>/dev/null \
            | ecryptfs-add-passphrase - 2>/dev/null \
            | sed -n 's/.*\[\([0-9a-zA-Z]*\)\].*/\1/p'`"
        fneksig="`echo -n "$passphrase" \
            | ecryptfs-unwrap-passphrase "$wrappedfnek" - 2>/dev/null \
            | ecryptfs-add-passphrase - 2>/dev/null \
            | sed -n 's/.*\[\([0-9a-zA-Z]*\)\].*/\1/p'`"
        if [ -z "$keysig" -o -z "$fneksig" ]; then
            error 1 "Failed to decrypt $NAME."
        fi

        # Create a new session, and link user keyring to that session,
        # as required by ecryptfs.
        keyctl new_session >/dev/null
        keyctl link @u @s

        mnt="ecryptfs_sig=$keysig,ecryptfs_fnek_sig=$fneksig"
        mnt="$mnt,ecryptfs_cipher=aes,ecryptfs_key_bytes=16"
        mnt="$mnt,ecryptfs_unlink_sigs,$MOUNTOPTS"

        if ! mount -i -t ecryptfs -o "$mnt" "$CHROOTSRC" "$CHROOT"; then
            error 1 "Failed to mount $NAME."
        fi

        mount -i -o 'remount,symfollow' "$CHROOT" 2>/dev/null || true

        whitelist "$CHROOT"
    fi

    # Perform the move
    if [ -z "$movesrc" ]; then
        continue
    fi
    response=y
    for file in "$movesrc/"*; do
        if [ "${file#*/ECRYPTFS_FNEK_ENCRYPTED}" != "$file" ]; then
            echo -n \
"About to continue encrypting the unencrypted portion of $NAME.
If this is unexpected, then it could mean that someone's trying to inject files
into your encrypted chroot, potentially allowing them to steal your data.
Please choose one of the following options:
yes  -- You are sure you want to continue moving the files in. They're yours.
del  -- You do not like these files and want them deleted permanently.
list -- You do not know what these files are and want to list them.
no   -- You don't want to decide one way or another quite yet.
> " 1>&2
            # Don't allow a response to be specified in env unless the password
            # was also specified in env.
            if [ -n "$CROUTON_PASSPHRASE" -a \
                    -n "$CROUTON_MOUNT_RESPONSE" ]; then
                response="$CROUTON_MOUNT_RESPONSE"
                echo "$response" 1>&2
            else
                read -r response
            fi
            break
        fi
    done
    case "$response" in
    y*|Y*) (
        echo -n "Encrypting $NAME; please wait..." 1>&2
        cd "$movesrc"
        tmp="`mktemp -d --tmpdir=. 'ECRYPTFS_MOVE_STAGING_XXXXXX'`"
        find -not -name 'ECRYPTFS_FNEK_ENCRYPTED*' \
             -not -wholename './ECRYPTFS_MOVE_STAGING_*' \
             -not -wholename '.' \
             -not -wholename './.ecryptfs' \
             -not -wholename './.crouton-targets' \
             -exec mkdir -p "$tmp/{}" ';' \
             -exec rmdir "$tmp/{}" ';' \
             '(' -prune , -exec mv -fT '{}' "$tmp/{}" ';' ')' 1>&2
        for tmp in ECRYPTFS_MOVE_STAGING_*; do
            (
                cd "$tmp"
                find '!' '(' -type d -exec test -d "$CHROOT/{}" ';' ')' \
                     '(' -prune , -exec mv -fT '{}' "$CHROOT/{}" ';' ')' \
                     -exec echo -n . ';' 1>&2
                find -depth -type d -not -wholename . \
                     -exec test -d "$CHROOT/{}" ';' \
                     -exec rmdir '{}' ';' 1>&2
            )
            rmdir "$tmp" 2>/dev/null || true
        done
        echo 'done.' 1>&2
    );;
    d*|D*) (
        echo "Deleting unencrypted files in $NAME; please wait..." 1>&2
        cd "$movesrc"
        find -not -name 'ECRYPTFS_FNEK_ENCRYPTED*' \
             -not -wholename '.' \
             -not -wholename './.ecryptfs' \
             -not -wholename './.crouton-targets' \
             '(' -prune , -exec rm -rvf '{}' ';' ')' 1>&2
        echo 'Done.' 1>&2
    );;
    l*|L*) (
        echo "Listing unencrypted files in $NAME; please wait..." 1>&2
        cd "$movesrc"
        find -not -name 'ECRYPTFS_FNEK_ENCRYPTED*' \
             -not -name 'ECRYPTFS_MOVE_STAGING_*' \
             -not -wholename '.' \
             -not -wholename './.ecryptfs' \
             -not -wholename './.crouton-targets' \
             -print -prune | cut -b2- 1>&2
        echo 'Done.' 1>&2
        exit 2
    );;
    esac
done

exit 0


================================================
FILE: host-bin/startcli
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

APPLICATION="${0##*/}"

USAGE="$APPLICATION [options]

Wraps enter-chroot to start a CLI session in a new VT.
By default, it will log into the primary user on the first chroot found.

Options are directly passed to enter-chroot; run enter-chroot to list them."

if [ -f /sbin/frecon ]; then
    # Until we get a stable interface to controlling frecon, just use the pty
    openvt=''
else
    openvt='openvt -vws --'
fi

export TERM='linux'
exec sh -e "`dirname "\`readlink -f -- "$0"\`"`/enter-chroot" -t cli-extra -l \
    "$@" "" $openvt


================================================
FILE: host-bin/starte17
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

APPLICATION="${0##*/}"

USAGE="$APPLICATION [options]

Wraps enter-chroot to start an e17 session.
By default, it will log into the primary user on the first chroot found.

Options are directly passed to enter-chroot; run enter-chroot to list them."

exec sh -e "`dirname "\`readlink -f -- "$0"\`"`/enter-chroot" -t e17 "$@" "" \
    exec xinit /usr/bin/enlightenment_start


================================================
FILE: host-bin/startgnome
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

APPLICATION="${0##*/}"

USAGE="$APPLICATION [options]

Wraps enter-chroot to start a GNOME session.
By default, it will log into the primary user on the first chroot found.

Options are directly passed to enter-chroot; run enter-chroot to list them."

exec sh -e "`dirname "\`readlink -f -- "$0"\`"`/enter-chroot" -t gnome "$@" "" \
    exec startgnome


================================================
FILE: host-bin/startkde
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

APPLICATION="${0##*/}"

USAGE="$APPLICATION [options]

Wraps enter-chroot to start a KDE session.
By default, it will log into the primary user on the first chroot found.

Options are directly passed to enter-chroot; run enter-chroot to list them."

exec sh -e "`dirname "\`readlink -f -- "$0"\`"`/enter-chroot" -t kde "$@" "" \
    exec xinit /usr/bin/startkde


================================================
FILE: host-bin/startkodi
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

APPLICATION="${0##*/}"

USAGE="$APPLICATION [options]

Wraps enter-chroot to start an KODI session.
By default, it will log into the primary user on the first chroot found.

Options are directly passed to enter-chroot; run enter-chroot to list them."

exec sh -e "`dirname "\`readlink -f -- "$0"\`"`/enter-chroot" -t kodi "$@" "" \
    exec croutonpowerd -i xinit /usr/bin/kodi --standalone


================================================
FILE: host-bin/startlxde
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

APPLICATION="${0##*/}"

USAGE="$APPLICATION [options]

Wraps enter-chroot to start an LXDE session.
By default, it will log into the primary user on the first chroot found.

Options are directly passed to enter-chroot; run enter-chroot to list them."

exec sh -e "`dirname "\`readlink -f -- "$0"\`"`/enter-chroot" -t lxde "$@" "" \
    exec xinit /usr/bin/startlxde


================================================
FILE: host-bin/startunity
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

APPLICATION="${0##*/}"

USAGE="$APPLICATION [options]

Wraps enter-chroot to start a Unity session.
By default, it will log into the primary user on the first chroot found.

Options are directly passed to enter-chroot; run enter-chroot to list them."

exec sh -e "`dirname "\`readlink -f -- "$0"\`"`/enter-chroot" -t unity "$@" "" \
    exec startunity


================================================
FILE: host-bin/startxfce4
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

APPLICATION="${0##*/}"

USAGE="$APPLICATION [options]

Wraps enter-chroot to start an Xfce session.
By default, it will log into the primary user on the first chroot found.

Options are directly passed to enter-chroot; run enter-chroot to list them."

exec sh -e "`dirname "\`readlink -f -- "$0"\`"`/enter-chroot" -t xfce "$@" "" \
    exec startxfce4


================================================
FILE: host-bin/startxiwi
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

APPLICATION="${0##*/}"
ENTERCHROOT="$(dirname "$(readlink -f -- "$0")")/enter-chroot"
OPTS_ENTER=''
OPTS_XIWI=''

USAGE="$APPLICATION [options] chroot_app [parameters]

Wraps enter-chroot to launch a window or tab in Chromium OS for any graphical application.
Applications launched in this way show in independent windows or tabs.

By default, it will use the primary user on the first xiwi-enabled chroot found and launch
the chroot_app in a window.

Options:
$("$ENTERCHROOT" -h 2>&1 | grep -e ' -[bckntu]')
    -F          Launch the chroot_app full-screen.
    -T          Launch the chroot_app in a tab.
    -f          Prevent xiwi from quitting automatically. (see NOTE below)

NOTE:
xiwi will normally close when the application returns. Some gui applications
fork before or during normal operation, which can confuse xiwi and cause it to
quit prematurely. If your application does not have a parameter that prevents
it from forking, and crouton is unable to automatically detect the fork, you can
use -f to prevent xiwi from quitting automatically.
xiwi will quit if you close the Chromium OS window when nothing is displayed.
  
You can cycle through multiple windows inside the application
via Ctrl-Alt-Tab/Ctrl-Alt-Shift-Tab, or close them via Ctrl-Alt-Shift-Escape.
If the chroot_app begins with 'start' but you still want to
use the default window manager, specify the full path of the application.
"

while getopts 'bc:k:n:t:u:FTf' OPT; do
    case "$OPT" in
      b) OPTS_ENTER="$OPTS_ENTER -$OPT";;
      c|k|n|t|u)
         OPTARG="$(echo -n "$OPTARG" | sed -e "s/'/'\\\\\\''/g")"
         OPTS_ENTER="$OPTS_ENTER -$OPT '$OPTARG'";;
      f|F|T) OPTS_XIWI="$OPTS_XIWI -$OPT";;
      \?) echo "$USAGE" 1>&2
          exit 2;;
    esac
done
shift "$((OPTIND-1))"

if [ "$#" = "0" ]; then 
    echo "$USAGE" 1>&2
    exit 2
fi

eval "exec sh -e \"\$ENTERCHROOT\" -t xiwi $OPTS_ENTER \
    exec xiwi $OPTS_XIWI \"\$@\""
    


================================================
FILE: host-bin/unmount-chroot
================================================
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

APPLICATION="${0##*/}"
ALLCHROOTS=''
BINDIR="`dirname "\`readlink -f -- "$0"\`"`"
CHROOTS="`readlink -m -- "$BINDIR/../chroots"`"
EXCLUDEROOT=''
FORCE=''
PRINT=''
SIGNAL='TERM'
TRIES=5
YES=''
ROOT="`readlink -m -- '/var/run/crouton'`"

USAGE="$APPLICATION [options] name [...]

Unmounts one or more chroots, optionally killing any processes still running
inside them.

By default, it will run in interactive mode where it will ask to kill any
remaining processes if unable to unmount the chroot within 5 seconds.

Options:
    -a          Unmount all chroots in the CHROOTS directory.
    -c CHROOTS  Directory the chroots are in. Default: $CHROOTS
    -f          Forces a chroot to unmount, potentially breaking or killing
                other instances of the same chroot.
    -k KILL     Send the processes SIGKILL instead of SIGTERM.
    -p          Print to STDOUT the processes stopping a chroot from unmounting.
    -t TRIES    Number of seconds to try before signalling the processes.
                Use -t inf to be exceedingly patient. Default: $TRIES
    -x          Keep the root directory of the chroot mounted.
    -y          Signal any remaining processes without confirmation.
                Automatically escalates from SIGTERM to SIGKILL."

# Common functions
. "$BINDIR/../installer/functions"

# Process arguments
getopts_string='ac:fkpt:xy'
while getopts_nextarg; do
    case "$getopts_var" in
    a) ALLCHROOTS='y';;
    c) CHROOTS="`readlink -m -- "$getopts_arg"`";;
    f) FORCE='y';;
    k) SIGNAL="KILL";;
    p) PRINT='y';;
    t) TRIES="$getopts_arg";;
    x) EXCLUDEROOT='y';;
    y) YES='a';;
    \?) error 2 "$USAGE";;
    esac
done

# Need at least one chroot listed, or -a; not both.
if [ $# = 0 -a -z "$ALLCHROOTS" ] || [ $# != 0 -a -n "$ALLCHROOTS" ]; then
    error 2 "$USAGE"
fi

# Make sure TRIES is valid
if [ "$TRIES" = inf ]; then
    TRIES=-1
elif [ "$TRIES" -lt -1 ]; then
    error 2 "$USAGE"
fi

# We need to run as root
if [ "$USER" != root -a "$UID" != 0 ]; then
    error 2 "$APPLICATION must be run as root."
fi

# Check if a chroot is running with this directory. We detect the
# appropriate commands by checking if the command's parent root is not equal
# to the pid's root. This avoids not unmounting due to a lazy-quitting
# background application within the chroot. We also don't consider processes
# that have a parent PID of 1 or that of session_manager's (which would mean an
# orphaned process in this case), as enter-chroot never orphans its children.
# $1: $base; the canonicalized base path of the chroot
# Returns: non-zero if the chroot is in use.
checkusage() {
    if [ -n "$FORCE" ]; then
        return 0
    fi
    local b="${1%/}/" pid ppid proot prootdir root rootdir pids=''
    local smgrpid="`pgrep -o -u 0 -x session_manager || echo 1`"
    for root in /proc/*/root; do
        if [ ! -r "$root" ]; then
            continue
        fi
        rootdir="`readlink -f -- "$root"`"
        rootdir="${rootdir%/}/"
        if [ "${rootdir#"$b"}" = "$rootdir" ]; then
            continue
        fi
        pid="${root#/proc/}"
        pid="${pid%/root}"
        ppid="`ps -p "$pid" -o ppid= 2>/dev/null | sed 's/ //g'`"
        if [ -z "$ppid" ] || [ "$ppid" -eq 1 -o "$ppid" -eq "$smgrpid" ]; then
            continue
        fi
        proot="/proc/$ppid/root"
        if [ -r "$proot" ]; then
            prootdir="`readlink -f -- "$proot"`"
            if [ "${prootdir%/}/" = "$rootdir" ]; then
                continue
            fi
        fi
        if [ -n "$PRINT" ]; then
            pids="$pids $pid"
            continue
        fi
        return 1
    done
    if [ -n "$PRINT" -a -n "$pids" ]; then
        ps -p "${pids# }" -o pid= -o cmd= || true
        return 1
    fi
    return 0
}

# If we specified all chroots, bring in all chroots.
if [ -n "$ALLCHROOTS" ]; then
    if [ ! -d "$CHROOTS" ]; then
        error 1 "$CHROOTS not found."
    fi
    set -- "$CHROOTS/"*
fi

# Follows and fixes dangerous symlinks, returning the canonicalized path.
fixabslinks() {
    local p="$CHROOT/$1" c
    # Follow and fix dangerous absolute symlinks
    while c="`readlink -m -- "$p"`" && [ "$c" != "$p" ]; do
        p="$CHROOT${c#"$CHROOT"}"
    done
    echo "$p"
}

# Unmount the specified chroot $1
# sets oldstyle if the chroot was unmounted in an old location.
# if oldstyle is set upon entry, skips the check for old-style mounts.
unmount() {
    NAME="${1#"$CHROOTS/"}"

    # Check for existence
    CHROOT="$CHROOTS/$NAME"
    if [ ! -d "$CHROOT" ]; then
        if [ -z "$ALLCHROOTS" ]; then
            echo "$CHROOT not found." 1>&2
            ret=1
        fi
        return 0
    fi

    # Switch to the true mount point, but sort of support old-style mounted
    # chroots with minimal false-positives to ease transition. Don't unmount
    # old-style twice in a row, though.
    CHROOTSRC="$CHROOT"
    oldencr="$CHROOTS/.secure/$NAME"
    if mountpoint -q "$oldencr" \
            && [ -d "$oldencr/etc/crouton" -a -z "$oldstyle" ]; then
        # Old encrypted chroots
        oldstyle='y'
        CHROOT="$oldencr"
        echo "$CHROOTSRC appears to be mounted in $CHROOT" 1>&2
    elif mountpoint -q "$CHROOT" \
            && [ -d "$CHROOT/etc/crouton" -a -z "$oldstyle" ]; then
        # Keep the chroot the same
        oldstyle='y'
        echo "$CHROOTSRC appears to be mounted in place" 1>&2
    else
        oldstyle=''
        CHROOT="$ROOT/${CHROOT#/}"
        if [ ! -d "$CHROOT" ]; then
            # Not mounted
            return 0
        fi
    fi

    base="`readlink -f -- "$CHROOT"`"

    if ! checkusage "$base"; then
        echo "Not unmounting $CHROOTSRC as another instance is using it." 1>&2
        ret=1
        return 0
    fi

    # Kill the chroot's system dbus if one is running; failure is fine
    env -i chroot "$CHROOT" su -s '/bin/sh' -c '
        pidfile="/var/run/dbus/pid"
        if [ ! -f "$pidfile" ]; then
            exit 0
        fi
        pid="`cat "$pidfile"`"
        if ! grep -q "^dbus-daemon" "/proc/$pid/cmdline" 2>/dev/null; then
            exit 0
        fi
        kill $pid' - root 2>/dev/null || true

    # Unmount all mounts
    ntries=0
    if [ -z "$EXCLUDEROOT" ]; then
        echo "Unmounting $CHROOTSRC..." 1>&2
    else
        echo "Pruning $CHROOTSRC mounts..." 1>&2
    fi
    baseesc="`echo "$base" | sed 's= =//=g'`"

    # Def
Download .txt
gitextract_imr3a977/

├── .github/
│   ├── CONTRIBUTING.md
│   └── ISSUE_TEMPLATE.md
├── .gitignore
├── AUTHORS
├── CONTRIBUTORS
├── LICENSE
├── Makefile
├── README.md
├── README.zh.md
├── build/
│   ├── CONTRIBUTORS.sed
│   ├── genversion.sh
│   ├── release.sh
│   └── wrapper.sh
├── chroot-bin/
│   ├── brightness
│   ├── crouton-noroot
│   ├── crouton-unity-autostart
│   ├── croutonclip
│   ├── croutoncycle
│   ├── croutonfindnacl
│   ├── croutonnotify
│   ├── croutonpowerd
│   ├── croutontriggerd
│   ├── croutonurlhandler
│   ├── croutonversion
│   ├── croutonxinitrc-wrapper
│   ├── gnome-session-wrapper
│   ├── host-dbus
│   ├── host-wayland
│   ├── setres
│   ├── startgnome
│   ├── startunity
│   ├── volume
│   ├── xinit
│   └── xiwi
├── chroot-etc/
│   ├── kodi-cycle.py
│   ├── kodi-keyboard.xml
│   ├── pulseaudio-default.pa
│   ├── unity-autostart.desktop
│   ├── unity-profiled
│   ├── xbindkeysrc.scm
│   ├── xiwi.conf
│   ├── xorg-dummy.conf
│   ├── xorg-intel-sna.conf
│   ├── xserverrc
│   ├── xserverrc-local.example
│   ├── xserverrc-xiwi
│   └── xserverrc-xorg
├── host-bin/
│   ├── crash_reporter_wrapper
│   ├── edit-chroot
│   ├── enter-chroot
│   ├── mount-chroot
│   ├── startcli
│   ├── starte17
│   ├── startgnome
│   ├── startkde
│   ├── startkodi
│   ├── startlxde
│   ├── startunity
│   ├── startxfce4
│   ├── startxiwi
│   └── unmount-chroot
├── host-ext/
│   ├── .gitignore
│   ├── crouton/
│   │   ├── background.html
│   │   ├── background.js
│   │   ├── first.html
│   │   ├── kiwi.nmf
│   │   ├── manifest.json
│   │   ├── popup.html
│   │   ├── popup.js
│   │   ├── window.html
│   │   └── window.js
│   ├── gencrx.sh
│   └── nacl_src/
│       ├── .gitignore
│       ├── Makefile
│       ├── keycode_converter.h
│       └── kiwi.cc
├── installer/
│   ├── .gitattributes
│   ├── crouton
│   ├── debian/
│   │   ├── defaults
│   │   └── releases
│   ├── functions
│   ├── kali/
│   │   ├── defaults
│   │   └── releases
│   ├── main.sh
│   ├── prepare.sh
│   └── ubuntu/
│       ├── ar
│       ├── bootstrap
│       ├── defaults
│       ├── getrelease.sh
│       ├── pkgdetails
│       ├── prepare
│       └── releases
├── src/
│   ├── fbserver-proto.h
│   ├── fbserver.c
│   ├── findnacld.c
│   ├── freon.c
│   ├── vtmonitor.c
│   ├── websocket.c
│   ├── websocket.h
│   └── xi2event.c
├── targets/
│   ├── audio
│   ├── chrome
│   ├── chrome-beta
│   ├── chrome-common
│   ├── chrome-dev
│   ├── chromium
│   ├── cli-extra
│   ├── common
│   ├── core
│   ├── e17
│   ├── extension
│   ├── gnome
│   ├── gnome-desktop
│   ├── gtk-extra
│   ├── kde
│   ├── kde-desktop
│   ├── keyboard
│   ├── kodi
│   ├── lxde
│   ├── lxde-desktop
│   ├── post-common
│   ├── touch
│   ├── unity
│   ├── unity-desktop
│   ├── x11
│   ├── x11-common
│   ├── xbmc
│   ├── xfce
│   ├── xfce-desktop
│   ├── xiwi
│   └── xorg
└── test/
    ├── autotest_control.template
    ├── daemon.sh
    ├── genreport.sh
    ├── reports/
    │   ├── 00-all.sh
    │   ├── 35-xorg.sh
    │   └── w0-common.sh
    ├── run.sh
    └── tests/
        ├── 00-tester
        ├── 10-basic
        ├── 11-32-on-64
        ├── 12-edit-chroot
        ├── 14-background
        ├── 15-media
        ├── 16-targetsfile
        ├── 17-encryption
        ├── 18-upgrade
        ├── 20-logind
        ├── 30-audio
        ├── 35-xorg
        ├── 37-xiwi
        ├── w0-common
        ├── w1-e17
        ├── w2-gnome
        ├── w2d-gnome-desktop
        ├── w3-kde
        ├── w3d-kde-desktop
        ├── w4-lxde
        ├── w4d-lxde-desktop
        ├── w5-unity
        ├── w5d-unity-desktop
        ├── w6-kodi
        ├── w7-xfce
        ├── w7d-xfce-desktop
        └── x0-alltargets
Download .txt
SYMBOL INDEX (167 symbols across 12 files)

FILE: host-ext/crouton/background.js
  function setStatus (line 61) | function setStatus(status, active) {
  function showHelp (line 72) | function showHelp() {
  function updateAvailable (line 76) | function updateAvailable(version) {
  function checkUpdate (line 87) | function checkUpdate(force) {
  function updateWindowList (line 102) | function updateWindowList(force) {
  function registerKiwi (line 120) | function registerKiwi(displaynum, window) {
  function closePopup (line 128) | function closePopup() {
  function refreshUI (line 136) | function refreshUI() {
  function clipboardStart (line 304) | function clipboardStart() {
  function websocketConnect (line 329) | function websocketConnect() {
  function websocketOpen (line 359) | function websocketOpen() {
  function readClipboard (line 364) | function readClipboard() {
  function writeClipboard (line 371) | function writeClipboard(str) {
  function websocketMessage (line 378) | function websocketMessage(evt) {
  function websocketClose (line 640) | function websocketClose() {
  function onFocusChanged (line 666) | function onFocusChanged(id, isTab) {
  function onRemoved (line 685) | function onRemoved(id, isTab) {
  function notificationClicked (line 701) | function notificationClicked(id) {
  function notificationClosed (line 709) | function notificationClosed(id, byUser) {
  function padstr0 (line 715) | function padstr0(i) {
  function printLog (line 724) | function printLog(str, level) {
  function error (line 745) | function error(str, enabled) {

FILE: host-ext/crouton/window.js
  function registerWindow (line 31) | function registerWindow(register) {
  function moduleDidLoad (line 37) | function moduleDidLoad() {
  function handleProgress (line 48) | function handleProgress(event) {
  function handleError (line 55) | function handleError(event) {
  function handleCrash (line 64) | function handleCrash(event) {
  function handleRequest (line 74) | function handleRequest(message, sender, sendResponse) {
  function setDebug (line 81) | function setDebug(debug) {
  function setHiDPI (line 97) | function setHiDPI(hidpi) {
  function setTitle (line 105) | function setTitle(title) {
  function setStatus (line 110) | function setStatus(message) {
  function showWarning (line 120) | function showWarning(message) {
  function showError (line 127) | function showError(message) {
  function addInfoLine (line 134) | function addInfoLine(div, message) {
  function handleMessage (line 145) | function handleMessage(message) {
  function kiwiResize (line 226) | function kiwiResize() {
  function handleResize (line 233) | function handleResize() {
  function handleFocusBlur (line 248) | function handleFocusBlur(evt) {

FILE: host-ext/nacl_src/keycode_converter.h
  function class (line 13) | class KeyCode {
  function class (line 36) | class KeyCodeConverter {

FILE: host-ext/nacl_src/kiwi.cc
  class KiwiInstance (line 34) | class KiwiInstance : public pp::Instance {
    method KiwiInstance (line 36) | explicit KiwiInstance(PP_Instance instance): pp::Instance(instance) {}
    method Init (line 41) | virtual bool Init(uint32_t argc, const char* argn[], const char* argv[...
    method HandleMessage (line 57) | virtual void HandleMessage(const pp::Var& var_message) {
    class Message (line 105) | class Message {
      method Message (line 107) | Message(pp::Instance* inst, const std::string& type, bool dummy):
      method Message (line 119) | Message& operator<<(const T& val) {
      method Message (line 124) | Message(Message&& other) = default;
      method Message (line 128) | Message(const Message& other) = delete;
      method Message (line 129) | Message& operator =(const Message&) = delete;
    method Message (line 137) | Message StatusMessage() {
      method Message (line 107) | Message(pp::Instance* inst, const std::string& type, bool dummy):
      method Message (line 119) | Message& operator<<(const T& val) {
      method Message (line 124) | Message(Message&& other) = default;
      method Message (line 128) | Message(const Message& other) = delete;
      method Message (line 129) | Message& operator =(const Message&) = delete;
    method Message (line 142) | Message WarningMessage() {
      method Message (line 107) | Message(pp::Instance* inst, const std::string& type, bool dummy):
      method Message (line 119) | Message& operator<<(const T& val) {
      method Message (line 124) | Message(Message&& other) = default;
      method Message (line 128) | Message(const Message& other) = delete;
      method Message (line 129) | Message& operator =(const Message&) = delete;
    method Message (line 148) | Message ErrorMessage() {
      method Message (line 107) | Message(pp::Instance* inst, const std::string& type, bool dummy):
      method Message (line 119) | Message& operator<<(const T& val) {
      method Message (line 124) | Message(Message&& other) = default;
      method Message (line 128) | Message(const Message& other) = delete;
      method Message (line 129) | Message& operator =(const Message&) = delete;
    method Message (line 153) | Message LogMessage(int level) {
      method Message (line 107) | Message(pp::Instance* inst, const std::string& type, bool dummy):
      method Message (line 119) | Message& operator<<(const T& val) {
      method Message (line 124) | Message(Message&& other) = default;
      method Message (line 128) | Message(const Message& other) = delete;
      method Message (line 129) | Message& operator =(const Message&) = delete;
    method ResizeMessage (line 166) | void ResizeMessage(int width, int height, float scale) {
    method ControlMessage (line 173) | void ControlMessage(const std::string& type, const std::string& str) {
    method SocketConnect (line 181) | void SocketConnect(int32_t /*result*/ = 0) {
    method OnSocketConnectCompletion (line 197) | void OnSocketConnectCompletion(int32_t result) {
    method SocketClose (line 221) | void SocketClose(const std::string& reason) {
    method OnSocketClosed (line 227) | void OnSocketClosed(int32_t result) {
    method CheckSize (line 240) | bool CheckSize(int length, int target, const std::string& type) {
    method SocketParseInitInformation (line 250) | bool SocketParseInitInformation(const char* data, int datalen) {
    method SocketParseVersion (line 260) | bool SocketParseVersion(const char* data, int datalen) {
    method SocketParseScreen (line 292) | bool SocketParseScreen(const char* data, int datalen) {
    method SocketParseCursor (line 335) | bool SocketParseCursor(const char* data, int datalen) {
    method SocketParseResolution (line 380) | bool SocketParseResolution(const char* data, int datalen) {
    method OnSocketReceiveCompletion (line 391) | void OnSocketReceiveCompletion(int32_t result) {
    method SocketReceive (line 462) | void SocketReceive(int32_t /*result*/ = 0) {
    method SocketSend (line 469) | void SocketSend(const pp::Var& var, bool flushmouse) {
    method DidChangeView (line 493) | virtual void DidChangeView(const pp::View& view) {
    method HandleInputEvent (line 501) | virtual bool HandleInputEvent(const pp::InputEvent& event) {
    method InitContext (line 732) | void InitContext() {
    method ChangeResolution (line 760) | void ChangeResolution(int width, int height) {
    method KeyCodeToKeySym (line 780) | uint32_t KeyCodeToKeySym(uint32_t keycode, const std::string& code) {
    method SetTargetFPS (line 851) | void SetTargetFPS(int new_target_fps) {
    method SendClick (line 864) | void SendClick(int button, int down) {
    method SendSearchKey (line 887) | void SendSearchKey(int down) {
    method SendKeySym (line 897) | void SendKeySym(uint32_t keysym, int down) {
    method SendKeyCode (line 912) | void SendKeyCode(uint8_t keycode, int down) {
    method RequestScreen (line 931) | void RequestScreen(int32_t token) {
    method OnFlush (line 971) | void OnFlush(int32_t /*result*/ = 0) {
    method Paint (line 1015) | void Paint(bool blank) {
    class Cursor (line 1103) | class Cursor {
  class KiwiModule (line 1116) | class KiwiModule : public pp::Module {
    method KiwiModule (line 1118) | KiwiModule() : pp::Module() {}
  type pp (line 1126) | namespace pp {
    function Module (line 1128) | Module* CreateModule() {

FILE: src/fbserver-proto.h
  type screen (line 19) | struct  __attribute__((__packed__)) screen {
  type screen_reply (line 30) | struct  __attribute__((__packed__)) screen_reply {
  type cursor (line 42) | struct  __attribute__((__packed__)) cursor {
  type cursor_reply (line 47) | struct  __attribute__((__packed__)) cursor_reply {
  type resolution (line 56) | struct  __attribute__((__packed__)) resolution {
  type key (line 63) | struct  __attribute__((__packed__)) key {
  type key_vf1 (line 71) | struct  __attribute__((__packed__)) key_vf1 {
  type mousemove (line 78) | struct  __attribute__((__packed__)) mousemove {
  type initinfo (line 85) | struct  __attribute__((__packed__)) initinfo {
  type mouseclick (line 91) | struct  __attribute__((__packed__)) mouseclick {

FILE: src/fbserver.c
  type cache_entry (line 35) | struct cache_entry {
  type cache_entry (line 42) | struct cache_entry
  type keybuttontype (line 46) | typedef enum { MOUSE=1, KEYBOARD=2 } keybuttontype;
  type keybutton (line 47) | struct keybutton {
  type keybutton (line 54) | struct keybutton
  function kb_add (line 58) | void kb_add(keybuttontype type, uint32_t code) {
  function kb_remove (line 74) | void kb_remove(keybuttontype type, uint32_t code) {
  function kb_release_all (line 88) | void kb_release_all() {
  function xerror_handler (line 105) | static int xerror_handler(Display *dpy, XErrorEvent *e) {
  function set_connected (line 118) | static void set_connected(Display *dpy, uint8_t connected) {
  function register_damage (line 131) | static void register_damage(Display *dpy, Window win) {
  function init_display (line 140) | static int init_display(char* name) {
  function change_resolution (line 194) | void change_resolution(const struct resolution* rin) {
  function close_mmap (line 237) | void close_mmap(struct cache_entry* entry) {
  function recv_pid_fd (line 249) | int recv_pid_fd(int conn)
  type cache_entry (line 287) | struct cache_entry
  type cache_entry (line 288) | struct cache_entry
  type sockaddr_un (line 328) | struct sockaddr_un
  type sockaddr (line 334) | struct sockaddr
  function write_image (line 380) | int write_image(const struct screen* screen) {
  function write_cursor (line 499) | int write_cursor() {
  function write_init (line 530) | void write_init() {
  function check_size (line 543) | int check_size(int length, int target, char* error) {
  function usage (line 553) | void usage(char* argv0) {
  function main (line 558) | int main(int argc, char** argv) {

FILE: src/findnacld.c
  function send_pid_fd (line 22) | int send_pid_fd(int conn, long pid, int fd)
  function find_nacl (line 56) | int find_nacl(int conn)
  function main (line 117) | int main()

FILE: src/freon.c
  function preload_init (line 49) | static void preload_init() {
  function set_display_lock (line 63) | static int set_display_lock(unsigned int pid) {
  function crtc_set_prop (line 104) | static int32_t crtc_set_prop(int fd, uint32_t crtc_id,
  function drm_reset_props (line 134) | static void drm_reset_props()
  function drm_disable_cursor (line 180) | static void drm_disable_cursor()
  function ioctl (line 217) | int ioctl(int fd, unsigned long int request, ...) {
  function _open (line 283) | static int _open(int (*origfunc)(const char *pathname, int flags, mode_t...
  function open (line 304) | int open(const char *pathname, int flags, ...) {
  function open64 (line 315) | int open64(const char *pathname, int flags, ...) {
  function close (line 326) | int close(int fd) {
  function uid_t (line 339) | uid_t getuid0(void) {

FILE: src/vtmonitor.c
  function main (line 21) | int main(int argc, char **argv) {

FILE: src/websocket.c
  function pipe_open_block (line 37) | static int pipe_open_block(const char* path, int oflag) {
  function pipeout_open (line 62) | static int pipeout_open() {
  function pipeout_close (line 95) | static void pipeout_close() {
  function pipeout_write (line 105) | static int pipeout_write(char* buffer, int len) {
  function pipeout_error (line 122) | static void pipeout_error(char* str) {
  function pipein_reopen (line 137) | static void pipein_reopen() {
  function pipein_read (line 152) | static void pipein_read() {
  function checkfifo (line 275) | int checkfifo(const char* filename) {
  function pipe_init (line 311) | void pipe_init() {
  function socket_client_handle_unrequested (line 353) | static int socket_client_handle_unrequested(const char* buffer,
  function socket_client_read (line 431) | static void socket_client_read() {
  function signal_handler (line 453) | static void signal_handler(int sig) {
  function main (line 457) | int main(int argc, char **argv) {

FILE: src/websocket.h
  function block_read (line 104) | static int block_read(int fd, char* buffer, size_t size) {
  function block_write (line 123) | static int block_write(int fd, char* buffer, size_t size) {
  function popen2 (line 143) | static int popen2(char* cmd, char *const argv[],
  function socket_client_close (line 306) | static void socket_client_close(int sendclose) {
  function socket_client_write_frame (line 330) | static int socket_client_write_frame(char* buffer, unsigned int size,
  function socket_client_read_frame_header (line 382) | static int socket_client_read_frame_header(int* fin, uint32_t* maskkey,
  function socket_client_read_frame_data (line 518) | static int socket_client_read_frame_data(char* buffer, unsigned int size,
  function socket_client_read_frame (line 545) | static int socket_client_read_frame(char* buffer, int size) {
  function socket_client_sendversion (line 578) | static int socket_client_sendversion(char* version) {
  function socket_server_error (line 625) | static void socket_server_error(int newclient_fd, int ok) {
  function socket_server_read_header (line 670) | static int socket_server_read_header(int newclient_fd, char* websocket_k...
  function socket_server_accept (line 806) | static int socket_server_accept(char* version) {
  function socket_server_init (line 905) | static void socket_server_init(int port_) {

FILE: src/xi2event.c
  function print_rawevent (line 18) | static void print_rawevent(XIRawEvent *event) {
  function usage (line 47) | void usage(char* argv0) {
  function main (line 54) | int main(int argc, char *argv[]) {
Condensed preview — 165 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (665K chars).
[
  {
    "path": ".github/CONTRIBUTING.md",
    "chars": 352,
    "preview": "## For users who want to report an issue\nPlease read [this wiki page]\n(https://github.com/dnschneid/crouton/wiki/Common-"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 179,
    "preview": "```\nPlease paste the output of the following command here: sudo edit-chroot -all\n```\n\n#### Please describe your issue:\n\n"
  },
  {
    "path": ".gitignore",
    "chars": 63,
    "preview": "*.tar.*\n.*.swp\n.*.tmp\nnacl_sdk/\n/crouton*\n/test/run\n/releases/\n"
  },
  {
    "path": "AUTHORS",
    "chars": 12,
    "preview": "Google, Inc\n"
  },
  {
    "path": "CONTRIBUTORS",
    "chars": 1064,
    "preview": "Aaron Zauner\nAlex Bennée\nAlfred Suleymanov\nAlfriadox\nAlireza Ghasemi\nAndrew Kanner\nAron Griffis\nAurelien Lourot\nAvi Zaja"
  },
  {
    "path": "LICENSE",
    "chars": 1562,
    "preview": "// Copyright (c) 2016 The crouton Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms,"
  },
  {
    "path": "Makefile",
    "chars": 3521,
    "preview": "# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style lice"
  },
  {
    "path": "README.md",
    "chars": 20537,
    "preview": "# crouton: Chromium OS Universal Chroot Environment\n\ncrouton is a set of scripts that bundle up into an easy-to-use,\nChr"
  },
  {
    "path": "README.zh.md",
    "chars": 3865,
    "preview": "# Crouton中文版教程\r\n\r\n> 基于crouton项目README的英文版进行汉化,部分内容没有进行汉化,建议有能力者优先阅读英文版本。\r\n\r\n## 简介\r\n\r\n​\tChroot是Chromium OS Universal Chro"
  },
  {
    "path": "build/CONTRIBUTORS.sed",
    "chars": 269,
    "preview": "s/^[ \\t0-9]*//\ns/^DennisL.*$/Dennis Lockhart/\ns/^drinkcat$/Nicolas Boichat/\ns/^divx118$/Maurice van Kruchten/\ns/^haberda"
  },
  {
    "path": "build/genversion.sh",
    "chars": 761,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "build/release.sh",
    "chars": 2411,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "build/wrapper.sh",
    "chars": 3851,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/brightness",
    "chars": 1076,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/crouton-noroot",
    "chars": 1001,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/crouton-unity-autostart",
    "chars": 1411,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/croutonclip",
    "chars": 4921,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/croutoncycle",
    "chars": 8365,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/croutonfindnacl",
    "chars": 2612,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/croutonnotify",
    "chars": 3234,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/croutonpowerd",
    "chars": 4190,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/croutontriggerd",
    "chars": 3266,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/croutonurlhandler",
    "chars": 786,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/croutonversion",
    "chars": 4688,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/croutonxinitrc-wrapper",
    "chars": 6079,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/gnome-session-wrapper",
    "chars": 1586,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/host-dbus",
    "chars": 520,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/host-wayland",
    "chars": 782,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/setres",
    "chars": 2645,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/startgnome",
    "chars": 286,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/startunity",
    "chars": 393,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/volume",
    "chars": 4912,
    "preview": "#!/bin/sh\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a BSD-"
  },
  {
    "path": "chroot-bin/xinit",
    "chars": 1100,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-bin/xiwi",
    "chars": 4720,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-etc/kodi-cycle.py",
    "chars": 584,
    "preview": "#!/usr/bin/env python\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is govern"
  },
  {
    "path": "chroot-etc/kodi-keyboard.xml",
    "chars": 628,
    "preview": "<!-- Copyright (c) 2016 The crouton Authors. All rights reserved.           -->\n<!-- Use of this source code is governed"
  },
  {
    "path": "chroot-etc/pulseaudio-default.pa",
    "chars": 492,
    "preview": "#!/usr/bin/pulseaudio -nF\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is go"
  },
  {
    "path": "chroot-etc/unity-autostart.desktop",
    "chars": 410,
    "preview": "# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style lice"
  },
  {
    "path": "chroot-etc/unity-profiled",
    "chars": 700,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-etc/xbindkeysrc.scm",
    "chars": 1191,
    "preview": ";; Copyright (c) 2016 The crouton Authors. All rights reserved.\n;; Use of this source code is governed by a BSD-style li"
  },
  {
    "path": "chroot-etc/xiwi.conf",
    "chars": 859,
    "preview": "# i3 config file (v4)\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is govern"
  },
  {
    "path": "chroot-etc/xorg-dummy.conf",
    "chars": 924,
    "preview": "# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style lice"
  },
  {
    "path": "chroot-etc/xorg-intel-sna.conf",
    "chars": 451,
    "preview": "# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style lice"
  },
  {
    "path": "chroot-etc/xserverrc",
    "chars": 566,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-etc/xserverrc-local.example",
    "chars": 583,
    "preview": "#!/bin/sh\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a BSD-"
  },
  {
    "path": "chroot-etc/xserverrc-xiwi",
    "chars": 627,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "chroot-etc/xserverrc-xorg",
    "chars": 1493,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/crash_reporter_wrapper",
    "chars": 7310,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/edit-chroot",
    "chars": 24194,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/enter-chroot",
    "chars": 27120,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/mount-chroot",
    "chars": 13706,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/startcli",
    "chars": 727,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/starte17",
    "chars": 561,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/startgnome",
    "chars": 540,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/startkde",
    "chars": 549,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/startkodi",
    "chars": 578,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/startlxde",
    "chars": 553,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/startunity",
    "chars": 540,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/startxfce4",
    "chars": 539,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/startxiwi",
    "chars": 2126,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-bin/unmount-chroot",
    "chars": 10764,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-ext/.gitignore",
    "chars": 54,
    "preview": "crouton.crx\ncrouton.zip\ncrouton.pem\ncrouton/kiwi.pexe\n"
  },
  {
    "path": "host-ext/crouton/background.html",
    "chars": 632,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<!-- C"
  },
  {
    "path": "host-ext/crouton/background.js",
    "chars": 27879,
    "preview": "// Copyright (c) 2016 The crouton Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style li"
  },
  {
    "path": "host-ext/crouton/first.html",
    "chars": 1930,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<!-- C"
  },
  {
    "path": "host-ext/crouton/kiwi.nmf",
    "chars": 109,
    "preview": "{\n  \"program\": {\n    \"portable\": {\n      \"pnacl-translate\": {\n        \"url\": \"kiwi.pexe\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "host-ext/crouton/manifest.json",
    "chars": 621,
    "preview": "{\n  \"manifest_version\": 2,\n\n  \"name\": \"crouton integration\",\n  \"short_name\": \"crouton\",\n  \"description\": \"Improves integ"
  },
  {
    "path": "host-ext/crouton/popup.html",
    "chars": 2370,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<!-- C"
  },
  {
    "path": "host-ext/crouton/popup.js",
    "chars": 304,
    "preview": "/* Copyright (c) 2016 The crouton Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style li"
  },
  {
    "path": "host-ext/crouton/window.html",
    "chars": 2809,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<!-- C"
  },
  {
    "path": "host-ext/crouton/window.js",
    "chars": 10829,
    "preview": "// Copyright (c) 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style l"
  },
  {
    "path": "host-ext/gencrx.sh",
    "chars": 1796,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "host-ext/nacl_src/.gitignore",
    "chars": 6,
    "preview": "pnacl\n"
  },
  {
    "path": "host-ext/nacl_src/Makefile",
    "chars": 1041,
    "preview": "# Copyright (c) 2016 The Chromium Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style lic"
  },
  {
    "path": "host-ext/nacl_src/keycode_converter.h",
    "chars": 7227,
    "preview": "/* Copyright (c) 2016 The crouton Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style li"
  },
  {
    "path": "host-ext/nacl_src/kiwi.cc",
    "chars": 41532,
    "preview": "/* Copyright (c) 2016 The crouton Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style li"
  },
  {
    "path": "installer/.gitattributes",
    "chars": 24,
    "preview": "crouton text diff merge\n"
  },
  {
    "path": "installer/debian/defaults",
    "chars": 894,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "installer/debian/releases",
    "chars": 112,
    "preview": "potato!\nwoody!\nsarge!\netch!\nlenny!\nsqueeze!\nwheezy!\njessie!\nstretch!\nbuster!\nbullseye\nbookworm\ntrixie\nforky\nsid\n"
  },
  {
    "path": "installer/functions",
    "chars": 9564,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "installer/kali/defaults",
    "chars": 792,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "installer/kali/releases",
    "chars": 31,
    "preview": "moto!\nkali!\nsana!\nkali-rolling\n"
  },
  {
    "path": "installer/main.sh",
    "chars": 28579,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "installer/prepare.sh",
    "chars": 12559,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "installer/ubuntu/ar",
    "chars": 2113,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "installer/ubuntu/bootstrap",
    "chars": 4632,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "installer/ubuntu/defaults",
    "chars": 926,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "installer/ubuntu/getrelease.sh",
    "chars": 1079,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "installer/ubuntu/pkgdetails",
    "chars": 7909,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "installer/ubuntu/prepare",
    "chars": 9616,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "installer/ubuntu/releases",
    "chars": 318,
    "preview": "warty!\nhoary!\nbreezy!\ndapper!\nedgy!\nfeisty!\ngutsy!\nhardy!\nintrepid!\njaunty!\nkarmic!\nlucid!\nmaverick!\nnatty!\noneiric!\npre"
  },
  {
    "path": "src/fbserver-proto.h",
    "chars": 2765,
    "preview": "/* Copyright (c) 2016 The crouton Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style li"
  },
  {
    "path": "src/fbserver.c",
    "chars": 20562,
    "preview": "/* Copyright (c) 2016 The crouton Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style li"
  },
  {
    "path": "src/findnacld.c",
    "chars": 4626,
    "preview": "/* Copyright (c) 2016 The crouton Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style li"
  },
  {
    "path": "src/freon.c",
    "chars": 10086,
    "preview": "/* Copyright (c) 2016 The crouton Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style li"
  },
  {
    "path": "src/vtmonitor.c",
    "chars": 1636,
    "preview": "/* Copyright (c) 2016 The crouton Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style li"
  },
  {
    "path": "src/websocket.c",
    "chars": 16760,
    "preview": "/* Copyright (c) 2016 The crouton Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style li"
  },
  {
    "path": "src/websocket.h",
    "chars": 28837,
    "preview": "/* Copyright (c) 2016 The crouton Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style li"
  },
  {
    "path": "src/xi2event.c",
    "chars": 4003,
    "preview": "/* Copyright (c) 2016 The crouton Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style li"
  },
  {
    "path": "targets/audio",
    "chars": 9741,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/chrome",
    "chars": 340,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/chrome-beta",
    "chars": 336,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/chrome-common",
    "chars": 1960,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/chrome-dev",
    "chars": 339,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/chromium",
    "chars": 578,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/cli-extra",
    "chars": 468,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/common",
    "chars": 4715,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/core",
    "chars": 5153,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/e17",
    "chars": 581,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/extension",
    "chars": 1979,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/gnome",
    "chars": 1287,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/gnome-desktop",
    "chars": 596,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The Chromium OS Authors. All rights reserved.\n# Use of this source code is governed by"
  },
  {
    "path": "targets/gtk-extra",
    "chars": 860,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/kde",
    "chars": 683,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/kde-desktop",
    "chars": 400,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The Chromium OS Authors. All rights reserved.\n# Use of this source code is governed by"
  },
  {
    "path": "targets/keyboard",
    "chars": 5172,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/kodi",
    "chars": 2432,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/lxde",
    "chars": 649,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/lxde-desktop",
    "chars": 402,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The Chromium OS Authors. All rights reserved.\n# Use of this source code is governed by"
  },
  {
    "path": "targets/post-common",
    "chars": 2265,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/touch",
    "chars": 4368,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/unity",
    "chars": 1790,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/unity-desktop",
    "chars": 384,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The Chromium OS Authors. All rights reserved.\n# Use of this source code is governed by"
  },
  {
    "path": "targets/x11",
    "chars": 509,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/x11-common",
    "chars": 2935,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/xbmc",
    "chars": 324,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/xfce",
    "chars": 1384,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/xfce-desktop",
    "chars": 573,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The Chromium OS Authors. All rights reserved.\n# Use of this source code is governed by"
  },
  {
    "path": "targets/xiwi",
    "chars": 12346,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "targets/xorg",
    "chars": 8391,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/autotest_control.template",
    "chars": 1082,
    "preview": "# Copyright (c) 2016 The Chromium OS Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style "
  },
  {
    "path": "test/daemon.sh",
    "chars": 22282,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/genreport.sh",
    "chars": 1127,
    "preview": "\n# Collect list of tests\ntests=\"`ls */results/*-test | sed -e 's|.*/\\([^\\.]*\\)\\..*|\\1|' | sort -u`\"\nmachines=\"`ls -d */s"
  },
  {
    "path": "test/reports/00-all.sh",
    "chars": 2157,
    "preview": "echo '<table class=\"outer\">'\necho '<tr class=\"outer\">'\necho '<th class=\"outer\"></th>'\necho '<th class=\"outer\">Status</th"
  },
  {
    "path": "test/reports/35-xorg.sh",
    "chars": 2241,
    "preview": "## Add output from 35-xorg tests\ntest=\"35-xorg\"\n\nxorgreleases=\"`for mach in $machines; do\n    for fulltest in \"$mach/res"
  },
  {
    "path": "test/reports/w0-common.sh",
    "chars": 2266,
    "preview": "\ntests=\"`ls */results/w*-test | sed -e 's|.*/||;s|\\..*||' | sort | uniq`\"\n\nif [ -z \"$tests\" ]; then\n    exit 0\nfi\n\nfor t"
  },
  {
    "path": "test/run.sh",
    "chars": 18246,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/00-tester",
    "chars": 1132,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/10-basic",
    "chars": 415,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/11-32-on-64",
    "chars": 471,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/12-edit-chroot",
    "chars": 7987,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/14-background",
    "chars": 1945,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/15-media",
    "chars": 2309,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/16-targetsfile",
    "chars": 1036,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/17-encryption",
    "chars": 5173,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/18-upgrade",
    "chars": 2724,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/20-logind",
    "chars": 581,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/30-audio",
    "chars": 2062,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/35-xorg",
    "chars": 1335,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The Chromium OS Authors. All rights reserved.\n# Use of this source code is governed by"
  },
  {
    "path": "test/tests/37-xiwi",
    "chars": 793,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The Chromium OS Authors. All rights reserved.\n# Use of this source code is governed by"
  },
  {
    "path": "test/tests/w0-common",
    "chars": 2033,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/w1-e17",
    "chars": 406,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/w2-gnome",
    "chars": 335,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/w2d-gnome-desktop",
    "chars": 343,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/w3-kde",
    "chars": 331,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/w3d-kde-desktop",
    "chars": 339,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/w4-lxde",
    "chars": 333,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/w4d-lxde-desktop",
    "chars": 341,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/w5-unity",
    "chars": 335,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/w5d-unity-desktop",
    "chars": 343,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/w6-kodi",
    "chars": 333,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/w7-xfce",
    "chars": 489,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/w7d-xfce-desktop",
    "chars": 342,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  },
  {
    "path": "test/tests/x0-alltargets",
    "chars": 1495,
    "preview": "#!/bin/sh -e\n# Copyright (c) 2016 The crouton Authors. All rights reserved.\n# Use of this source code is governed by a B"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the dnschneid/crouton GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 165 files (608.4 KB), approximately 177.5k tokens, and a symbol index with 167 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!