printer.pp 6.4 KB

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