Browse code

Merge remote-tracking branch 'origin/disable_signals-create_escape_sequence'

Solomon Hykes authored on 2013/04/10 04:56:32
Showing 4 changed files
... ...
@@ -134,6 +134,12 @@ docker pull base
134 134
 docker run -i -t base /bin/bash
135 135
 ```
136 136
 
137
+Detaching from the interactive shell
138
+------------------------------------
139
+```
140
+# In order to detach without killing the shell, you can use the escape sequence Ctrl-p + Ctrl-q
141
+# Note: this works only in tty mode (run with -t option).
142
+```
137 143
 
138 144
 Starting a long-running worker process
139 145
 --------------------------------------
... ...
@@ -255,7 +255,11 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
255 255
 				if container.Config.StdinOnce && !container.Config.Tty {
256 256
 					defer cStdin.Close()
257 257
 				}
258
-				_, err := io.Copy(cStdin, stdin)
258
+				if container.Config.Tty {
259
+					_, err = CopyEscapable(cStdin, stdin)
260
+				} else {
261
+					_, err = io.Copy(cStdin, stdin)
262
+				}
259 263
 				if err != nil {
260 264
 					Debugf("[error] attach stdin: %s\n", err)
261 265
 				}
... ...
@@ -15,7 +15,8 @@ void MakeRaw(int fd) {
15 15
   ioctl(fd, TCGETS, &t);
16 16
 
17 17
   t.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
18
-  t.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
18
+  t.c_oflag &= ~OPOST;
19
+  t.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
19 20
   t.c_cflag &= ~(CSIZE | PARENB);
20 21
   t.c_cflag |= CS8;
21 22
 
... ...
@@ -341,3 +341,46 @@ func TruncateId(id string) string {
341 341
 	}
342 342
 	return id[:shortLen]
343 343
 }
344
+
345
+// Code c/c from io.Copy() modified to handle escape sequence
346
+func CopyEscapable(dst io.Writer, src io.ReadCloser) (written int64, err error) {
347
+	buf := make([]byte, 32*1024)
348
+	for {
349
+		nr, er := src.Read(buf)
350
+		if nr > 0 {
351
+			// ---- Docker addition
352
+			// char 16 is C-p
353
+			if nr == 1 && buf[0] == 16 {
354
+				nr, er = src.Read(buf)
355
+				// char 17 is C-q
356
+				if nr == 1 && buf[0] == 17 {
357
+					if err := src.Close(); err != nil {
358
+						return 0, err
359
+					}
360
+					return 0, io.EOF
361
+				}
362
+			}
363
+			// ---- End of docker
364
+			nw, ew := dst.Write(buf[0:nr])
365
+			if nw > 0 {
366
+				written += int64(nw)
367
+			}
368
+			if ew != nil {
369
+				err = ew
370
+				break
371
+			}
372
+			if nr != nw {
373
+				err = io.ErrShortWrite
374
+				break
375
+			}
376
+		}
377
+		if er == io.EOF {
378
+			break
379
+		}
380
+		if er != nil {
381
+			err = er
382
+			break
383
+		}
384
+	}
385
+	return written, err
386
+}