john@jwt.UUCP (John Temples) (04/05/91)
In article <jono.670739550@dec06> jono@dec06.cs.monash.edu.au (Jonathan Oliver) writes: > system("copy file1 file2"); > >there was not enough memory to perform the copy. The two problems with your approach are that system() has to load a copy of the command processor to do its job (which takes additional time and memory), and you're assuming that there's a command called "copy" on the system running your program. Since "copy" is a COMMAND.COM internal command, and not everyone who runs DOS uses COMMAND.COM, your program is non-portable. Also, system() usually fails when your switch character is not set to "/". In other words, system() is not usually a wise choice in any "serious" program. You should open "file1" and "file2" and do the copy yourself, something like this: int copy(FILE *infile, FILE *outfile) { char buf[BUFSIZ]; int cnt; while (cnt = fread(buf, sizeof(*buf), sizeof(buf), infile)) if (fwrite(buf, sizeof(*buf), cnt, outfile) != cnt) return 1; /* probably disk full */ return 0; } -- John W. Temples -- john@jwt.UUCP (uunet!jwt!john)
dcc@hpopd.pwd.hp.com (Daniel Creswell) (04/05/91)
Try looking at the routines 'execv' and 'execl' which may do the trick. I think you'll find that use of 'system' creates a new environment for the command as it has to create a command.com and then run the program (if it behaves like Unix!). Trouble is you'd have to use 'xcopy' for this I think cos you need to execute another program and copy is resident in command.com. Xcopy doesn't need command.com and so it should be possible to call this directly - provided you can obtain it's path..... Dunno how much help that is but I think it's the only way to go.... Cheers,Dan C.
tr@SAMADAMS.PRINCETON.EDU (Tom Reingold) (04/06/91)
To my thinking, the solution offered by John Temples is the most reliable and straightforward. I would add that since you may want to preserve the timestamp on the file, that you should look into the stat() and utime() functions. I hope they are provided by your library. They are in my Microsoft library. Used properly, you can set the timestamp on the destination file to be the same as that on the source file. If you don't have them, use DOS calls. I recommend the former because they are clones of UNIX calls, thus your program is more portable. -- Tom Reingold tr@samadams.princeton.edu OR ...!princeton!samadams!tr "Warning: Do not drive with Auto-Shade in place. Remove from windshield before starting ignition."
stanley@phoenix.com (John Stanley) (04/08/91)
john@jwt.UUCP (John Temples) writes: > In article <jono.670739550@dec06> jono@dec06.cs.monash.edu.au (Jonathan Olive > > system("copy file1 file2"); > > > >there was not enough memory to perform the copy. > > The two problems with your approach are that system() has to load a > copy of the command processor to do its job (which takes additional > time and memory), A valid complaint about system() on any OS. > and you're assuming that there's a command called > "copy" on the system running your program. Copy is one of those commands that seems to be everywhere. If you were trying to do a 'hyteiwk a b', you might be worried that hyteiwk is not everywhere. Or, you could supply a copy of it with each system you sell. Added value! > Since "copy" is a > COMMAND.COM internal command, and not everyone who runs DOS uses > COMMAND.COM, your program is non-portable. Do other PC OS's really not have a command called 'copy'? Do they REALLY not have the capability of having a simple batch file to create that command? How poor a system! > Also, system() usually > fails when your switch character is not set to "/". I have heard that much software fails when the switch isn't /. > In other words, > system() is not usually a wise choice in any "serious" program. I disagree. The only drawback to system() is the speed penalty of loading another shell. There are some very good uses for system(). > You should open "file1" and "file2" and do the copy yourself, something > like this: Here is the best proof that system() is the proper choice. You have left out the hardest part of the operation -- opening the files. True, MS-DOS and UNIX are quite happy with stream files. But when you invoke the name of the god Portability, you invoke more than those OS's. Look at VMS (and probably MVS and a dozen others), who have many types of files. (In fact, VMS's stream_lf file came about only after C was implemented on it.) If you dare open a fixed length record file with stream attributes, you get faulty data. How do you tell the record type? You have to stat() the file. Now, to be portable, you will need to code into your open function a test for many different file types. And hope that the next release of the OS doesn't add a few more. Or, you can code in a simple system() of 'copy a b', and let the OS writers worry about file types and anything else system specific. And if you don't have a 'copy' command, write a batch file (or alias, or ...) to do it. Here is another good use for system(). How do you print from within a program? I hate to tell you, but opening the device LPT1:, or PRN:, is REALLY non-portable. Not even from OS to OS, but from one PC to another. With the easy possibility of 5 printers attached to one PC, and a myriad others through networks, plus all the other OS's and the odd ways they handle printers, system() is about the only option. Either that, or you write configuration code to handle every case you can think of, and I can guarantee that you will miss some. And you will have trouble getting data to the printer yourself that 'copy' will not. I have one program that I have gone to the extent of 'biosprint()' and there is STILL a problem with something swallowing bytes here and there that does not happen with 'copy'. So, write your data to a file. Use the system command 'printfile filename'. Then write a batch file to implement the printfile command. Yeah, it is slower, but it sure beats trying to maintain a mountain of code, and it allows the USER to configure his printing as he wishes. When you can tell a customer 'here is how to do what you want', instead of 'not supported', you both win.
john@jwt.UUCP (John Temples) (04/09/91)
In article <Nuq3Z1w163w@phoenix.com> stanley@phoenix.com (John Stanley) writes: > Copy is one of those commands that seems to be everywhere. > Do other PC OS's really not have a command called 'copy'? Do they >REALLY not have the capability of having a simple batch file to create >that command? How poor a system! You don't even have to go to another OS to lose "copy" -- just install the MKS toolkit, or any other package which replaces COMMAND.COM with something usable. Have you ever seen a professional program which, in its installation instructions, says "now, if your system does not have a 'copy' command, you must create a batch file that copies a file from the first argument to the second." I certainly haven't. And what if you have a 'copy' command, but the arguments to it are not interpreted as 'copy from to'? >> Also, system() usually >> fails when your switch character is not set to "/". > > I have heard that much software fails when the switch isn't /. I wouldn't go so far as to say "much", but why use a system call which has a known common failure mode? (under DOS, anyway.) >The only drawback to system() is the speed penalty of loading >another shell. What about the memory cost of the extra shell? Certainly a concern under DOS, and the reason this thread was started! > Here is the best proof that system() is the proper choice. You have >left out the hardest part of the operation -- opening the files. True, >MS-DOS and UNIX are quite happy with stream files. But when you invoke >the name of the god Portability, you invoke more than those OS's. If you're going to write a program that does file I/O and try to run it on different platforms which have different file system semantics, you're not going to be able to avoid OS-specific code. Ok, so you've copied a file with the system() call. Now how do you *read* a file into your program? > Here is another good use for system(). How do you print from within a >program? [...] system() is about the only option. So, write your data >to a file. Use the system command 'printfile filename'. Then write a >batch file to implement the printfile command. Yea, but the "printfile" command already exists on my system and sends the file to the line printer. I guess I can't use your program to print files to the laser printer, huh? And again, have you ever seen a professional program that required you to set up a batch file to print programs? Or for that matter, a program that required a user to even know what a batch file is? The correct way to do it, if you want to configure for different printing environments, is to ask the user what command will print a file to the desired printer. Then exec() or spawn() this program, handing it the print file on its standard input, if possible. Of course, under a single-tasking environment like DOS, you may end up having to talk directly to the hardware. -- John W. Temples -- john@jwt.UUCP (uunet!jwt!john)