简体   繁体   中英

Return to main C program after calling shell script

I have a C program running on my Raspberry-Pi that continuously reads serial info from an AVR. I want to write the history of commands received using a simple shell script:

#!/bin/bash

echo "Command $2 received from address $1" 

date_time=$(date)                       #read current date from terminal
echo " $date_time Address: $1 Cmd: $2" >> file.txt      #echo address & command to file, redirect stdio

exit 0

This script works perfectly when called within terminal with the proper arguments, however, I want to execute it each time that a command is read from the serial line. The C program currently reads the command & address and prints it to the standard io, so what I would like to do is call the script after this, to write data to a file.

When calling the script in my code like this:

    char* args[3];
char* program="ioExport.sh";
    args[1]=addr;
    args[2]=cmd;
    args[3]=NULL;
    execv(program,args);

it exits the main program. How can I return to the main program after calling the script? Or is there a way to do it when running the script as a background process? I'm aware that it would be much simpler to do it with standard C file i/o, but if it's possible using the shell, I'd like to do that :)

Regards, Jaco

The exec family of function replaces the process with the new process. They only return in case of an error.

What you seem to want is the system function, which creates a shell process for you and then executes the command in the argument.

By the way, you set up your argument array wrong anyway, remember that arrays indices start with zero . Also, the first entry in the argument array should be the program name, meaning you need to set argument[0] to program , and of course change the array size to four.


However, as trojanfoe notes, you don't really need to call a shell script at all unless there are some other special commands that needs to be run when you receive the message.If you just want to print some logging information to a file you can do it from inside the program very easily:

/* First get the date and time string */
time_t now = time(NULL);
char *timestring = ctime(&now);

/* It contains a trailing newline, remove that by */
/* overwriting the newline with the string terminator */
timestring[strlen(timestring) - 1] = '\0';

/* Open the file for appending (i.e. writing at the end) */
FILE *file = fopen("file.txt", "a");

/* And write your message to your file */
fprintf(file, "%s Address: %s Cmd: %s\n", timestring, addr, cmd);

/* Close the file */
fclose(file);

Put this in a separate function, that you call whenever you need. And note that if you want to write more to the file, then you could open it at the beginning of the program and not close it until you are exiting the program.

Calling a shell script, especially so frequently, will cripple the performance of your program, so use built-in logging functionality instead. You might need to change the semantics of logData() as I don't know what form your "command" and "address" takes.

logger.h:

#pragma once

#include <stdbool.h>

extern bool logOpen(const char *filename);
extern void logData(const char *command, const char *address);
extern void logClose();

logger.c:

#include "logger.h"
#include <stdio.h>
#include <sys/time.h>

static FILE *logfp = NULL;

bool logOpen(const char *filename) {
    logfp = fopen(filename, "w+");
    return logfp != NULL;
}

void logData(const char *command, const char *address) {
    struct timeval tv;
    struct tm tm;

    if (!logfp)
        return;

    gettimeofday(&tv, 0);
    localtime_r(&tv.tv_sec, &tm);

    fprintf(logfp, "%02d:%02d:%02d.%03u: command='%s' address='%s'\n",
        tm.tm_hour, tm.tm_min, tm.tm_sec, (unsigned)(tv.tv_usec / 1000),
        command, address);

}

void logClose() {
    if (logfp) {
        fclose(logfp);
        logfp = NULL;
    }
}

main.c:

#include "logger.h"

int main(int argc, const char **argv) {

    logOpen("file.log");

    logData("Command 1", "Address 1");
    logData("Command 2", "Address 2");
    logData("Command 3", "Address 3");
    logData("Command 4", "Address 4");

    logClose();
    return 0;
}

Compilation and testing:

$ clang -o test main.c logger.c
$ ./test
$ more file.log
13:40:08.399: command='Command 1' address='Address 1'
13:40:08.399: command='Command 2' address='Address 2'
13:40:08.399: command='Command 3' address='Address 3'
13:40:08.399: command='Command 4' address='Address 4'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM