LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   linux machine shutdown from a C program (https://www.linuxquestions.org/questions/programming-9/linux-machine-shutdown-from-a-c-program-737895/)

vijay_babu1981 07-05-2009 03:13 PM

linux machine shutdown from a C program
 
Hello experts:

I need to 'shutdown -hP TIME' my system everyday. I have a C program which runs on this PC and I want this shutdown command to be a part of that C program. This C program is launched automatically as I have added it in System->Preferences->Personal->Sessions (Fedora 10). Note that the C code does not run in a terminal.

I have tried using the following without success in my C program:

'system("sudo shutdown -h TIME");'

AND

#define SUDO "/usr/bin/sudo"
int main(void)
{
char *arg0;//this should be actual command itself
char *arg1,*arg2,*arg3,*arg4;
arg0 = "sudo";
arg1 = "shutdown";
arg2 = "-h";
arg3 = "01:30";
arg4 = (char *)NULL;
execl(SUDO,arg0,arg1,arg2,arg3,arg4);
sleep(60*60);
return 0;
}

I can see that shutdown process isn't launched at all (ps -e |grep shutdown) in above examples, although other parts of the program run perfectly fine (even the code just above and below the shutdown command).

I have also seen that when I run the 'shutdown -h TIME &' command from a terminal, and close the terminal (exit) then the shutdown is also killed. It is not living beyond or without a terminal.

Can someone help me shutdown my computer using a timer without a terminal. (Please note that I do not want to use a terminal as it interferes with certain other processes).

Regards
Vijay

metrofox 07-05-2009 05:14 PM

I'm studying C and I ain't sure at all, but I think there shouldn't be a "return" in "int main(void)", if you use void you mustn't put a return there ;) Please correct me if I'm wrong...

ArfaSmif 07-05-2009 05:15 PM

If I understand you correctly, you simply want to shutdown your machine at the same time each day without any manual intervention. If this is the case the easiest way to do this is to set up a "cron" job (man cron) as root which runs the shutdown command for you.

Uncle_Theodore 07-05-2009 05:53 PM

Quote:

Originally Posted by metrofox (Post 3597734)
I'm studying C and I ain't sure at all, but I think there shouldn't be a "return" in "int main(void)", if you use void you mustn't put a return there ;) Please correct me if I'm wrong...

OK, I'll correct you, 'cause you're wrong. :)
The return type of 'main' here is 'int'. Hence "return 0;"
'void' is the argument type of 'main'

To the OP: why don't you try

execl("/usr/bin/sudo", "/sbin/shutdown", "-h", "1:30", (char*)NULL);

Not sure if it's gonna work, though...

jlinkels 07-05-2009 09:02 PM

Quote:

Originally Posted by vijay_babu1981 (Post 3597648)
#define SUDO "/usr/bin/sudo"
arg0 = "sudo";
execl(SUDO,arg0,arg1,arg2,arg3,arg4);

Why do you put sudo twice in the call?

jlinkels

wje_lq 07-05-2009 10:02 PM

Quote:

Originally Posted by jlinkels (Post 3597888)
Why do you put sudo twice in the call?

The first occurrence indicates the program to be run.

The second occurrence is the first parameter to the program. It is customary to have the first parameter of the program be the name of the program being run. For example, if you run this shell script:
Code:

cat > 1.c <<EOD; gcc 1.c -o 1; ./1 alpha beta gamma
#include <stdio.h>
int main(int argc,char **argv)
{
  int jndex;

  for(jndex=0;
      argv[jndex];
      jndex++
    )
  {
    printf("argument %d is %s\n",jndex,argv[jndex]);
  }

  return 0;

} /* main() */

you'll get this output:
Code:

argument 0 is ./1
argument 1 is alpha
argument 2 is beta
argument 3 is gamma


metrofox 07-06-2009 05:16 AM

Quote:

Originally Posted by Uncle_Theodore (Post 3597758)
OK, I'll correct you, 'cause you're wrong. :)
The return type of 'main' here is 'int'. Hence "return 0;"
'void' is the argument type of 'main'

To the OP: why don't you try

execl("/usr/bin/sudo", "/sbin/shutdown", "-h", "1:30", (char*)NULL);

Not sure if it's gonna work, though...

Ok, thank you very much ;)

jlinkels 07-06-2009 05:38 AM

Quote:

Originally Posted by wje_lq (Post 3597930)
The first occurrence indicates the program to be run.

The call as it is now is:
Code:

execl (/usr/bin/sudo, sudo, shutdown...)
So /usr/bin/sudo is the program to be called and sudo is the first parameter?

I know that argv[0] is the name of the program, but you don't have to pass yourself, it is placed for you there by the kernel.

The documentation of execl does not mention that I have to put the name of the program as first parameter passed to the program

Quote:

Originally Posted by Uncle_Theodore
execl("/usr/bin/sudo", "/sbin/shutdown", "-h", "1:30", (char*)NULL);

I still think this is the correct call.



jlinkels

vijay_babu1981 07-06-2009 06:02 AM

hello friends,

thanks for all the replies.

arfasmif's comments seems useful. i will try to setup a cron job.

jlinkels comment "why do i put sudo twice in execl".

execl man page says:

The const char *arg and subsequent ellipses in the execl(), execlp(),
and execle() functions can be thought of as arg0, arg1, ..., argn.
Together they describe a list of one or more pointers to null-termi-
nated strings that represent the argument list available to the exe-
cuted program. The first argument, by convention, should point to the
filename associated with the file being executed.
The list of argu-
ments must be terminated by a NULL pointer, and, since these are vari-
adic functions, this pointer must be cast (char *) NULL."


Uncle theodore and jlinkels command does not work:
execl("/usr/bin/sudo", "/sbin/shutdown", "-h", "1:30", (char*)NULL);

I get the following if I use this command:

[vijay@localhost tmp1]$ usage: shutdown -h | -K | -k | -L | -l | -V | -v
usage: shutdown [-bEHPS] [-r role] [-p prompt] [-t type] [-u username|#uid]
[VAR=value] {-i | -s | <command>}
usage: shutdown -e [-S] [-p prompt] [-u username|#uid] file ...

[1]+ Exit 1 ./shutdowntest


BTW, My original command with 2 sudo's work fine when the program is launched from a terminal and the terminal is kept open.

I am hoping the cron job should work! Any other suggestions would be welcome.

Thanks again
Vijay

vijay_babu1981 07-06-2009 07:11 AM

Hi

Cron job seems to work fine...

I set up the root's crontab as:

35 17 * * * /sbin/shutdown -h +5

and restarted the PC. The computer went to halt automatically at the desired time.

thanks to ArfaSmif.

Regards
Vijay

wje_lq 07-06-2009 06:57 PM

Quote:

Originally Posted by jlinkels (Post 3598272)
I know that argv[0] is the name of the program, but you don't have to pass yourself, it is placed for you there by the kernel.

No, it's placed there by whoever does the exec*() call. If you run a program from the command line, it's bash that passes the program name as argv[0], because it's bash that calls exec*().

jlinkels 07-06-2009 08:39 PM

Hm, after all it is according to the man page if you realize that the first parameter is the first parameter in the arg list, not the first parameter in the exec* call.

For this specific call it looks redundant to pass both the command to be executed and the name of the file to be executed, but I guess that for other members of the exec* family it makes more sense.

And one is never too old to learn :)

jlinkels

Uncle_Theodore 07-06-2009 08:48 PM

Yeah, I also tried a couple of things, so does
Code:

execl("/usr/bin/sudo", "/usr/bin/sudo", "/sbin/shutdown", "-h", "1:30", (char*)NULL);
work?

wje_lq 07-06-2009 10:55 PM

Quote:

Originally Posted by jlinkels (Post 3599109)
For this specific call it looks redundant to pass both the command to be executed and the name of the file to be executed, but I guess that for other members of the exec* family it makes more sense.

When it comes to the significance of the arguments passed to the program about to be run, all members of the exec* family have the same meaning, but in different forms. And although the first parameter "means" the name of the file to be run, it can occasionally differ, with useful effect.

For example, if you use any member of the exec* family to run a program which is actually a symbolic link to another program, that second program will be run, but the argument will remain unchanged, because it was specified by the caller of the exec* function.

An example of this, at least on Slackware, is the poweroff command, which is a symbolic link to the halt command. The halt command examines argv[0] to see whether it was first called indeed as halt, or as something else. It thus knows what it's expected to do.

nanoo 07-09-2009 11:21 AM

system("shutdown -h 2:17");


All times are GMT -5. The time now is 09:38 PM.