Pelles C forum
General => Chit-Chat => Topic started by: czerny on May 03, 2014, 03:38:34 PM
-
In the following site http://www.unix.com/programming/37678-c-brain-teaser.html (http://www.unix.com/programming/37678-c-brain-teaser.html) is the following brainteaser:
Write a C program to do a small task(lets say just simply printing a "Hello World" or so) such that the program should only give output or the desired result only once after it got compiled and should never give the output nor do anything else. The program should not make use of files or any extrnal means of storing some data.
One of the solutions presented at that site is:
#include <stdio.h>
#include <io.h>
int main (int argc, char* argv[])
{
printf ("Bye Bye Cruel World :-( \n");
return (_unlink (argv[0]));
}
but this does not work neither in a windows environment nor in many unix environments.
What are other solutions?
-
Hi Czerny,
It doesn't work because trying to delete the executable from inside it causes an access fault because the file is locked while it is executing.
I have seen the solution somewhere when I'll remember I'll tell you. But is something complicated as to inject code to a different process to delete file after the locking by OS has been removed, or something the like...
Start looking here (http://www.catch22.net/tuts/self-deleting-executables), or here (http://blogorama.nerdworks.in/comment.aspx?entryID=21).
-
One nasty trick (on 32-bit OS only) is to write a few bytes to disk containing a 16-bit DOS exe which kills the 32-bit parent process and then itself.
This works fine in assembler:
CASE WM_DESTROY
invoke PostQuitMessage, NULL
Launch Cat$("cmd.exe /c del "+CL$(0)), SW_HIDE, 1 ; timeout 1 ms
... but no success with what seems to me the C equivalent:
case WM_DESTROY:
{
char buffer[300]; // MAX_PATH+15, ca.
lstrcpy(buffer, "cmd.exe /c del ");
GetModuleFileName(0, buffer+15, 285);
// MessageBox(0, buffer, 0, MB_OK);
PostQuitMessage(0);
system(buffer);
}
GOTCHA!! Forget system...
case WM_DESTROY:
{
char buffer[300]; // MAX_PATH+15, ca.
lstrcpy(buffer, "cmd.exe /c del ");
GetModuleFileName(0, buffer+15, 285);
PostQuitMessage(0);
WinExec(buffer, SW_HIDE);
}
-
One nasty trick (on 32-bit OS only) is to write a few bytes to disk containing a 16-bit DOS exe which kills the 32-bit parent process and then itself.
This works fine in assembler:<snip>
Maybe, but it is against the requirements of the task:The program should not make use of files or any extrnal means of storing some data.
Ralf
-
Maybe, but it is against the requirements of the task:The program should not make use of files or any extrnal means of storing some data.
Ralf
The part below "GOTCHA" fits the requirement of the task.
-
Nice, it works.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
void KillMe(void)
{
char szBuf[260+11] = "cmd /c del ";
GetModuleFileName(0, &szBuf[11], 260);
WinExec(szBuf, SW_HIDE);
}
int main(int argc, char **argv)
{
KillMe();
return 0;
}
-
KillMe();
Sleep(20); // works
Sleep(30); // doesn't work
return 0;
There is not much time, not enough for a gui programm, I guess.
But that was not the challenge.
-
Here is an article about self-deleting exes: http://www.catch22.net/tuts/self-deleting-executables (http://www.catch22.net/tuts/self-deleting-executables)
But there should exist other ways (without deleting the exe) eventually!
Self-modifying code shouldn' be possible in this case? Or is it still possible?
Don't know, if the following solutions are not against the rules:
- use exe's creation time, last access time difference
- use the exe's attrib-flag as work/work not flag
-
There is not much time, not enough for a gui programm, I guess.
There is plenty of time. This works on my slow old machine.
case WM_DESTROY:
{
char buffer[300]; // MAX_PATH+15, ca.
lstrcpy(buffer, "cmd.exe /c del ");
GetModuleFileName(0, buffer+15, 285);
PostQuitMessage(0);
WinExec(buffer, SW_HIDE);
Sleep(30); // just for fun
}
-
This works on my slow old machine.
There is always a slower machine. ;)
-
How slow ?
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
...
KillMe();
return msg.wParam;
}