LEFT | RIGHT |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package ssh | 5 package ssh |
6 | 6 |
7 // Session implements an interactive session described in | 7 // Session implements an interactive session described in |
8 // "RFC 4254, section 6". | 8 // "RFC 4254, section 6". |
9 | 9 |
10 import ( | 10 import ( |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 Stdout io.Writer | 66 Stdout io.Writer |
67 Stderr io.Writer | 67 Stderr io.Writer |
68 | 68 |
69 *clientChan // the channel backing this session | 69 *clientChan // the channel backing this session |
70 | 70 |
71 started bool // true once Start, Run or Shell is invoked. | 71 started bool // true once Start, Run or Shell is invoked. |
72 copyFuncs []func() error | 72 copyFuncs []func() error |
73 errch chan error // one send per copyFunc | 73 errch chan error // one send per copyFunc |
74 | 74 |
75 // true if pipe method is active | 75 // true if pipe method is active |
76 stdinpipe, stdoutpipe, stderrpipe bool | 76 stdinpipe, stdoutpipe, stderrpipe bool |
77 } | 77 } |
78 | 78 |
79 // RFC 4254 Section 6.4. | 79 // RFC 4254 Section 6.4. |
80 type setenvRequest struct { | 80 type setenvRequest struct { |
81 PeersId uint32 | 81 PeersId uint32 |
82 Request string | 82 Request string |
83 WantReply bool | 83 WantReply bool |
84 Name string | 84 Name string |
85 Value string | 85 Value string |
86 } | 86 } |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 return nil | 232 return nil |
233 case *channelRequestFailureMsg: | 233 case *channelRequestFailureMsg: |
234 return errors.New("request failed") | 234 return errors.New("request failed") |
235 } | 235 } |
236 return fmt.Errorf("unknown packet %T received: %v", msg, msg) | 236 return fmt.Errorf("unknown packet %T received: %v", msg, msg) |
237 } | 237 } |
238 | 238 |
239 func (s *Session) start() error { | 239 func (s *Session) start() error { |
240 s.started = true | 240 s.started = true |
241 | 241 |
242 » type F func(*Session) error | 242 » type F func(*Session) |
243 for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Sessi
on).stderr} { | 243 for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Sessi
on).stderr} { |
244 » » if err := setupFd(s); err != nil { | 244 » » setupFd(s) |
245 » » » return err | |
246 » » } | |
247 } | 245 } |
248 | 246 |
249 s.errch = make(chan error, len(s.copyFuncs)) | 247 s.errch = make(chan error, len(s.copyFuncs)) |
250 for _, fn := range s.copyFuncs { | 248 for _, fn := range s.copyFuncs { |
251 go func(fn func() error) { | 249 go func(fn func() error) { |
252 s.errch <- fn() | 250 s.errch <- fn() |
253 }(fn) | 251 }(fn) |
254 } | 252 } |
255 return nil | 253 return nil |
256 } | 254 } |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 return errors.New("wait: remote command exited without e
xit status or exit signal") | 331 return errors.New("wait: remote command exited without e
xit status or exit signal") |
334 } | 332 } |
335 wm.status = 128 | 333 wm.status = 128 |
336 if _, ok := signals[Signal(wm.signal)]; ok { | 334 if _, ok := signals[Signal(wm.signal)]; ok { |
337 wm.status += signals[Signal(wm.signal)] | 335 wm.status += signals[Signal(wm.signal)] |
338 } | 336 } |
339 } | 337 } |
340 return &ExitError{wm} | 338 return &ExitError{wm} |
341 } | 339 } |
342 | 340 |
343 func (s *Session) stdin() error { | 341 func (s *Session) stdin() { |
344 if s.stdinpipe { | 342 if s.stdinpipe { |
345 » » return nil | 343 » » return |
346 } | 344 } |
347 if s.Stdin == nil { | 345 if s.Stdin == nil { |
348 s.Stdin = new(bytes.Buffer) | 346 s.Stdin = new(bytes.Buffer) |
349 } | 347 } |
350 s.copyFuncs = append(s.copyFuncs, func() error { | 348 s.copyFuncs = append(s.copyFuncs, func() error { |
351 _, err := io.Copy(s.clientChan.stdin, s.Stdin) | 349 _, err := io.Copy(s.clientChan.stdin, s.Stdin) |
352 if err1 := s.clientChan.stdin.Close(); err == nil { | 350 if err1 := s.clientChan.stdin.Close(); err == nil { |
353 err = err1 | 351 err = err1 |
354 } | 352 } |
355 return err | 353 return err |
356 }) | 354 }) |
357 » return nil | 355 } |
358 } | 356 |
359 | 357 func (s *Session) stdout() { |
360 func (s *Session) stdout() error { | |
361 if s.stdoutpipe { | 358 if s.stdoutpipe { |
362 » » return nil | 359 » » return |
363 } | 360 } |
364 if s.Stdout == nil { | 361 if s.Stdout == nil { |
365 s.Stdout = ioutil.Discard | 362 s.Stdout = ioutil.Discard |
366 } | 363 } |
367 s.copyFuncs = append(s.copyFuncs, func() error { | 364 s.copyFuncs = append(s.copyFuncs, func() error { |
368 _, err := io.Copy(s.Stdout, s.clientChan.stdout) | 365 _, err := io.Copy(s.Stdout, s.clientChan.stdout) |
369 return err | 366 return err |
370 }) | 367 }) |
371 » return nil | 368 } |
372 } | 369 |
373 | 370 func (s *Session) stderr() { |
374 func (s *Session) stderr() error { | |
375 if s.stderrpipe { | 371 if s.stderrpipe { |
376 » » return nil | 372 » » return |
377 } | 373 } |
378 if s.Stderr == nil { | 374 if s.Stderr == nil { |
379 s.Stderr = ioutil.Discard | 375 s.Stderr = ioutil.Discard |
380 } | 376 } |
381 s.copyFuncs = append(s.copyFuncs, func() error { | 377 s.copyFuncs = append(s.copyFuncs, func() error { |
382 _, err := io.Copy(s.Stderr, s.clientChan.stderr) | 378 _, err := io.Copy(s.Stderr, s.clientChan.stderr) |
383 return err | 379 return err |
384 }) | 380 }) |
385 return nil | |
386 } | 381 } |
387 | 382 |
388 // StdinPipe returns a pipe that will be connected to the | 383 // StdinPipe returns a pipe that will be connected to the |
389 // remote command's standard input when the command starts. | 384 // remote command's standard input when the command starts. |
390 func (s *Session) StdinPipe() (io.WriteCloser, error) { | 385 func (s *Session) StdinPipe() (io.WriteCloser, error) { |
391 if s.Stdin != nil { | 386 if s.Stdin != nil { |
392 return nil, errors.New("ssh: Stdin already set") | 387 return nil, errors.New("ssh: Stdin already set") |
393 } | 388 } |
394 if s.started { | 389 if s.started { |
395 return nil, errors.New("ssh: StdinPipe after process started") | 390 return nil, errors.New("ssh: StdinPipe after process started") |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 } | 485 } |
491 | 486 |
492 // Lang returns the language tag. See RFC 3066 | 487 // Lang returns the language tag. See RFC 3066 |
493 func (w Waitmsg) Lang() string { | 488 func (w Waitmsg) Lang() string { |
494 return w.lang | 489 return w.lang |
495 } | 490 } |
496 | 491 |
497 func (w Waitmsg) String() string { | 492 func (w Waitmsg) String() string { |
498 return fmt.Sprintf("Process exited with: %v. Reason was: %v (%v)", w.sta
tus, w.msg, w.signal) | 493 return fmt.Sprintf("Process exited with: %v. Reason was: %v (%v)", w.sta
tus, w.msg, w.signal) |
499 } | 494 } |
LEFT | RIGHT |