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