linuxvcs.pp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. unit linuxvcs;
  2. {*****************************************************************************}
  3. interface
  4. {*****************************************************************************}
  5. const vcs_device:shortint=-1;
  6. function try_grab_vcsa:boolean;
  7. {*****************************************************************************}
  8. implementation
  9. {*****************************************************************************}
  10. uses baseunix,strings;
  11. function try_grab_vcsa_in_path(path:Pchar;len:cardinal):boolean;
  12. const grab_vcsa='/grab_vcsa';
  13. grab_vcsa_s:array[1..length(grab_vcsa)] of char=grab_vcsa;
  14. var p:Pchar;
  15. child:Tpid;
  16. status:cint;
  17. pstat:stat;
  18. begin
  19. getmem(p,len+length(grab_vcsa)+1);
  20. move(path^,p^,len);
  21. move(grab_vcsa_s,(p+len)^,length(grab_vcsa));
  22. (p+len+length(grab_vcsa))^:=#0;
  23. {Check if file exists.}
  24. if fpstat(p,pstat)<>0 then
  25. begin
  26. try_grab_vcsa_in_path:=false;
  27. exit;
  28. end;
  29. child:=fpfork;
  30. if child=0 then
  31. begin
  32. fpexecve(p,nil,nil);
  33. halt(255); {fpexec must have failed...}
  34. end;
  35. fpwaitpid(child,status,0);
  36. try_grab_vcsa_in_path:=status=0; {Return true if success.}
  37. freemem(p);
  38. end;
  39. function try_grab_vcsa:boolean;
  40. {If we cannot open /dev/vcsa0-31 it usually because we do not have
  41. permission. At login the owner of the tty you login is set to yourself.
  42. This is not done for vcsa, which is kinda strange as vcsa is revoke from
  43. you when you log out. We try to call a setuid root helper which chowns
  44. the vcsa device so we can get access to the screen buffer...}
  45. var path,p:Pchar;
  46. begin
  47. try_grab_vcsa:=false;
  48. path:=fpgetenv('PATH');
  49. if path=nil then
  50. exit;
  51. p:=strscan(path,':');
  52. while p<>nil do
  53. begin
  54. if try_grab_vcsa_in_path(path,p-path) then
  55. begin
  56. try_grab_vcsa:=true;
  57. exit;
  58. end;
  59. path:=p+1;
  60. p:=strscan(path,':');
  61. end;
  62. if try_grab_vcsa_in_path(path,strlen(path)) then
  63. exit;
  64. end;
  65. procedure detect_linuxvcs;
  66. var f:text;
  67. f_open : boolean;
  68. c,pc:char;
  69. pid,cpid,dummy:longint;
  70. device:dword;
  71. s:string[15];
  72. begin
  73. {Extremely aggressive VCSA detection. Works even through Midnight
  74. Commander. Idea from the C++ Turbo Vision project, credits go
  75. to Martynas Kunigelis <[email protected]>.}
  76. pid:=fpgetpid;
  77. f_open:=false;
  78. {$push}
  79. {$I-}
  80. {$R-}
  81. repeat
  82. cpid:=pid;
  83. str(pid,s);
  84. assign(f,'/proc/'+s+'/stat');
  85. reset(f);
  86. if ioresult<>0 then
  87. exit;
  88. f_open:=true;
  89. { from here we can discard I/O errors, as long as we avoid
  90. infinite loops }
  91. { first number is pid }
  92. dummy:=0;
  93. read(f,dummy);
  94. if dummy<>pid then
  95. exit;
  96. { after comes the name of the binary within (), look for closing brace followed by space }
  97. c:=#0;
  98. repeat
  99. pc:=c;
  100. read(f,c);
  101. if ioresult<>0 then
  102. break;
  103. until (pc=')') and (c=' ');
  104. { now comes the state letter }
  105. repeat
  106. read(f,c);
  107. if ioresult<>0 then
  108. break;
  109. until c=' ';
  110. { parent pid }
  111. pid:=-1;
  112. read(f,pid);
  113. { process group }
  114. read(f,dummy);
  115. { session }
  116. read(f,dummy);
  117. { device number }
  118. device:=0;
  119. read(f,device);
  120. close(f);
  121. f_open:=false;
  122. if (device and $ffffffc0)=$00000400 then {/dev/tty*}
  123. begin
  124. vcs_device:=device and $3f;
  125. break;
  126. end;
  127. until (device=0) {Not attached to a terminal, i.e. an xterm.}
  128. or (pid=-1)
  129. or (cpid=pid);
  130. if f_open then
  131. close(f);
  132. {$pop}
  133. end;
  134. begin
  135. {Put in procedure because there are quite a bit of variables which are made
  136. temporary this way.}
  137. detect_linuxvcs;
  138. end.