| ︙ | | |
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
-
+
|
* data dynamically allocated: instead, the backend handle is just
* a null pointer and ignored everywhere.
*/
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED
#define _GNU_SOURCE
#include <features.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <termios.h>
#include <grp.h>
#include <utmp.h>
#include <pwd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <errno.h>
#include "putty.h"
#ifndef FALSE
|
| ︙ | | |
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
-
-
-
-
-
+
+
+
+
+
-
|
#endif
static Config pty_cfg;
static int pty_master_fd;
static void *pty_frontend;
static char pty_name[FILENAME_MAX];
static int pty_signal_pipe[2];
static int pty_stamped_utmp = 0;
static int pty_child_pid;
static int pty_utmp_helper_pid, pty_utmp_helper_pipe;
static int pty_term_width, pty_term_height;
static int pty_child_dead, pty_finished;
static int pty_exit_code;
#ifndef OMIT_UTMP
static struct utmp utmp_entry;
#endif
char **pty_argv;
int use_pty_argv = TRUE;
static void pty_close(void);
#ifndef OMIT_UTMP
static int pty_utmp_helper_pid, pty_utmp_helper_pipe;
static int pty_stamped_utmp = 0;
static struct utmp utmp_entry;
static void setup_utmp(char *ttyname, char *location)
{
#ifndef OMIT_UTMP
#ifdef HAVE_LASTLOG
struct lastlog lastlog_entry;
FILE *lastlog;
#endif
struct passwd *pw;
FILE *wtmp;
time_t uttime;
|
| ︙ | | |
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
-
-
|
fwrite(&lastlog_entry, 1, sizeof(lastlog_entry), lastlog);
fclose(lastlog);
}
#endif
pty_stamped_utmp = 1;
#endif
}
static void cleanup_utmp(void)
{
#ifndef OMIT_UTMP
FILE *wtmp;
time_t uttime;
if (!pty_stamped_utmp)
return;
utmp_entry.ut_type = DEAD_PROCESS;
|
| ︙ | | |
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
-
+
+
+
|
utmpname(UTMP_FILE);
setutent();
pututline(&utmp_entry);
endutent();
#endif
pty_stamped_utmp = 0; /* ensure we never double-cleanup */
#endif
}
#endif
static void sigchld_handler(int signum)
{
write(pty_signal_pipe[1], "x", 1);
}
#ifndef OMIT_UTMP
static void fatal_sig_handler(int signum)
{
putty_signal(signum, SIG_DFL);
cleanup_utmp();
setuid(getuid());
raise(signum);
}
#endif
static void pty_open_master(void)
{
#ifdef BSD_PTYS
const char chars1[] = "pqrstuvwxyz";
const char chars2[] = "0123456789abcdef";
const char *p1, *p2;
|
| ︙ | | |
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
|
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
|
+
+
|
* also fork off a utmp helper process and communicate with it by
* means of a pipe; the utmp helper will keep privileges in order
* to clean up utmp when we exit (i.e. when its end of our pipe
* closes).
*/
void pty_pre_init(void)
{
#ifndef OMIT_UTMP
pid_t pid;
int pipefd[2];
#endif
/* set the child signal handler straight away; it needs to be set
* before we ever fork. */
putty_signal(SIGCHLD, sigchld_handler);
pty_master_fd = -1;
if (geteuid() != getuid() || getegid() != getgid()) {
|
| ︙ | | |
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
|
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
|
-
+
|
pty_utmp_helper_pid = pid;
pty_utmp_helper_pipe = pipefd[1];
}
#endif
/* Drop privs. */
{
int gid = getgid(), uid = getuid();
#ifndef HAVE_NO_SETRESUID
int gid = getgid(), uid = getuid();
int setresgid(gid_t, gid_t, gid_t);
int setresuid(uid_t, uid_t, uid_t);
setresgid(gid, gid, gid);
setresuid(uid, uid, uid);
#else
setgid(getgid());
setuid(getuid());
|
| ︙ | | |
516
517
518
519
520
521
522
523
524
525
526
527
528
529
|
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
|
+
|
{
struct termios attrs;
tcgetattr(pty_master_fd, &attrs);
attrs.c_cc[VERASE] = cfg->bksp_is_delete ? '\177' : '\010';
tcsetattr(pty_master_fd, TCSANOW, &attrs);
}
#ifndef OMIT_UTMP
/*
* Stamp utmp (that is, tell the utmp helper process to do so),
* or not.
*/
if (!cfg->stamp_utmp) {
close(pty_utmp_helper_pipe); /* just let the child process die */
pty_utmp_helper_pipe = -1;
|
| ︙ | | |
537
538
539
540
541
542
543
544
545
546
547
548
549
550
|
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
|
+
|
close(pty_utmp_helper_pipe); /* arrgh, just give up */
pty_utmp_helper_pipe = -1;
break;
}
pos += ret;
}
}
#endif
windowid = get_windowid(pty_frontend);
/*
* Fork and execute the command.
*/
pid = fork();
|
| ︙ | | |
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
|
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
|
-
+
-
+
|
dup2(slavefd, 0);
dup2(slavefd, 1);
dup2(slavefd, 2);
setsid();
ioctl(slavefd, TIOCSCTTY, 1);
pgrp = getpid();
tcsetpgrp(slavefd, pgrp);
setpgrp();
setpgrp(pgrp, pgrp);
close(open(pty_name, O_WRONLY, 0));
setpgrp();
setpgrp(pgrp, pgrp);
/* Close everything _else_, for tidiness. */
for (i = 3; i < 1024; i++)
close(i);
{
char term_env_var[10 + sizeof(cfg->termtype)];
sprintf(term_env_var, "TERM=%s", cfg->termtype);
putenv(term_env_var);
|
| ︙ | | |
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
|
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
|
+
+
|
static void pty_close(void)
{
if (pty_master_fd >= 0) {
close(pty_master_fd);
pty_master_fd = -1;
}
#ifndef OMIT_UTMP
if (pty_utmp_helper_pipe >= 0) {
close(pty_utmp_helper_pipe); /* this causes utmp to be cleaned up */
pty_utmp_helper_pipe = -1;
}
#endif
}
/*
* Called to query the current socket sendability status.
*/
static int pty_sendbuffer(void *handle)
{
|
| ︙ | | |