Pelles C forum

General => Chit-Chat => Topic started by: czerny on May 03, 2014, 03:38:34 PM

Title: Cruel World
Post 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:

Code: [Select]
#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?
Title: Re: Cruel World
Post by: frankie on May 03, 2014, 04:24:52 PM
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).
Title: Re: Cruel World
Post by: jj2007 on May 03, 2014, 09:22:35 PM
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);
      }
Title: Re: Cruel World
Post by: Bitbeisser on May 04, 2014, 01:52:57 AM
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:
Quote
The program should not make use of files or any extrnal means of storing some data.
Ralf
Title: Re: Cruel World
Post by: jj2007 on May 04, 2014, 04:07:32 AM
Maybe, but it is against the requirements of the task:
Quote
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.
Title: Re: Cruel World
Post by: TimoVJL on May 04, 2014, 07:22:04 AM
Nice, it works.
Code: [Select]
#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;
}
Title: Re: Cruel World
Post by: czerny on May 04, 2014, 04:26:09 PM
Code: [Select]
    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.
Title: Re: Cruel World
Post by: czerny on May 04, 2014, 04:45:48 PM
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
Title: Re: Cruel World
Post by: jj2007 on May 04, 2014, 07:42:54 PM
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
      }
Title: Re: Cruel World
Post by: czerny on May 04, 2014, 08:21:01 PM
This works on my slow old machine.
There is always a slower machine. ;)
Title: Re: Cruel World
Post by: TimoVJL on May 04, 2014, 08:30:46 PM
How slow ?
Code: [Select]
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
...
KillMe();
return msg.wParam;
}