master
c 9,336 lines 237 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 dev_pt_2.c
8
9 Abstract:
10
11 This file is a test for the Pseudo Terminals: /dev/ptmx, /dev/pts/<n>
12 devices.
13
14 --*/
15
16 #include "dev_pt_common.h"
17 #include <sys/mount.h>
18 #include <libmount/libmount.h>
19
20 //
21 // Globals.
22 //
23
24 #define LXT_NAME "dev_pt_2"
25 #define PTS_START_CONTROL_CHAR "^S"
26 #define PTS_STOP_CONTROL_CHAR "^Q"
27 #define PTS_TEST_MNT "/data/pts"
28
29 typedef struct _PT_THREAD_PARAMETERS
30 {
31 pid_t ForegroundId;
32 int PtmFd;
33 int PtsFd;
34 pid_t SessionId;
35 PLXT_SYNCHRONIZATION_EVENT SynchronizationEventChild;
36 PLXT_SYNCHRONIZATION_EVENT SynchronizationEventParent;
37 } PT_THREAD_PARAMETERS, *PPT_THREAD_PARAMETERS;
38
39 //
40 // Functions.
41 //
42
43 void* PtBackgroundDisassociateTty6Thread(PPT_THREAD_PARAMETERS ThreadParameters);
44
45 int PtBackgroundSwitchToForegroundWorker(bool UseMasterEndpoint);
46
47 //
48 // Test cases.
49 //
50
51 LXT_VARIATION_HANDLER PtBackgroundBasic;
52 LXT_VARIATION_HANDLER PtBackgroundBlockedSignals;
53 LXT_VARIATION_HANDLER PtBackgroundDisassociateTty1;
54 LXT_VARIATION_HANDLER PtBackgroundDisassociateTty2;
55 LXT_VARIATION_HANDLER PtBackgroundDisassociateTty3;
56 LXT_VARIATION_HANDLER PtBackgroundDisassociateTty4;
57 LXT_VARIATION_HANDLER PtBackgroundDisassociateTty5;
58 LXT_VARIATION_HANDLER PtBackgroundDisassociateTty6;
59 LXT_VARIATION_HANDLER PtBackgroundSwitchToForeground;
60 LXT_VARIATION_HANDLER PtBufferTerminalFill;
61 LXT_VARIATION_HANDLER PtControllingTerminalForeground;
62 LXT_VARIATION_HANDLER PtControllingTerminalForeground2;
63 LXT_VARIATION_HANDLER PtControllingTerminalForeground3;
64 LXT_VARIATION_HANDLER PtControllingTerminalForeground4;
65 LXT_VARIATION_HANDLER PtControllingTerminalForeground5;
66 LXT_VARIATION_HANDLER PtControllingTerminalForeground6;
67 LXT_VARIATION_HANDLER PtControllingTerminalForeground7;
68 LXT_VARIATION_HANDLER PtMountBasic;
69 LXT_VARIATION_HANDLER PtPacketBasic1;
70 LXT_VARIATION_HANDLER PtPacketBasic2;
71 LXT_VARIATION_HANDLER PtPacketBasic3;
72 LXT_VARIATION_HANDLER PtPacketBasic4;
73 LXT_VARIATION_HANDLER PtPacketToggleMode1;
74 LXT_VARIATION_HANDLER PtPacketToggleMode2;
75 LXT_VARIATION_HANDLER PtPacketToggleMode3;
76 LXT_VARIATION_HANDLER PtPacketToggleMode4;
77 LXT_VARIATION_HANDLER PtPacketToggleMode5;
78 LXT_VARIATION_HANDLER PtPacketToggleMode6;
79 LXT_VARIATION_HANDLER PtPacketToggleMode7;
80 LXT_VARIATION_HANDLER PtPacketFlushRead1;
81 LXT_VARIATION_HANDLER PtPacketFlushRead2;
82 LXT_VARIATION_HANDLER PtPacketFlushRead3;
83 LXT_VARIATION_HANDLER PtPacketFlushWrite1;
84 LXT_VARIATION_HANDLER PtPacketFlushWrite2;
85 LXT_VARIATION_HANDLER PtPacketFlushReadWrite1;
86 LXT_VARIATION_HANDLER PtPacketFlushReadWrite2;
87 LXT_VARIATION_HANDLER PtPacketFlushReadWrite3;
88 LXT_VARIATION_HANDLER PtPacketFlushReadWrite4;
89 LXT_VARIATION_HANDLER PtPacketFlushReadWrite5;
90 LXT_VARIATION_HANDLER PtPacketHangup;
91 LXT_VARIATION_HANDLER PtPacketControlCharCheck1;
92 LXT_VARIATION_HANDLER PtPacketControlCharCheck2;
93 LXT_VARIATION_HANDLER PtPacketControlCharCheck3;
94 LXT_VARIATION_HANDLER PtPacketToggleWithControlByte;
95 LXT_VARIATION_HANDLER PtSessionBasicMaster;
96 LXT_VARIATION_HANDLER PtSuspendOutput1;
97 LXT_VARIATION_HANDLER PtSuspendOutput2;
98 LXT_VARIATION_HANDLER PtSuspendOutput3;
99 LXT_VARIATION_HANDLER PtSuspendOutput4;
100 LXT_VARIATION_HANDLER PtSuspendOutput5;
101 LXT_VARIATION_HANDLER PtSuspendOutput6;
102 LXT_VARIATION_HANDLER PtSuspendOutput7;
103 LXT_VARIATION_HANDLER PtSuspendOutput8;
104 LXT_VARIATION_HANDLER PtSuspendOutput9;
105 LXT_VARIATION_HANDLER PtSuspendOutput10;
106 LXT_VARIATION_HANDLER PtSuspendOutput11;
107 LXT_VARIATION_HANDLER PtSuspendOutput12;
108 LXT_VARIATION_HANDLER PtSuspendOutput13;
109 LXT_VARIATION_HANDLER PtSuspendOutput14;
110 LXT_VARIATION_HANDLER PtSuspendOutput15;
111 LXT_VARIATION_HANDLER PtSuspendOutput16;
112
113 //
114 // Global constants
115 //
116
117 static const LXT_VARIATION g_LxtVariations[] = {
118 {"Controlling terminal foreground tests", PtControllingTerminalForeground},
119 {"Controlling terminal foreground tests (part 2)", PtControllingTerminalForeground2},
120 {"Controlling terminal foreground tests (part 3)", PtControllingTerminalForeground3},
121 {"Controlling terminal foreground tests (part 4)", PtControllingTerminalForeground4},
122 {"Controlling terminal foreground tests (part 5)", PtControllingTerminalForeground5},
123 {"Controlling terminal foreground tests (part 6)", PtControllingTerminalForeground6},
124 {"Controlling terminal foreground tests (part 7)", PtControllingTerminalForeground7},
125 {"Basic background IO", PtBackgroundBasic},
126 {"Background IO with signals blocked", PtBackgroundBlockedSignals},
127 {"Disassociate from a controlling terminal", PtBackgroundDisassociateTty1},
128 {"Disassociate from a controlling terminal (part 2)", PtBackgroundDisassociateTty2},
129 {"Disassociate from a controlling terminal (part 3)", PtBackgroundDisassociateTty3},
130 {"Disassociate from a controlling terminal (part 4)", PtBackgroundDisassociateTty4},
131 {"Disassociate from a controlling terminal (part 5)", PtBackgroundDisassociateTty5},
132 {"Disassociate from a controlling terminal (part 6)", PtBackgroundDisassociateTty6},
133 {"Background switching to foreground", PtBackgroundSwitchToForeground},
134
135 //
136 // TODO_LX: Implement master endpoint that can be a controlling terminal.
137 //
138 //{ "Session with basic controlling terminal IO (master endpoint)", PtSessionBasicMaster },
139 //
140
141 {"PT terminal buffer fill", PtBufferTerminalFill},
142 {"PT basic mount verification", PtMountBasic},
143 {"PT Basic packet-mode", PtPacketBasic1},
144 {"PT Basic packet-mode (part 2)", PtPacketBasic2},
145 {"PT Basic packet-mode (part 3)", PtPacketBasic3},
146 {"PT Basic packet-mode (part 4)", PtPacketBasic4},
147 {"PT toggle packet-mode", PtPacketToggleMode1},
148 {"PT toggle packet-mode (part 2)", PtPacketToggleMode2},
149 {"PT toggle packet-mode (part 3)", PtPacketToggleMode3},
150 {"PT toggle packet-mode (part 4)", PtPacketToggleMode4},
151 {"PT toggle packet-mode (part 5)", PtPacketToggleMode5},
152 {"PT toggle packet-mode (part 6)", PtPacketToggleMode6},
153 {"PT toggle packet-mode (part 7)", PtPacketToggleMode7},
154 {"PT packet-mode flush read queue", PtPacketFlushRead1},
155 {"PT packet-mode flush read queue (part 2)", PtPacketFlushRead2},
156 {"PT packet-mode flush read queue (part 3)", PtPacketFlushRead3},
157 {"PT packet-mode flush write queue", PtPacketFlushWrite1},
158 {"PT packet-mode flush write queue (part 2)", PtPacketFlushWrite2},
159 {"PT packet-mode flush read/write queue", PtPacketFlushReadWrite1},
160 {"PT packet-mode flush read/write queue (part 2)", PtPacketFlushReadWrite2},
161 {"PT packet-mode flush read/write queue (part 3)", PtPacketFlushReadWrite3},
162 {"PT packet-mode flush read/write queue (part 4)", PtPacketFlushReadWrite4},
163 {"PT packet-mode flush read/write queue (part 5)", PtPacketFlushReadWrite5},
164 {"PT packet-mode hangup", PtPacketHangup},
165 {"PT packet-mode Ctrl-C", PtPacketControlCharCheck1},
166 {"PT packet-mode START/STOP assignment", PtPacketControlCharCheck2},
167 {"PT packet-mode START/STOP", PtPacketControlCharCheck3},
168 {"PT packet-mode toggle with control byte", PtPacketToggleWithControlByte},
169 {"PT suspend output", PtSuspendOutput1},
170 {"PT suspend output (part 2)", PtSuspendOutput2},
171 {"PT suspend output (part 3)", PtSuspendOutput3},
172 {"PT suspend output (part 4)", PtSuspendOutput4},
173 {"PT suspend output (part 5)", PtSuspendOutput5},
174 {"PT suspend output (part 6)", PtSuspendOutput6},
175 {"PT suspend output (part 7)", PtSuspendOutput7},
176 {"PT suspend output (part 8)", PtSuspendOutput8},
177 {"PT suspend output (part 9)", PtSuspendOutput9},
178 {"PT suspend output (part 10)", PtSuspendOutput10},
179 {"PT suspend output (part 11)", PtSuspendOutput11},
180 {"PT suspend output (part 12)", PtSuspendOutput12},
181 {"PT suspend output (part 13)", PtSuspendOutput13},
182 {"PT suspend output (part 14)", PtSuspendOutput14},
183 {"PT suspend output (part 15)", PtSuspendOutput15},
184 {"PT suspend output (part 16)", PtSuspendOutput16},
185 };
186
187 int DevPtTwoTestEntry(int Argc, char* Argv[])
188
189 /*++
190
191 Routine Description:
192
193 This routine main entry point for the pty(2) test.
194
195 Arguments:
196
197 Argc - Supplies the number of command line arguments.
198
199 Argv - Supplies the command line arguments.
200
201 Return Value:
202
203 Returns 0 on success, -1 on failure.
204
205 --*/
206
207 {
208
209 LXT_ARGS Args;
210 int Result;
211
212 LxtCheckErrno(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
213 LXT_SYNCHRONIZATION_POINT_INIT();
214 LxtCheckErrno(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
215
216 ErrorExit:
217 LXT_SYNCHRONIZATION_POINT_DESTROY();
218 LxtUninitialize();
219 return !LXT_SUCCESS(Result);
220 }
221
222 int PtBackgroundBasic(PLXT_ARGS Args)
223
224 /*++
225
226 Routine Description:
227
228 This routine performs basic IO checks from a background process.
229
230 Arguments:
231
232 Args - Supplies the command line arguments.
233
234 Return Value:
235
236 Returns 0 on success, -1 on failure.
237
238 --*/
239
240 {
241
242 pid_t ChildPid;
243 pid_t ForegroundId;
244 int PtmFd;
245 int PtsFd;
246 int Result;
247 pid_t SessionId;
248 int Status;
249 pid_t TerminalForegroundId;
250 pid_t TerminalSessionId;
251
252 //
253 // Initialize locals
254 //
255
256 ChildPid = -1;
257 PtmFd = -1;
258 PtsFd = -1;
259
260 LXT_SYNCHRONIZATION_POINT_START();
261 LxtCheckErrno(ChildPid = ForkPtyBackground(&PtmFd, &PtsFd, &ForegroundId));
262 if (ChildPid == 0)
263 {
264 LxtCheckResult(LxtSignalInitialize());
265 LxtCheckResult(LxtSignalSetupHandler(SIGTTOU, SA_SIGINFO));
266 LxtCheckResult(LxtSignalSetupHandler(SIGTTIN, SA_SIGINFO));
267 LxtCheckResult(SessionId = getsid(0));
268 LxtCheckErrno(TerminalSessionId = tcgetsid(PtsFd));
269 LxtCheckEqual(SessionId, TerminalSessionId, "%d");
270 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtsFd));
271 LxtCheckEqual(ForegroundId, TerminalForegroundId, "%d");
272 LxtCheckErrnoFailure(RawInit(PtsFd), EINTR);
273 LxtCheckResult(LxtSignalCheckReceived(SIGTTOU));
274 LxtSignalResetReceived();
275 LxtCheckErrno(SimpleReadWriteCheckEx(PtmFd, PtsFd, SimpleReadWriteBackgroundSignalNoStop));
276 LxtCheckResult(LxtSignalCheckReceived(SIGTTIN));
277 LxtSignalResetReceived();
278 LxtCheckErrno(tcflush(PtmFd, TCIFLUSH));
279
280 //
281 // Temporarily block SIGTTOU in order to enable TOSTOP
282 //
283
284 LxtCheckErrnoZeroSuccess(LxtSignalBlock(SIGTTOU));
285 LxtCheckErrno(RawInit(PtsFd));
286 LxtCheckResult(LxtSignalCheckNoSignal());
287 LxtCheckErrnoZeroSuccess(LxtSignalUnblock(SIGTTOU));
288
289 //
290 // Try again with TOSTOP enabled
291 //
292
293 LxtLogInfo("Check with TOSTOP flag enabled");
294 LxtSignalSetAllowMultiple(TRUE);
295 LxtCheckErrno(SimpleReadWriteCheckEx(PtmFd, PtsFd, SimpleReadWriteBackgroundSignal));
296 LxtCheckResult(LxtSignalCheckReceived(SIGTTIN));
297 LxtCheckResult(LxtSignalCheckReceived(SIGTTOU));
298 LxtSignalResetReceived();
299 }
300
301 ErrorExit:
302 if ((ChildPid != 0) && (PtmFd != -1))
303 {
304 close(PtmFd);
305 }
306
307 if ((ChildPid != 0) && (PtsFd != -1))
308 {
309 close(PtsFd);
310 }
311
312 LXT_SYNCHRONIZATION_POINT_END();
313 return Result;
314 }
315
316 int PtBackgroundBlockedSignals(PLXT_ARGS Args)
317
318 /*++
319
320 Routine Description:
321
322 This routine performs IO checks from a background thread that has blocked
323 SIGTTIN and SIGTTOU.
324
325 Arguments:
326
327 Args - Supplies the command line arguments.
328
329 Return Value:
330
331 Returns 0 on success, -1 on failure.
332
333 --*/
334
335 {
336
337 pid_t ChildPid;
338 pid_t ForegroundId;
339 int PtmFd;
340 int PtsFd;
341 int Result;
342 int Status;
343
344 //
345 // Initialize locals
346 //
347
348 ChildPid = -1;
349 PtmFd = -1;
350 PtsFd = -1;
351
352 LXT_SYNCHRONIZATION_POINT_START();
353 LxtCheckErrno(ChildPid = ForkPtyBackground(&PtmFd, &PtsFd, &ForegroundId));
354 if (ChildPid == 0)
355 {
356 LxtCheckResult(LxtSignalInitialize());
357 LxtCheckResult(LxtSignalSetupHandler(SIGTTOU, SA_SIGINFO));
358 LxtCheckResult(LxtSignalSetupHandler(SIGTTIN, SA_SIGINFO));
359 LxtCheckErrnoZeroSuccess(LxtSignalBlock(SIGTTIN));
360 LxtCheckErrnoZeroSuccess(LxtSignalBlock(SIGTTOU));
361 LxtCheckErrno(RawInit(PtsFd));
362 LxtCheckErrno(SimpleReadWriteCheckEx(PtmFd, PtsFd, SimpleReadWriteBackgroundNoSignal));
363 LxtCheckResult(LxtSignalCheckNoSignal());
364 }
365
366 ErrorExit:
367 if ((ChildPid != 0) && (PtmFd != -1))
368 {
369 close(PtmFd);
370 }
371
372 if ((ChildPid != 0) && (PtsFd != -1))
373 {
374 close(PtsFd);
375 }
376
377 LXT_SYNCHRONIZATION_POINT_END();
378 return Result;
379 }
380
381 int PtBackgroundSwitchToForeground(PLXT_ARGS Args)
382
383 /*++
384
385 Routine Description:
386
387 This routine moves from a background process to a foreground process, with
388 sanity IO checks.
389
390 Arguments:
391
392 Args - Supplies the command line arguments.
393
394 Return Value:
395
396 Returns 0 on success, -1 on failure.
397
398 --*/
399
400 {
401
402 int Result;
403
404 LxtCheckErrno(PtBackgroundSwitchToForegroundWorker(false));
405
406 //
407 // TODO_LX: Implement master endpoint that can be a controlling terminal.
408 //
409
410 // LxtCheckErrno(PtBackgroundSwitchToForegroundWorker(true));
411
412 ErrorExit:
413 return Result;
414 }
415
416 int PtBackgroundSwitchToForegroundWorker(bool UseMasterEndpoint)
417
418 /*++
419
420 Routine Description:
421
422 This routine moves from a background process to a foreground process, with
423 sanity IO checks.
424
425 Arguments:
426
427 UseMasterEndpoint - Supplies the flag indicating whether the call should be
428 made on the master or the subordinate endpoints.
429
430 Return Value:
431
432 Returns 0 on success, -1 on failure.
433
434 --*/
435
436 {
437
438 pid_t ChildPid;
439 pid_t ForegroundId;
440 int PtmFd;
441 int PtsFd;
442 int Result;
443 pid_t SessionId;
444 int Status;
445 pid_t TerminalForegroundId;
446 pid_t TerminalSessionId;
447
448 //
449 // Initialize locals
450 //
451
452 ChildPid = -1;
453 PtmFd = -1;
454 PtsFd = -1;
455
456 LXT_SYNCHRONIZATION_POINT_START();
457 LxtCheckErrno(ChildPid = ForkPtyBackground(&PtmFd, &PtsFd, &ForegroundId));
458 if (ChildPid == 0)
459 {
460 LxtCheckResult(LxtSignalInitialize());
461 LxtCheckResult(LxtSignalSetupHandler(SIGTTOU, SA_SIGINFO));
462 LxtCheckResult(LxtSignalSetupHandler(SIGTTIN, SA_SIGINFO));
463 LxtCheckErrnoFailure(tcsetpgrp((UseMasterEndpoint) ? PtmFd : PtsFd, getpgid(0)), EINTR);
464
465 LxtCheckResult(LxtSignalCheckReceived(SIGTTOU));
466 LxtSignalResetReceived();
467
468 //
469 // Temporarily block SIGTTOU to force process to foreground.
470 //
471
472 LxtCheckErrnoZeroSuccess(LxtSignalBlock(SIGTTOU));
473 LxtCheckErrno(tcsetpgrp((UseMasterEndpoint) ? PtmFd : PtsFd, getpgid(0)));
474
475 LxtCheckErrnoZeroSuccess(LxtSignalUnblock(SIGTTOU));
476
477 //
478 // Verify foreground IO behavior.
479 //
480
481 LxtCheckResult(SessionId = getsid(0));
482 LxtCheckErrno(TerminalSessionId = tcgetsid(PtsFd));
483 LxtCheckEqual(SessionId, TerminalSessionId, "%d");
484 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtsFd));
485 LxtCheckNotEqual(ForegroundId, TerminalForegroundId, "%d");
486 LxtCheckErrno(RawInit(PtsFd));
487 LxtCheckErrno(SimpleReadWriteCheck(PtmFd, PtsFd));
488 LxtCheckResult(LxtSignalCheckNoSignal());
489 LxtSignalResetReceived();
490 }
491
492 ErrorExit:
493 if ((ChildPid != 0) && (PtmFd != -1))
494 {
495 close(PtmFd);
496 }
497
498 if ((ChildPid != 0) && (PtsFd != -1))
499 {
500 close(PtsFd);
501 }
502
503 LXT_SYNCHRONIZATION_POINT_END();
504 return Result;
505 }
506
507 int PtBackgroundDisassociateTty1(PLXT_ARGS Args)
508
509 /*++
510
511 Routine Description:
512
513 This routine removes the controlling terminal from a background thread and
514 then tests ioctl behavior.
515
516 Arguments:
517
518 Args - Supplies the command line arguments.
519
520 Return Value:
521
522 Returns 0 on success, -1 on failure.
523
524 --*/
525
526 {
527
528 pid_t ChildPid;
529 tcflag_t ControlFlags;
530 pid_t ForegroundId;
531 int PtmFd;
532 int PtsFd;
533 int Result;
534 pid_t SessionId;
535 int Status;
536 pid_t TerminalForegroundId;
537 pid_t TerminalSessionId;
538 struct winsize WindowSizeM;
539
540 //
541 // Initialize locals
542 //
543
544 ChildPid = -1;
545 PtmFd = -1;
546 PtsFd = -1;
547
548 LXT_SYNCHRONIZATION_POINT_START();
549 LxtCheckErrno(ChildPid = ForkPtyBackground(&PtmFd, &PtsFd, &ForegroundId));
550 if (ChildPid == 0)
551 {
552 LxtCheckResult(LxtSignalInitialize());
553 LxtCheckResult(LxtSignalSetupHandler(SIGTTOU, SA_SIGINFO));
554 LxtCheckResult(LxtSignalSetupHandler(SIGTTIN, SA_SIGINFO));
555 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
556 LxtCheckResult(LxtSignalSetupHandler(SIGCONT, SA_SIGINFO));
557 LxtCheckResult(SessionId = getsid(0));
558
559 //
560 // Disconnect the controlling terminal.
561 //
562
563 LxtCheckErrno(ioctl(PtsFd, TIOCNOTTY, (char*)NULL));
564 LxtCheckResult(LxtSignalCheckNoSignal());
565
566 //
567 // Test various ioctl behavior on the subordinate endpoint.
568 //
569
570 LxtCheckErrno(TerminalSettingsGetControlFlags(PtsFd, &ControlFlags));
571 LxtCheckErrno(TerminalSettingsSetControlFlags(PtsFd, ControlFlags));
572 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), ENOTTY);
573 LxtCheckErrnoFailure(tcsetpgrp(PtsFd, getpgid(0)), ENOTTY);
574
575 LxtCheckErrnoFailure(tcgetsid(PtsFd), ENOTTY);
576 LxtCheckErrno(ioctl(PtsFd, TIOCGWINSZ, &WindowSizeM));
577 LxtCheckErrno(ioctl(PtsFd, TIOCSWINSZ, &WindowSizeM));
578 LxtCheckErrno(tcflow(PtsFd, TCOOFF));
579 LxtCheckErrno(tcflow(PtsFd, TCOON));
580 LxtCheckErrno(tcflow(PtsFd, TCIOFF));
581 LxtCheckErrno(tcflow(PtsFd, TCION));
582 LxtCheckErrnoFailure(ioctl(PtsFd, TIOCSCTTY, (char*)NULL), EPERM);
583 LxtCheckErrnoFailure(ioctl(PtsFd, TIOCNOTTY, (char*)NULL), ENOTTY);
584 LxtCheckErrno(tcdrain(PtsFd));
585 LxtCheckErrno(tcflush(PtsFd, TCIOFLUSH));
586 LxtCheckErrno(ioctl(PtsFd, TIOCSTI, "x"));
587 LxtCheckErrnoFailure(ioctl(PtsFd, TIOCSTI, (char*)NULL), EFAULT);
588
589 //
590 // Test various ioctl behavior on the master endpoint.
591 //
592
593 LxtCheckErrno(TerminalSettingsGetControlFlags(PtmFd, &ControlFlags));
594 LxtCheckErrno(TerminalSettingsSetControlFlags(PtmFd, ControlFlags));
595
596 //
597 // On Linux, The master endpoint returns the foreground/session state.
598 //
599
600 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtmFd));
601 LxtCheckEqual(TerminalForegroundId, ForegroundId, "%d");
602 LxtCheckErrnoFailure(tcsetpgrp(PtmFd, getpgid(0)), ENOTTY);
603
604 LxtCheckErrno(TerminalSessionId = tcgetsid(PtmFd));
605 LxtCheckEqual(TerminalSessionId, SessionId, "%d");
606 LxtCheckErrno(ioctl(PtmFd, TIOCGWINSZ, &WindowSizeM));
607 LxtCheckErrno(ioctl(PtmFd, TIOCSWINSZ, &WindowSizeM));
608 LxtCheckErrno(tcflow(PtmFd, TCOOFF));
609 LxtCheckErrno(tcflow(PtmFd, TCOON));
610 LxtCheckErrno(tcflow(PtmFd, TCIOFF));
611 LxtCheckErrno(tcflow(PtmFd, TCION));
612 LxtCheckErrnoFailure(ioctl(PtmFd, TIOCSCTTY, (char*)NULL), EPERM);
613 LxtCheckErrnoFailure(ioctl(PtmFd, TIOCNOTTY, (char*)NULL), ENOTTY);
614 LxtCheckErrno(tcdrain(PtmFd));
615 LxtCheckErrno(tcflush(PtmFd, TCIOFLUSH));
616 LxtCheckErrno(ioctl(PtmFd, TIOCSTI, "x"));
617 LxtCheckErrnoFailure(ioctl(PtmFd, TIOCSTI, (char*)NULL), EFAULT);
618 }
619
620 ErrorExit:
621 if ((ChildPid != 0) && (PtmFd != -1))
622 {
623 close(PtmFd);
624 }
625
626 if ((ChildPid != 0) && (PtsFd != -1))
627 {
628 close(PtsFd);
629 }
630
631 LXT_SYNCHRONIZATION_POINT_END();
632
633 return Result;
634 }
635
636 int PtBackgroundDisassociateTty2(PLXT_ARGS Args)
637
638 /*++
639
640 Routine Description:
641
642 This routine removes the controlling terminal from a background thread.
643
644 Arguments:
645
646 Args - Supplies the command line arguments.
647
648 Return Value:
649
650 Returns 0 on success, -1 on failure.
651
652 --*/
653
654 {
655
656 pid_t ChildPid;
657 BOOLEAN EndChildPidSynchronization;
658 pid_t ForegroundId;
659 int PtmFd;
660 int PtsFd;
661 int Result;
662 pid_t SessionId;
663 int Status;
664 pid_t TerminalForegroundId;
665 pid_t TerminalSessionId;
666
667 //
668 // Initialize locals
669 //
670
671 ChildPid = -1;
672 EndChildPidSynchronization = TRUE;
673 PtmFd = -1;
674 PtsFd = -1;
675
676 LXT_SYNCHRONIZATION_POINT_START();
677 LxtCheckErrno(ChildPid = ForkPtyBackground(&PtmFd, &PtsFd, &ForegroundId));
678 if (ChildPid == 0)
679 {
680 LxtCheckResult(LxtSignalInitialize());
681 LxtCheckResult(LxtSignalSetupHandler(SIGTTOU, SA_SIGINFO));
682 LxtCheckResult(LxtSignalSetupHandler(SIGTTIN, SA_SIGINFO));
683 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
684 LxtCheckResult(LxtSignalSetupHandler(SIGCONT, SA_SIGINFO));
685 LxtCheckResult(SessionId = getsid(0));
686
687 //
688 // Allow the other thread to try to disassociate the terminal, and wait
689 // for that to complete.
690 //
691
692 LXT_SYNCHRONIZATION_POINT();
693 LxtCheckResult(LxtSignalCheckNoSignal());
694
695 //
696 // Check session and foreground process group for both endpoints of
697 // the psuedo-terminal.
698 //
699
700 LxtCheckErrno(TerminalSessionId = tcgetsid(PtsFd));
701 LxtCheckEqual(TerminalSessionId, SessionId, "%d");
702 LxtCheckErrno(TerminalSessionId = tcgetsid(PtmFd));
703 LxtCheckEqual(TerminalSessionId, SessionId, "%d");
704 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtsFd));
705 LxtCheckEqual(TerminalForegroundId, ForegroundId, "%d");
706 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtmFd));
707 LxtCheckEqual(TerminalForegroundId, ForegroundId, "%d");
708
709 //
710 // Disconnect the controlling terminal.
711 //
712
713 LxtCheckErrno(ioctl(PtsFd, TIOCNOTTY, (char*)NULL));
714 LxtCheckResult(LxtSignalCheckNoSignal());
715
716 //
717 // Trying to disconnect again should fail.
718 //
719
720 LxtCheckErrnoFailure(ioctl(PtsFd, TIOCNOTTY, (char*)NULL), ENOTTY);
721
722 //
723 // The terminal is no longer associated, so it is expected to fail the
724 // commands to retrieve session and foreground process group.
725 //
726
727 LxtCheckErrnoFailure(TerminalSessionId = tcgetsid(PtsFd), ENOTTY);
728 LxtCheckErrnoFailure(TerminalForegroundId = tcgetpgrp(PtsFd), ENOTTY);
729
730 //
731 // On Linux, The master endpoint returns the foreground/session state.
732 //
733
734 LxtCheckErrno(TerminalSessionId = tcgetsid(PtmFd));
735 LxtCheckEqual(TerminalSessionId, SessionId, "%d");
736 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtmFd));
737 LxtCheckEqual(TerminalForegroundId, ForegroundId, "%d");
738
739 //
740 // Do a simple IO check.
741 //
742
743 LxtCheckErrno(RawInit(PtsFd));
744 LxtCheckErrno(SimpleReadWriteCheck(PtmFd, PtsFd));
745 LxtCheckResult(LxtSignalCheckNoSignal());
746 }
747 else
748 {
749
750 //
751 // Try to disassociate terminal from another session.
752 //
753
754 LxtCheckErrnoFailure(ioctl(PtsFd, TIOCNOTTY, (char*)NULL), ENOTTY);
755 LXT_SYNCHRONIZATION_POINT();
756 LxtCheckErrno(TEMP_FAILURE_RETRY(Result = waitpid(ChildPid, &Status, 0)));
757 EndChildPidSynchronization = FALSE;
758 LxtCheckResult(WIFEXITED(Status) ? 0 : -1);
759 LxtCheckResult((int)(char)WEXITSTATUS(Status));
760
761 //
762 // Check status of master endpoint after session is gone.
763 //
764
765 LxtCheckErrnoFailure(tcgetsid(PtmFd), ENOTTY);
766 LxtCheckErrno(tcgetpgrp(PtmFd));
767 }
768
769 ErrorExit:
770 if ((ChildPid != 0) && (PtmFd != -1))
771 {
772 close(PtmFd);
773 }
774
775 if ((ChildPid != 0) && (PtsFd != -1))
776 {
777 close(PtsFd);
778 }
779
780 if (EndChildPidSynchronization != FALSE)
781 {
782 LXT_SYNCHRONIZATION_POINT_END();
783 }
784
785 return Result;
786 }
787
788 int PtBackgroundDisassociateTty3(PLXT_ARGS Args)
789
790 /*++
791
792 Routine Description:
793
794 This routine removes the controlling terminal from a foreground thread and
795 checks the behavior on both foreground and background threads.
796
797 Arguments:
798
799 Args - Supplies the command line arguments.
800
801 Return Value:
802
803 Returns 0 on success, -1 on failure.
804
805 --*/
806
807 {
808
809 pid_t ChildPid;
810 BOOLEAN EndChildPidSynchronization;
811 pid_t ForegroundId;
812 pid_t GrandChildPid;
813 int PtmFd;
814 int PtsFd;
815 int Result;
816 pid_t SessionId;
817 int Status;
818 pid_t TerminalForegroundId;
819 pid_t TerminalSessionId;
820 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildPid);
821
822 //
823 // Initialize locals
824 //
825
826 ChildPid = -1;
827 EndChildPidSynchronization = TRUE;
828 GrandChildPid = -1;
829 PtmFd = -1;
830 PtsFd = -1;
831 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildPid);
832
833 LXT_SYNCHRONIZATION_POINT_START();
834 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
835 if (ChildPid == 0)
836 {
837 LxtCheckResult(LxtSignalInitialize());
838 LxtSignalSetAllowMultiple(TRUE);
839 LxtCheckResult(LxtSignalSetupHandler(SIGTTOU, SA_SIGINFO));
840 LxtCheckResult(LxtSignalSetupHandler(SIGTTIN, SA_SIGINFO));
841 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
842 LxtCheckResult(LxtSignalSetupHandler(SIGCONT, SA_SIGINFO));
843 LxtCheckResult(ForegroundId = getpid());
844 LxtCheckResult(SessionId = getsid(0));
845
846 //
847 // Allow the other thread to try to disassociate the terminal, and wait
848 // for that to complete.
849 //
850
851 LXT_SYNCHRONIZATION_POINT();
852 LXT_SYNCHRONIZATION_POINT();
853 LxtCheckResult(LxtSignalCheckNoSignal());
854
855 //
856 // Fork again to create a foreground and background thread.
857 //
858
859 LXT_SYNCHRONIZATION_POINT_START_FOR(GrandChildPid);
860 LxtCheckErrno(GrandChildPid = fork());
861 if (GrandChildPid == 0)
862 {
863 LxtCheckResult(LxtSignalInitialize());
864 LxtSignalSetAllowMultiple(TRUE);
865 LxtCheckResult(LxtSignalSetupHandler(SIGTTOU, SA_SIGINFO));
866 LxtCheckResult(LxtSignalSetupHandler(SIGTTIN, SA_SIGINFO));
867 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
868 LxtCheckResult(LxtSignalSetupHandler(SIGCONT, SA_SIGINFO));
869
870 //
871 // Move to the background.
872 //
873
874 LxtLogInfo("Moving thread %d to the background.", getpid());
875 LxtCheckErrno(setpgid(0, 0));
876
877 //
878 // Check session and foreground process group for both endpoints of
879 // the psuedo-terminal.
880 //
881
882 LxtCheckErrno(TerminalSessionId = tcgetsid(PtsFd));
883 LxtCheckEqual(TerminalSessionId, SessionId, "%d");
884 LxtCheckErrno(TerminalSessionId = tcgetsid(PtmFd));
885 LxtCheckEqual(TerminalSessionId, SessionId, "%d");
886 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtsFd));
887 LxtCheckEqual(TerminalForegroundId, ForegroundId, "%d");
888 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtmFd));
889 LxtCheckEqual(TerminalForegroundId, ForegroundId, "%d");
890
891 //
892 // Signal the foreground thread to disconnect the controlling
893 // terminal, and wait for the signal that it has completed.
894 //
895
896 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
897 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
898 LxtCheckResult(LxtSignalCheckNoSignal());
899 LxtCheckErrnoFailure(tcgetsid(PtsFd), ENOTTY);
900 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), ENOTTY);
901
902 //
903 // On Linux, The master endpoint returns foreground/session state,
904 // but instead of failing the foreground group query will just
905 // return 0.
906 //
907
908 LxtCheckErrnoFailure(tcgetsid(PtmFd), ENOTTY);
909 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtmFd));
910 LxtCheckEqual(TerminalForegroundId, 0, "%d");
911
912 //
913 // Do a simple IO test.
914 //
915
916 LxtCheckErrno(RawInit(PtsFd));
917 LxtCheckErrno(SimpleReadWriteCheck(PtmFd, PtsFd));
918 LxtCheckResult(LxtSignalCheckNoSignal());
919 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
920 }
921 else
922 {
923 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
924 LxtCheckErrno(ioctl(PtsFd, TIOCNOTTY, (char*)NULL));
925 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
926
927 //
928 // TODO_LX: Support SIGCONT.
929 //
930 // LxtCheckResult(LxtSignalCheckReceived(SIGCONT));
931 //
932
933 LxtCheckResult(LxtSignalCheckReceived(SIGHUP));
934 LxtSignalResetReceived();
935 LxtCheckErrnoFailure(ioctl(PtsFd, TIOCNOTTY, (char*)NULL), ENOTTY);
936
937 //
938 // The terminal is no longer associated, so it is expected to fail the
939 // commands to retrieve session and foreground process group.
940 //
941
942 LxtCheckErrnoFailure(tcgetsid(PtsFd), ENOTTY);
943 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), ENOTTY);
944
945 //
946 // On Linux, The master endpoint returns foreground/session state,
947 // but instead of failing the foreground group query will just
948 // return 0.
949 //
950
951 LxtCheckErrnoFailure(tcgetsid(PtmFd), ENOTTY);
952 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtmFd));
953 LxtCheckEqual(TerminalForegroundId, 0, "%d");
954
955 //
956 // Wait for other thread to finish its IO test, then do an IO test
957 // here.
958 //
959
960 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
961 LxtCheckErrno(RawInit(PtsFd));
962 LxtCheckErrno(SimpleReadWriteCheck(PtmFd, PtsFd));
963 LxtCheckResult(LxtSignalCheckNoSignal());
964 }
965 }
966 else
967 {
968
969 //
970 // Try to disassociate terminal from another session.
971 //
972
973 LXT_SYNCHRONIZATION_POINT();
974 LxtCheckErrnoFailure(ioctl(PtsFd, TIOCNOTTY, (char*)NULL), ENOTTY);
975 LXT_SYNCHRONIZATION_POINT();
976
977 //
978 // Wait for the child here in order to run more tests after the session
979 // has been destroyed.
980 //
981
982 LxtCheckErrno(TEMP_FAILURE_RETRY(Result = waitpid(ChildPid, &Status, 0)));
983 EndChildPidSynchronization = FALSE;
984 LxtCheckResult(WIFEXITED(Status) ? 0 : -1);
985 LxtCheckResult((int)(char)WEXITSTATUS(Status));
986
987 //
988 // Check status of master endpoint after session is gone.
989 //
990
991 LxtCheckErrnoFailure(tcgetsid(PtmFd), ENOTTY);
992 LxtCheckErrno(tcgetpgrp(PtmFd));
993 }
994
995 ErrorExit:
996 if ((ChildPid != 0) && (PtmFd != -1))
997 {
998 close(PtmFd);
999 }
1000
1001 if ((ChildPid != 0) && (PtsFd != -1))
1002 {
1003 close(PtsFd);
1004 }
1005
1006 LXT_SYNCHRONIZATION_POINT_END_FOR(GrandChildPid, TRUE);
1007 if (EndChildPidSynchronization != FALSE)
1008 {
1009 LXT_SYNCHRONIZATION_POINT_END();
1010 }
1011
1012 return Result;
1013 }
1014
1015 int PtBackgroundDisassociateTty4(PLXT_ARGS Args)
1016
1017 /*++
1018
1019 Routine Description:
1020
1021 This routine removes the controlling terminal from a background thread and
1022 checks the behavior on both foreground and background threads.
1023
1024 Arguments:
1025
1026 Args - Supplies the command line arguments.
1027
1028 Return Value:
1029
1030 Returns 0 on success, -1 on failure.
1031
1032 --*/
1033
1034 {
1035
1036 pid_t ChildPid;
1037 BOOLEAN EndChildPidSynchronization;
1038 pid_t ForegroundId;
1039 pid_t GrandChildPid;
1040 int PtmFd;
1041 int PtsFd;
1042 int Result;
1043 pid_t SessionId;
1044 int Status;
1045 pid_t TerminalForegroundId;
1046 pid_t TerminalSessionId;
1047 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildPid);
1048
1049 //
1050 // Initialize locals
1051 //
1052
1053 ChildPid = -1;
1054 EndChildPidSynchronization = TRUE;
1055 GrandChildPid = -1;
1056 PtmFd = -1;
1057 PtsFd = -1;
1058 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildPid);
1059
1060 LXT_SYNCHRONIZATION_POINT_START();
1061 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
1062 if (ChildPid == 0)
1063 {
1064 LxtCheckResult(LxtSignalInitialize());
1065 LxtSignalSetAllowMultiple(TRUE);
1066 LxtCheckResult(LxtSignalSetupHandler(SIGTTOU, SA_SIGINFO));
1067 LxtCheckResult(LxtSignalSetupHandler(SIGTTIN, SA_SIGINFO));
1068 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
1069 LxtCheckResult(LxtSignalSetupHandler(SIGCONT, SA_SIGINFO));
1070 LxtCheckResult(ForegroundId = getpid());
1071 LxtCheckResult(SessionId = getsid(0));
1072
1073 //
1074 // Allow the other thread to try to disassociate the terminal, and wait
1075 // for that to complete.
1076 //
1077
1078 LXT_SYNCHRONIZATION_POINT();
1079 LXT_SYNCHRONIZATION_POINT();
1080 LxtCheckResult(LxtSignalCheckNoSignal());
1081
1082 //
1083 // Fork again to create a foreground and background thread.
1084 //
1085
1086 LXT_SYNCHRONIZATION_POINT_START_FOR(GrandChildPid);
1087 LxtCheckErrno(GrandChildPid = fork());
1088 if (GrandChildPid == 0)
1089 {
1090 EndChildPidSynchronization = FALSE;
1091 LxtCheckResult(LxtSignalInitialize());
1092 LxtSignalSetAllowMultiple(TRUE);
1093 LxtCheckResult(LxtSignalSetupHandler(SIGTTOU, SA_SIGINFO));
1094 LxtCheckResult(LxtSignalSetupHandler(SIGTTIN, SA_SIGINFO));
1095 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
1096 LxtCheckResult(LxtSignalSetupHandler(SIGCONT, SA_SIGINFO));
1097
1098 //
1099 // Move to the background.
1100 //
1101
1102 LxtLogInfo("Moving thread %d to the background.", getpid());
1103 LxtCheckErrno(setpgid(0, 0));
1104
1105 //
1106 // Check session and foreground process group for both endpoints of
1107 // the psuedo-terminal.
1108 //
1109
1110 LxtCheckErrno(TerminalSessionId = tcgetsid(PtsFd));
1111 LxtCheckEqual(TerminalSessionId, SessionId, "%d");
1112 LxtCheckErrno(TerminalSessionId = tcgetsid(PtmFd));
1113 LxtCheckEqual(TerminalSessionId, SessionId, "%d");
1114 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtsFd));
1115 LxtCheckEqual(TerminalForegroundId, ForegroundId, "%d");
1116 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtmFd));
1117 LxtCheckEqual(TerminalForegroundId, ForegroundId, "%d");
1118
1119 //
1120 // Disconnect the controlling terminal.
1121 //
1122
1123 LxtLogInfo(
1124 "Disconnecting controlling terminal from background "
1125 "thread %d.",
1126 getpid());
1127
1128 LxtCheckErrno(ioctl(PtsFd, TIOCNOTTY, (char*)NULL));
1129 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
1130 LxtCheckResult(LxtSignalCheckNoSignal());
1131
1132 //
1133 // Check session and foreground process group again.
1134 //
1135
1136 LxtLogInfo("Checking ioctls from thread %d after disconnect.", getpid());
1137 LxtCheckErrnoFailure(tcgetsid(PtsFd), ENOTTY);
1138 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), ENOTTY);
1139
1140 //
1141 // On Linux, The master endpoint returns the foreground/session
1142 // state.
1143 //
1144
1145 LxtCheckErrno(TerminalSessionId = tcgetsid(PtmFd));
1146 LxtCheckEqual(TerminalSessionId, SessionId, "%d");
1147 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtmFd));
1148 LxtCheckEqual(TerminalForegroundId, ForegroundId, "%d");
1149
1150 //
1151 // Do a simple IO test.
1152 //
1153
1154 LxtCheckErrno(RawInit(PtsFd));
1155 LxtCheckErrno(SimpleReadWriteCheck(PtmFd, PtsFd));
1156 LxtCheckResult(LxtSignalCheckNoSignal());
1157 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
1158 }
1159 else
1160 {
1161
1162 //
1163 // Wait for the background thread to disconnect from the
1164 // controlling terminal.
1165 //
1166
1167 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
1168 LxtCheckResult(LxtSignalCheckNoSignal());
1169
1170 //
1171 // Check session and foreground process group for both endpoints of
1172 // the psuedo-terminal.
1173 //
1174
1175 LxtCheckErrno(TerminalSessionId = tcgetsid(PtsFd));
1176 LxtCheckEqual(TerminalSessionId, SessionId, "%d");
1177 LxtCheckErrno(TerminalSessionId = tcgetsid(PtmFd));
1178 LxtCheckEqual(TerminalSessionId, SessionId, "%d");
1179 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtsFd));
1180 LxtCheckEqual(TerminalForegroundId, ForegroundId, "%d");
1181 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtmFd));
1182 LxtCheckEqual(TerminalForegroundId, ForegroundId, "%d");
1183
1184 //
1185 // Wait for other thread to finish its IO test, then do an IO test
1186 // here.
1187 //
1188
1189 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
1190 LxtCheckErrno(RawInit(PtsFd));
1191 LxtCheckErrno(SimpleReadWriteCheck(PtmFd, PtsFd));
1192 LxtCheckResult(LxtSignalCheckNoSignal());
1193 }
1194 }
1195 else
1196 {
1197
1198 //
1199 // Try to disassociate terminal from another session.
1200 //
1201
1202 LXT_SYNCHRONIZATION_POINT();
1203 LxtCheckErrnoFailure(ioctl(PtsFd, TIOCNOTTY, (char*)NULL), ENOTTY);
1204 LXT_SYNCHRONIZATION_POINT();
1205
1206 //
1207 // Wait for the child here in order to run more tests after the session
1208 // has been destroyed.
1209 //
1210
1211 LxtLogInfo("Waiting for child thread %d to exit.", ChildPid);
1212 LxtCheckErrno(TEMP_FAILURE_RETRY(Result = waitpid(ChildPid, &Status, 0)));
1213 EndChildPidSynchronization = FALSE;
1214 LxtCheckResult(WIFEXITED(Status) ? 0 : -1);
1215 LxtCheckResult((int)(char)WEXITSTATUS(Status));
1216
1217 //
1218 // Check status of master endpoint after session is gone.
1219 //
1220
1221 LxtCheckErrnoFailure(tcgetsid(PtmFd), ENOTTY);
1222 LxtCheckErrno(tcgetpgrp(PtmFd));
1223 }
1224
1225 ErrorExit:
1226 LxtLogInfo("Exiting thread %d with Result = %d.", getpid(), Result);
1227 if ((ChildPid != 0) && (PtmFd != -1))
1228 {
1229 close(PtmFd);
1230 }
1231
1232 if ((ChildPid != 0) && (PtsFd != -1))
1233 {
1234 close(PtsFd);
1235 }
1236
1237 LXT_SYNCHRONIZATION_POINT_END_FOR(GrandChildPid, TRUE);
1238 if (EndChildPidSynchronization != FALSE)
1239 {
1240 LXT_SYNCHRONIZATION_POINT_END();
1241 }
1242
1243 return Result;
1244 }
1245
1246 int PtBackgroundDisassociateTty5(PLXT_ARGS Args)
1247
1248 /*++
1249
1250 Routine Description:
1251
1252 This routine removes the controlling terminal from a background thread,
1253 switches to a new session and establishes a new controlling terminal.
1254
1255 Arguments:
1256
1257 Args - Supplies the command line arguments.
1258
1259 Return Value:
1260
1261 Returns 0 on success, -1 on failure.
1262
1263 --*/
1264
1265 {
1266
1267 pid_t ChildPid;
1268 pid_t ForegroundId;
1269 pid_t GrandChildPid;
1270 pid_t GrandChildSessionId;
1271 int PtmFd;
1272 int Ptm2Fd;
1273 int PtsFd;
1274 int Pts2Fd;
1275 int Result;
1276 int SerialNumber;
1277 pid_t SessionId;
1278 int Status;
1279 pid_t TerminalForegroundId;
1280 pid_t TerminalSessionId;
1281 struct winsize WindowSizeM;
1282 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildPid);
1283
1284 //
1285 // Initialize locals
1286 //
1287
1288 ChildPid = -1;
1289 GrandChildPid = -1;
1290 PtmFd = -1;
1291 Ptm2Fd = -1;
1292 PtsFd = -1;
1293 Pts2Fd = -1;
1294 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildPid);
1295
1296 LXT_SYNCHRONIZATION_POINT_START();
1297 LxtCheckErrno(ChildPid = ForkPtyBackground(&PtmFd, &PtsFd, &ForegroundId));
1298 if (ChildPid == 0)
1299 {
1300 LxtCheckResult(LxtSignalInitialize());
1301 LxtSignalSetAllowMultiple(TRUE);
1302 LxtCheckResult(LxtSignalSetupHandler(SIGTTOU, SA_SIGINFO));
1303 LxtCheckResult(LxtSignalSetupHandler(SIGTTIN, SA_SIGINFO));
1304 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
1305 LxtCheckResult(LxtSignalSetupHandler(SIGCONT, SA_SIGINFO));
1306 LxtCheckResult(ForegroundId = getpid());
1307 LxtCheckResult(SessionId = getsid(0));
1308
1309 //
1310 // Disconnect the controlling terminal.
1311 //
1312
1313 LxtLogInfo(
1314 "Disconnecting controlling terminal from background "
1315 "thread %d.",
1316 getpid());
1317
1318 LxtCheckErrno(ioctl(PtsFd, TIOCNOTTY, (char*)NULL));
1319 LxtCheckResult(LxtSignalCheckNoSignal());
1320
1321 //
1322 // Create a second set of endpoints.
1323 //
1324
1325 LxtCheckErrno(OpenMasterSubordinate(&Ptm2Fd, &Pts2Fd, NULL, &SerialNumber));
1326 LxtLogInfo("Second master opened at FD:%d", Ptm2Fd);
1327 LxtLogInfo("Second subordinate Serial Number: %d", SerialNumber);
1328 LxtLogInfo("Second subordinate opened at FD:%d", Pts2Fd);
1329
1330 //
1331 // Fork again to test terminal behavior on new thread after disconnect.
1332 //
1333
1334 LxtCheckErrno(GrandChildPid = fork());
1335 if (GrandChildPid == 0)
1336 {
1337 LxtCheckResult(LxtSignalInitialize());
1338 LxtSignalSetAllowMultiple(TRUE);
1339 LxtCheckResult(LxtSignalSetupHandler(SIGTTOU, SA_SIGINFO));
1340 LxtCheckResult(LxtSignalSetupHandler(SIGTTIN, SA_SIGINFO));
1341 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
1342 LxtCheckResult(LxtSignalSetupHandler(SIGCONT, SA_SIGINFO));
1343
1344 //
1345 // Check that the new thread is still disconnected from the
1346 // original endpoints, and not associated with the new endpoints.
1347 //
1348
1349 LxtCheckErrnoFailure(tcgetsid(PtsFd), ENOTTY);
1350 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), ENOTTY);
1351 LxtCheckErrnoFailure(tcgetsid(Pts2Fd), ENOTTY);
1352 LxtCheckErrnoFailure(tcgetpgrp(Pts2Fd), ENOTTY);
1353
1354 //
1355 // Try to add a controlling terminal before creating a new session.
1356 //
1357
1358 LxtCheckErrnoFailure(ioctl(Pts2Fd, TIOCSCTTY, (char*)NULL), EPERM);
1359 LxtCheckErrnoFailure(ioctl(PtsFd, TIOCNOTTY, (char*)NULL), ENOTTY);
1360
1361 //
1362 // Create a new session.
1363 //
1364
1365 LxtCheckErrno(GrandChildSessionId = setsid());
1366
1367 //
1368 // Check that the thread, now inside a new session is still
1369 // disconnected from any endpoints.
1370 //
1371
1372 LxtCheckErrnoFailure(tcgetsid(PtsFd), ENOTTY);
1373 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), ENOTTY);
1374 LxtCheckErrnoFailure(tcgetsid(Pts2Fd), ENOTTY);
1375 LxtCheckErrnoFailure(tcgetpgrp(Pts2Fd), ENOTTY);
1376
1377 //
1378 // Try to add a controlling terminal inside the new session.
1379 //
1380
1381 LxtCheckErrno(ioctl(Pts2Fd, TIOCSCTTY, (char*)NULL));
1382 LxtCheckResult(ForegroundId = getpid());
1383
1384 //
1385 // Check session and foreground process group again.
1386 //
1387
1388 LxtCheckErrno(TerminalSessionId = tcgetsid(Pts2Fd));
1389 LxtCheckEqual(GrandChildSessionId, TerminalSessionId, "%d");
1390 LxtCheckErrno(TerminalSessionId = tcgetsid(Ptm2Fd));
1391 LxtCheckEqual(GrandChildSessionId, TerminalSessionId, "%d");
1392 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(Pts2Fd));
1393 LxtCheckEqual(ForegroundId, TerminalForegroundId, "%d");
1394 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(Ptm2Fd));
1395 LxtCheckEqual(ForegroundId, TerminalForegroundId, "%d");
1396 LxtCheckErrno(RawInit(Pts2Fd));
1397 LxtCheckErrno(SimpleReadWriteCheck(Ptm2Fd, Pts2Fd));
1398 LxtCheckResult(LxtSignalCheckNoSignal());
1399 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
1400 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
1401 }
1402 else
1403 {
1404
1405 //
1406 // Try cross-session access to the endpoints.
1407 //
1408
1409 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
1410 LxtCheckErrnoFailure(tcgetsid(Pts2Fd), ENOTTY);
1411 LxtCheckErrno(TerminalSessionId = tcgetsid(Ptm2Fd));
1412 LxtCheckNotEqual(SessionId, TerminalSessionId, "%d");
1413 LxtCheckErrnoFailure(tcgetpgrp(Pts2Fd), ENOTTY);
1414 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(Ptm2Fd));
1415 LxtCheckNotEqual(ForegroundId, TerminalForegroundId, "%d");
1416 LxtCheckErrnoFailure(tcsetpgrp(Pts2Fd, getpgid(0)), ENOTTY);
1417 LxtCheckErrno(ioctl(Pts2Fd, TIOCGWINSZ, &WindowSizeM));
1418 LxtCheckErrno(ioctl(Ptm2Fd, TIOCGWINSZ, &WindowSizeM));
1419 LxtCheckErrno(ioctl(Pts2Fd, TIOCSWINSZ, &WindowSizeM));
1420 LxtCheckErrno(ioctl(Ptm2Fd, TIOCSWINSZ, &WindowSizeM));
1421 LxtCheckErrno(tcflow(Pts2Fd, TCOOFF));
1422 LxtCheckErrno(tcflow(Ptm2Fd, TCOOFF));
1423 LxtCheckErrno(tcflow(Pts2Fd, TCOON));
1424 LxtCheckErrno(tcflow(Ptm2Fd, TCOON));
1425 LxtCheckErrno(tcflow(Pts2Fd, TCIOFF));
1426 LxtCheckErrno(tcflow(Ptm2Fd, TCIOFF));
1427 LxtCheckErrno(tcflow(Pts2Fd, TCION));
1428 LxtCheckErrno(tcflow(Ptm2Fd, TCION));
1429 LxtCheckErrnoFailure(ioctl(Pts2Fd, TIOCSCTTY, (char*)NULL), EPERM);
1430 LxtCheckErrnoFailure(ioctl(Ptm2Fd, TIOCSCTTY, (char*)NULL), EPERM);
1431 LxtCheckErrnoFailure(ioctl(Pts2Fd, TIOCNOTTY, (char*)NULL), ENOTTY);
1432 LxtCheckErrnoFailure(ioctl(Ptm2Fd, TIOCNOTTY, (char*)NULL), ENOTTY);
1433 LxtCheckErrno(tcdrain(Pts2Fd));
1434 LxtCheckErrno(tcdrain(Ptm2Fd));
1435 LxtCheckErrno(tcflush(Pts2Fd, TCIOFLUSH));
1436 LxtCheckErrno(tcflush(Ptm2Fd, TCIOFLUSH));
1437
1438 //
1439 // Test IO.
1440 //
1441
1442 LxtCheckErrno(RawInit(Pts2Fd));
1443 LxtCheckErrno(SimpleReadWriteCheck(Ptm2Fd, Pts2Fd));
1444 LxtCheckResult(LxtSignalCheckNoSignal());
1445
1446 //
1447 // Test TIOCSTI.
1448 //
1449
1450 LxtCheckErrno(ioctl(Pts2Fd, TIOCSTI, "x"));
1451 LxtCheckErrno(ioctl(Ptm2Fd, TIOCSTI, "x"));
1452 LxtCheckErrnoFailure(ioctl(Pts2Fd, TIOCSTI, (char*)NULL), EFAULT);
1453 LxtCheckErrnoFailure(ioctl(Ptm2Fd, TIOCSTI, (char*)NULL), EFAULT);
1454 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
1455 }
1456 }
1457
1458 ErrorExit:
1459 LxtLogInfo("Exiting thread %d with Result = %d.", getpid(), Result);
1460 if (Ptm2Fd != -1)
1461 {
1462 close(Ptm2Fd);
1463 }
1464
1465 if (Pts2Fd != -1)
1466 {
1467 close(Pts2Fd);
1468 }
1469
1470 if ((ChildPid != 0) && (PtmFd != -1))
1471 {
1472 close(PtmFd);
1473 }
1474
1475 if ((ChildPid != 0) && (PtsFd != -1))
1476 {
1477 close(PtsFd);
1478 }
1479
1480 LXT_SYNCHRONIZATION_POINT_END_FOR(GrandChildPid, TRUE);
1481 if (GrandChildPid != 0)
1482 {
1483 LXT_SYNCHRONIZATION_POINT_END();
1484 }
1485
1486 return Result;
1487 }
1488
1489 int PtBackgroundDisassociateTty6(PLXT_ARGS Args)
1490
1491 /*++
1492
1493 Routine Description:
1494
1495 This routine removes the controlling terminal from another thread created
1496 with CLONE_THREAD and checks the behavior on all threads.
1497
1498 Arguments:
1499
1500 Args - Supplies the command line arguments.
1501
1502 Return Value:
1503
1504 Returns 0 on success, -1 on failure.
1505
1506 --*/
1507
1508 {
1509
1510 pid_t ChildPid;
1511 LXT_CLONE_ARGS CloneArgs;
1512 pid_t ForegroundId;
1513 pthread_t GrandChildTid;
1514 void* GrandChildResult;
1515 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildTid);
1516 int PtmFd;
1517 int PtsFd;
1518 int Result;
1519 pid_t SessionId;
1520 int Status;
1521 pid_t TerminalForegroundId;
1522 pid_t TerminalSessionId;
1523 PT_THREAD_PARAMETERS ThreadParameters;
1524
1525 //
1526 // Initialize locals
1527 //
1528
1529 ChildPid = -1;
1530 GrandChildTid = 0;
1531 memset(&CloneArgs, 0, sizeof(CloneArgs));
1532 PtmFd = -1;
1533 PtsFd = -1;
1534 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildTid);
1535
1536 LxtCheckErrno(ChildPid = ForkPtyBackground(&PtmFd, &PtsFd, &ForegroundId));
1537 if (ChildPid == 0)
1538 {
1539 LxtCheckResult(LxtSignalInitialize());
1540 LxtSignalSetAllowMultiple(TRUE);
1541 LxtCheckResult(LxtSignalSetupHandler(SIGTTOU, SA_SIGINFO));
1542 LxtCheckResult(LxtSignalSetupHandler(SIGTTIN, SA_SIGINFO));
1543 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
1544 LxtCheckResult(LxtSignalSetupHandler(SIGCONT, SA_SIGINFO));
1545 LxtCheckResult(SessionId = getsid(0));
1546
1547 //
1548 // Clone a new thread.
1549 //
1550
1551 memset(&ThreadParameters, 0, sizeof(ThreadParameters));
1552 ThreadParameters.ForegroundId = ForegroundId;
1553 ThreadParameters.PtmFd = PtmFd;
1554 ThreadParameters.PtsFd = PtsFd;
1555 ThreadParameters.SessionId = SessionId;
1556 ThreadParameters.SynchronizationEventChild = LxtSyncGrandChildTidChild;
1557 ThreadParameters.SynchronizationEventParent = LxtSyncGrandChildTidParent;
1558 LxtCheckErrno(pthread_create(&GrandChildTid, NULL, (void* (*)(void*))PtBackgroundDisassociateTty6Thread, &ThreadParameters));
1559
1560 //
1561 // Wait for the other thread to disconnect from the
1562 // controlling terminal.
1563 //
1564
1565 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildTid);
1566 LxtCheckResult(LxtSignalCheckNoSignal());
1567
1568 LxtCheckErrnoFailure(tcgetsid(PtsFd), ENOTTY);
1569 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), ENOTTY);
1570
1571 //
1572 // On Linux, The master endpoint returns the foreground/session
1573 // state.
1574 //
1575
1576 LxtCheckErrno(TerminalSessionId = tcgetsid(PtmFd));
1577 LxtCheckEqual(TerminalSessionId, SessionId, "%d");
1578 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(PtmFd));
1579 LxtCheckEqual(TerminalForegroundId, ForegroundId, "%d");
1580
1581 //
1582 // Wait for other thread to finish its IO test, then do an IO test
1583 // here.
1584 //
1585
1586 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildTid);
1587 LxtCheckErrno(RawInit(PtsFd));
1588 LxtCheckErrno(SimpleReadWriteCheck(PtmFd, PtsFd));
1589 LxtCheckResult(LxtSignalCheckNoSignal());
1590 }
1591 else
1592 {
1593
1594 //
1595 // Wait for the child here in order to run more tests after the session
1596 // has been destroyed.
1597 //
1598
1599 LxtLogInfo("Waiting for child thread %d to exit.", ChildPid);
1600 LxtCheckErrno(TEMP_FAILURE_RETRY(Result = waitpid(ChildPid, &Status, 0)));
1601 LxtCheckResult(WIFEXITED(Status) ? 0 : -1);
1602 LxtCheckResult((int)(char)WEXITSTATUS(Status));
1603
1604 //
1605 // Check status of master endpoint after session is gone.
1606 //
1607
1608 LxtCheckErrnoFailure(tcgetsid(PtmFd), ENOTTY);
1609 LxtCheckErrno(tcgetpgrp(PtmFd));
1610 }
1611
1612 ErrorExit:
1613 LxtLogInfo("Exiting thread %d with Result = %d.", getpid(), Result);
1614 if (GrandChildTid > 0)
1615 {
1616 if (Result < 0)
1617 {
1618 LxtSynchronizationEventFail(LxtSyncGrandChildTidChild);
1619 }
1620
1621 Result = pthread_join(GrandChildTid, &GrandChildResult);
1622 if (Result != 0)
1623 {
1624 LxtLogError("Failed pthread_join with error %d", Result);
1625 }
1626 else
1627 {
1628
1629 Result = (int)(long)GrandChildResult;
1630 }
1631
1632 exit(Result);
1633 }
1634
1635 if ((ChildPid != 0) && (PtmFd != -1))
1636 {
1637 close(PtmFd);
1638 }
1639
1640 if ((ChildPid != 0) && (PtsFd != -1))
1641 {
1642 close(PtsFd);
1643 }
1644
1645 return Result;
1646 }
1647
1648 void* PtBackgroundDisassociateTty6Thread(PPT_THREAD_PARAMETERS ThreadParameters)
1649
1650 /*++
1651
1652 Routine Description:
1653
1654 This routine is called on a new thread from PtBackgroundDisassociateTty6.
1655
1656 Arguments:
1657
1658 ThreadParameters - Supplies thread parameters.
1659
1660 Return Value:
1661
1662 Returns 0 on success, -1 on failure.
1663
1664 --*/
1665
1666 {
1667
1668 int Result;
1669 pid_t TerminalForegroundId;
1670 pid_t TerminalSessionId;
1671
1672 LxtCheckResult(LxtSignalInitializeThread());
1673 LxtSignalSetAllowMultiple(TRUE);
1674 LxtCheckResult(LxtSignalSetupHandler(SIGTTOU, SA_SIGINFO));
1675 LxtCheckResult(LxtSignalSetupHandler(SIGTTIN, SA_SIGINFO));
1676 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
1677 LxtCheckResult(LxtSignalSetupHandler(SIGCONT, SA_SIGINFO));
1678
1679 //
1680 // Check session and foreground process group for both endpoints of
1681 // the psuedo-terminal.
1682 //
1683
1684 LxtCheckErrno(TerminalSessionId = tcgetsid(ThreadParameters->PtsFd));
1685 LxtCheckEqual(TerminalSessionId, ThreadParameters->SessionId, "%d");
1686 LxtCheckErrno(TerminalSessionId = tcgetsid(ThreadParameters->PtmFd));
1687 LxtCheckEqual(TerminalSessionId, ThreadParameters->SessionId, "%d");
1688 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(ThreadParameters->PtsFd));
1689 LxtCheckEqual(TerminalForegroundId, ThreadParameters->ForegroundId, "%d");
1690 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(ThreadParameters->PtmFd));
1691 LxtCheckEqual(TerminalForegroundId, ThreadParameters->ForegroundId, "%d");
1692
1693 //
1694 // Disconnect the controlling terminal.
1695 //
1696
1697 LxtLogInfo("Disconnecting controlling terminal from thread %d.", gettid());
1698
1699 LxtCheckErrno(ioctl(ThreadParameters->PtsFd, TIOCNOTTY, (char*)NULL));
1700 LxtCheckResult(LxtSignalCheckNoSignal());
1701 LXT_SYNCHRONIZATION_POINT_SYNCVARS(TRUE, ThreadParameters->SynchronizationEventParent, ThreadParameters->SynchronizationEventChild);
1702
1703 //
1704 // Check session and foreground process group again.
1705 //
1706
1707 LxtLogInfo("Checking ioctls from thread %d after disconnect.", gettid());
1708 LxtCheckErrnoFailure(tcgetsid(ThreadParameters->PtsFd), ENOTTY);
1709 LxtCheckErrnoFailure(tcgetpgrp(ThreadParameters->PtsFd), ENOTTY);
1710
1711 //
1712 // On Linux, The master endpoint returns the foreground/session
1713 // state.
1714 //
1715
1716 LxtCheckErrno(TerminalSessionId = tcgetsid(ThreadParameters->PtmFd));
1717 LxtCheckEqual(TerminalSessionId, ThreadParameters->SessionId, "%d");
1718 LxtCheckErrno(TerminalForegroundId = tcgetpgrp(ThreadParameters->PtmFd));
1719 LxtCheckEqual(TerminalForegroundId, ThreadParameters->ForegroundId, "%d");
1720
1721 //
1722 // Do a simple IO test.
1723 //
1724
1725 LxtCheckErrno(RawInit(ThreadParameters->PtsFd));
1726 LxtCheckErrno(SimpleReadWriteCheck(ThreadParameters->PtmFd, ThreadParameters->PtsFd));
1727
1728 LxtCheckResult(LxtSignalCheckNoSignal());
1729 LXT_SYNCHRONIZATION_POINT_SYNCVARS(TRUE, ThreadParameters->SynchronizationEventParent, ThreadParameters->SynchronizationEventChild);
1730
1731 ErrorExit:
1732 LxtLogInfo("Exiting thread %d with Result = %d", gettid(), Result);
1733 if (Result < 0)
1734 {
1735 LxtSynchronizationEventFail(ThreadParameters->SynchronizationEventParent);
1736 }
1737
1738 return (void*)(long)Result;
1739 }
1740
1741 int PtBufferTerminalFill(PLXT_ARGS Args)
1742
1743 /*++
1744
1745 Routine Description:
1746
1747 This routine checks the internal implementation of the buffer by attempting
1748 to fill it.
1749
1750 Arguments:
1751
1752 Args - Supplies the command line arguments.
1753
1754 Return Value:
1755
1756 Returns 0 on success, -1 on failure.
1757
1758 --*/
1759
1760 {
1761
1762 int BytesReadWrite;
1763 int PtmFd;
1764 int PtmFlags;
1765 int PtsFd;
1766 int Result;
1767 int SerialNumber;
1768 struct timeval Timeout;
1769 char WriteBuffer[] = "abcdefghijklmn";
1770 char WriteBuffer2[] = "0123456\n789ABC";
1771 size_t WriteBufferLen;
1772 fd_set WriteFds;
1773
1774 //
1775 // Initialize locals.
1776 //
1777
1778 PtmFd = -1;
1779 PtsFd = -1;
1780 WriteBufferLen = sizeof(WriteBuffer) - 1;
1781
1782 //
1783 // Open Master-Subordinate.
1784 //
1785
1786 LxtCheckErrno(OpenMasterSubordinate(&PtmFd, &PtsFd, NULL, &SerialNumber));
1787 LxtLogInfo("Master opened at FD:%d", PtmFd);
1788 LxtLogInfo("Subordinate Serial Number: %d", SerialNumber);
1789 LxtLogInfo("Subordinate opened at FD:%d", PtsFd);
1790
1791 //
1792 // Mark the master non-blocking and write to it in a loop.
1793 // When it is out of room, it will return with EAGAIN.
1794 //
1795
1796 fcntl(PtmFd, F_SETFL, O_NONBLOCK);
1797 LxtLogInfo("Filling up the buffer - this might take some time...");
1798 for (;;)
1799 {
1800 BytesReadWrite = write(PtmFd, WriteBuffer, WriteBufferLen);
1801 if (BytesReadWrite != WriteBufferLen)
1802 {
1803 break;
1804 }
1805 }
1806
1807 //
1808 // Given the odd number of bytes written, it is expected for the write
1809 // to fail partway through the last transfer, returning a non-zero
1810 // number of bytes written.
1811 //
1812 // N.B. On Ubuntu16, because the buffer size grows asynchronously under
1813 // pressure the buffer may be writeable again by this point.
1814 //
1815
1816 if (BytesReadWrite < 0)
1817 {
1818 LxtLogError("Write failed with errno %d: %s", errno, strerror(errno));
1819 Result = -1;
1820 goto ErrorExit;
1821 }
1822
1823 LxtLogInfo("Last write was %d bytes of the %d byte buffer", BytesReadWrite, WriteBufferLen);
1824
1825 LxtCheckNotEqual(BytesReadWrite, WriteBufferLen, "%llu");
1826
1827 memset(&Timeout, 0, sizeof(Timeout));
1828 Timeout.tv_sec = 2;
1829 FD_ZERO(&WriteFds);
1830 FD_SET(PtmFd, &WriteFds);
1831 LxtCheckErrno(select((PtmFd + 1), NULL, &WriteFds, NULL, &Timeout));
1832 LxtCheckEqual(Result, 1, "%d");
1833
1834 LxtCheckErrno(BytesReadWrite = write(PtmFd, WriteBuffer2, WriteBufferLen));
1835 LxtLogInfo("Last write was %d bytes of the %d byte buffer", BytesReadWrite, WriteBufferLen);
1836
1837 memset(&Timeout, 0, sizeof(Timeout));
1838 Timeout.tv_sec = 2;
1839 FD_ZERO(&WriteFds);
1840 FD_SET(PtmFd, &WriteFds);
1841 LxtCheckErrno(select((PtmFd + 1), NULL, &WriteFds, NULL, &Timeout));
1842
1843 //
1844 // On Ubuntu16 the characters after the '\n' are added to the next
1845 // allocated page of terminal buffer. On WSL there is no dynamic allocation
1846 // so this will return after writing the '\n'. In both cases, the
1847 // characters before the '\n' are discarded by virtue of being replaced
1848 // by the subsequent character until finally hitting the '\n'.
1849 //
1850
1851 if (BytesReadWrite == WriteBufferLen)
1852 {
1853 LxtCheckEqual(Result, 1, "%d");
1854 }
1855 else
1856 {
1857 LxtCheckEqual(Result, 0, "%d");
1858 }
1859
1860 ErrorExit:
1861 if (PtmFd != -1)
1862 {
1863 close(PtmFd);
1864 }
1865
1866 if (PtsFd != -1)
1867 {
1868 close(PtsFd);
1869 }
1870
1871 return Result;
1872 }
1873
1874 int PtControllingTerminalForeground(PLXT_ARGS Args)
1875
1876 /*++
1877
1878 Routine Description:
1879
1880 This routine terminates the session leader of a terminal and checks various
1881 foreground behaviors.
1882
1883 Arguments:
1884
1885 Args - Supplies the command line arguments.
1886
1887 Return Value:
1888
1889 Returns 0 on success, -1 on failure.
1890
1891 --*/
1892
1893 {
1894
1895 pid_t ChildPid;
1896 bool EndChildPidSynchronization;
1897 bool EndGrandChildPidSynchronization;
1898 pid_t ForegroundId;
1899 pid_t GrandChildPid;
1900 int PtmFd;
1901 int PtsFd;
1902 int Result;
1903 pid_t SelfPid;
1904 int Status;
1905 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildPid);
1906
1907 ChildPid = -1;
1908 EndChildPidSynchronization = true;
1909 EndGrandChildPidSynchronization = true;
1910 GrandChildPid = -1;
1911 PtmFd = -1;
1912 PtsFd = -1;
1913
1914 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildPid);
1915 LXT_SYNCHRONIZATION_POINT_START();
1916 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
1917 if (ChildPid == 0)
1918 {
1919 LxtCheckResult(LxtSignalInitialize());
1920 LxtSignalSetAllowMultiple(TRUE);
1921 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
1922
1923 //
1924 // Verify current foreground process group.
1925 //
1926
1927 SelfPid = getpid();
1928 LxtCheckErrno(ForegroundId = tcgetpgrp(PtsFd));
1929 LxtCheckEqual(SelfPid, ForegroundId, "%d");
1930
1931 LxtClose(PtmFd);
1932 PtmFd = -1;
1933
1934 LXT_SYNCHRONIZATION_POINT_START_FOR(GrandChildPid);
1935 LxtCheckErrno(GrandChildPid = fork());
1936 if (GrandChildPid == 0)
1937 {
1938 EndChildPidSynchronization = false;
1939 LxtCheckResult(LxtSignalInitialize());
1940 LxtSignalSetAllowMultiple(TRUE);
1941 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
1942
1943 //
1944 // Move to standalone process group.
1945 //
1946
1947 LxtCheckErrno(setpgid(0, 0));
1948
1949 //
1950 // Have parent set this process as foreground group.
1951 //
1952
1953 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
1954 LxtSignalWait();
1955 LxtCheckResult(LxtSignalCheckNoSignal());
1956 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
1957
1958 //
1959 // Wait for session leader to terminate.
1960 //
1961
1962 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
1963 EndChildPidSynchronization = true;
1964 LXT_SYNCHRONIZATION_POINT();
1965 LxtSignalWait();
1966 LxtCheckResult(LxtSignalCheckReceived(SIGHUP));
1967 LxtSignalResetReceived();
1968 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), ENOTTY);
1969 LxtCheckErrnoFailure(tcgetsid(PtsFd), ENOTTY);
1970
1971 //
1972 // Wait for master endpoint to close.
1973 //
1974
1975 LXT_SYNCHRONIZATION_POINT();
1976 LxtSignalWait();
1977 LxtCheckResult(LxtSignalCheckNoSignal());
1978 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
1979 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
1980 LXT_SYNCHRONIZATION_POINT();
1981 }
1982 else
1983 {
1984
1985 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
1986
1987 //
1988 // Set (grand)child as the foreground process group.
1989 //
1990
1991 LxtCheckErrno(tcsetpgrp(PtsFd, GrandChildPid));
1992 LxtCheckErrno(ForegroundId = tcgetpgrp(PtsFd));
1993 LxtCheckEqual(GrandChildPid, ForegroundId, "%d");
1994
1995 //
1996 // Terminating before child.
1997 //
1998
1999 EndGrandChildPidSynchronization = false;
2000
2001 //
2002 // Communication with parent is now via grandchild.
2003 //
2004
2005 EndChildPidSynchronization = false;
2006 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2007 LXT_SYNCHRONIZATION_POINT();
2008 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2009 _exit(0);
2010 }
2011 }
2012 else
2013 {
2014
2015 //
2016 // Wait for the child to terminate. The grandchild should still be
2017 // running.
2018 //
2019
2020 LXT_SYNCHRONIZATION_POINT();
2021 EndChildPidSynchronization = false;
2022 LxtCheckErrno(TEMP_FAILURE_RETRY(Result = waitpid(ChildPid, &Status, 0)));
2023
2024 EndChildPidSynchronization = FALSE;
2025 LxtCheckResult(WIFEXITED(Status) ? 0 : -1);
2026 LxtCheckResult((int)(char)WEXITSTATUS(Status));
2027
2028 //
2029 // Signal grandchild that its parent has terminated.
2030 //
2031
2032 LXT_SYNCHRONIZATION_POINT();
2033
2034 //
2035 // Close the master endpoint and signal the grandchild.
2036 //
2037
2038 LXT_SYNCHRONIZATION_POINT();
2039 LxtClose(PtmFd);
2040 PtmFd = -1;
2041 LXT_SYNCHRONIZATION_POINT();
2042 }
2043
2044 Result = 0;
2045
2046 ErrorExit:
2047 LxtLogInfo("Thread exit: %d, Result=%d", getpid(), Result);
2048 if (PtmFd != -1)
2049 {
2050 close(PtmFd);
2051 }
2052
2053 if (PtsFd != -1)
2054 {
2055 close(PtsFd);
2056 }
2057
2058 if (EndGrandChildPidSynchronization)
2059 {
2060 LXT_SYNCHRONIZATION_POINT_END_FOR(GrandChildPid, TRUE);
2061 }
2062
2063 if (EndChildPidSynchronization)
2064 {
2065 LXT_SYNCHRONIZATION_POINT_END();
2066 }
2067
2068 return Result;
2069 }
2070
2071 int PtControllingTerminalForeground2(PLXT_ARGS Args)
2072
2073 /*++
2074
2075 Routine Description:
2076
2077 This routine closes the master endpoint of a terminal and checks various
2078 foreground behaviors.
2079
2080 Arguments:
2081
2082 Args - Supplies the command line arguments.
2083
2084 Return Value:
2085
2086 Returns 0 on success, -1 on failure.
2087
2088 --*/
2089
2090 {
2091
2092 pid_t ChildPid;
2093 bool EndChildPidSynchronization;
2094 bool EndGrandChildPidSynchronization;
2095 pid_t ForegroundId;
2096 pid_t GrandChildPid;
2097 int PtmFd;
2098 int PtsFd;
2099 int Result;
2100 pid_t SelfPid;
2101 int Status;
2102 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildPid);
2103
2104 ChildPid = -1;
2105 EndChildPidSynchronization = true;
2106 EndGrandChildPidSynchronization = true;
2107 GrandChildPid = -1;
2108 PtmFd = -1;
2109 PtsFd = -1;
2110
2111 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildPid);
2112 LXT_SYNCHRONIZATION_POINT_START();
2113 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
2114 if (ChildPid == 0)
2115 {
2116 LxtCheckResult(LxtSignalInitialize());
2117 LxtSignalSetAllowMultiple(TRUE);
2118 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
2119
2120 //
2121 // Verify current foreground process group.
2122 //
2123
2124 SelfPid = getpid();
2125 LxtCheckErrno(ForegroundId = tcgetpgrp(PtsFd));
2126 LxtCheckEqual(SelfPid, ForegroundId, "%d");
2127
2128 LxtClose(PtmFd);
2129 PtmFd = -1;
2130
2131 LXT_SYNCHRONIZATION_POINT_START_FOR(GrandChildPid);
2132 LxtCheckErrno(GrandChildPid = fork());
2133 if (GrandChildPid == 0)
2134 {
2135 EndChildPidSynchronization = false;
2136 LxtCheckResult(LxtSignalInitialize());
2137 LxtSignalSetAllowMultiple(TRUE);
2138 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
2139
2140 //
2141 // Move to standalone process group.
2142 //
2143
2144 LxtCheckErrno(setpgid(0, 0));
2145
2146 //
2147 // Have parent set this process as foreground group and close the
2148 // master endpoint.
2149 //
2150
2151 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2152 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2153 LxtSignalWait();
2154 LxtCheckResult(LxtSignalCheckNoSignal());
2155
2156 //
2157 // Signal parent to terminate and take over communication with
2158 // grand-parent.
2159 //
2160
2161 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2162 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
2163 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
2164
2165 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2166 EndChildPidSynchronization = true;
2167 LxtSignalWait();
2168 LxtCheckResult(LxtSignalCheckReceived(SIGHUP));
2169 LxtSignalResetReceived();
2170 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
2171 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
2172
2173 //
2174 // Wait for session leader to terminate.
2175 //
2176
2177 LXT_SYNCHRONIZATION_POINT();
2178 LxtSignalWait();
2179 LxtCheckResult(LxtSignalCheckNoSignal());
2180 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
2181 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
2182 }
2183 else
2184 {
2185
2186 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2187
2188 //
2189 // Set (grand)child as the foreground process group.
2190 //
2191
2192 LxtCheckErrno(tcsetpgrp(PtsFd, GrandChildPid));
2193
2194 //
2195 // Signal parent to close last master endpoint descriptor.
2196 //
2197
2198 LXT_SYNCHRONIZATION_POINT();
2199 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2200 LxtSignalWait();
2201 LxtCheckResult(LxtSignalCheckReceived(SIGHUP));
2202 LxtSignalResetReceived();
2203 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
2204 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
2205 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2206
2207 //
2208 // Terminating before child.
2209 //
2210
2211 EndGrandChildPidSynchronization = false;
2212
2213 //
2214 // Communication with parent is now via grandchild.
2215 //
2216
2217 EndChildPidSynchronization = false;
2218 LXT_SYNCHRONIZATION_POINT();
2219 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2220 _exit(0);
2221 }
2222 }
2223 else
2224 {
2225 LXT_SYNCHRONIZATION_POINT();
2226 LxtClose(PtmFd);
2227 PtmFd = -1;
2228 LXT_SYNCHRONIZATION_POINT();
2229
2230 //
2231 // Wait for the child to terminate. The grandchild should still be
2232 // running.
2233 //
2234
2235 EndChildPidSynchronization = false;
2236 LxtCheckErrno(TEMP_FAILURE_RETRY(Result = waitpid(ChildPid, &Status, 0)));
2237
2238 LxtCheckResult(WIFEXITED(Status) ? 0 : -1);
2239 LxtCheckResult((int)(char)WEXITSTATUS(Status));
2240
2241 //
2242 // Signal grandchild that its parent has terminated.
2243 //
2244
2245 LXT_SYNCHRONIZATION_POINT();
2246 }
2247
2248 Result = 0;
2249
2250 ErrorExit:
2251 if (PtmFd != -1)
2252 {
2253 close(PtmFd);
2254 }
2255
2256 if (PtsFd != -1)
2257 {
2258 close(PtsFd);
2259 }
2260
2261 if (EndGrandChildPidSynchronization)
2262 {
2263 LXT_SYNCHRONIZATION_POINT_END_FOR(GrandChildPid, TRUE);
2264 }
2265
2266 if (EndChildPidSynchronization)
2267 {
2268 LXT_SYNCHRONIZATION_POINT_END();
2269 }
2270
2271 return Result;
2272 }
2273
2274 int PtControllingTerminalForeground3(PLXT_ARGS Args)
2275
2276 /*++
2277
2278 Routine Description:
2279
2280 This routine disconnects the terminal via TIOCNOTTY and checks various
2281 foreground behaviors.
2282
2283 Arguments:
2284
2285 Args - Supplies the command line arguments.
2286
2287 Return Value:
2288
2289 Returns 0 on success, -1 on failure.
2290
2291 --*/
2292
2293 {
2294
2295 pid_t ChildPid;
2296 bool EndChildPidSynchronization;
2297 bool EndGrandChildPidSynchronization;
2298 pid_t ForegroundId;
2299 pid_t GrandChildPid;
2300 int PtmFd;
2301 int PtsFd;
2302 int Result;
2303 pid_t SelfPid;
2304 int Status;
2305 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildPid);
2306
2307 ChildPid = -1;
2308 EndChildPidSynchronization = true;
2309 EndGrandChildPidSynchronization = true;
2310 GrandChildPid = -1;
2311 PtmFd = -1;
2312 PtsFd = -1;
2313
2314 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildPid);
2315 LXT_SYNCHRONIZATION_POINT_START();
2316 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
2317 if (ChildPid == 0)
2318 {
2319 LxtCheckResult(LxtSignalInitialize());
2320 LxtSignalSetAllowMultiple(TRUE);
2321 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
2322
2323 //
2324 // Verify current foreground process group.
2325 //
2326
2327 SelfPid = getpid();
2328 LxtCheckErrno(ForegroundId = tcgetpgrp(PtsFd));
2329 LxtCheckEqual(SelfPid, ForegroundId, "%d");
2330
2331 LxtClose(PtmFd);
2332 PtmFd = -1;
2333
2334 LXT_SYNCHRONIZATION_POINT_START_FOR(GrandChildPid);
2335 LxtCheckErrno(GrandChildPid = fork());
2336 if (GrandChildPid == 0)
2337 {
2338 EndChildPidSynchronization = false;
2339 LxtCheckResult(LxtSignalInitialize());
2340 LxtSignalSetAllowMultiple(TRUE);
2341 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
2342
2343 //
2344 // Move to standalone process group.
2345 //
2346
2347 LxtCheckErrno(setpgid(0, 0));
2348
2349 //
2350 // Have parent set this process as foreground group and disconnect
2351 // the session terminal.
2352 //
2353
2354 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2355 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2356 LxtSignalWait();
2357 LxtCheckResult(LxtSignalCheckReceived(SIGHUP));
2358 LxtSignalResetReceived();
2359 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), ENOTTY);
2360 LxtCheckErrnoFailure(tcgetsid(PtsFd), ENOTTY);
2361
2362 //
2363 // Signal parent to close last descriptor.
2364 //
2365
2366 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2367 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2368 EndChildPidSynchronization = true;
2369 LxtSignalWait();
2370 LxtCheckResult(LxtSignalCheckNoSignal());
2371 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
2372 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
2373
2374 //
2375 // Wait for session leader to terminate.
2376 //
2377
2378 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2379 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2380 LXT_SYNCHRONIZATION_POINT();
2381 LxtSignalWait();
2382 LxtCheckResult(LxtSignalCheckNoSignal());
2383 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
2384 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
2385 }
2386 else
2387 {
2388
2389 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2390
2391 //
2392 // Set (grand)child as the foreground process group.
2393 //
2394
2395 LxtCheckErrno(tcsetpgrp(PtsFd, GrandChildPid));
2396
2397 //
2398 // Disassociate terminal.
2399 //
2400
2401 LxtCheckErrno(ioctl(PtsFd, TIOCNOTTY, (char*)NULL));
2402 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2403 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2404
2405 //
2406 // Signal parent to close last master endpoint descriptor. No
2407 // signal is expected because the terminal has been disconnected.
2408 //
2409
2410 LXT_SYNCHRONIZATION_POINT();
2411 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2412 LxtSignalWait();
2413 LxtCheckResult(LxtSignalCheckNoSignal());
2414 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
2415 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
2416 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2417
2418 //
2419 // Terminating before child.
2420 //
2421
2422 EndGrandChildPidSynchronization = false;
2423
2424 //
2425 // Communication with parent is now via grandchild.
2426 //
2427
2428 EndChildPidSynchronization = false;
2429 LXT_SYNCHRONIZATION_POINT();
2430 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2431 _exit(0);
2432 }
2433 }
2434 else
2435 {
2436 LXT_SYNCHRONIZATION_POINT();
2437 LxtClose(PtmFd);
2438 PtmFd = -1;
2439 LXT_SYNCHRONIZATION_POINT();
2440
2441 //
2442 // Wait for the child to terminate. The grandchild should still be
2443 // running.
2444 //
2445
2446 EndChildPidSynchronization = false;
2447 LxtCheckErrno(TEMP_FAILURE_RETRY(Result = waitpid(ChildPid, &Status, 0)));
2448
2449 LxtCheckResult(WIFEXITED(Status) ? 0 : -1);
2450 LxtCheckResult((int)(char)WEXITSTATUS(Status));
2451
2452 //
2453 // Signal grandchild that its parent has terminated.
2454 //
2455
2456 LXT_SYNCHRONIZATION_POINT();
2457 }
2458
2459 Result = 0;
2460
2461 ErrorExit:
2462 if (PtmFd != -1)
2463 {
2464 close(PtmFd);
2465 }
2466
2467 if (PtsFd != -1)
2468 {
2469 close(PtsFd);
2470 }
2471
2472 if (EndGrandChildPidSynchronization)
2473 {
2474 LXT_SYNCHRONIZATION_POINT_END_FOR(GrandChildPid, TRUE);
2475 }
2476
2477 if (EndChildPidSynchronization)
2478 {
2479 LXT_SYNCHRONIZATION_POINT_END();
2480 }
2481
2482 return Result;
2483 }
2484
2485 int PtControllingTerminalForeground4(PLXT_ARGS Args)
2486
2487 /*++
2488
2489 Routine Description:
2490
2491 This routine closes the master endpoint of a terminal where the session
2492 leader is ignoring SIGHUP, and checks various foreground behaviors.
2493
2494 Arguments:
2495
2496 Args - Supplies the command line arguments.
2497
2498 Return Value:
2499
2500 Returns 0 on success, -1 on failure.
2501
2502 --*/
2503
2504 {
2505
2506 pid_t ChildPid;
2507 bool EndChildPidSynchronization;
2508 bool EndGrandChildPidSynchronization;
2509 pid_t ForegroundId;
2510 pid_t GrandChildPid;
2511 int PtmFd;
2512 int PtsFd;
2513 int Result;
2514 pid_t SelfPid;
2515 int Status;
2516 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildPid);
2517
2518 ChildPid = -1;
2519 EndChildPidSynchronization = true;
2520 EndGrandChildPidSynchronization = true;
2521 GrandChildPid = -1;
2522 PtmFd = -1;
2523 PtsFd = -1;
2524
2525 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildPid);
2526 LXT_SYNCHRONIZATION_POINT_START();
2527 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
2528 if (ChildPid == 0)
2529 {
2530 LxtCheckResult(LxtSignalInitialize());
2531 LxtSignalSetAllowMultiple(TRUE);
2532 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
2533
2534 //
2535 // Verify current foreground process group.
2536 //
2537
2538 SelfPid = getpid();
2539 LxtCheckErrno(ForegroundId = tcgetpgrp(PtsFd));
2540 LxtCheckEqual(SelfPid, ForegroundId, "%d");
2541
2542 LxtClose(PtmFd);
2543 PtmFd = -1;
2544
2545 LXT_SYNCHRONIZATION_POINT_START_FOR(GrandChildPid);
2546 LxtCheckErrno(GrandChildPid = fork());
2547 if (GrandChildPid == 0)
2548 {
2549 EndChildPidSynchronization = false;
2550 LxtCheckResult(LxtSignalInitialize());
2551 LxtSignalSetAllowMultiple(TRUE);
2552 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
2553
2554 //
2555 // Move to standalone process group.
2556 //
2557
2558 LxtCheckErrno(setpgid(0, 0));
2559
2560 //
2561 // Have parent set this process as foreground group and close the
2562 // master endpoint.
2563 //
2564
2565 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2566 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2567 LxtSignalWait();
2568 LxtCheckResult(LxtSignalCheckNoSignal());
2569
2570 //
2571 // Signal parent to terminate and take over communication with
2572 // grand-parent.
2573 //
2574
2575 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2576 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
2577 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
2578
2579 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2580 EndChildPidSynchronization = true;
2581 LxtSignalWait();
2582 LxtCheckResult(LxtSignalCheckReceived(SIGHUP));
2583 LxtSignalResetReceived();
2584 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
2585 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
2586
2587 //
2588 // Wait for session leader to terminate.
2589 //
2590
2591 LXT_SYNCHRONIZATION_POINT();
2592 LxtSignalWait();
2593 LxtCheckResult(LxtSignalCheckNoSignal());
2594 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
2595 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
2596 }
2597 else
2598 {
2599
2600 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2601
2602 //
2603 // Set (grand)child as the foreground process group.
2604 //
2605
2606 LxtCheckErrno(tcsetpgrp(PtsFd, GrandChildPid));
2607
2608 //
2609 // Ignore SIGHUP on the session leader.
2610 //
2611
2612 LxtCheckErrno(LxtSignalIgnore(SIGHUP));
2613
2614 //
2615 // Signal parent to close last master endpoint descriptor.
2616 //
2617
2618 LXT_SYNCHRONIZATION_POINT();
2619 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2620 LxtSignalWait();
2621 LxtCheckResult(LxtSignalCheckNoSignal());
2622 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
2623 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
2624 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2625
2626 //
2627 // Terminating before child.
2628 //
2629
2630 EndGrandChildPidSynchronization = false;
2631
2632 //
2633 // Communication with parent is now via grandchild.
2634 //
2635
2636 EndChildPidSynchronization = false;
2637 LXT_SYNCHRONIZATION_POINT();
2638 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2639 _exit(0);
2640 }
2641 }
2642 else
2643 {
2644 LXT_SYNCHRONIZATION_POINT();
2645 LxtClose(PtmFd);
2646 PtmFd = -1;
2647 LXT_SYNCHRONIZATION_POINT();
2648
2649 //
2650 // Wait for the child to terminate. The grandchild should still be
2651 // running.
2652 //
2653
2654 EndChildPidSynchronization = false;
2655 LxtCheckErrno(TEMP_FAILURE_RETRY(Result = waitpid(ChildPid, &Status, 0)));
2656
2657 LxtCheckResult(WIFEXITED(Status) ? 0 : -1);
2658 LxtCheckResult((int)(char)WEXITSTATUS(Status));
2659
2660 //
2661 // Signal grandchild that its parent has terminated.
2662 //
2663
2664 LXT_SYNCHRONIZATION_POINT();
2665 }
2666
2667 Result = 0;
2668
2669 ErrorExit:
2670 if (PtmFd != -1)
2671 {
2672 close(PtmFd);
2673 }
2674
2675 if (PtsFd != -1)
2676 {
2677 close(PtsFd);
2678 }
2679
2680 if (EndGrandChildPidSynchronization)
2681 {
2682 LXT_SYNCHRONIZATION_POINT_END_FOR(GrandChildPid, TRUE);
2683 }
2684
2685 if (EndChildPidSynchronization)
2686 {
2687 LXT_SYNCHRONIZATION_POINT_END();
2688 }
2689
2690 return Result;
2691 }
2692
2693 int PtControllingTerminalForeground5(PLXT_ARGS Args)
2694
2695 /*++
2696
2697 Routine Description:
2698
2699 This routine connects a second process to the current foreground process
2700 group and checks various foreground properties.
2701
2702 Arguments:
2703
2704 Args - Supplies the command line arguments.
2705
2706 Return Value:
2707
2708 Returns 0 on success, -1 on failure.
2709
2710 --*/
2711
2712 {
2713
2714 pid_t ChildPid;
2715 bool EndChildPidSynchronization;
2716 pid_t ForegroundId;
2717 pid_t GrandChildPid;
2718 pid_t GrandChildPid2;
2719 int PtmFd;
2720 int PtsFd;
2721 int Result;
2722 pid_t SelfPid;
2723 int Status;
2724 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildPid);
2725 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildPid2);
2726
2727 ChildPid = -1;
2728 EndChildPidSynchronization = true;
2729 GrandChildPid = -1;
2730 GrandChildPid2 = -1;
2731 PtmFd = -1;
2732 PtsFd = -1;
2733
2734 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildPid);
2735 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildPid2);
2736 LXT_SYNCHRONIZATION_POINT_START();
2737 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
2738 if (ChildPid == 0)
2739 {
2740 LxtCheckResult(LxtSignalInitialize());
2741 LxtSignalSetAllowMultiple(TRUE);
2742 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
2743
2744 //
2745 // Verify current foreground process group.
2746 //
2747
2748 SelfPid = getpid();
2749 LxtCheckErrno(ForegroundId = tcgetpgrp(PtsFd));
2750 LxtCheckEqual(SelfPid, ForegroundId, "%d");
2751
2752 LxtClose(PtmFd);
2753 PtmFd = -1;
2754
2755 LXT_SYNCHRONIZATION_POINT_START_FOR(GrandChildPid);
2756 LxtCheckErrno(GrandChildPid = fork());
2757 if (GrandChildPid == 0)
2758 {
2759 EndChildPidSynchronization = false;
2760 LxtCheckResult(LxtSignalInitialize());
2761 LxtSignalSetAllowMultiple(TRUE);
2762 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
2763
2764 //
2765 // Move to standalone process group.
2766 //
2767
2768 LxtCheckErrno(setpgid(0, 0));
2769
2770 //
2771 // Have parent set this process as foreground group.
2772 //
2773
2774 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2775
2776 //
2777 // Wait for test to finish before terminating.
2778 //
2779
2780 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2781 LxtCheckResult(LxtSignalCheckReceived(SIGHUP));
2782 goto ErrorExit;
2783 }
2784
2785 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2786
2787 //
2788 // Set (grand)child as the foreground process group.
2789 //
2790
2791 LxtCheckErrno(tcsetpgrp(PtsFd, GrandChildPid));
2792 LxtCheckErrno(ForegroundId = tcgetpgrp(PtsFd));
2793 LxtCheckEqual(ForegroundId, GrandChildPid, "%d");
2794 LxtCheckErrno(tcgetsid(PtsFd));
2795
2796 //
2797 // Start another child and try to connect to previous process group.
2798 //
2799
2800 LXT_SYNCHRONIZATION_POINT_START_FOR(GrandChildPid2);
2801 LxtCheckErrno(GrandChildPid2 = fork());
2802 if (GrandChildPid2 == 0)
2803 {
2804 EndChildPidSynchronization = false;
2805 LxtCheckResult(LxtSignalInitialize());
2806 LxtSignalSetAllowMultiple(TRUE);
2807 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
2808
2809 //
2810 // Attempt to move to previously created process group.
2811 //
2812
2813 LxtCheckErrno(setpgid(0, GrandChildPid));
2814
2815 //
2816 // Signal parent to disconnect from the terminal.
2817 //
2818
2819 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
2820 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
2821
2822 LxtSignalWait();
2823 LxtCheckResult(LxtSignalCheckReceived(SIGHUP));
2824 LxtSignalResetReceived();
2825 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), ENOTTY);
2826 LxtCheckErrnoFailure(tcgetsid(PtsFd), ENOTTY);
2827
2828 //
2829 // Signal parent to close the terminal descriptor.
2830 //
2831
2832 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
2833 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
2834
2835 LxtSignalWait();
2836 LxtCheckResult(LxtSignalCheckNoSignal());
2837 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
2838 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
2839
2840 //
2841 // Terminate.
2842 //
2843
2844 goto ErrorExit;
2845 }
2846
2847 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
2848
2849 //
2850 // Disconnect terminal.
2851 //
2852
2853 LxtCheckErrno(ioctl(PtsFd, TIOCNOTTY, (char*)NULL));
2854 LxtSignalWait();
2855 LxtCheckResult(LxtSignalCheckNoSignal());
2856 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
2857
2858 //
2859 // Signal parent to close last master endpoint descriptor.
2860 //
2861
2862 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
2863 LXT_SYNCHRONIZATION_POINT();
2864 LxtSignalWait();
2865 LxtCheckResult(LxtSignalCheckNoSignal());
2866 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
2867 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
2868 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
2869
2870 //
2871 // Signal original child to exit.
2872 //
2873
2874 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2875 }
2876 else
2877 {
2878 LXT_SYNCHRONIZATION_POINT();
2879 LxtClose(PtmFd);
2880 PtmFd = -1;
2881 }
2882
2883 Result = 0;
2884
2885 ErrorExit:
2886 if (PtmFd != -1)
2887 {
2888 close(PtmFd);
2889 }
2890
2891 if (PtsFd != -1)
2892 {
2893 close(PtsFd);
2894 }
2895
2896 LXT_SYNCHRONIZATION_POINT_END_FOR(GrandChildPid2, TRUE);
2897 LXT_SYNCHRONIZATION_POINT_END_FOR(GrandChildPid, TRUE);
2898 if (EndChildPidSynchronization)
2899 {
2900 LXT_SYNCHRONIZATION_POINT_END();
2901 }
2902
2903 return Result;
2904 }
2905
2906 int PtControllingTerminalForeground6(PLXT_ARGS Args)
2907
2908 /*++
2909
2910 Routine Description:
2911
2912 This routine terminates the current foreground process group and checks
2913 various foreground properties.
2914
2915 Arguments:
2916
2917 Args - Supplies the command line arguments.
2918
2919 Return Value:
2920
2921 Returns 0 on success, -1 on failure.
2922
2923 --*/
2924
2925 {
2926
2927 pid_t ChildPid;
2928 bool EndChildPidSynchronization;
2929 bool EndGrandChildPidSynchronization;
2930 pid_t ForegroundId;
2931 pid_t GrandChildPid;
2932 pid_t GrandChildPid2;
2933 int PtmFd;
2934 int PtsFd;
2935 int Result;
2936 pid_t SelfPid;
2937 int Status;
2938 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildPid);
2939 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildPid2);
2940
2941 ChildPid = -1;
2942 EndChildPidSynchronization = true;
2943 EndGrandChildPidSynchronization = true;
2944 GrandChildPid = -1;
2945 GrandChildPid2 = -1;
2946 PtmFd = -1;
2947 PtsFd = -1;
2948
2949 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildPid);
2950 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildPid2);
2951 LXT_SYNCHRONIZATION_POINT_START();
2952 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
2953 if (ChildPid == 0)
2954 {
2955 LxtCheckResult(LxtSignalInitialize());
2956 LxtSignalSetAllowMultiple(TRUE);
2957 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
2958
2959 //
2960 // Verify current foreground process group.
2961 //
2962
2963 SelfPid = getpid();
2964 LxtCheckErrno(ForegroundId = tcgetpgrp(PtsFd));
2965 LxtCheckEqual(SelfPid, ForegroundId, "%d");
2966
2967 LxtClose(PtmFd);
2968 PtmFd = -1;
2969
2970 LXT_SYNCHRONIZATION_POINT_START_FOR(GrandChildPid);
2971 LxtCheckErrno(GrandChildPid = fork());
2972 if (GrandChildPid == 0)
2973 {
2974 EndChildPidSynchronization = false;
2975 LxtCheckResult(LxtSignalInitialize());
2976 LxtSignalSetAllowMultiple(TRUE);
2977 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
2978
2979 //
2980 // Move to standalone process group.
2981 //
2982
2983 LxtCheckErrno(setpgid(0, 0));
2984
2985 //
2986 // Have parent set this process as foreground group.
2987 //
2988
2989 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2990 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
2991
2992 //
2993 // Terminate.
2994 //
2995
2996 goto ErrorExit;
2997 }
2998
2999 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
3000
3001 //
3002 // Set (grand)child as the foreground process group.
3003 //
3004
3005 LxtCheckErrno(tcsetpgrp(PtsFd, GrandChildPid));
3006
3007 //
3008 // Wait for child to terminate.
3009 //
3010
3011 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
3012 EndGrandChildPidSynchronization = false;
3013 LxtCheckErrno(TEMP_FAILURE_RETRY(Result = waitpid(GrandChildPid, &Status, 0)));
3014
3015 LxtCheckResult(WIFEXITED(Status) ? 0 : -1);
3016 LxtCheckResult((int)(char)WEXITSTATUS(Status));
3017
3018 LxtCheckErrno(ForegroundId = tcgetpgrp(PtsFd));
3019 LxtCheckEqual(ForegroundId, GrandChildPid, "%d");
3020 LxtCheckErrno(tcgetsid(PtsFd));
3021
3022 //
3023 // Start another child and try to connect to previous process group.
3024 //
3025
3026 LXT_SYNCHRONIZATION_POINT_START_FOR(GrandChildPid2);
3027 LxtCheckErrno(GrandChildPid2 = fork());
3028 if (GrandChildPid2 == 0)
3029 {
3030 EndChildPidSynchronization = false;
3031 LxtCheckResult(LxtSignalInitialize());
3032 LxtSignalSetAllowMultiple(TRUE);
3033 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
3034
3035 //
3036 // Attempt to move to previously created process group of now
3037 // terminated process.
3038 //
3039
3040 LxtCheckErrnoFailure(setpgid(0, GrandChildPid), EPERM);
3041
3042 //
3043 // Signal parent to disconnect from the terminal.
3044 //
3045
3046 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3047 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3048
3049 LxtSignalWait();
3050 LxtCheckResult(LxtSignalCheckNoSignal());
3051 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), ENOTTY);
3052 LxtCheckErrnoFailure(tcgetsid(PtsFd), ENOTTY);
3053
3054 //
3055 // Signal parent to close the terminal descriptor.
3056 //
3057
3058 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3059 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3060
3061 LxtSignalWait();
3062 LxtCheckResult(LxtSignalCheckNoSignal());
3063 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
3064 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
3065
3066 //
3067 // Terminate.
3068 //
3069
3070 goto ErrorExit;
3071 }
3072
3073 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3074
3075 //
3076 // Disconnect terminal.
3077 //
3078
3079 LxtCheckErrno(ioctl(PtsFd, TIOCNOTTY, (char*)NULL));
3080 LxtSignalWait();
3081 LxtCheckResult(LxtSignalCheckNoSignal());
3082 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3083
3084 //
3085 // Signal parent to close last master endpoint descriptor.
3086 //
3087
3088 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3089 LXT_SYNCHRONIZATION_POINT();
3090 LxtSignalWait();
3091 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3092 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
3093 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
3094 }
3095 else
3096 {
3097 LXT_SYNCHRONIZATION_POINT();
3098 LxtClose(PtmFd);
3099 PtmFd = -1;
3100 }
3101
3102 Result = 0;
3103
3104 ErrorExit:
3105 if (PtmFd != -1)
3106 {
3107 close(PtmFd);
3108 }
3109
3110 if (PtsFd != -1)
3111 {
3112 close(PtsFd);
3113 }
3114
3115 LXT_SYNCHRONIZATION_POINT_END_FOR(GrandChildPid2, TRUE);
3116 if (EndGrandChildPidSynchronization)
3117 {
3118 LXT_SYNCHRONIZATION_POINT_END_FOR(GrandChildPid, TRUE);
3119 }
3120
3121 if (EndChildPidSynchronization)
3122 {
3123 LXT_SYNCHRONIZATION_POINT_END();
3124 }
3125
3126 return Result;
3127 }
3128
3129 int PtControllingTerminalForeground7(PLXT_ARGS Args)
3130
3131 /*++
3132
3133 Routine Description:
3134
3135 This routine connects a second process to an existing foreground group,
3136 disconnects it from the controlling terminal and then tests various
3137 properties.
3138
3139 Arguments:
3140
3141 Args - Supplies the command line arguments.
3142
3143 Return Value:
3144
3145 Returns 0 on success, -1 on failure.
3146
3147 --*/
3148
3149 {
3150
3151 pid_t ChildPid;
3152 bool EndChildPidSynchronization;
3153 pid_t ForegroundId;
3154 pid_t GrandChildPid;
3155 pid_t GrandChildPid2;
3156 int PtmFd;
3157 int PtsFd;
3158 int Result;
3159 pid_t SelfPid;
3160 int Status;
3161 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildPid);
3162 LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(GrandChildPid2);
3163
3164 ChildPid = -1;
3165 EndChildPidSynchronization = true;
3166 GrandChildPid = -1;
3167 GrandChildPid2 = -1;
3168 PtmFd = -1;
3169 PtsFd = -1;
3170
3171 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildPid);
3172 LXT_SYNCHRONIZATION_POINT_INIT_FOR(GrandChildPid2);
3173 LXT_SYNCHRONIZATION_POINT_START();
3174 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
3175 if (ChildPid == 0)
3176 {
3177 LxtCheckResult(LxtSignalInitialize());
3178 LxtSignalSetAllowMultiple(TRUE);
3179 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
3180
3181 //
3182 // Verify current foreground process group.
3183 //
3184
3185 SelfPid = getpid();
3186 LxtCheckErrno(ForegroundId = tcgetpgrp(PtsFd));
3187 LxtCheckEqual(SelfPid, ForegroundId, "%d");
3188
3189 LxtClose(PtmFd);
3190 PtmFd = -1;
3191
3192 LXT_SYNCHRONIZATION_POINT_START_FOR(GrandChildPid);
3193 LxtCheckErrno(GrandChildPid = fork());
3194 if (GrandChildPid == 0)
3195 {
3196 EndChildPidSynchronization = false;
3197 LxtCheckResult(LxtSignalInitialize());
3198 LxtSignalSetAllowMultiple(TRUE);
3199 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
3200
3201 //
3202 // Move to standalone process group.
3203 //
3204
3205 LxtCheckErrno(setpgid(0, 0));
3206
3207 //
3208 // Have parent set this process as foreground group.
3209 //
3210
3211 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
3212
3213 //
3214 // Wait for test to finish before terminating.
3215 //
3216
3217 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
3218 LxtCheckResult(LxtSignalCheckReceived(SIGHUP));
3219 goto ErrorExit;
3220 }
3221
3222 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
3223
3224 //
3225 // Set (grand)child as the foreground process group.
3226 //
3227
3228 LxtCheckErrno(tcsetpgrp(PtsFd, GrandChildPid));
3229 LxtCheckErrno(ForegroundId = tcgetpgrp(PtsFd));
3230 LxtCheckEqual(ForegroundId, GrandChildPid, "%d");
3231 LxtCheckErrno(tcgetsid(PtsFd));
3232
3233 //
3234 // Start another child and try to connect to previous process group.
3235 //
3236
3237 LXT_SYNCHRONIZATION_POINT_START_FOR(GrandChildPid2);
3238 LxtCheckErrno(GrandChildPid2 = fork());
3239 if (GrandChildPid2 == 0)
3240 {
3241 EndChildPidSynchronization = false;
3242 LxtCheckResult(LxtSignalInitialize());
3243 LxtSignalSetAllowMultiple(TRUE);
3244 LxtCheckResult(LxtSignalSetupHandler(SIGHUP, SA_SIGINFO));
3245
3246 //
3247 // Attempt to move to previously created process group.
3248 //
3249
3250 LxtCheckErrno(setpgid(0, GrandChildPid));
3251
3252 //
3253 // Disconnect from the controlling terminal.
3254 //
3255
3256 LxtCheckErrno(ioctl(PtsFd, TIOCNOTTY, (char*)NULL));
3257
3258 //
3259 // Signal parent to disconnect from the terminal.
3260 //
3261
3262 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3263 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3264
3265 LxtSignalWait();
3266 LxtCheckResult(LxtSignalCheckReceived(SIGHUP));
3267 LxtSignalResetReceived();
3268 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), ENOTTY);
3269 LxtCheckErrnoFailure(tcgetsid(PtsFd), ENOTTY);
3270
3271 //
3272 // Signal parent to close the terminal descriptor.
3273 //
3274
3275 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3276 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3277
3278 LxtSignalWait();
3279 LxtCheckResult(LxtSignalCheckNoSignal());
3280 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
3281 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
3282
3283 //
3284 // Terminate.
3285 //
3286
3287 goto ErrorExit;
3288 }
3289
3290 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3291
3292 //
3293 // Disconnect terminal.
3294 //
3295
3296 LxtCheckErrno(ioctl(PtsFd, TIOCNOTTY, (char*)NULL));
3297 LxtSignalWait();
3298 LxtCheckResult(LxtSignalCheckNoSignal());
3299 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3300
3301 //
3302 // Signal parent to close last master endpoint descriptor.
3303 //
3304
3305 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3306 LXT_SYNCHRONIZATION_POINT();
3307 LxtSignalWait();
3308 LxtCheckResult(LxtSignalCheckNoSignal());
3309 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid2);
3310 LxtCheckErrnoFailure(tcgetpgrp(PtsFd), EIO);
3311 LxtCheckErrnoFailure(tcgetsid(PtsFd), EIO);
3312
3313 //
3314 // Signal original child to exit.
3315 //
3316
3317 LXT_SYNCHRONIZATION_POINT_FOR(GrandChildPid);
3318 }
3319 else
3320 {
3321 LXT_SYNCHRONIZATION_POINT();
3322 LxtClose(PtmFd);
3323 PtmFd = -1;
3324 }
3325
3326 Result = 0;
3327
3328 ErrorExit:
3329 if (PtmFd != -1)
3330 {
3331 close(PtmFd);
3332 }
3333
3334 if (PtsFd != -1)
3335 {
3336 close(PtsFd);
3337 }
3338
3339 LXT_SYNCHRONIZATION_POINT_END_FOR(GrandChildPid2, TRUE);
3340 LXT_SYNCHRONIZATION_POINT_END_FOR(GrandChildPid, TRUE);
3341 if (EndChildPidSynchronization)
3342 {
3343 LXT_SYNCHRONIZATION_POINT_END();
3344 }
3345
3346 return Result;
3347 }
3348
3349 int PtMountBasic(PLXT_ARGS Args)
3350
3351 /*++
3352
3353 Routine Description:
3354
3355 This routine verifies basic mount operations on the devpts file system.
3356
3357 Arguments:
3358
3359 Args - Supplies the command line arguments.
3360
3361 Return Value:
3362
3363 Returns 0 on success, -1 on failure.
3364
3365 --*/
3366
3367 {
3368
3369 gid_t CurrentGid;
3370 uid_t CurrentUid;
3371 char EndpointName[sizeof(PTS_TEST_MNT) + 4];
3372 struct stat EndpointStat;
3373 int PtmFd;
3374 int PtmFd2;
3375 char* PtmxName = PTS_TEST_MNT "/ptmx";
3376 struct stat PtmxStat;
3377 int PtsFd;
3378 int Result;
3379 int SerialNumber;
3380
3381 PtmFd = -1;
3382 PtmFd2 = -1;
3383 PtsFd = -1;
3384
3385 CurrentUid = geteuid();
3386 CurrentGid = getegid();
3387
3388 //
3389 // Create an endpoint to test default vs new mounts.
3390 //
3391
3392 LxtCheckErrno(OpenMasterSubordinate(&PtmFd, &PtsFd, NULL, &SerialNumber));
3393 if (SerialNumber > 999)
3394 {
3395 LxtLogError("Unexpectedly large number of opened ptys!");
3396 Result = -1;
3397 goto ErrorExit;
3398 }
3399
3400 sprintf(EndpointName, "%s/%d", PTS_TEST_MNT, SerialNumber);
3401
3402 //
3403 // Create a temporary directory to create mounts.
3404 //
3405
3406 LxtCheckErrnoZeroSuccess(mkdir(PTS_TEST_MNT, 0777));
3407
3408 //
3409 // Mount the default devpts instance.
3410 //
3411
3412 LxtCheckErrnoZeroSuccess(mount(NULL, PTS_TEST_MNT, "devpts", MS_NOEXEC | MS_NOSUID | MS_RELATIME, NULL));
3413
3414 //
3415 // Verify previously created endpoint exists in the new mount.
3416 //
3417
3418 LxtCheckErrno(stat(EndpointName, &EndpointStat));
3419 LxtCheckErrno(stat(PtmxName, &PtmxStat));
3420 LxtCheckErrno(umount(PTS_TEST_MNT));
3421
3422 //
3423 // Mount with "newinstance" option.
3424 //
3425
3426 LxtCheckErrnoZeroSuccess(mount(NULL, PTS_TEST_MNT, "devpts", MS_NOEXEC | MS_NOSUID | MS_RELATIME, "newinstance"));
3427
3428 //
3429 // Verify previously created endpoint does not exist in the new mount.
3430 //
3431
3432 LxtCheckErrnoFailure(stat(EndpointName, &EndpointStat), ENOENT);
3433 LxtCheckErrno(stat(PtmxName, &PtmxStat));
3434
3435 //
3436 // Check default ptmxmode settings.
3437 //
3438
3439 LxtCheckEqual(PtmxStat.st_mode, S_IFCHR, "%d");
3440
3441 //
3442 // Create a new endpoint and check default UID/GID/mode settings.
3443 //
3444
3445 sprintf(EndpointName, "%s/0", PTS_TEST_MNT);
3446 LxtCheckErrno((PtmFd2 = open(PtmxName, O_RDWR)));
3447 LxtCheckErrno(stat(EndpointName, &EndpointStat));
3448 LxtCheckEqual(EndpointStat.st_uid, CurrentUid, "%d");
3449 LxtCheckEqual(EndpointStat.st_gid, CurrentGid, "%d");
3450 LxtCheckEqual(EndpointStat.st_mode, (S_IFCHR | 0600), "%d");
3451 LxtClose(PtmFd2);
3452 LxtCheckErrno(umount(PTS_TEST_MNT));
3453
3454 //
3455 // Mount with "newinstance" and specify UID/GID/mode/ptmxmode options.
3456 //
3457
3458 LxtCheckErrnoZeroSuccess(mount(
3459 NULL, PTS_TEST_MNT, "devpts", MS_NOEXEC | MS_NOSUID | MS_RELATIME, "newinstance,uid=0,gid=5,mode=0620,ptmxmode=666"));
3460
3461 LxtCheckErrno(stat(PtmxName, &PtmxStat));
3462
3463 //
3464 // Check default ptmxmode settings.
3465 //
3466
3467 LxtCheckEqual(PtmxStat.st_mode, (S_IFCHR | 0666), "%d");
3468
3469 //
3470 // Create a new endpoint and check default UID/GID/mode settings.
3471 //
3472
3473 sprintf(EndpointName, "%s/0", PTS_TEST_MNT);
3474 LxtCheckErrno((PtmFd2 = open(PtmxName, O_RDWR)));
3475 LxtCheckErrno(stat(EndpointName, &EndpointStat));
3476 LxtCheckEqual(EndpointStat.st_uid, 0, "%d");
3477 LxtCheckEqual(EndpointStat.st_gid, 5, "%d");
3478 LxtCheckEqual(EndpointStat.st_mode, (S_IFCHR | 0620), "%d");
3479 LxtClose(PtmFd2);
3480 LxtCheckErrno(umount(PTS_TEST_MNT));
3481
3482 ErrorExit:
3483 if (PtmFd != -1)
3484 {
3485 close(PtmFd);
3486 }
3487
3488 if (PtmFd2 != -1)
3489 {
3490 close(PtmFd2);
3491 }
3492
3493 if (PtsFd != -1)
3494 {
3495 close(PtsFd);
3496 }
3497
3498 umount(PTS_TEST_MNT);
3499 rmdir(PTS_TEST_MNT);
3500 return Result;
3501 }
3502
3503 int PtPacketBasic1(PLXT_ARGS Args)
3504
3505 /*++
3506
3507 Routine Description:
3508
3509 This routine sets packet-mode and checks the set value.
3510
3511 Arguments:
3512
3513 Args - Supplies the command line arguments.
3514
3515 Return Value:
3516
3517 Returns 0 on success, -1 on failure.
3518
3519 --*/
3520
3521 {
3522
3523 int BytesReadWrite;
3524 char ControlByte;
3525 int PacketMode;
3526 int PtmFd;
3527 int PtmFlags;
3528 int PtsFd;
3529 fd_set ReadFds;
3530 int Result;
3531 int SerialNumber;
3532 struct timeval Timeout;
3533
3534 //
3535 // Initialize locals.
3536 //
3537
3538 PtmFd = -1;
3539 PtsFd = -1;
3540
3541 //
3542 // Open Master-Subordinate.
3543 //
3544
3545 LxtCheckErrno(OpenMasterSubordinate(&PtmFd, &PtsFd, NULL, &SerialNumber));
3546 LxtLogInfo("Master opened at FD:%d", PtmFd);
3547 LxtLogInfo("Subordinate Serial Number: %d", SerialNumber);
3548 LxtLogInfo("Subordinate opened at FD:%d", PtsFd);
3549
3550 //
3551 // Verify packet-mode is off (0) to start.
3552 //
3553
3554 LxtCheckErrno(ioctl(PtmFd, TIOCGPKT, &PacketMode));
3555 LxtCheckEqual(PacketMode, 0, "%d");
3556
3557 //
3558 // Turn on packet-mode using a non-zero value.
3559 //
3560
3561 PacketMode = 0x123;
3562 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
3563
3564 //
3565 // Verify packet-mode value.
3566 //
3567
3568 LxtCheckErrno(ioctl(PtmFd, TIOCGPKT, &PacketMode));
3569 LxtCheckEqual(PacketMode, 1, "%d");
3570
3571 //
3572 // Verify no data waiting.
3573 //
3574
3575 memset(&Timeout, 0, sizeof(Timeout));
3576 FD_ZERO(&ReadFds);
3577 FD_SET(PtmFd, &ReadFds);
3578 LxtCheckErrno(select((PtmFd + 1), &ReadFds, NULL, NULL, &Timeout));
3579 LxtCheckEqual(Result, 0, "%d");
3580
3581 //
3582 // Verify no data available to read.
3583 //
3584
3585 LxtCheckErrno(PtmFlags = fcntl(PtmFd, F_GETFL, 0));
3586 LxtCheckErrno(fcntl(PtmFd, F_SETFL, (PtmFlags | O_NONBLOCK)));
3587 LxtCheckErrnoFailure(BytesReadWrite = read(PtmFd, &ControlByte, sizeof(ControlByte)), EAGAIN);
3588 LxtCheckErrno(fcntl(PtmFd, F_SETFL, PtmFlags));
3589
3590 ErrorExit:
3591 if (PtmFd != -1)
3592 {
3593 close(PtmFd);
3594 }
3595
3596 if (PtsFd != -1)
3597 {
3598 close(PtsFd);
3599 }
3600
3601 return Result;
3602 }
3603
3604 int PtPacketBasic2(PLXT_ARGS Args)
3605
3606 /*++
3607
3608 Routine Description:
3609
3610 This routine performs a basic packet-mode pseudo terminal test. The steps are:
3611 - Turn on packet mode.
3612 - Perform simple read/write check on the master-subordinate.
3613
3614 Arguments:
3615
3616 Args - Supplies the command line arguments.
3617
3618 Return Value:
3619
3620 Returns 0 on success, -1 on failure.
3621
3622 --*/
3623
3624 {
3625
3626 int PacketMode;
3627 int PtmFd;
3628 int PtsFd;
3629 int Result;
3630 int SerialNumber;
3631
3632 //
3633 // Initialize locals.
3634 //
3635
3636 PtmFd = -1;
3637 PtsFd = -1;
3638
3639 //
3640 // Open Master-Subordinate.
3641 //
3642
3643 LxtCheckErrno(OpenMasterSubordinate(&PtmFd, &PtsFd, NULL, &SerialNumber));
3644 LxtLogInfo("Master opened at FD:%d", PtmFd);
3645 LxtLogInfo("Subordinate Serial Number: %d", SerialNumber);
3646 LxtLogInfo("Subordinate opened at FD:%d", PtsFd);
3647
3648 //
3649 // Turn on packet-mode.
3650 //
3651
3652 PacketMode = 1;
3653 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
3654
3655 //
3656 // Test simple send/receive.
3657 //
3658
3659 LxtCheckErrno(SimpleReadWriteCheck(PtmFd, PtsFd));
3660
3661 //
3662 // Enable raw mode.
3663 //
3664
3665 LxtCheckErrno(RawInit(PtsFd));
3666
3667 //
3668 // Test simple send/receive.
3669 //
3670
3671 LxtCheckErrno(SimpleReadWriteCheck(PtmFd, PtsFd));
3672
3673 ErrorExit:
3674 if (PtmFd != -1)
3675 {
3676 close(PtmFd);
3677 }
3678
3679 if (PtsFd != -1)
3680 {
3681 close(PtsFd);
3682 }
3683
3684 return Result;
3685 }
3686
3687 int PtPacketBasic3(PLXT_ARGS Args)
3688
3689 /*++
3690
3691 Routine Description:
3692
3693 This routine performs a basic packet-mode pseudo terminal test. The steps are:
3694 - Turns off canonical mode to avoid line discipline.
3695 - Turn on packet mode.
3696 - Read back partial message.
3697
3698
3699 Arguments:
3700
3701 Args - Supplies the command line arguments.
3702
3703 Return Value:
3704
3705 Returns 0 on success, -1 on failure.
3706
3707 --*/
3708
3709 {
3710
3711 int BytesReadWrite;
3712 int ExpectedResult;
3713 const char* Greetings = "Hi there!!";
3714 int PacketMode;
3715 int PtmFd;
3716 int PtsFd;
3717 char ReadBuffer[20];
3718 int Result;
3719 int SerialNumber;
3720
3721 //
3722 // Initialize locals.
3723 //
3724
3725 PtmFd = -1;
3726 PtsFd = -1;
3727
3728 //
3729 // Open Master-Subordinate.
3730 //
3731
3732 LxtCheckErrno(OpenMasterSubordinate(&PtmFd, &PtsFd, NULL, &SerialNumber));
3733 LxtLogInfo("Master opened at FD:%d", PtmFd);
3734 LxtLogInfo("Subordinate Serial Number: %d", SerialNumber);
3735 LxtLogInfo("Subordinate opened at FD:%d", PtsFd);
3736
3737 //
3738 // Configure as raw / packet-mode.
3739 //
3740
3741 LxtCheckErrno(RawInit(PtsFd));
3742 PacketMode = 1;
3743 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
3744
3745 //
3746 // Write to subordinate.
3747 //
3748
3749 ExpectedResult = strlen(Greetings);
3750 LxtCheckErrno(BytesReadWrite = write(PtsFd, Greetings, ExpectedResult));
3751 LxtCheckFnResults("write", BytesReadWrite, ExpectedResult);
3752 LxtCheckErrno(tcdrain(PtsFd));
3753
3754 //
3755 // Read just header byte from master.
3756 //
3757
3758 LxtLogInfo("Reading header byte from master");
3759 LxtCheckErrno(BytesReadWrite = read(PtmFd, ReadBuffer, 1));
3760 LxtCheckFnResults("read", BytesReadWrite, 1);
3761 LxtCheckEqual(ReadBuffer[0], 0, "%hhd");
3762
3763 //
3764 // Original message should still be there.
3765 //
3766
3767 LxtLogInfo("Checking for remaining message from master");
3768 memset(ReadBuffer, 0, sizeof(ReadBuffer));
3769 LxtCheckErrno(BytesReadWrite = read(PtmFd, ReadBuffer, sizeof(ReadBuffer)));
3770 LxtCheckFnResults("read", BytesReadWrite, ExpectedResult + 1);
3771 ReadBuffer[BytesReadWrite] = '\0';
3772 LxtCheckEqual(ReadBuffer[0], 0, "%hhd");
3773 LxtCheckStringEqual(ReadBuffer + 1, Greetings);
3774
3775 //
3776 // Write to master.
3777 //
3778
3779 LxtCheckErrno(BytesReadWrite = write(PtmFd, Greetings, ExpectedResult));
3780 LxtCheckFnResults("write", BytesReadWrite, ExpectedResult);
3781 LxtCheckErrno(tcdrain(PtmFd));
3782
3783 //
3784 // Read from subordinate.
3785 //
3786
3787 LxtLogInfo("Reading from subordinate");
3788 LxtCheckErrno(BytesReadWrite = read(PtsFd, ReadBuffer, 1));
3789 LxtCheckFnResults("read", BytesReadWrite, 1);
3790 LxtCheckEqual(ReadBuffer[0], Greetings[0], "%hhd");
3791 memset(ReadBuffer, 0, sizeof(ReadBuffer));
3792 LxtCheckErrno(BytesReadWrite = read(PtsFd, ReadBuffer, sizeof(ReadBuffer)));
3793 LxtCheckFnResults("read", BytesReadWrite, ExpectedResult - 1);
3794 ReadBuffer[BytesReadWrite] = '\0';
3795 LxtCheckStringEqual(ReadBuffer, Greetings + 1);
3796
3797 ErrorExit:
3798 if (PtmFd != -1)
3799 {
3800 close(PtmFd);
3801 }
3802
3803 if (PtsFd != -1)
3804 {
3805 close(PtsFd);
3806 }
3807
3808 return Result;
3809 }
3810
3811 int PtPacketBasic4(PLXT_ARGS Args)
3812
3813 /*++
3814
3815 Routine Description:
3816
3817 This routine performs a basic packet-mode pseudo terminal test. The steps are:
3818 - Turns off canonical mode to avoid line discipline.
3819 - Turn on packet mode.
3820 - Read back partial messages.
3821
3822
3823 Arguments:
3824
3825 Args - Supplies the command line arguments.
3826
3827 Return Value:
3828
3829 Returns 0 on success, -1 on failure.
3830
3831 --*/
3832
3833 {
3834
3835 int BytesReadWrite;
3836 int ExpectedResult;
3837 const char* Greetings = "Hi there!!";
3838 int PacketMode;
3839 int PtmFd;
3840 int PtsFd;
3841 char ReadBuffer[20];
3842 int Result;
3843 int SerialNumber;
3844
3845 //
3846 // Initialize locals.
3847 //
3848
3849 PtmFd = -1;
3850 PtsFd = -1;
3851
3852 //
3853 // Open Master-Subordinate.
3854 //
3855
3856 LxtCheckErrno(OpenMasterSubordinate(&PtmFd, &PtsFd, NULL, &SerialNumber));
3857 LxtLogInfo("Master opened at FD:%d", PtmFd);
3858 LxtLogInfo("Subordinate Serial Number: %d", SerialNumber);
3859 LxtLogInfo("Subordinate opened at FD:%d", PtsFd);
3860
3861 //
3862 // Configure as raw / packet-mode.
3863 //
3864
3865 LxtCheckErrno(RawInit(PtsFd));
3866 PacketMode = 1;
3867 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
3868
3869 //
3870 // Write to subordinate.
3871 //
3872
3873 ExpectedResult = strlen(Greetings);
3874 LxtCheckErrno(BytesReadWrite = write(PtsFd, Greetings, ExpectedResult));
3875 LxtCheckFnResults("write", BytesReadWrite, ExpectedResult);
3876 LxtCheckErrno(tcdrain(PtsFd));
3877
3878 //
3879 // Read first two bytes from master.
3880 //
3881
3882 LxtLogInfo("Reading two bytes from master");
3883 LxtCheckErrno(BytesReadWrite = read(PtmFd, ReadBuffer, 2));
3884 LxtCheckFnResults("read", BytesReadWrite, 2);
3885 LxtCheckEqual(ReadBuffer[0], 0, "%hhd");
3886 LxtCheckEqual(ReadBuffer[1], Greetings[0], "%hhd");
3887
3888 //
3889 // Check for remaining message bytes.
3890 //
3891
3892 LxtLogInfo("Checking for remaining message from master");
3893 memset(ReadBuffer, 0, sizeof(ReadBuffer));
3894 LxtCheckErrno(BytesReadWrite = read(PtmFd, ReadBuffer, sizeof(ReadBuffer)));
3895 LxtCheckFnResults("read", BytesReadWrite, ExpectedResult);
3896 ReadBuffer[BytesReadWrite] = '\0';
3897 LxtCheckEqual(ReadBuffer[0], 0, "%hhd");
3898 LxtCheckStringEqual(ReadBuffer + 1, Greetings + 1);
3899
3900 ErrorExit:
3901 if (PtmFd != -1)
3902 {
3903 close(PtmFd);
3904 }
3905
3906 if (PtsFd != -1)
3907 {
3908 close(PtsFd);
3909 }
3910
3911 return Result;
3912 }
3913
3914 int PtPacketToggleMode1(PLXT_ARGS Args)
3915
3916 /*++
3917
3918 Routine Description:
3919
3920 This routine sends a message to the subordinate with packet-mode off, turns
3921 it on and reads from master.
3922
3923 Arguments:
3924
3925 Args - Supplies the command line arguments.
3926
3927 Return Value:
3928
3929 Returns 0 on success, -1 on failure.
3930
3931 --*/
3932
3933 {
3934
3935 int BytesReadWrite;
3936 int ExpectedResult;
3937 const char* Greetings = "Hi there!!";
3938 int PacketMode;
3939 int PtmFd;
3940 int PtsFd;
3941 char ReadBuffer[20];
3942 int Result;
3943 int SerialNumber;
3944
3945 //
3946 // Initialize locals.
3947 //
3948
3949 PtmFd = -1;
3950 PtsFd = -1;
3951
3952 //
3953 // Open Master-Subordinate.
3954 //
3955
3956 LxtCheckErrno(OpenMasterSubordinate(&PtmFd, &PtsFd, NULL, &SerialNumber));
3957 LxtLogInfo("Master opened at FD:%d", PtmFd);
3958 LxtLogInfo("Subordinate Serial Number: %d", SerialNumber);
3959 LxtLogInfo("Subordinate opened at FD:%d", PtsFd);
3960
3961 //
3962 // Configure as raw.
3963 //
3964
3965 LxtCheckErrno(RawInit(PtsFd));
3966
3967 //
3968 // Write to subordinate.
3969 //
3970
3971 ExpectedResult = strlen(Greetings);
3972 LxtCheckErrno(BytesReadWrite = write(PtsFd, Greetings, ExpectedResult));
3973 LxtCheckFnResults("write", BytesReadWrite, ExpectedResult);
3974 LxtCheckErrno(tcdrain(PtsFd));
3975
3976 //
3977 // Configure as packet-mode.
3978 //
3979
3980 LxtCheckErrno(RawInit(PtsFd));
3981 PacketMode = 1;
3982 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
3983
3984 //
3985 // Read message from master.
3986 //
3987
3988 LxtLogInfo("Reading from master");
3989 memset(ReadBuffer, 0, sizeof(ReadBuffer));
3990 LxtCheckErrno(BytesReadWrite = read(PtmFd, ReadBuffer, sizeof(ReadBuffer)));
3991 LxtCheckFnResults("read", BytesReadWrite, ExpectedResult + 1);
3992 ReadBuffer[BytesReadWrite] = '\0';
3993 LxtCheckEqual(ReadBuffer[0], 0, "%hhd");
3994 LxtCheckStringEqual(ReadBuffer + 1, Greetings);
3995
3996 ErrorExit:
3997 if (PtmFd != -1)
3998 {
3999 close(PtmFd);
4000 }
4001
4002 if (PtsFd != -1)
4003 {
4004 close(PtsFd);
4005 }
4006
4007 return Result;
4008 }
4009
4010 int PtPacketToggleMode2(PLXT_ARGS Args)
4011
4012 /*++
4013
4014 Routine Description:
4015
4016 This routine sends a message to the subordinate with packet-mode on, turns
4017 it off and reads from master.
4018
4019
4020 Arguments:
4021
4022 Args - Supplies the command line arguments.
4023
4024 Return Value:
4025
4026 Returns 0 on success, -1 on failure.
4027
4028 --*/
4029
4030 {
4031
4032 int BytesReadWrite;
4033 int ExpectedResult;
4034 const char* Greetings = "Hi there!!";
4035 int PacketMode;
4036 int PtmFd;
4037 int PtsFd;
4038 char ReadBuffer[20];
4039 int Result;
4040 int SerialNumber;
4041
4042 //
4043 // Initialize locals.
4044 //
4045
4046 PtmFd = -1;
4047 PtsFd = -1;
4048
4049 //
4050 // Open Master-Subordinate.
4051 //
4052
4053 LxtCheckErrno(OpenMasterSubordinate(&PtmFd, &PtsFd, NULL, &SerialNumber));
4054 LxtLogInfo("Master opened at FD:%d", PtmFd);
4055 LxtLogInfo("Subordinate Serial Number: %d", SerialNumber);
4056 LxtLogInfo("Subordinate opened at FD:%d", PtsFd);
4057
4058 //
4059 // Configure as raw / packet-mode.
4060 //
4061
4062 LxtCheckErrno(RawInit(PtsFd));
4063 PacketMode = 1;
4064 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
4065
4066 //
4067 // Write to subordinate.
4068 //
4069
4070 ExpectedResult = strlen(Greetings);
4071 LxtCheckErrno(BytesReadWrite = write(PtsFd, Greetings, ExpectedResult));
4072 LxtCheckFnResults("write", BytesReadWrite, ExpectedResult);
4073 LxtCheckErrno(tcdrain(PtsFd));
4074
4075 //
4076 // Turn off packet-mode.
4077 //
4078
4079 PacketMode = 0;
4080 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
4081
4082 //
4083 // Read message from master.
4084 //
4085
4086 LxtLogInfo("Reading from master");
4087 memset(ReadBuffer, 0, sizeof(ReadBuffer));
4088 LxtCheckErrno(BytesReadWrite = read(PtmFd, ReadBuffer, sizeof(ReadBuffer)));
4089 LxtCheckFnResults("read", BytesReadWrite, ExpectedResult);
4090 ReadBuffer[BytesReadWrite] = '\0';
4091 LxtCheckStringEqual(ReadBuffer, Greetings);
4092
4093 ErrorExit:
4094 if (PtmFd != -1)
4095 {
4096 close(PtmFd);
4097 }
4098
4099 if (PtsFd != -1)
4100 {
4101 close(PtsFd);
4102 }
4103
4104 return Result;
4105 }
4106
4107 int PtPacketToggleMode3(PLXT_ARGS Args)
4108
4109 /*++
4110
4111 Routine Description:
4112
4113 This routine performs operations that would normally result in a packet
4114 mode status, then turns on packet mode and checks the control byte.
4115
4116 Arguments:
4117
4118 Args - Supplies the command line arguments.
4119
4120 Return Value:
4121
4122 Returns 0 on success, -1 on failure.
4123
4124 --*/
4125
4126 {
4127
4128 int BytesReadWrite;
4129 cc_t ControlArray[NCCS];
4130 char DefaultStartChar;
4131 int ExpectedResult;
4132 int FileFlags;
4133 int PacketMode;
4134 int PtmFd;
4135 int PtsFd;
4136 char ReadBuffer[20];
4137 fd_set ReadFds;
4138 int Result;
4139 int SerialNumber;
4140 struct timeval Timeout;
4141
4142 //
4143 // Initialize locals.
4144 //
4145
4146 PtmFd = -1;
4147 PtsFd = -1;
4148
4149 //
4150 // Open Master-Subordinate.
4151 //
4152
4153 LxtCheckErrno(OpenMasterSubordinate(&PtmFd, &PtsFd, NULL, &SerialNumber));
4154 LxtLogInfo("Master opened at FD:%d", PtmFd);
4155 LxtLogInfo("Subordinate Serial Number: %d", SerialNumber);
4156 LxtLogInfo("Subordinate opened at FD:%d", PtsFd);
4157
4158 //
4159 // Fetch the default control character array values.
4160 //
4161
4162 LxtCheckResult(TerminalSettingsGetControlArray(PtmFd, ControlArray));
4163 DefaultStartChar = ControlArray[VSTART];
4164
4165 //
4166 // Modify the start control character.
4167 //
4168
4169 ControlArray[VSTART] = _POSIX_VDISABLE;
4170 LxtCheckResult(TerminalSettingsSetControlArray(PtmFd, ControlArray));
4171
4172 //
4173 // Suspend output on subordinate.
4174 //
4175
4176 LxtCheckErrno(tcflow(PtsFd, TCOOFF));
4177
4178 //
4179 // Flush subordinate read and write queues.
4180 //
4181
4182 LxtCheckErrno(tcflush(PtsFd, TCIOFLUSH));
4183
4184 //
4185 // Configure packet-mode.
4186 //
4187
4188 PacketMode = 1;
4189 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
4190
4191 //
4192 // Master endpoint should not be ready for read.
4193 //
4194
4195 memset(&Timeout, 0, sizeof(Timeout));
4196 FD_ZERO(&ReadFds);
4197 FD_SET(PtmFd, &ReadFds);
4198 LxtCheckErrno(select((PtmFd + 1), &ReadFds, NULL, NULL, &Timeout));
4199 LxtCheckEqual(Result, 0, "%d");
4200
4201 //
4202 // No data expected.
4203 //
4204
4205 LxtCheckErrno(FileFlags = fcntl(PtmFd, F_GETFL, 0));
4206 LxtCheckErrno(fcntl(PtmFd, F_SETFL, (FileFlags | O_NONBLOCK)));
4207 LxtCheckErrnoFailure(BytesReadWrite = read(PtmFd, ReadBuffer, sizeof(ReadBuffer)), EAGAIN);
4208 LxtCheckErrno(fcntl(PtmFd, F_SETFL, FileFlags));
4209
4210 //
4211 // Now with packet-mode enabled, undo/redo the previous steps.
4212 //
4213
4214 //
4215 // Modify the start control character.
4216 //
4217
4218 ControlArray[VSTART] = DefaultStartChar;
4219 LxtCheckResult(TerminalSettingsSetControlArray(PtmFd, ControlArray));
4220
4221 //
4222 // Resume output on subordinate.
4223 //
4224
4225 LxtCheckErrno(tcflow(PtsFd, TCOON));
4226
4227 //
4228 // Flush subordinate read and write queues.
4229 //
4230
4231 LxtCheckErrno(tcflush(PtsFd, TCIOFLUSH));
4232
4233 //
4234 // Master endpoint should now be ready for read.
4235 //
4236
4237 FD_SET(PtmFd, &ReadFds);
4238 LxtCheckErrno(select((PtmFd + 1), &ReadFds, NULL, NULL, &Timeout));
4239 LxtCheckEqual(Result, 1, "%d");
4240
4241 //
4242 // Read control byte.
4243 //
4244
4245 LxtLogInfo("Reading from master");
4246 LxtCheckErrno(BytesReadWrite = read(PtmFd, ReadBuffer, sizeof(ReadBuffer)));
4247 LxtCheckFnResults("read", BytesReadWrite, 1);
4248 LxtCheckEqual(ReadBuffer[0], (TIOCPKT_FLUSHREAD | TIOCPKT_FLUSHWRITE | TIOCPKT_START | TIOCPKT_DOSTOP), "%hhd");
4249
4250 ErrorExit:
4251 if (PtmFd != -1)
4252 {
4253 close(PtmFd);
4254 }
4255
4256 if (PtsFd != -1)
4257 {
4258 close(PtsFd);
4259 }
4260
4261 return Result;
4262 }
4263
4264 int PtPacketToggleMode4(PLXT_ARGS Args)
4265
4266 /*++
4267
4268 Routine Description:
4269
4270 This routine waits for data on the master subordinate on one thread, while
4271 a second thread switches the master endpoint to packet-mode and flushes
4272 the read queue.
4273
4274 Arguments:
4275
4276 Args - Supplies the command line arguments.
4277
4278 Return Value:
4279
4280 Returns 0 on success, -1 on failure.
4281
4282 --*/
4283
4284 {
4285
4286 int BytesReadWrite;
4287 pid_t ChildPid;
4288 int ExpectedResult;
4289 int PacketMode;
4290 int PtmFd;
4291 int PtsFd;
4292 char ReadBuffer[20];
4293 fd_set ReadFds;
4294 int Result;
4295 int Status;
4296 struct timeval Timeout;
4297
4298 //
4299 // Initialize locals
4300 //
4301
4302 ChildPid = -1;
4303 PtmFd = -1;
4304 PtsFd = -1;
4305
4306 LXT_SYNCHRONIZATION_POINT_START();
4307 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
4308 if (ChildPid == 0)
4309 {
4310 memset(&Timeout, 0, sizeof(Timeout));
4311 Timeout.tv_sec = 3;
4312 FD_ZERO(&ReadFds);
4313 FD_SET(PtmFd, &ReadFds);
4314 LxtCheckErrno(select((PtmFd + 1), &ReadFds, NULL, NULL, &Timeout));
4315 LxtCheckEqual(Result, 1, "%d");
4316 }
4317 else
4318 {
4319
4320 //
4321 // Give child a chance to wait in select system call.
4322 //
4323
4324 sleep(1);
4325
4326 //
4327 // Enable packet mode.
4328 //
4329
4330 PacketMode = 1;
4331 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
4332 sleep(1);
4333
4334 //
4335 // Flush subordinate read queue.
4336 //
4337
4338 LxtCheckErrno(tcflush(PtsFd, TCIFLUSH));
4339 }
4340
4341 ErrorExit:
4342 if ((ChildPid != 0) && (PtmFd != -1))
4343 {
4344 close(PtmFd);
4345 }
4346
4347 if ((ChildPid != 0) && (PtsFd != -1))
4348 {
4349 close(PtsFd);
4350 }
4351
4352 LXT_SYNCHRONIZATION_POINT_END();
4353 return Result;
4354 }
4355
4356 int PtPacketToggleMode5(PLXT_ARGS Args)
4357
4358 /*++
4359
4360 Routine Description:
4361
4362 This routine enables packet mode and then waits for data on the master
4363 subordinate on one thread. A second thread disables packet-mode on the
4364 master endpoint and flushes the read queue.
4365
4366 Arguments:
4367
4368 Args - Supplies the command line arguments.
4369
4370 Return Value:
4371
4372 Returns 0 on success, -1 on failure.
4373
4374 --*/
4375
4376 {
4377
4378 int BytesReadWrite;
4379 pid_t ChildPid;
4380 int ExpectedResult;
4381 int PacketMode;
4382 int PtmFd;
4383 int PtsFd;
4384 char ReadBuffer[20];
4385 fd_set ReadFds;
4386 int Result;
4387 int Status;
4388 struct timeval Timeout;
4389
4390 //
4391 // Initialize locals
4392 //
4393
4394 ChildPid = -1;
4395 PtmFd = -1;
4396 PtsFd = -1;
4397
4398 LXT_SYNCHRONIZATION_POINT_START();
4399 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
4400 if (ChildPid == 0)
4401 {
4402
4403 //
4404 // Enable packet mode.
4405 //
4406
4407 PacketMode = 1;
4408 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
4409
4410 //
4411 // Wait for data on master.
4412 //
4413
4414 memset(&Timeout, 0, sizeof(Timeout));
4415 Timeout.tv_sec = 2;
4416 FD_ZERO(&ReadFds);
4417 FD_SET(PtmFd, &ReadFds);
4418 LxtCheckErrno(select((PtmFd + 1), &ReadFds, NULL, NULL, &Timeout));
4419 LxtCheckEqual(Result, 0, "%d");
4420 }
4421 else
4422 {
4423
4424 //
4425 // Give child a chance to wait in select system call.
4426 //
4427
4428 sleep(1);
4429
4430 //
4431 // Disable packet mode.
4432 //
4433
4434 PacketMode = 0;
4435 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
4436
4437 //
4438 // Flush subordinate read queue.
4439 //
4440
4441 LxtCheckErrno(tcflush(PtsFd, TCIFLUSH));
4442 }
4443
4444 ErrorExit:
4445 if ((ChildPid != 0) && (PtmFd != -1))
4446 {
4447 close(PtmFd);
4448 }
4449
4450 if ((ChildPid != 0) && (PtsFd != -1))
4451 {
4452 close(PtsFd);
4453 }
4454
4455 LXT_SYNCHRONIZATION_POINT_END();
4456 return Result;
4457 }
4458
4459 int PtPacketToggleMode6(PLXT_ARGS Args)
4460
4461 /*++
4462
4463 Routine Description:
4464
4465 This routine enables packet mode and starts a read. A second thread
4466 disables packet-mode and writes data.
4467
4468 Arguments:
4469
4470 Args - Supplies the command line arguments.
4471
4472 Return Value:
4473
4474 Returns 0 on success, -1 on failure.
4475
4476 --*/
4477
4478 {
4479
4480 int BytesReadWrite;
4481 pid_t ChildPid;
4482 int ExpectedResult;
4483 const char* Greetings = "Hi there!!";
4484 int PacketMode;
4485 int PtmFd;
4486 int PtsFd;
4487 char ReadBuffer[20];
4488 int Result;
4489 int Status;
4490
4491 //
4492 // Initialize locals
4493 //
4494
4495 ChildPid = -1;
4496 PtmFd = -1;
4497 PtsFd = -1;
4498
4499 LXT_SYNCHRONIZATION_POINT_START()
4500 ExpectedResult = strlen(Greetings);
4501 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
4502 if (ChildPid == 0)
4503 {
4504
4505 //
4506 // Configure as raw / packet-mode.
4507 //
4508
4509 LxtCheckErrno(RawInit(PtsFd));
4510 PacketMode = 1;
4511 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
4512
4513 //
4514 // Read message from master.
4515 //
4516
4517 LxtLogInfo("Reading from master");
4518 memset(ReadBuffer, 0, sizeof(ReadBuffer));
4519 LxtCheckErrno(BytesReadWrite = read(PtmFd, ReadBuffer, sizeof(ReadBuffer)));
4520 LxtCheckFnResults("read", BytesReadWrite, ExpectedResult + 1);
4521 ReadBuffer[BytesReadWrite] = '\0';
4522 LxtCheckEqual(ReadBuffer[0], 0, "%hhd");
4523 LxtCheckStringEqual(ReadBuffer + 1, Greetings);
4524 }
4525 else
4526 {
4527
4528 //
4529 // Give child a chance to wait in read system call.
4530 //
4531
4532 sleep(1);
4533
4534 //
4535 // Disable packet mode.
4536 //
4537
4538 PacketMode = 0;
4539 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
4540
4541 //
4542 // Write to subordinate.
4543 //
4544
4545 LxtCheckErrno(BytesReadWrite = write(PtsFd, Greetings, ExpectedResult));
4546 LxtCheckFnResults("write", BytesReadWrite, ExpectedResult);
4547 LxtCheckErrno(tcdrain(PtsFd));
4548 }
4549
4550 ErrorExit:
4551 if ((ChildPid != 0) && (PtmFd != -1))
4552 {
4553 close(PtmFd);
4554 }
4555
4556 if ((ChildPid != 0) && (PtsFd != -1))
4557 {
4558 close(PtsFd);
4559 }
4560
4561 LXT_SYNCHRONIZATION_POINT_END();
4562 return Result;
4563 }
4564
4565 int PtPacketToggleMode7(PLXT_ARGS Args)
4566
4567 /*++
4568
4569 Routine Description:
4570
4571 This routine starts a read on the master endpoint. A second thread
4572 enables packet-mode and writes data.
4573
4574 Arguments:
4575
4576 Args - Supplies the command line arguments.
4577
4578 Return Value:
4579
4580 Returns 0 on success, -1 on failure.
4581
4582 --*/
4583
4584 {
4585
4586 int BytesReadWrite;
4587 pid_t ChildPid;
4588 int ExpectedResult;
4589 const char* Greetings = "Hi there!!";
4590 int PacketMode;
4591 int PtmFd;
4592 int PtsFd;
4593 char ReadBuffer[20];
4594 int Result;
4595 int Status;
4596
4597 //
4598 // Initialize locals
4599 //
4600
4601 ChildPid = -1;
4602 PtmFd = -1;
4603 PtsFd = -1;
4604
4605 LXT_SYNCHRONIZATION_POINT_START();
4606 ExpectedResult = strlen(Greetings);
4607 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
4608 if (ChildPid == 0)
4609 {
4610
4611 //
4612 // Configure as raw.
4613 //
4614
4615 LxtCheckErrno(RawInit(PtsFd));
4616
4617 //
4618 // Read message from master.
4619 //
4620
4621 LxtLogInfo("Reading from master");
4622 memset(ReadBuffer, 0, sizeof(ReadBuffer));
4623 LxtCheckErrno(BytesReadWrite = read(PtmFd, ReadBuffer, sizeof(ReadBuffer)));
4624 LxtCheckFnResults("read", BytesReadWrite, ExpectedResult);
4625 ReadBuffer[BytesReadWrite] = '\0';
4626 LxtCheckStringEqual(ReadBuffer, Greetings);
4627 }
4628 else
4629 {
4630
4631 //
4632 // Give child a chance to wait in read system call.
4633 //
4634
4635 sleep(1);
4636
4637 //
4638 // Enable packet mode.
4639 //
4640
4641 PacketMode = 1;
4642 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
4643
4644 //
4645 // Write to subordinate.
4646 //
4647
4648 LxtCheckErrno(BytesReadWrite = write(PtsFd, Greetings, ExpectedResult));
4649 LxtCheckFnResults("write", BytesReadWrite, ExpectedResult);
4650 LxtCheckErrno(tcdrain(PtsFd));
4651 }
4652
4653 ErrorExit:
4654 if ((ChildPid != 0) && (PtmFd != -1))
4655 {
4656 close(PtmFd);
4657 }
4658
4659 if ((ChildPid != 0) && (PtsFd != -1))
4660 {
4661 close(PtsFd);
4662 }
4663
4664 LXT_SYNCHRONIZATION_POINT_END();
4665 return Result;
4666 }
4667
4668 int PtPacketFlushRead1(PLXT_ARGS Args)
4669
4670 /*++
4671
4672 Routine Description:
4673
4674 This routine flushes the subordinate read queue.
4675
4676
4677 Arguments:
4678
4679 Args - Supplies the command line arguments.
4680
4681 Return Value:
4682
4683 Returns 0 on success, -1 on failure.
4684
4685 --*/
4686
4687 {
4688
4689 int BytesReadWrite;
4690 int PacketMode;
4691 int PtmFd;
4692 int PtsFd;
4693 char ReadBuffer[1];
4694 fd_set ReadFds;
4695 int Result;
4696 int SerialNumber;
4697 struct timeval Timeout;
4698
4699 //
4700 // Initialize locals.
4701 //
4702
4703 PtmFd = -1;
4704 PtsFd = -1;
4705
4706 //
4707 // Open Master-Subordinate.
4708 //
4709
4710 LxtCheckErrno(OpenMasterSubordinate(&PtmFd, &PtsFd, NULL, &SerialNumber));
4711 LxtLogInfo("Master opened at FD:%d", PtmFd);
4712 LxtLogInfo("Subordinate Serial Number: %d", SerialNumber);
4713 LxtLogInfo("Subordinate opened at FD:%d", PtsFd);
4714
4715 //
4716 // Configure as raw / packet-mode.
4717 //
4718
4719 LxtCheckErrno(RawInit(PtsFd));
4720 PacketMode = 1;
4721 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
4722
4723 //
4724 // Flush subordinate read queue.
4725 //
4726
4727 LxtCheckErrno(tcflush(PtsFd, TCIFLUSH));
4728
4729 //
4730 // Check for available data.
4731 //
4732
4733 LxtLogInfo("Verifying master has data to read...");
4734 memset(&Timeout, 0, sizeof(Timeout));
4735 FD_ZERO(&ReadFds);
4736 FD_SET(PtmFd, &ReadFds);
4737 LxtCheckErrno(select((PtmFd + 1), &ReadFds, NULL, NULL, &Timeout));
4738 LxtCheckEqual(Result, 1, "%d");
4739
4740 //
4741 // Read control byte.
4742 //
4743
4744 LxtLogInfo("Reading from master");
4745 LxtCheckErrno(BytesReadWrite = read(PtmFd, ReadBuffer, sizeof(ReadBuffer)));
4746 LxtCheckFnResults("read", BytesReadWrite, 1);
4747 LxtCheckEqual(ReadBuffer[0], TIOCPKT_FLUSHREAD, "%hhd");
4748
4749 ErrorExit:
4750 if (PtmFd != -1)
4751 {
4752 close(PtmFd);
4753 }
4754
4755 if (PtsFd != -1)
4756 {
4757 close(PtsFd);
4758 }
4759
4760 return Result;
4761 }
4762
4763 int PtPacketFlushRead2(PLXT_ARGS Args)
4764
4765 /*++
4766
4767 Routine Description:
4768
4769 This routine sends a message to the subordinate with packet-mode on, then
4770 flushes the subordinate read queue.
4771
4772 Arguments:
4773
4774 Args - Supplies the command line arguments.
4775
4776 Return Value:
4777
4778 Returns 0 on success, -1 on failure.
4779
4780 --*/
4781
4782 {
4783
4784 int BytesReadWrite;
4785 int ExpectedResult;
4786 const char* Greetings = "Hi there!!";
4787 int PacketMode;
4788 int PtmFd;
4789 int PtsFd;
4790 char ReadBuffer[20];
4791 fd_set ReadFds;
4792 int Result;
4793 int SerialNumber;
4794 struct timeval Timeout;
4795
4796 //
4797 // Initialize locals.
4798 //
4799
4800 PtmFd = -1;
4801 PtsFd = -1;
4802
4803 //
4804 // Open Master-Subordinate.
4805 //
4806
4807 LxtCheckErrno(OpenMasterSubordinate(&PtmFd, &PtsFd, NULL, &SerialNumber));
4808 LxtLogInfo("Master opened at FD:%d", PtmFd);
4809 LxtLogInfo("Subordinate Serial Number: %d", SerialNumber);
4810 LxtLogInfo("Subordinate opened at FD:%d", PtsFd);
4811
4812 //
4813 // Configure as raw / packet-mode.
4814 //
4815
4816 LxtCheckErrno(RawInit(PtsFd));
4817 PacketMode = 1;
4818 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
4819
4820 //
4821 // Write to subordinate.
4822 //
4823
4824 ExpectedResult = strlen(Greetings);
4825 LxtCheckErrno(BytesReadWrite = write(PtsFd, Greetings, ExpectedResult));
4826 LxtCheckFnResults("write", BytesReadWrite, ExpectedResult);
4827 LxtCheckErrno(tcdrain(PtsFd));
4828
4829 //
4830 // Flush subordinate read queue.
4831 //
4832
4833 LxtCheckErrno(tcflush(PtsFd, TCIFLUSH));
4834
4835 //
4836 // Check for available data.
4837 //
4838
4839 LxtLogInfo("Verifying master has data to read...");
4840 memset(&Timeout, 0, sizeof(Timeout));
4841 FD_ZERO(&ReadFds);
4842 FD_SET(PtmFd, &ReadFds);
4843 LxtCheckErrno(select((PtmFd + 1), &ReadFds, NULL, NULL, &Timeout));
4844 LxtCheckEqual(Result, 1, "%d");
4845
4846 //
4847 // Read control byte.
4848 //
4849
4850 LxtLogInfo("Reading from master");
4851 LxtCheckErrno(BytesReadWrite = read(PtmFd, ReadBuffer, sizeof(ReadBuffer)));
4852 LxtCheckFnResults("read", BytesReadWrite, 1);
4853 LxtCheckEqual(ReadBuffer[0], TIOCPKT_FLUSHREAD, "%hhd");
4854
4855 //
4856 // Read message from master.
4857 //
4858
4859 LxtLogInfo("Reading from master");
4860 memset(ReadBuffer, 0, sizeof(ReadBuffer));
4861 LxtCheckErrno(BytesReadWrite = read(PtmFd, ReadBuffer, sizeof(ReadBuffer)));
4862 LxtCheckFnResults("read", BytesReadWrite, ExpectedResult + 1);
4863 ReadBuffer[BytesReadWrite] = '\0';
4864 LxtCheckEqual(ReadBuffer[0], 0, "%hhd");
4865 LxtCheckStringEqual(ReadBuffer + 1, Greetings);
4866
4867 ErrorExit:
4868 if (PtmFd != -1)
4869 {
4870 close(PtmFd);
4871 }
4872
4873 if (PtsFd != -1)
4874 {
4875 close(PtsFd);
4876 }
4877
4878 return Result;
4879 }
4880
4881 int PtPacketFlushRead3(PLXT_ARGS Args)
4882
4883 /*++
4884
4885 Routine Description:
4886
4887 This routine waits for data on the master subordinate on one thread, while
4888 a second thread flushes the read queue.
4889
4890 Arguments:
4891
4892 Args - Supplies the command line arguments.
4893
4894 Return Value:
4895
4896 Returns 0 on success, -1 on failure.
4897
4898 --*/
4899
4900 {
4901
4902 int BytesReadWrite;
4903 pid_t ChildPid;
4904 int ExpectedResult;
4905 int PacketMode;
4906 int PtmFd;
4907 int PtsFd;
4908 char ReadBuffer[20];
4909 int Result;
4910 int Status;
4911
4912 //
4913 // Initialize locals
4914 //
4915
4916 ChildPid = -1;
4917 PtmFd = -1;
4918 PtsFd = -1;
4919
4920 LXT_SYNCHRONIZATION_POINT_START();
4921 LxtCheckErrno(ChildPid = ForkPty(&PtmFd, &PtsFd));
4922 if (ChildPid == 0)
4923 {
4924
4925 //
4926 // Enable packet mode.
4927 //
4928
4929 PacketMode = 1;
4930 LxtCheckErrno(ioctl(PtmFd, TIOCPKT, &PacketMode));
4931
4932 //
4933 // Read from master.
4934 //
4935
4936 LxtLogInfo("Reading from master");
4937 LxtCheckErrno(BytesReadWrite = read(PtmFd, ReadBuffer, sizeof(ReadBuffer)));
4938 LxtCheckFnResults("read", BytesReadWrite, 1);
4939 LxtCheckEqual(ReadBuffer[0], TIOCPKT_FLUSHREAD, "%hhd");
4940 }
4941 else
4942 {
4943
4944 //
4945 // Give child a chance to wait in the read system call.
4946 //
4947
4948 sleep(1);
4949
4950 //
4951 // Flush subordinate read queue.
4952 //
4953
4954 LxtCheckErrno(tcflush(PtsFd, TCIFLUSH));
4955 }
4956
4957 ErrorExit:
4958 if ((ChildPid != 0) && (PtmFd != -1))
4959 {
4960 close(PtmFd);
4961 }
4962
4963 if ((ChildPid != 0) && (PtsFd != -1))
4964 {
4965 close(PtsFd);
4966 }
4967
4968 LXT_SYNCHRONIZATION_POINT_END();
4969 return Result;
4970 }
4971
4972 int PtPacketFlushWrite1(PLXT_ARGS Args)
4973
4974 /*++
4975
4976 Routine Description:
4977
4978 This routine flushes the subordinate write queue.
4979
4980
4981 Arguments:
4982
4983 Args - Supplies the command line arguments.
4984
4985 Return Value:
4986
4987 Returns 0 on success, -1 on failure.
4988
4989 --*/
4990
4991 {
4992
4993 int BytesReadWrite;
4994 int PacketMode;
4995 int PtmFd;
4996 int PtsFd;
4997 char ReadBuffer[1];
4998 fd_set ReadFds;
4999 int Result;
5000 int SerialNumber;
Showing first 5,000 of 9,336 lines. View raw