]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/lldb/source/Host/common/File.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / lldb / source / Host / common / File.cpp
1 //===-- File.cpp ------------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Host/File.h"
11
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <limits.h>
15 #include <stdarg.h>
16 #include <stdio.h>
17 #include <sys/stat.h>
18
19 #ifdef _WIN32
20 #include "lldb/Host/windows/windows.h"
21 #else
22 #include <sys/ioctl.h>
23 #endif
24
25 #include "lldb/Core/DataBufferHeap.h"
26 #include "lldb/Core/Error.h"
27 #include "lldb/Host/Config.h"
28 #include "lldb/Host/FileSpec.h"
29
30 using namespace lldb;
31 using namespace lldb_private;
32
33 static const char *
34 GetStreamOpenModeFromOptions (uint32_t options)
35 {
36     if (options & File::eOpenOptionAppend)
37     {
38         if (options & File::eOpenOptionRead)
39         {
40             if (options & File::eOpenOptionCanCreateNewOnly)
41                 return "a+x";
42             else
43                 return "a+";
44         }
45         else if (options & File::eOpenOptionWrite)
46         {
47             if (options & File::eOpenOptionCanCreateNewOnly)
48                 return "ax";
49             else
50                 return "a";
51         }
52     }
53     else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite)
54     {
55         if (options & File::eOpenOptionCanCreate)
56         {
57             if (options & File::eOpenOptionCanCreateNewOnly)
58                 return "w+x";
59             else
60                 return "w+";
61         }
62         else
63             return "r+";
64     }
65     else if (options & File::eOpenOptionRead)
66     {
67         return "r";
68     }
69     else if (options & File::eOpenOptionWrite)
70     {
71         return "w";
72     }
73     return NULL;
74 }
75
76 int File::kInvalidDescriptor = -1;
77 FILE * File::kInvalidStream = NULL;
78
79 File::File(const char *path, uint32_t options, uint32_t permissions) :
80     m_descriptor (kInvalidDescriptor),
81     m_stream (kInvalidStream),
82     m_options (),
83     m_own_stream (false),
84     m_own_descriptor (false),
85     m_is_interactive (eLazyBoolCalculate),
86     m_is_real_terminal (eLazyBoolCalculate)
87 {
88     Open (path, options, permissions);
89 }
90
91 File::File (const FileSpec& filespec,
92             uint32_t options,
93             uint32_t permissions) :
94     m_descriptor (kInvalidDescriptor),
95     m_stream (kInvalidStream),
96     m_options (0),
97     m_own_stream (false),
98     m_own_descriptor (false),
99     m_is_interactive (eLazyBoolCalculate),
100     m_is_real_terminal (eLazyBoolCalculate)
101
102 {
103     if (filespec)
104     {
105         Open (filespec.GetPath().c_str(), options, permissions);
106     }
107 }
108
109 File::File (const File &rhs) :
110     m_descriptor (kInvalidDescriptor),
111     m_stream (kInvalidStream),
112     m_options (0),
113     m_own_stream (false),
114     m_own_descriptor (false),
115     m_is_interactive (eLazyBoolCalculate),
116     m_is_real_terminal (eLazyBoolCalculate)
117 {
118     Duplicate (rhs);
119 }
120     
121
122 File &
123 File::operator = (const File &rhs)
124 {
125     if (this != &rhs)
126         Duplicate (rhs);        
127     return *this;
128 }
129
130 File::~File()
131 {
132     Close ();
133 }
134
135
136 int
137 File::GetDescriptor() const
138 {
139     if (DescriptorIsValid())
140         return m_descriptor;
141
142     // Don't open the file descriptor if we don't need to, just get it from the
143     // stream if we have one.
144     if (StreamIsValid())
145         return fileno (m_stream);
146
147     // Invalid descriptor and invalid stream, return invalid descriptor.
148     return kInvalidDescriptor;
149 }
150
151 void
152 File::SetDescriptor (int fd, bool transfer_ownership)
153 {
154     if (IsValid())
155         Close();
156     m_descriptor = fd;
157     m_own_descriptor = transfer_ownership;
158 }
159
160
161 FILE *
162 File::GetStream ()
163 {
164     if (!StreamIsValid())
165     {
166         if (DescriptorIsValid())
167         {
168             const char *mode = GetStreamOpenModeFromOptions (m_options);
169             if (mode)
170             {
171                 if (!m_own_descriptor)
172                 {
173                     // We must duplicate the file descriptor if we don't own it because
174                     // when you call fdopen, the stream will own the fd
175 #ifdef _WIN32
176                     m_descriptor = ::_dup(GetDescriptor());
177 #else
178                     m_descriptor = ::fcntl(GetDescriptor(), F_DUPFD);
179 #endif
180                     m_own_descriptor = true;
181                 }
182
183                 do
184                 {
185                     m_stream = ::fdopen (m_descriptor, mode);
186                 } while (m_stream == NULL && errno == EINTR);
187
188                 // If we got a stream, then we own the stream and should no
189                 // longer own the descriptor because fclose() will close it for us
190
191                 if (m_stream)
192                 {
193                     m_own_stream = true;
194                     m_own_descriptor = false;
195                 }
196             }
197         }
198     }
199     return m_stream;
200 }
201
202
203 void
204 File::SetStream (FILE *fh, bool transfer_ownership)
205 {
206     if (IsValid())
207         Close();
208     m_stream = fh;
209     m_own_stream = transfer_ownership;
210 }
211
212 Error
213 File::Duplicate (const File &rhs)
214 {
215     Error error;
216     if (IsValid ())
217         Close();
218
219     if (rhs.DescriptorIsValid())
220     {
221 #ifdef _WIN32
222         m_descriptor = ::_dup(rhs.GetDescriptor());
223 #else
224         m_descriptor = ::fcntl(rhs.GetDescriptor(), F_DUPFD);
225 #endif
226         if (!DescriptorIsValid())
227             error.SetErrorToErrno();
228         else
229         {
230             m_options = rhs.m_options;
231             m_own_descriptor = true;
232         }
233     }
234     else
235     {
236         error.SetErrorString ("invalid file to duplicate");
237     }
238     return error;
239 }
240
241 Error
242 File::Open (const char *path, uint32_t options, uint32_t permissions)
243 {
244     Error error;
245     if (IsValid())
246         Close ();
247
248     int oflag = 0;
249     const bool read = options & eOpenOptionRead;
250     const bool write = options & eOpenOptionWrite;
251     if (write)
252     {
253         if (read)
254             oflag |= O_RDWR;
255         else
256             oflag |= O_WRONLY;
257         
258         if (options & eOpenOptionAppend)
259             oflag |= O_APPEND;
260
261         if (options & eOpenOptionTruncate)
262             oflag |= O_TRUNC;
263
264         if (options & eOpenOptionCanCreate)
265             oflag |= O_CREAT;
266         
267         if (options & eOpenOptionCanCreateNewOnly)
268             oflag |= O_CREAT | O_EXCL;
269     }
270     else if (read)
271     {
272         oflag |= O_RDONLY;
273
274 #ifndef _WIN32
275         if (options & eOpenoptionDontFollowSymlinks)
276             oflag |= O_NOFOLLOW;
277 #endif
278     }
279     
280 #ifndef _WIN32
281     if (options & eOpenOptionNonBlocking)
282         oflag |= O_NONBLOCK;
283 #else
284     oflag |= O_BINARY;
285 #endif
286
287     mode_t mode = 0;
288     if (oflag & O_CREAT)
289     {
290         if (permissions & lldb::eFilePermissionsUserRead)     mode |= S_IRUSR;
291         if (permissions & lldb::eFilePermissionsUserWrite)    mode |= S_IWUSR;
292         if (permissions & lldb::eFilePermissionsUserExecute)  mode |= S_IXUSR;
293         if (permissions & lldb::eFilePermissionsGroupRead)    mode |= S_IRGRP;
294         if (permissions & lldb::eFilePermissionsGroupWrite)   mode |= S_IWGRP;
295         if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP;
296         if (permissions & lldb::eFilePermissionsWorldRead)    mode |= S_IROTH;
297         if (permissions & lldb::eFilePermissionsWorldWrite)   mode |= S_IWOTH;
298         if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH;
299     }
300
301     do
302     {
303         m_descriptor = ::open(path, oflag, mode);
304     } while (m_descriptor < 0 && errno == EINTR);
305
306     if (!DescriptorIsValid())
307         error.SetErrorToErrno();
308     else
309     {
310         m_own_descriptor = true;
311         m_options = options;
312     }
313     
314     return error;
315 }
316
317 uint32_t
318 File::GetPermissions (const char *path, Error &error)
319 {
320     if (path && path[0])
321     {
322         struct stat file_stats;
323         if (::stat (path, &file_stats) == -1)
324             error.SetErrorToErrno();
325         else
326         {
327             error.Clear();
328             return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
329         }
330     }
331     else
332     {
333         if (path)
334             error.SetErrorString ("invalid path");
335         else
336             error.SetErrorString ("empty path");        
337     }
338     return 0;
339 }
340
341 uint32_t
342 File::GetPermissions(Error &error) const
343 {
344     int fd = GetDescriptor();
345     if (fd != kInvalidDescriptor)
346     {
347         struct stat file_stats;
348         if (::fstat (fd, &file_stats) == -1)
349             error.SetErrorToErrno();
350         else
351         {
352             error.Clear();
353             return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
354         }
355     }
356     else
357     {
358         error.SetErrorString ("invalid file descriptor");
359     }
360     return 0;
361 }
362
363
364 Error
365 File::Close ()
366 {
367     Error error;
368     if (StreamIsValid() && m_own_stream)
369     {
370         if (::fclose (m_stream) == EOF)
371             error.SetErrorToErrno();
372     }
373     
374     if (DescriptorIsValid() && m_own_descriptor)
375     {
376         if (::close (m_descriptor) != 0)
377             error.SetErrorToErrno();
378     }
379     m_descriptor = kInvalidDescriptor;
380     m_stream = kInvalidStream;
381     m_options = 0;
382     m_own_stream = false;
383     m_own_descriptor = false;
384     m_is_interactive = eLazyBoolCalculate;
385     m_is_real_terminal = eLazyBoolCalculate;
386     return error;
387 }
388
389
390 Error
391 File::GetFileSpec (FileSpec &file_spec) const
392 {
393     Error error;
394 #ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED
395     if (IsValid ())
396     {
397         char path[PATH_MAX];
398         if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
399             error.SetErrorToErrno();
400         else
401             file_spec.SetFile (path, false);
402     }
403     else 
404     {
405         error.SetErrorString("invalid file handle");
406     }
407 #elif defined(__linux__)
408     char proc[64];
409     char path[PATH_MAX];
410     if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
411         error.SetErrorString ("cannot resolve file descriptor");
412     else
413     {
414         ssize_t len;
415         if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
416             error.SetErrorToErrno();
417         else
418         {
419             path[len] = '\0';
420             file_spec.SetFile (path, false);
421         }
422     }
423 #else
424     error.SetErrorString ("File::GetFileSpec is not supported on this platform");
425 #endif
426
427     if (error.Fail())
428         file_spec.Clear();
429     return error;
430 }
431
432 off_t
433 File::SeekFromStart (off_t offset, Error *error_ptr)
434 {
435     off_t result = 0;
436     if (DescriptorIsValid())
437     {
438         result = ::lseek (m_descriptor, offset, SEEK_SET);
439
440         if (error_ptr)
441         {
442             if (result == -1)
443                 error_ptr->SetErrorToErrno();
444             else
445                 error_ptr->Clear();
446         }
447     }
448     else if (StreamIsValid ())
449     {
450         result = ::fseek(m_stream, offset, SEEK_SET);
451         
452         if (error_ptr)
453         {
454             if (result == -1)
455                 error_ptr->SetErrorToErrno();
456             else
457                 error_ptr->Clear();
458         }
459     }
460     else if (error_ptr)
461     {
462         error_ptr->SetErrorString("invalid file handle");
463     }
464     return result;
465 }
466
467 off_t
468 File::SeekFromCurrent (off_t offset,  Error *error_ptr)
469 {
470     off_t result = -1;
471     if (DescriptorIsValid())
472     {
473         result = ::lseek (m_descriptor, offset, SEEK_CUR);
474         
475         if (error_ptr)
476         {
477             if (result == -1)
478                 error_ptr->SetErrorToErrno();
479             else
480                 error_ptr->Clear();
481         }
482     }
483     else if (StreamIsValid ())
484     {
485         result = ::fseek(m_stream, offset, SEEK_CUR);
486         
487         if (error_ptr)
488         {
489             if (result == -1)
490                 error_ptr->SetErrorToErrno();
491             else
492                 error_ptr->Clear();
493         }
494     }
495     else if (error_ptr)
496     {
497         error_ptr->SetErrorString("invalid file handle");
498     }
499     return result;
500 }
501
502 off_t
503 File::SeekFromEnd (off_t offset, Error *error_ptr)
504 {
505     off_t result = -1;
506     if (DescriptorIsValid())
507     {
508         result = ::lseek (m_descriptor, offset, SEEK_END);
509         
510         if (error_ptr)
511         {
512             if (result == -1)
513                 error_ptr->SetErrorToErrno();
514             else
515                 error_ptr->Clear();
516         }
517     }
518     else if (StreamIsValid ())
519     {
520         result = ::fseek(m_stream, offset, SEEK_END);
521         
522         if (error_ptr)
523         {
524             if (result == -1)
525                 error_ptr->SetErrorToErrno();
526             else
527                 error_ptr->Clear();
528         }
529     }
530     else if (error_ptr)
531     {
532         error_ptr->SetErrorString("invalid file handle");
533     }
534     return result;
535 }
536
537 Error
538 File::Flush ()
539 {
540     Error error;
541     if (StreamIsValid())
542     {
543         int err = 0;
544         do
545         {
546             err = ::fflush (m_stream);
547         } while (err == EOF && errno == EINTR);
548         
549         if (err == EOF)
550             error.SetErrorToErrno();
551     }
552     else if (!DescriptorIsValid())
553     {
554         error.SetErrorString("invalid file handle");
555     }
556     return error;
557 }
558
559
560 Error
561 File::Sync ()
562 {
563     Error error;
564     if (DescriptorIsValid())
565     {
566 #ifdef _WIN32
567         int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
568         if (err == 0)
569             error.SetErrorToGenericError();
570 #else
571         int err = 0;
572         do
573         {
574             err = ::fsync (m_descriptor);
575         } while (err == -1 && errno == EINTR);
576         
577         if (err == -1)
578             error.SetErrorToErrno();
579 #endif
580     }
581     else 
582     {
583         error.SetErrorString("invalid file handle");
584     }
585     return error;
586 }
587
588 Error
589 File::Read (void *buf, size_t &num_bytes)
590 {
591     Error error;
592     ssize_t bytes_read = -1;
593     if (DescriptorIsValid())
594     {
595         do
596         {
597             bytes_read = ::read (m_descriptor, buf, num_bytes);
598         } while (bytes_read < 0 && errno == EINTR);
599
600         if (bytes_read == -1)
601         {
602             error.SetErrorToErrno();
603             num_bytes = 0;
604         }
605         else
606             num_bytes = bytes_read;
607     }
608     else if (StreamIsValid())
609     {
610         bytes_read = ::fread (buf, 1, num_bytes, m_stream);
611
612         if (bytes_read == 0)
613         {
614             if (::feof(m_stream))
615                 error.SetErrorString ("feof");
616             else if (::ferror (m_stream))
617                 error.SetErrorString ("ferror");
618             num_bytes = 0;
619         }
620         else
621             num_bytes = bytes_read;
622     }
623     else 
624     {
625         num_bytes = 0;
626         error.SetErrorString("invalid file handle");
627     }
628     return error;
629 }
630           
631 Error
632 File::Write (const void *buf, size_t &num_bytes)
633 {
634     Error error;
635     ssize_t bytes_written = -1;
636     if (DescriptorIsValid())
637     {
638         do
639         {
640             bytes_written = ::write (m_descriptor, buf, num_bytes);
641         } while (bytes_written < 0 && errno == EINTR);
642
643         if (bytes_written == -1)
644         {
645             error.SetErrorToErrno();
646             num_bytes = 0;
647         }
648         else
649             num_bytes = bytes_written;
650     }
651     else if (StreamIsValid())
652     {
653         bytes_written = ::fwrite (buf, 1, num_bytes, m_stream);
654
655         if (bytes_written == 0)
656         {
657             if (::feof(m_stream))
658                 error.SetErrorString ("feof");
659             else if (::ferror (m_stream))
660                 error.SetErrorString ("ferror");
661             num_bytes = 0;
662         }
663         else
664             num_bytes = bytes_written;
665         
666     }
667     else 
668     {
669         num_bytes = 0;
670         error.SetErrorString("invalid file handle");
671     }
672     return error;
673 }
674
675
676 Error
677 File::Read (void *buf, size_t &num_bytes, off_t &offset)
678 {
679 #ifndef _WIN32
680     Error error;
681     int fd = GetDescriptor();
682     if (fd != kInvalidDescriptor)
683     {
684         ssize_t bytes_read = -1;
685         do
686         {
687             bytes_read = ::pread (fd, buf, num_bytes, offset);
688         } while (bytes_read < 0 && errno == EINTR);
689
690         if (bytes_read < 0)
691         {
692             num_bytes = 0;
693             error.SetErrorToErrno();
694         }
695         else
696         {
697             offset += bytes_read;
698             num_bytes = bytes_read;
699         }
700     }
701     else 
702     {
703         num_bytes = 0;
704         error.SetErrorString("invalid file handle");
705     }
706     return error;
707 #else
708     long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
709     SeekFromStart(offset);
710     Error error = Read(buf, num_bytes);
711     if (!error.Fail())
712         SeekFromStart(cur);
713     return error;
714 #endif
715 }
716
717 Error
718 File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp)
719 {
720     Error error;
721     
722     if (num_bytes > 0)
723     {
724         int fd = GetDescriptor();
725         if (fd != kInvalidDescriptor)
726         {
727             struct stat file_stats;
728             if (::fstat (fd, &file_stats) == 0)
729             {
730                 if (file_stats.st_size > offset)
731                 {
732                     const size_t bytes_left = file_stats.st_size - offset;
733                     if (num_bytes > bytes_left)
734                         num_bytes = bytes_left;
735                         
736                     std::unique_ptr<DataBufferHeap> data_heap_ap;
737                     data_heap_ap.reset(new DataBufferHeap(num_bytes + (null_terminate ? 1 : 0), '\0'));
738                         
739                     if (data_heap_ap.get())
740                     {
741                         error = Read (data_heap_ap->GetBytes(), num_bytes, offset);
742                         if (error.Success())
743                         {
744                             // Make sure we read exactly what we asked for and if we got
745                             // less, adjust the array
746                             if (num_bytes < data_heap_ap->GetByteSize())
747                                 data_heap_ap->SetByteSize(num_bytes);
748                             data_buffer_sp.reset(data_heap_ap.release());
749                             return error;
750                         }
751                     }
752                 }
753                 else 
754                     error.SetErrorString("file is empty");
755             }
756             else
757                 error.SetErrorToErrno();
758         }
759         else 
760             error.SetErrorString("invalid file handle");
761     }
762     else
763         error.SetErrorString("invalid file handle");
764
765     num_bytes = 0;
766     data_buffer_sp.reset();
767     return error;
768 }
769
770 Error
771 File::Write (const void *buf, size_t &num_bytes, off_t &offset)
772 {
773     Error error;
774     int fd = GetDescriptor();
775     if (fd != kInvalidDescriptor)
776     {
777 #ifndef _WIN32
778         ssize_t bytes_written = -1;
779         do
780         {
781             bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset);
782         } while (bytes_written < 0 && errno == EINTR);
783
784         if (bytes_written < 0)
785         {
786             num_bytes = 0;
787             error.SetErrorToErrno();
788         }
789         else
790         {
791             offset += bytes_written;
792             num_bytes = bytes_written;
793         }
794 #else
795         long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
796         error = Write(buf, num_bytes);
797         long after = ::lseek(m_descriptor, 0, SEEK_CUR);
798
799         if (!error.Fail())
800             SeekFromStart(cur);
801
802         ssize_t bytes_written = after - cur;
803         offset = after;
804 #endif
805     }
806     else 
807     {
808         num_bytes = 0;
809         error.SetErrorString("invalid file handle");
810     }
811     return error;
812 }
813
814 //------------------------------------------------------------------
815 // Print some formatted output to the stream.
816 //------------------------------------------------------------------
817 size_t
818 File::Printf (const char *format, ...)
819 {
820     va_list args;
821     va_start (args, format);
822     size_t result = PrintfVarArg (format, args);
823     va_end (args);
824     return result;
825 }
826
827 //------------------------------------------------------------------
828 // Print some formatted output to the stream.
829 //------------------------------------------------------------------
830 size_t
831 File::PrintfVarArg (const char *format, va_list args)
832 {
833     size_t result = 0;
834     if (DescriptorIsValid())
835     {
836         char *s = NULL;
837         result = vasprintf(&s, format, args);
838         if (s != NULL)
839         {
840             if (result > 0)
841             {
842                 size_t s_len = result;
843                 Write (s, s_len);
844                 result = s_len;
845             }
846             free (s);
847         }
848     }
849     else if (StreamIsValid())
850     {
851         result = ::vfprintf (m_stream, format, args);
852     }
853     return result;
854 }
855
856 mode_t
857 File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options)
858 {
859     mode_t mode = 0;
860     if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
861         mode |= O_RDWR;
862     else if (open_options & eOpenOptionWrite)
863         mode |= O_WRONLY;
864     
865     if (open_options & eOpenOptionAppend)
866         mode |= O_APPEND;
867
868     if (open_options & eOpenOptionTruncate)
869         mode |= O_TRUNC;
870
871     if (open_options & eOpenOptionNonBlocking)
872         mode |= O_NONBLOCK;
873
874     if (open_options & eOpenOptionCanCreateNewOnly)
875         mode |= O_CREAT | O_EXCL;
876     else if (open_options & eOpenOptionCanCreate)
877         mode |= O_CREAT;
878
879     return mode;
880 }
881
882 void
883 File::CalculateInteractiveAndTerminal ()
884 {
885     const int fd = GetDescriptor();
886     if (fd >= 0)
887     {
888         m_is_interactive = eLazyBoolNo;
889         m_is_real_terminal = eLazyBoolNo;
890 #ifndef _MSC_VER
891         if (isatty(fd))
892         {
893             m_is_interactive = eLazyBoolYes;
894             struct winsize window_size;
895             if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0)
896             {
897                 if (window_size.ws_col > 0)
898                     m_is_real_terminal = eLazyBoolYes;
899             }
900         }
901 #endif
902     }
903 }
904
905 bool
906 File::GetIsInteractive ()
907 {
908     if (m_is_interactive == eLazyBoolCalculate)
909         CalculateInteractiveAndTerminal ();
910     return m_is_interactive == eLazyBoolYes;
911 }
912
913 bool
914 File::GetIsRealTerminal ()
915 {
916     if (m_is_real_terminal == eLazyBoolCalculate)
917         CalculateInteractiveAndTerminal();
918     return m_is_real_terminal == eLazyBoolYes;
919 }
920