printer.pp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Michael Van Canneyt,
  4. member of the Free Pascal development team.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. { Change Log
  12. ----------
  13. Started by Michael Van Canneyt, 1996
  14. ([email protected])
  15. Current version is 0.9
  16. Date Version Who Comments
  17. 1999-2000 by 0.8 Michael Initial implementation
  18. 11/97 0.9 Peter Vreman <[email protected]>
  19. Unit now depends on the
  20. linux unit only.
  21. Cleaned up code.
  22. ---------------------------------------------------------------------}
  23. {$IFNDEF FPC_DOTTEDUNITS}
  24. Unit printer;
  25. {$ENDIF FPC_DOTTEDUNITS}
  26. Interface
  27. {.$DEFINE PRINTERDEBUG}
  28. {$I printerh.inc}
  29. Procedure AssignLst ( Var F : text; ToFile : string);
  30. {
  31. Assigns to F a printing device. ToFile is a string with the following form:
  32. '|filename options' : This sets up a pipe with the program filename,
  33. with the given options
  34. 'filename' : Prints to file filename. Filename can contain the string 'PID'
  35. (No Quotes), which will be replaced by the PID of your program.
  36. When closing lst, the file will be sent to lpr and deleted.
  37. (lpr should be in PATH)
  38. 'filename|' Idem as previous, only the file is NOT sent to lpr, nor is it
  39. deleted.
  40. (useful for opening /dev/printer or for later printing)
  41. Lst is set up using '/tmp/PID.lst'. You can change this behaviour at
  42. compile time, setting the DefFile constant.
  43. }
  44. Implementation
  45. {$IFDEF FPC_DOTTEDUNITS}
  46. Uses UnixApi.Unix,UnixApi.Base,System.Strings;
  47. {$ELSE FPC_DOTTEDUNITS}
  48. Uses Unix,BaseUnix,Strings;
  49. {$ENDIF FPC_DOTTEDUNITS}
  50. {$I printer.inc}
  51. {
  52. include definition of textrec
  53. }
  54. Const
  55. P_TOF = 1; { Print to file }
  56. P_TOFNP = 2; { Print to File, don't spool }
  57. P_TOP = 3; { Print to Pipe }
  58. Var
  59. Lpr : String[255]; { Contains path to lpr binary, including null AnsiChar }
  60. Procedure PrintAndDelete (const f: RawByteString);
  61. var
  62. i: pid_t;
  63. p,pp : PPAnsiChar;
  64. begin
  65. if lpr='' then
  66. exit;
  67. i:=fpFork;
  68. if i<0 then
  69. exit; { No printing was done. We leave the file where it is.}
  70. if i=0 then
  71. begin
  72. { We're in the child }
  73. getmem(p,12);
  74. if p=nil then
  75. halt(127);
  76. pp:=p;
  77. pp^:=@lpr[1];
  78. inc(pp);
  79. pp^:=@f[1];
  80. inc(pp);
  81. pp^:=nil;
  82. fpExecve(lpr,p,envp);
  83. { In trouble here ! }
  84. fpexit(127)
  85. end
  86. else
  87. begin
  88. { We're in the parent. }
  89. if waitprocess(i)<>0 then
  90. exit;
  91. { Erase the file }
  92. fpUnlink(f);
  93. end;
  94. end;
  95. Procedure OpenLstPipe ( Var F : Text);
  96. var
  97. r: rawbytestring;
  98. begin
  99. {$ifdef FPC_ANSI_TEXTFILEREC}
  100. { encoding is already correct }
  101. r:=textrec(f).name;
  102. SetCodePage(r,DefaultFileSystemCodePage,false);
  103. {$else}
  104. r:=ToSingleByteFileSystemEncodedFileName(textrec(f).name);
  105. {$endif}
  106. POpen (f,r,'W');
  107. end;
  108. Procedure OpenLstFile ( Var F : Text);
  109. var
  110. i : cint;
  111. r: rawbytestring;
  112. begin
  113. {$IFDEF PRINTERDEBUG}
  114. writeln ('Printer : In OpenLstFile');
  115. {$ENDIF}
  116. If textrec(f).mode <> fmoutput then
  117. exit;
  118. textrec(f).userdata[15]:=0; { set Zero length flag }
  119. {$ifdef FPC_ANSI_TEXTFILEREC}
  120. { encoding is already correct }
  121. r:=textrec(f).name;
  122. SetCodePage(r,DefaultFileSystemCodePage,false);
  123. {$else}
  124. r:=ToSingleByteFileSystemEncodedFileName(textrec(f).name);
  125. {$endif}
  126. repeat
  127. i:=fpOpen(pansichar(r),(Open_WrOnly or Open_Creat), 438);
  128. until (i<>-1) or (fpgeterrno<>ESysEINTR);
  129. if i<0 then
  130. textrec(f).mode:=fmclosed
  131. else
  132. textrec(f).handle:=i;
  133. end;
  134. Procedure CloseLstFile ( Var F : Text);
  135. var
  136. res: cint;
  137. begin
  138. {$IFDEF PRINTERDEBUG}
  139. writeln ('Printer : In CloseLstFile');
  140. {$ENDIF}
  141. repeat
  142. res:=fpclose (textrec(f).handle);
  143. until (res<>-1) or (fpgeterrno<>ESysEINTR);
  144. { In case length is zero, don't print : lpr would give an error }
  145. if (textrec(f).userdata[15]=0) and (textrec(f).userdata[16]=P_TOF) then
  146. begin
  147. {$IFDEF FPC_ANSI_TEXTFILEREC}
  148. fpUnlink(pansichar(@textrec(f).name));
  149. {$ELSE}
  150. fpUnlink(ToSingleByteFileSystemEncodedFileName(textrec(f).name));
  151. {$ENDIF}
  152. exit
  153. end;
  154. { Non empty : needs printing ? }
  155. if (textrec(f).userdata[16]=P_TOF) then
  156. {$IFDEF FPC_ANSI_TEXTFILEREC}
  157. PrintAndDelete (textrec(f).name);
  158. {$ELSE}
  159. PrintAndDelete (ToSingleByteFileSystemEncodedFileName(textrec(f).name));
  160. {$ENDIF}
  161. textrec(f).mode:=fmclosed
  162. end;
  163. Procedure InOutLstFile ( Var F : text);
  164. var
  165. res: cint;
  166. begin
  167. {$IFDEF PRINTERDEBUG}
  168. writeln ('Printer : In InOutLstFile');
  169. {$ENDIF}
  170. If textrec(f).mode<>fmoutput then
  171. exit;
  172. if textrec(f).bufpos<>0 then
  173. textrec(f).userdata[15]:=1; { Set it is not empty. Important when closing !!}
  174. repeat
  175. res:=fpwrite(textrec(f).handle,textrec(f).bufptr^,textrec(f).bufpos);
  176. until (res<>-1) or (fpgeterrno<>ESysEINTR);
  177. textrec(f).bufpos:=0;
  178. end;
  179. function SubstPidInName (const S: rawbytestring): rawbytestring;
  180. var
  181. i : longint;
  182. temp : string[8];
  183. begin
  184. i:=pos('PID',s);
  185. if i=0 then
  186. SubstPidInName := S
  187. else
  188. begin
  189. Str (fpGetPid, Temp);
  190. SubstPidInName := Copy (S, 1, Pred (I)) + Temp +
  191. Copy (S, I + 3, Length (S) - I - 2);
  192. {$IFDEF PRINTERDEBUG}
  193. writeln ('Print : Filename became : ', Result);
  194. {$ENDIF}
  195. end;
  196. end;
  197. Procedure AssignLst ( Var F : text; ToFile : string);
  198. begin
  199. {$IFDEF PRINTERDEBUG}
  200. writeln ('Printer : In AssignLst');
  201. {$ENDIF}
  202. If ToFile='' then
  203. exit;
  204. textrec(f).bufptr:=@textrec(f).buffer;
  205. textrec(f).bufsize:=128;
  206. ToFile := SubstPidInName (ToFile);
  207. if ToFile[1]='|' then
  208. begin
  209. Assign(f,Copy(ToFile,2,255));
  210. textrec(f).userdata[16]:=P_TOP;
  211. textrec(f).OpenFunc:=@OpenLstPipe;
  212. end
  213. else
  214. begin
  215. if Tofile[Length(ToFile)]='|' then
  216. begin
  217. Assign(f,Copy(ToFile,1,length(Tofile)-1));
  218. textrec(f).userdata[16]:=P_TOFNP;
  219. end
  220. else
  221. begin
  222. Assign(f,ToFile);
  223. textrec(f).userdata[16]:=P_TOF;
  224. end;
  225. textrec(f).OpenFunc:=@OpenLstFile;
  226. textrec(f).CloseFunc:=@CloseLstFile;
  227. textrec(f).InoutFunc:=@InoutLstFile;
  228. textrec(f).FlushFunc:=@InoutLstFile;
  229. end;
  230. end;
  231. begin
  232. InitPrinter (SubstPidInName ('/tmp/PID.lst'));
  233. SetPrinterExit;
  234. Lpr := '/usr/bin/lpr';
  235. end.