jillj@brspyr1.BRS.Com (Jill Jacomine) (11/29/89)
I am trying to execute the DOS (version 3.1) print command from within an executable (compliled using MSC 5.1). The command I am using is: spawnvp(P_WAIT,"print.com",args); The value of args is "print /D:prn filename". Now, this works well enough to print the file out, the problem seems to be setting the device within the program eats up about 200k of memory, and never lets it go. (I tried setting the device before executing the program, and it seems to work fine, therefore I am relativly sure the problem is with the /D:prn option). A chkdsk before running the program shows 655360 bytes total memory and 594256 bytes free, after execution it is 426720 bytes total memory and 356616 bytes free. I have tried using the SYSTEM function, as well as different SPAWN functions, but they all yield the same results. Has anyone else come across this problem, or can anyone offer information as to why this happens and how it can be corrected. Thanks in advance. Jill Jacomine ------------------------------------------------------------------------------ ////////////////////////////////////////////////////////////////////////////// ------------------------------------------------------------------------------ Jill Jacomine (jill@brspyr1.BRS.COM) UUCP: BRS Information Technologies Latham, NY
gs940971@longs.LANCE.ColoState.Edu (glen sunada f84) (11/29/89)
In article <6534@brspyr1.BRS.Com>, jillj@brspyr1.BRS.Com (Jill Jacomine) writes: > I am trying to execute the DOS (version 3.1) print command from within > an executable (compliled using MSC 5.1). The command I am using is: > > spawnvp(P_WAIT,"print.com",args); [deleted stuff] > within the program eats up about 200k of memory, and never lets it go. > (I tried setting the device before executing the program, and it seems > to work fine, therefore I am relativly sure the problem is with the > /D:prn option). A chkdsk before running the program shows 655360 bytes [deleted stuff] > I have tried using the SYSTEM function, as well as different SPAWN > functions, but they all yield the same results. Has anyone else come > across this problem, or can anyone offer information as to why this > happens and how it can be corrected. The problem is that the DOS print command is not just a file printer but also a siak based print sppooler and scheduler (sp?). To correctly spool and schedule jobs print needs to make part of its code resident. Print uses some mechanism to detect if it is already resident to prevent multiple copies of the resident code. I do not know how this is done but one way may be to check trough the interrupt linkages and see if print is there (I think i saw somewhere that print preempts one of the user interrupts for communication to the resedent code but I can no prove this). The best solution is to write your own printout routine in your program. If the progam is to be used in house only then just make sure that the print command has always been installed before running your program. Glen U. Sunada gs940971@longs.LANCE.ColoState.EDU ARPA Internet (preferred) ...!ncar!boulder!ccncsu!longs.LANCE.ColoState.EDU!gs940971 UUCP We have only ignorence to fear
swh@hpcupt1.HP.COM (Steve Harrold) (11/30/89)
Re: Using PRINT from within a program I haven't tried your particular program setup, but I suspect you may be overlooking the fact that, although PRINT is not a TSR in the usual sense, it does grab memory for its buffers and some code, and never ever again lets go of it. This is necessary because PRINT operates in the background while you do additional work. When control comes back from PRINT, it has not yet completed its operation. Since the memory is not freed, you end up with fragmented memory; DOS does not handle this well, satisfying all of subsequent memory requests from only one free memory hole. The only thing you can do to get around this is to start PRINT once BEFORE to run your program. In this way, the PRINT memory is assigned at the top of memory (or is it at the bottom? At any rate, memory fragmentation is avoided). A good place to do this is in your AUTOEXEC.BAT file. Hope this helps.
gs940971@longs.LANCE.ColoState.Edu (glen sunada f84) (11/30/89)
In my article I expressed ignorence to the mechanism used to communicate with print I recieved a mail message from Raymond Chen at Berkley that set me on the correct path to locateing that method. I then looked up the specifics in the Waite Group's _MS-DOS Developers Guide_ Second editions. What follows is my reply to him: >>Print uses some mechanism to detect if it is already resident to prevent >>multiple copies of the resident code. I do not know how this is done > >It installs itself into the DOS multiplex interrupt (Int 21, ah = 2f, >I think). This is a quasi-standard way of checking for multiple >installations, once you get an official multiplex ID number. I found my DOS reference and print does install itself on the DOS Multiplex interrupts. That is interruipt 2f. The calling parameters for interrupt 2f are as follows. AH = program code (supplied DOS codes as folows) 01 - print 02 - assign 10 - share b7 - append AL = requested function code 00 - get installed state (all) 01 - submit file to print DS:DX = pointer to submit packet 0 + DWORD pointer to ASCIIZ filespec 02 - cancel file in print queue DS:DX = pointer to fully qualified (no wild card) ASCIIZ filespec to cancel 03 - Cancel all files in print queue 04 - pause print and return status (I don't know the return codes here) 05 - end of print status (I don't know these reutrns either) Gaurenteed return codes if CF = 1 AX = error code if AL = 0FF a program with your identifier is installed if AL = 0 no program with your identifer installed ok to install if AL = 1 no program with your identifer installed not ok to install Glen Sunada gs940971@longs.LANCE.ColoState.EDU ARPA Internet (preferred) ...ncar!boulder!ccncsu!longs.LANCE.ColoState.EDU!gs940971 UUCP Money is the root of all evil. Men need roots. - Lazerus Long
cramer@optilink.UUCP (Clayton Cramer) (11/30/89)
In article <6534@brspyr1.BRS.Com>, jillj@brspyr1.BRS.Com (Jill Jacomine) writes: > I am trying to execute the DOS (version 3.1) print command from within > an executable (compliled using MSC 5.1). The command I am using is: > > spawnvp(P_WAIT,"print.com",args); > > The value of args is "print /D:prn filename". Now, this works well > enough to print the file out, the problem seems to be setting the device > within the program eats up about 200k of memory, and never lets it go. > (I tried setting the device before executing the program, and it seems > to work fine, therefore I am relativly sure the problem is with the > /D:prn option). A chkdsk before running the program shows 655360 bytes > total memory and 594256 bytes free, after execution it is 426720 bytes > total memory and 356616 bytes free. > > I have tried using the SYSTEM function, as well as different SPAWN > functions, but they all yield the same results. Has anyone else come > across this problem, or can anyone offer information as to why this > happens and how it can be corrected. > > Jill Jacomine Yes, it gobbles up memory doing it this way, but I've never seen it grab so much memory, and keep it gobbled. I solved the problem by writing some C to call the BIOS routines. (Thanks to the several people on the net who helped me find a bug). Here's some code that you may find useful, and doesn't require bringing up another copy of DOS, or burning any unnecessary RAM to do print spooling. /*============================================================================ OMSPOOL.C: Print Spooling functions. This module contains print spooling functions for use by OMAPS. Glossary: abbr - abbreviation ============================================================================*/ #include <dos.h> #include <stdlib.h> #include <process.h> #define TRUE 1 #define FALSE 0 typedef int bool; typedef struct tSub { char ByteLevel; char* FileName; } tSub; /*===Entries================================================================*/ int SpoolFile(char*); /* add a file to the print queue */ bool SpoolInstall(void); /* install the print spooler */ bool SpoolInstalled(void); /* is the print spooler installed? */ int SpoolRemoveFile(char*); /* remove a spooled file from queue */ int SpoolTerminate(void); /* terminate the spool queue */ int TestDiagT1Admin(void); /* testing & diagnostics T1 */ /*===Functions=============================================================*/ /*==========================================================================*/ /*---------------------------------------------------------------------------- SpoolFile: Add a file to the print queue. Adds a file to the print spool queue. RETURN: int print spool error code (0 = no error) GLOBALS: none ----------------------------------------------------------------------------*/ int SpoolFile(FileName) char* FileName; /* IN: ptr to filename to add to queue */ { union REGS InRegs; union REGS OutRegs; struct SREGS SegRegs; int ErrCode; tSub SubmitFile; tSub* pSubmitFile; pSubmitFile = &SubmitFile; InRegs.x.ax = 0x101; SubmitFile.ByteLevel = 0; SubmitFile.FileName = FileName; InRegs.x.dx = FP_OFF(pSubmitFile); SegRegs.ds = FP_SEG(pSubmitFile); int86x(0x2f, &InRegs, &OutRegs, &SegRegs); if(OutRegs.x.cflag) ErrCode = OutRegs.x.ax; else ErrCode = 0; return(ErrCode); } /*---------------------------------------------------------------------------- SpoolInstall: Install the print spooler. Installs the print spooler. RETURN: bool TRUE: successfully installed FALSE: failed to install GLOBALS: none ----------------------------------------------------------------------------*/ bool SpoolInstall() { return(0 == system("PRINT")); } /*---------------------------------------------------------------------------- SpoolInstalled: Is the print spooler installed? Checks to see if the print spooler is already installed. RETURN: bool TRUE: already installed FALSE: not yet GLOBALS: none ----------------------------------------------------------------------------*/ bool SpoolInstalled() { union REGS InRegs; union REGS OutRegs; struct SREGS SegRegs; int ErrCode; InRegs.x.ax = 0x100; int86x(0x2f, &InRegs, &OutRegs, &SegRegs); return(OutRegs.h.al == 0xff); } /*---------------------------------------------------------------------------- SpoolRemoveFile: Remove a file from the print queue. Removes the specified file from the print spooler queue. RETURN: int print spooler error code GLOBALS: none ----------------------------------------------------------------------------*/ int SpoolRemoveFile(FileName) char* FileName; /* IN: ptr to filename to remove from queue */ { union REGS InRegs; union REGS OutRegs; struct SREGS SegRegs; int ErrCode; InRegs.x.ax = 0x102; InRegs.x.dx = FP_OFF(FileName); SegRegs.ds = FP_SEG(FileName); int86x(0x2f, &InRegs, &OutRegs, &SegRegs); if(OutRegs.x.cflag) ErrCode = OutRegs.x.ax; else ErrCode = 0; return(ErrCode); } /*---------------------------------------------------------------------------- SpoolTerminate: Clear the queue. Removes all current jobs from the print spooler queue. RETURN: int print spooler error code (0 = no error) GLOBALS: none ----------------------------------------------------------------------------*/ int SpoolTerminate() { union REGS InRegs; union REGS OutRegs; struct SREGS SegRegs; int ErrCode; InRegs.x.ax = 0x103; int86x(0x2f, &InRegs, &OutRegs, &SegRegs); if(OutRegs.x.cflag) ErrCode = OutRegs.x.ax; else ErrCode = 0; return(ErrCode); } -- Clayton E. Cramer {pyramid,pixar,tekbspa}!optilink!cramer My definition of social justice: those who refuse to work deserve to go hungry. =============================================================================== Disclaimer? You must be kidding! No company would hold opinions like mine!
pipkins@qmsseq.imagen.com (Jeff Pipkins) (12/01/89)
In article <6534@brspyr1.BRS.Com> jillj@brspyr1.BRS.Com (Jill Jacomine) writes: >I am trying to execute the DOS (version 3.1) print command from within >an executable (compliled using MSC 5.1). The command I am using is: > > spawnvp(P_WAIT,"print.com",args); > >The value of args is "print /D:prn filename". Now, this works well >enough to print the file out, the problem seems to be setting the device >within the program eats up about 200k of memory, and never lets it go. >(I tried setting the device before executing the program, and it seems >to work fine, therefore I am relativly sure the problem is with the >/D:prn option). A chkdsk before running the program shows 655360 bytes >total memory and 594256 bytes free, after execution it is 426720 bytes >total memory and 356616 bytes free. PRINT is a "TSR" program. The first time you run it, it installs itself into your precious memory. If your program loads it, realize that chances are very high that it will be loaded RIGHT AFTER your program in memory. After your program terminates, PRINT STAYS THERE -- and you have irrecoverable memory fragmentation. DOS usually loads new programs in the first hole that it will fit in, so a program may use that hole, but if it tries to use the DOS SETBLOCK function to increase its size, it will most likely fail. This problem occurs any time a nonresident program loads a resident program. I have only thought of two possible work-arounds, and I don't like either of them: 1) Reserve enough memory below your program so that you can load the TSR there. 2) Modify DOSs memory control blocks to allocate just the right size block high in memory; then use the overlay option of DOSs EXEC function to load the program into that memory. I would be very interested in hearing other possible solutions from anyone else! /*=======================================================================*\ Jeff Pipkins: pipkins@imagen.com My views are not necessarily shared by my employer or the IRS. That explains a lot about my paycheck. "Why is it that unpitted dates have pits and pitted dates do not?" \*=======================================================================*/
miller@b-mrda.boeing.com (Mark Miller) (12/02/89)
Jill: From the print options you specified, it doesn't sound like you're looking for the PRINT command to do anything more than dump a file to the printer. The only advantage to using PRINT is that PRINT uses a spooler to do the trick. The disadvantage is that PRINT does load a memory-resident segment that doesn't go away. I have two suggestions: 1. If you don't need a spooler and you're not in a hurry, simply open the file for reading and send it to stdprn (defaults to lpt1:) via fprintf. 2. If you're in a hurry, write a small custom spooler hanging off the INT8 (timer tick) interrupt for your application. Either of these returns full control of the memory to you. Good luck. Let me know how it works out. Mark Miller miller@b-mrda.boeing.com
john@wsl.UUCP (John Allen on wsl) (12/05/89)
Minor correction -- PRINT.COM is a TSR, in fact it is the original TSR. Print should never be loaded from within an application unless it has been previously loaded from either the command line or a BATCH file. Your suggestion to load it from autoexec is absolutely correct. -- People that don't know want to know from the people that do know and if the poeple that do know don't tell the people that don't know then the people that don't know still won't know. "Don't quote me on any issue whatsoever."