123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2000 by Michael Van Canneyt,
- member of the Free Pascal development team.
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- { Change Log
- ----------
- Started by Michael Van Canneyt, 1996
- ([email protected])
- Current version is 0.9
- Date Version Who Comments
- 1999-2000 by 0.8 Michael Initial implementation
- 11/97 0.9 Peter Vreman <[email protected]>
- Unit now depends on the
- linux unit only.
- Cleaned up code.
- ---------------------------------------------------------------------}
- Unit printer;
- Interface
- {.$DEFINE PRINTERDEBUG}
- {$I printerh.inc}
- Procedure AssignLst ( Var F : text; ToFile : string);
- {
- Assigns to F a printing device. ToFile is a string with the following form:
- '|filename options' : This sets up a pipe with the program filename,
- with the given options
- 'filename' : Prints to file filename. Filename can contain the string 'PID'
- (No Quotes), which will be replaced by the PID of your program.
- When closing lst, the file will be sent to lpr and deleted.
- (lpr should be in PATH)
- 'filename|' Idem as previous, only the file is NOT sent to lpr, nor is it
- deleted.
- (useful for opening /dev/printer or for later printing)
- Lst is set up using '/tmp/PID.lst'. You can change this behaviour at
- compile time, setting the DefFile constant.
- }
- Implementation
- Uses Unix,BaseUnix,Strings;
- {$I printer.inc}
- {
- include definition of textrec
- }
- {$i textrec.inc}
- Const
- P_TOF = 1; { Print to file }
- P_TOFNP = 2; { Print to File, don't spool }
- P_TOP = 3; { Print to Pipe }
- Var
- Lpr : String[255]; { Contains path to lpr binary, including null char }
- Procedure PrintAndDelete (f:string);
- var
- i: pid_t;
- p,pp : ppchar;
- begin
- f:=f+#0;
- if lpr='' then
- exit;
- i:=fpFork;
- if i<0 then
- exit; { No printing was done. We leave the file where it is.}
- if i=0 then
- begin
- { We're in the child }
- getmem(p,12);
- if p=nil then
- halt(127);
- pp:=p;
- pp^:=@lpr[1];
- inc(pp);
- pp^:=@f[1];
- inc(pp);
- pp^:=nil;
- fpExecve(lpr,p,envp);
- { In trouble here ! }
- fpexit(127)
- end
- else
- begin
- { We're in the parent. }
- if waitprocess(i)<>0 then
- exit;
- { Erase the file }
- fpUnlink(f);
- end;
- end;
- Procedure OpenLstPipe ( Var F : Text);
- begin
- POpen (f,StrPas(textrec(f).name),'W');
- end;
- Procedure OpenLstFile ( Var F : Text);
- var
- i : cint;
- begin
- {$IFDEF PRINTERDEBUG}
- writeln ('Printer : In OpenLstFile');
- {$ENDIF}
- If textrec(f).mode <> fmoutput then
- exit;
- textrec(f).userdata[15]:=0; { set Zero length flag }
- repeat
- i:=fpOpen(StrPas(textrec(f).name),(Open_WrOnly or Open_Creat), 438);
- until (i<>-1) or (fpgeterrno<>ESysEINTR);
- if i<0 then
- textrec(f).mode:=fmclosed
- else
- textrec(f).handle:=i;
- end;
- Procedure CloseLstFile ( Var F : Text);
- var
- res: cint;
- begin
- {$IFDEF PRINTERDEBUG}
- writeln ('Printer : In CloseLstFile');
- {$ENDIF}
- repeat
- res:=fpclose (textrec(f).handle);
- until (res<>-1) or (fpgeterrno<>ESysEINTR);
- { In case length is zero, don't print : lpr would give an error }
- if (textrec(f).userdata[15]=0) and (textrec(f).userdata[16]=P_TOF) then
- begin
- fpUnlink(StrPas(textrec(f).name));
- exit
- end;
- { Non empty : needs printing ? }
- if (textrec(f).userdata[16]=P_TOF) then
- PrintAndDelete (strpas(textrec(f).name));
- textrec(f).mode:=fmclosed
- end;
- Procedure InOutLstFile ( Var F : text);
- var
- res: cint;
- begin
- {$IFDEF PRINTERDEBUG}
- writeln ('Printer : In InOutLstFile');
- {$ENDIF}
- If textrec(f).mode<>fmoutput then
- exit;
- if textrec(f).bufpos<>0 then
- textrec(f).userdata[15]:=1; { Set it is not empty. Important when closing !!}
- repeat
- res:=fpwrite(textrec(f).handle,textrec(f).bufptr^,textrec(f).bufpos);
- until (res<>-1) or (fpgeterrno<>ESysEINTR);
- textrec(f).bufpos:=0;
- end;
- function SubstPidInName (const S: string): string;
- var
- i : longint;
- temp : string[8];
- begin
- i:=pos('PID',s);
- if i=0 then
- SubstPidInName := S
- else
- begin
- Str (fpGetPid, Temp);
- SubstPidInName := Copy (S, 1, Pred (I)) + Temp +
- Copy (S, I + 3, Length (S) - I - 2);
- {$IFDEF PRINTERDEBUG}
- writeln ('Print : Filename became : ', Result);
- {$ENDIF}
- end;
- end;
- Procedure AssignLst ( Var F : text; ToFile : string);
- begin
- {$IFDEF PRINTERDEBUG}
- writeln ('Printer : In AssignLst');
- {$ENDIF}
- If ToFile='' then
- exit;
- textrec(f).bufptr:=@textrec(f).buffer;
- textrec(f).bufsize:=128;
- ToFile := SubstPidInName (ToFile);
- if ToFile[1]='|' then
- begin
- Assign(f,Copy(ToFile,2,255));
- textrec(f).userdata[16]:=P_TOP;
- textrec(f).OpenFunc:=@OpenLstPipe;
- end
- else
- begin
- if Tofile[Length(ToFile)]='|' then
- begin
- Assign(f,Copy(ToFile,1,length(Tofile)-1));
- textrec(f).userdata[16]:=P_TOFNP;
- end
- else
- begin
- Assign(f,ToFile);
- textrec(f).userdata[16]:=P_TOF;
- end;
- textrec(f).OpenFunc:=@OpenLstFile;
- textrec(f).CloseFunc:=@CloseLstFile;
- textrec(f).InoutFunc:=@InoutLstFile;
- textrec(f).FlushFunc:=@InoutLstFile;
- end;
- end;
- begin
- InitPrinter (SubstPidInName ('/tmp/PID.lst'));
- SetPrinterExit;
- Lpr := '/usr/bin/lpr';
- end.
|