1

So Im rather new to the C language exec family functions and was wondering why cal returns

usage: cal [-13smjyV] [[[day] month] year]

When passed to execve(); below

    pid = fork( ) ;
    if ( pid == 0 )  {
            char *myArgv[ ] = { "cal", "4", "1980", "NULL"};
            char *myEnv[ ] = { "HOME=/usr/bin", NULL}  ;
            execve( "/usr/bin/cal", myArgv, myEnv) ;
    } else {
            printf("parent process waiting for execve complete \n" );
    }

whereas when I call 'cal 4 1980' manually through my terminal I get an actual printout?

          April 1980     
     Su Mo Tu We Th Fr Sa
            1  2  3  4  5
      6  7  8  9 10 11 12
     13 14 15 16 17 18 19
     20 21 22 23 24 25 26
     27 28 29 30
Anon451
  • 43
  • 4
  • regarding: `execve( "/usr/bin/cal", myArgv, myEnv) ;` This would be much better written as: `execve( "/usr/bin/cal", myArgv, myEnv) ; perror( "execve failed" ); exit( EXIT_FAILURE );` – user3629249 Nov 21 '19 at 06:04
  • regarding: `printf("parent process waiting for execve complete \n" );` should be followed by: `waitpid( pid, NULL, 0 );` – user3629249 Nov 21 '19 at 06:06
  • Note: the posted code fails to check for a failure of the function: `fork()` Remember that `fork()` has the three return types: 1) <0 means an error occurred 2) ==0 means in the child process 3) >0 means in the parent process – user3629249 Nov 21 '19 at 06:08
  • 1
    Maybe it gets confused when you clobber the entire environment but `HOME`? – ikegami Nov 21 '19 at 06:27

2 Answers2

2

So it looks like the reason the program wasn't printing the calendar was because I didn't NULL terminate the myArgv char array on line 3 properly and instead ended the array with "NULL" with quotes, instead I should have terminated with just NULL without quotes.

Anon451
  • 43
  • 4
0

the following proposed code:

  1. cleanly compiles
  2. performs the desired functionality
  3. properly checks for errors

Note: the need to execute /bin/bash -c to execute a program from the environment

and now the proposed code:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main( void )
{
    pid_t pid = fork( );
    switch( pid )
    {
        case -1:
            perror( "fork failed" );
            exit( EXIT_FAILURE );
            break;

        case 0:
            // in child process
            {
                //char *myArgv[ ] = { "-c", "/usr/bin/cal", "4", "1980", "NULL"};
                //char *myEnv[ ] = { "HOME=/usr/bin", NULL}  ;
                execlp( "/bin/bash", "bash", "-c", "/usr/bin/cal", "-S", "4", "1980", NULL) ;
                perror( "execve failed" );
                exit( EXIT_FAILURE );
            }
            break;

        default:
            // in parent process
            printf("parent process waiting for execlp>>bash>>cal to complete \n" );
            waitpid( pid, NULL, 0 );
            break;
    }           
}

a run of the program results in:

parent process waiting for execlp>>bash>>cal to complete 
   November 2019      
Su Mo Tu We Th Fr Sa  
                1  2  
 3  4  5  6  7  8  9  
10 11 12 13 14 15 16  
17 18 19 20 21 22 23  
24 25 26 27 28 29 30  
user3629249
  • 16,402
  • 1
  • 16
  • 17