mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge branch 'graph' of github.com:dotcloud/docker into graph
This commit is contained in:
commit
db8f2a1a9d
13 changed files with 166 additions and 100 deletions
112
README.md
112
README.md
|
@ -1,9 +1,9 @@
|
|||
Docker: the Linux container runtime
|
||||
===================================
|
||||
|
||||
Docker complements LXC with a high-level API with operates at the process level. It runs unix processes with strong guarantees of isolation and repeatability across servers.
|
||||
Docker complements LXC with a high-level API which operates at the process level. It runs unix processes with strong guarantees of isolation and repeatability across servers.
|
||||
|
||||
Is is a great building block for automating distributed systems: large-scale web deployments, database clusters, continuous deployment systems, private PaaS, service-oriented architectures, etc.
|
||||
Docker is a great building block for automating distributed systems: large-scale web deployments, database clusters, continuous deployment systems, private PaaS, service-oriented architectures, etc.
|
||||
|
||||
<img src="http://bricks.argz.com/bricksfiles/lego/07000/7823/012.jpg"/>
|
||||
|
||||
|
@ -27,7 +27,7 @@ Notable features
|
|||
|
||||
* Copy-on-write: root filesystems are created using copy-on-write, which makes deployment extremeley fast, memory-cheap and disk-cheap.
|
||||
|
||||
* Logging: the standard streams (stdout/stderr/stdin) of each process container is collected and logged for real-time or batch retrieval.
|
||||
* Logging: the standard streams (stdout/stderr/stdin) of each process container are collected and logged for real-time or batch retrieval.
|
||||
|
||||
* Change management: changes to a container's filesystem can be committed into a new image and re-used to create more containers. No templating or manual configuration required.
|
||||
|
||||
|
@ -58,28 +58,28 @@ Installing on Ubuntu 12.04 and 12.10
|
|||
|
||||
1. Install dependencies:
|
||||
|
||||
```bash
|
||||
sudo apt-get install lxc wget bsdtar curl
|
||||
sudo apt-get install linux-image-extra-`uname -r`
|
||||
```
|
||||
```bash
|
||||
sudo apt-get install lxc wget bsdtar curl
|
||||
sudo apt-get install linux-image-extra-`uname -r`
|
||||
```
|
||||
|
||||
The `linux-image-extra` package is needed on standard Ubuntu EC2 AMIs in order to install the aufs kernel module.
|
||||
The `linux-image-extra` package is needed on standard Ubuntu EC2 AMIs in order to install the aufs kernel module.
|
||||
|
||||
2. Install the latest docker binary:
|
||||
|
||||
```bash
|
||||
wget http://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-master.tgz
|
||||
tar -xf docker-master.tgz
|
||||
```
|
||||
```bash
|
||||
wget http://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-master.tgz
|
||||
tar -xf docker-master.tgz
|
||||
```
|
||||
|
||||
3. Run your first container!
|
||||
|
||||
```bash
|
||||
cd docker-master
|
||||
sudo ./docker run -a -i -t base /bin/bash
|
||||
```
|
||||
```bash
|
||||
cd docker-master
|
||||
sudo ./docker run -a -i -t base /bin/bash
|
||||
```
|
||||
|
||||
Consider adding docker to your `PATH` for simplicity.
|
||||
Consider adding docker to your `PATH` for simplicity.
|
||||
|
||||
Installing on other Linux distributions
|
||||
---------------------------------------
|
||||
|
@ -99,12 +99,12 @@ with VirtualBox as well as on Amazon EC2. Vagrant 1.1 is required for
|
|||
EC2, but deploying is as simple as:
|
||||
|
||||
```bash
|
||||
$ export AWS_ACCESS_KEY_ID=xxx \
|
||||
AWS_SECRET_ACCESS_KEY=xxx \
|
||||
AWS_KEYPAIR_NAME=xxx \
|
||||
AWS_SSH_PRIVKEY=xxx
|
||||
$ vagrant plugin install vagrant-aws
|
||||
$ vagrant up --provider=aws
|
||||
$ export AWS_ACCESS_KEY_ID=xxx \
|
||||
AWS_SECRET_ACCESS_KEY=xxx \
|
||||
AWS_KEYPAIR_NAME=xxx \
|
||||
AWS_SSH_PRIVKEY=xxx
|
||||
$ vagrant plugin install vagrant-aws
|
||||
$ vagrant up --provider=aws
|
||||
```
|
||||
|
||||
The environment variables are:
|
||||
|
@ -115,11 +115,11 @@ The environment variables are:
|
|||
* `AWS_SSH_PRIVKEY` - The path to the private key for the named keypair
|
||||
|
||||
For VirtualBox, you can simply ignore setting any of the environment
|
||||
variables and omit the ``provider`` flag. VirtualBox is still supported with
|
||||
Vagrant <= 1.1:
|
||||
variables and omit the `provider` flag. VirtualBox is still supported with
|
||||
Vagrant <= 1.1:
|
||||
|
||||
```bash
|
||||
$ vagrant up
|
||||
$ vagrant up
|
||||
```
|
||||
|
||||
|
||||
|
@ -131,12 +131,12 @@ Running an interactive shell
|
|||
----------------------------
|
||||
|
||||
```bash
|
||||
# Download a base image
|
||||
docker import base
|
||||
# Download a base image
|
||||
docker import base
|
||||
|
||||
# Run an interactive shell in the base image,
|
||||
# allocate a tty, attach stdin and stdout
|
||||
docker run -a -i -t base /bin/bash
|
||||
# Run an interactive shell in the base image,
|
||||
# allocate a tty, attach stdin and stdout
|
||||
docker run -a -i -t base /bin/bash
|
||||
```
|
||||
|
||||
|
||||
|
@ -144,17 +144,17 @@ Starting a long-running worker process
|
|||
--------------------------------------
|
||||
|
||||
```bash
|
||||
# Run docker in daemon mode
|
||||
(docker -d || echo "Docker daemon already running") &
|
||||
# Run docker in daemon mode
|
||||
(docker -d || echo "Docker daemon already running") &
|
||||
|
||||
# Start a very useful long-running process
|
||||
JOB=$(docker run base /bin/sh -c "while true; do echo Hello world; sleep 1; done")
|
||||
# Start a very useful long-running process
|
||||
JOB=$(docker run base /bin/sh -c "while true; do echo Hello world; sleep 1; done")
|
||||
|
||||
# Collect the output of the job so far
|
||||
docker logs $JOB
|
||||
# Collect the output of the job so far
|
||||
docker logs $JOB
|
||||
|
||||
# Kill the job
|
||||
docker kill $JOB
|
||||
# Kill the job
|
||||
docker kill $JOB
|
||||
```
|
||||
|
||||
|
||||
|
@ -162,7 +162,7 @@ Listing all running containers
|
|||
------------------------------
|
||||
|
||||
```bash
|
||||
docker ps
|
||||
docker ps
|
||||
```
|
||||
|
||||
|
||||
|
@ -170,17 +170,17 @@ Expose a service on a TCP port
|
|||
------------------------------
|
||||
|
||||
```bash
|
||||
# Expose port 4444 of this container, and tell netcat to listen on it
|
||||
JOB=$(docker run -p 4444 base /bin/nc -l -p 4444)
|
||||
# Expose port 4444 of this container, and tell netcat to listen on it
|
||||
JOB=$(docker run -p 4444 base /bin/nc -l -p 4444)
|
||||
|
||||
# Which public port is NATed to my container?
|
||||
PORT=$(docker port $JOB 4444)
|
||||
# Which public port is NATed to my container?
|
||||
PORT=$(docker port $JOB 4444)
|
||||
|
||||
# Connect to the public port via the host's public address
|
||||
echo hello world | nc $(hostname) $PORT
|
||||
# Connect to the public port via the host's public address
|
||||
echo hello world | nc $(hostname) $PORT
|
||||
|
||||
# Verify that the network connection worked
|
||||
echo "Daemon received: $(docker logs $JOB)"
|
||||
# Verify that the network connection worked
|
||||
echo "Daemon received: $(docker logs $JOB)"
|
||||
```
|
||||
|
||||
Contributing to Docker
|
||||
|
@ -195,10 +195,10 @@ Contribution guidelines
|
|||
|
||||
We are always thrilled to receive pull requests, and do our best to process them as fast as possible. Not sure if that typo is worth a pull request? Do it! We will appreciate it.
|
||||
|
||||
If your pull request is not accepted on the first try, don't be discouraged! If there's a problen with the implementation, hopefully you received feedback on what to improve.
|
||||
If your pull request is not accepted on the first try, don't be discouraged! If there's a problem with the implementation, hopefully you received feedback on what to improve.
|
||||
|
||||
We're trying very hard to keep Docker lean and focused. We don't want it to do everything for everybody. This means that we might decide against incorporating a new feature.
|
||||
However there might be a way to implement that feature *on top of* docker.
|
||||
However, there might be a way to implement that feature *on top of* docker.
|
||||
|
||||
### Discuss your design on the mailing list
|
||||
|
||||
|
@ -207,7 +207,7 @@ you in the right direction, give feedback on your design, and maybe point out if
|
|||
|
||||
### Create issues...
|
||||
|
||||
Any significant improvement should be documented as a github issue before anybody start working on it.
|
||||
Any significant improvement should be documented as [a github issue](https://github.com/dotcloud/docker/issues) before anybody starts working on it.
|
||||
|
||||
### ...but check for existing issues first!
|
||||
|
||||
|
@ -224,9 +224,9 @@ Golang has a great testing suite built in: use it! Take a look at existing tests
|
|||
Setting up a dev environment
|
||||
----------------------------
|
||||
|
||||
Instructions that is verified to work on Ubuntu 12.10,
|
||||
Instructions that have been verified to work on Ubuntu 12.10,
|
||||
|
||||
```
|
||||
```bash
|
||||
sudo apt-get -y install lxc wget bsdtar curl libsqlite3-dev golang git pkg-config
|
||||
|
||||
export GOPATH=~/go/
|
||||
|
@ -243,7 +243,7 @@ go install -v github.com/dotcloud/docker/...
|
|||
|
||||
Then run the docker daemon,
|
||||
|
||||
```
|
||||
```bash
|
||||
sudo $GOPATH/bin/docker -d
|
||||
```
|
||||
|
||||
|
@ -254,9 +254,9 @@ What is a Standard Container?
|
|||
=============================
|
||||
|
||||
Docker defines a unit of software delivery called a Standard Container. The goal of a Standard Container is to encapsulate a software component and all its dependencies in
|
||||
a format that is self-describing and portable, so that any compliant runtime can run it without extra dependency, regardless of the underlying machine and the contents of the container.
|
||||
a format that is self-describing and portable, so that any compliant runtime can run it without extra dependencies, regardless of the underlying machine and the contents of the container.
|
||||
|
||||
The spec for Standard Containers is currently work in progress, but it is very straightforward. It mostly defines 1) an image format, 2) a set of standard operations, and 3) an execution environment.
|
||||
The spec for Standard Containers is currently a work in progress, but it is very straightforward. It mostly defines 1) an image format, 2) a set of standard operations, and 3) an execution environment.
|
||||
|
||||
A great analogy for this is the shipping container. Just like Standard Containers are a fundamental unit of software delivery, shipping containers (http://bricks.argz.com/ins/7823-1/12) are a fundamental unit of physical delivery.
|
||||
|
||||
|
|
37
Vagrantfile
vendored
37
Vagrantfile
vendored
|
@ -1,7 +1,7 @@
|
|||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
Vagrant.configure("1") do |config|
|
||||
def v10(config)
|
||||
# All Vagrant configuration is done here. The most common configuration
|
||||
# options are documented and commented below. For a complete reference,
|
||||
# please see the online documentation at vagrantup.com.
|
||||
|
@ -20,7 +20,7 @@ Vagrant.configure("1") do |config|
|
|||
# via the IP. Host-only networks can talk to the host machine as well as
|
||||
# any other machines on the same network, but cannot be accessed (through this
|
||||
# network interface) by any external networks.
|
||||
# config.vm.network :hostonly, "192.168.33.10"
|
||||
config.vm.network :hostonly, "192.168.33.10"
|
||||
|
||||
# Assign this VM to a bridged network, allowing you to connect directly to a
|
||||
# network using the host's network device. This makes the VM appear as another
|
||||
|
@ -34,6 +34,9 @@ Vagrant.configure("1") do |config|
|
|||
# Share an additional folder to the guest VM. The first argument is
|
||||
# an identifier, the second is the path on the guest to mount the
|
||||
# folder, and the third is the path on the host to the actual folder.
|
||||
if not File.exist? File.expand_path '~/docker'
|
||||
Dir.mkdir(File.expand_path '~/docker')
|
||||
end
|
||||
config.vm.share_folder "v-data", "~/docker", "~/docker"
|
||||
|
||||
# Enable provisioning with Puppet stand alone. Puppet manifests
|
||||
|
@ -99,21 +102,29 @@ Vagrant.configure("1") do |config|
|
|||
# chef.validation_client_name = "ORGNAME-validator"
|
||||
end
|
||||
|
||||
Vagrant.configure("2") do |config|
|
||||
"#{Vagrant::VERSION}" < "1.1.0" and Vagrant::Config.run do |config|
|
||||
v10(config)
|
||||
end
|
||||
|
||||
"#{Vagrant::VERSION}" >= "1.1.0" and Vagrant.configure("1") do |config|
|
||||
v10(config)
|
||||
end
|
||||
|
||||
"#{Vagrant::VERSION}" >= "1.1.0" and Vagrant.configure("2") do |config|
|
||||
config.vm.provider :aws do |aws|
|
||||
config.vm.box = "dummy"
|
||||
config.vm.box_url = "https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box"
|
||||
config.vm.box = "dummy"
|
||||
config.vm.box_url = "https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box"
|
||||
aws.access_key_id = ENV["AWS_ACCESS_KEY_ID"]
|
||||
aws.secret_access_key = ENV["AWS_SECRET_ACCESS_KEY"]
|
||||
aws.keypair_name = ENV["AWS_KEYPAIR_NAME"]
|
||||
aws.ssh_private_key_path = ENV["AWS_SSH_PRIVKEY"]
|
||||
aws.region = "us-east-1"
|
||||
aws.secret_access_key = ENV["AWS_SECRET_ACCESS_KEY"]
|
||||
aws.keypair_name = ENV["AWS_KEYPAIR_NAME"]
|
||||
aws.ssh_private_key_path = ENV["AWS_SSH_PRIVKEY"]
|
||||
aws.region = "us-east-1"
|
||||
aws.ami = "ami-1c1e8075"
|
||||
aws.ssh_username = "vagrant"
|
||||
aws.instance_type = "t1.micro"
|
||||
aws.instance_type = "t1.micro"
|
||||
end
|
||||
config.vm.provider :virtualbox do |vb|
|
||||
config.vm.box = "quantal64_3.5.0-25"
|
||||
config.vm.box_url = "http://get.docker.io/vbox/ubuntu/12.10/quantal64_3.5.0-25.box"
|
||||
end
|
||||
config.vm.box = "quantal64_3.5.0-25"
|
||||
config.vm.box_url = "http://get.docker.io/vbox/ubuntu/12.10/quantal64_3.5.0-25.box"
|
||||
end
|
||||
end
|
||||
|
|
15
commands.go
15
commands.go
|
@ -391,7 +391,7 @@ func (srv *Server) CmdImport(stdin io.ReadCloser, stdout io.Writer, args ...stri
|
|||
// Optionally register the image at REPO/TAG
|
||||
if repository := cmd.Arg(1); repository != "" {
|
||||
tag := cmd.Arg(2) // Repository will handle an empty tag properly
|
||||
if err := srv.runtime.repositories.Set(repository, tag, img.Id); err != nil {
|
||||
if err := srv.runtime.repositories.Set(repository, tag, img.Id, true); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -764,6 +764,19 @@ func (p *ports) Set(value string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (srv *Server) CmdTag(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
|
||||
cmd := rcli.Subcmd(stdout, "tag", "[OPTIONS] IMAGE REPOSITORY [TAG]", "Tag an image into a repository")
|
||||
force := cmd.Bool("f", false, "Force")
|
||||
if err := cmd.Parse(args); err != nil {
|
||||
return nil
|
||||
}
|
||||
if cmd.NArg() < 2 {
|
||||
cmd.Usage()
|
||||
return nil
|
||||
}
|
||||
return srv.runtime.repositories.Set(cmd.Arg(1), cmd.Arg(2), cmd.Arg(0), *force)
|
||||
}
|
||||
|
||||
func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
|
||||
cmd := rcli.Subcmd(stdout, "run", "[OPTIONS] IMAGE COMMAND [ARG...]", "Run a command in a new container")
|
||||
fl_user := cmd.String("u", "", "Username or UID")
|
||||
|
|
4
docs/README.md
Normal file
4
docs/README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
Docs readme
|
||||
===========
|
||||
|
||||
Let's see if this file shows up as we hope it does.
|
|
@ -95,7 +95,8 @@ func getIfaceAddr(name string) (net.Addr, error) {
|
|||
case len(addrs4) == 0:
|
||||
return nil, fmt.Errorf("Interface %v has no IP addresses", name)
|
||||
case len(addrs4) > 1:
|
||||
return nil, fmt.Errorf("Interface %v has more than 1 IPv4 address", name)
|
||||
fmt.Printf("Interface %v has more than 1 IPv4 address. Defaulting to using %v\n",
|
||||
name, (addrs4[0].(*net.IPNet)).IP)
|
||||
}
|
||||
return addrs4[0], nil
|
||||
}
|
||||
|
@ -123,6 +124,9 @@ func (mapper *PortMapper) setup() error {
|
|||
if err := iptables("-t", "nat", "-A", "PREROUTING", "-j", "DOCKER"); err != nil {
|
||||
return errors.New("Unable to setup port networking: Failed to inject docker in PREROUTING chain")
|
||||
}
|
||||
if err := iptables("-t", "nat", "-A", "OUTPUT", "-j", "DOCKER"); err != nil {
|
||||
return errors.New("Unable to setup port networking: Failed to inject docker in OUTPUT chain")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ class docker {
|
|||
owner => "root",
|
||||
group => "root",
|
||||
content => template("docker/dockerd.conf"),
|
||||
require => Exec["fetch-docker"],
|
||||
require => Exec["copy-docker-bin"],
|
||||
}
|
||||
|
||||
file { "/home/vagrant":
|
||||
|
|
|
@ -8,5 +8,5 @@ respawn
|
|||
|
||||
script
|
||||
test -f /etc/default/locale && . /etc/default/locale || true
|
||||
LANG=$LANG LC_ALL=$LANG /usr/local/bin/docker -d
|
||||
LANG=$LANG LC_ALL=$LANG /usr/local/bin/docker -d >> /var/log/dockerd 2>&1
|
||||
end script
|
||||
|
|
|
@ -175,7 +175,7 @@ func (graph *Graph) PullRepository(user, repoName, askedTag string, repositories
|
|||
if err = graph.PullImage(rev, authConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = repositories.Set(repoName, tag, rev); err != nil {
|
||||
if err = repositories.Set(repoName, tag, rev, true); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -201,7 +201,7 @@ func (runtime *Runtime) Commit(id, repository, tag string) (*Image, error) {
|
|||
}
|
||||
// Register the image if needed
|
||||
if repository != "" {
|
||||
if err := runtime.repositories.Set(repository, tag, img.Id); err != nil {
|
||||
if err := runtime.repositories.Set(repository, tag, img.Id, true); err != nil {
|
||||
return img, err
|
||||
}
|
||||
}
|
||||
|
|
11
tags.go
11
tags.go
|
@ -83,7 +83,11 @@ func (store *TagStore) LookupImage(name string) (*Image, error) {
|
|||
return img, nil
|
||||
}
|
||||
|
||||
func (store *TagStore) Set(repoName, tag, revision string) error {
|
||||
func (store *TagStore) Set(repoName, tag, imageName string, force bool) error {
|
||||
img, err := store.LookupImage(imageName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tag == "" {
|
||||
tag = DEFAULT_TAG
|
||||
}
|
||||
|
@ -101,9 +105,12 @@ func (store *TagStore) Set(repoName, tag, revision string) error {
|
|||
repo = r
|
||||
} else {
|
||||
repo = make(map[string]string)
|
||||
if old, exists := store.Repositories[repoName]; exists && !force {
|
||||
return fmt.Errorf("Tag %s:%s is already set to %s", repoName, tag, old)
|
||||
}
|
||||
store.Repositories[repoName] = repo
|
||||
}
|
||||
repo[tag] = revision
|
||||
repo[tag] = img.Id
|
||||
return store.Save()
|
||||
}
|
||||
|
||||
|
|
21
term/term.go
21
term/term.go
|
@ -114,27 +114,6 @@ func IsTerminal(fd int) bool {
|
|||
return err == 0
|
||||
}
|
||||
|
||||
// MakeRaw put the terminal connected to the given file descriptor into raw
|
||||
// mode and returns the previous state of the terminal so that it can be
|
||||
// restored.
|
||||
func MakeRaw(fd int) (*State, error) {
|
||||
var oldState State
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newState := oldState.termios
|
||||
newState.Iflag &^= ISTRIP | INLCR | IGNCR | IXON | IXOFF
|
||||
newState.Iflag |= ICRNL
|
||||
newState.Oflag |= ONLCR
|
||||
newState.Lflag &^= ECHO | ICANON | ISIG
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &oldState, nil
|
||||
}
|
||||
|
||||
// Restore restores the terminal connected to the given file descriptor to a
|
||||
// previous state.
|
||||
func Restore(fd int, state *State) error {
|
||||
|
|
|
@ -1,8 +1,32 @@
|
|||
package term
|
||||
|
||||
import "syscall"
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
getTermios = syscall.TIOCGETA
|
||||
setTermios = syscall.TIOCSETA
|
||||
)
|
||||
|
||||
// MakeRaw put the terminal connected to the given file descriptor into raw
|
||||
// mode and returns the previous state of the terminal so that it can be
|
||||
// restored.
|
||||
func MakeRaw(fd int) (*State, error) {
|
||||
var oldState State
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newState := oldState.termios
|
||||
newState.Iflag &^= ISTRIP | INLCR | IGNCR | IXON | IXOFF
|
||||
newState.Iflag |= ICRNL
|
||||
newState.Oflag |= ONLCR
|
||||
newState.Lflag &^= ECHO | ICANON | ISIG
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &oldState, nil
|
||||
}
|
|
@ -1,8 +1,32 @@
|
|||
package term
|
||||
|
||||
import "syscall"
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
getTermios = syscall.TCGETS
|
||||
setTermios = syscall.TCSETS
|
||||
)
|
||||
|
||||
// MakeRaw put the terminal connected to the given file descriptor into raw
|
||||
// mode and returns the previous state of the terminal so that it can be
|
||||
// restored.
|
||||
func MakeRaw(fd int) (*State, error) {
|
||||
var oldState State
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newState := oldState.termios
|
||||
newState.Iflag &^= ISTRIP | IXON | IXOFF
|
||||
newState.Iflag |= ICRNL
|
||||
newState.Oflag |= ONLCR
|
||||
newState.Lflag &^= ECHO | ICANON | ISIG
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &oldState, nil
|
||||
}
|
Loading…
Reference in a new issue