How to execute a terminal command in C? - c

I'm writing a program in C. I want to get the current hour,minute, second, and nanosecond in the form of H:M:S:3N. Basically. echo "$(date +' %H:%M:%S:%3N')" command does what I want. How can I execute it in my C code and print the result?
Any help is appreciated!

You are looking for strftime. eg:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int
main(int argc, char **argv)
{
int rv = EXIT_SUCCESS;
struct timeval tv;
struct tm *tm;
char *default_args[] = { "%H:%M:%S %B %d, %Y", NULL };
if( gettimeofday(&tv, NULL) == -1 ){
perror("gettimeofday");
exit(1);
}
argv = argc < 2 ? default_args : argv + 1;
tm = gmtime(&tv.tv_sec);
for( ; *argv; argv += 1 ){
char buf[1024];
const char *fmt = *argv;
if( strftime(buf, sizeof buf, fmt, tm) ){
printf("%s\n", buf);
} else {
fprintf(stderr, "Error formatting %s\n", fmt);
rv = EXIT_FAILURE;
}
}
return rv;
}
Note that %N is not generally supported by strftime, so you'll have to parse nano seconds manually.

Related

posix regular expression for parsing uevent causing error

I am trying to parse uevent using this below code but I think my regular expression is not proper causing regcomp function to fail.
Can anyone help? I am trying to do something like this.
#include <stdio.h>
#include <string.h>
#include <regex.h>
int main ()
{
char * source = "change#/devices/soc/799999.i2c/i2c-3/3-0015/power_supply/battery";
char * regexString = "(?<action>[a-zA-Z]+)#\\/(?<dev_path>.*)\\/(?<subsystem>[a-zA-z]+)\\/(?<name>[a-zA-z]+)";
size_t maxGroups = 4;
regex_t regexCompiled;
regmatch_t groupArray[maxGroups];
if (regcomp(&regexCompiled, regexString, REG_EXTENDED))
{
printf("Could not compile regular expression.\n");
return 1;
};
regfree(&regexCompiled);
return 0;
}
I am getting "Could not compile regular expression.". It means regcomp didn't recognize the regex.
When I report on the error using the code:
#include <stdio.h>
#include <string.h>
#include <regex.h>
int main(void)
{
//char * source = "change#/devices/soc/799999.i2c/i2c-3/3-0015/power_supply/battery";
char * regexString = "(?<action>[a-zA-Z]+)#\\/(?<dev_path>.*)\\/(?<subsystem>[a-zA-z]+)\\/(?<name>[a-zA-z]+)";
//size_t maxGroups = 4;
regex_t regexCompiled;
//regmatch_t groupArray[maxGroups];
int rc;
if ((rc = regcomp(&regexCompiled, regexString, REG_EXTENDED)) != 0)
{
char buffer[1024];
regerror(rc, &regexCompiled, buffer, sizeof(buffer));
printf("Could not compile regular expression (%d: %s).\n", rc, buffer);
return 1;
}
regfree(&regexCompiled);
return 0;
}
I get the output:
Could not compile regular expression (13: repetition-operator operand invalid).
The problem is in the notation (? you are using:
"(?<action>[a-zA-Z]+)#\\/(?<dev_path>.*)\\/(?<subsystem>[a-zA-z]+)\\/(?<name>[a-zA-z]+)"
That notation is for PCRE and not POSIX. And PCRE uses ? after ( precisely because it isn't valid in other regex systems (such as POSIX).
So, if you want to use PCRE regexes, install and use the PCRE library.
Otherwise, you'll need to use:
"([a-zA-Z]+)#\\/(.*)\\/([a-zA-z]+)\\/([a-zA-z]+)"
With that in place, and noting that you need a regmatch_t for the whole of the string that's matched plus 4 captured groups (for a total of 5 captures), you can write:
#include <stdio.h>
#include <string.h>
#include <regex.h>
int main(void)
{
char *source = "change#/devices/soc/799999.i2c/i2c-3/3-0015/power_supply/battery";
// char * regexString = "(?<action>[a-zA-Z]+)#\\/(?<dev_path>.*)\\/(?<subsystem>[a-zA-z]+)\\/(?<name>[a-zA-z]+)";
size_t maxGroups = 5;
char *regexString = "([a-zA-Z]+)#\\/(.*)\\/([a-zA-z]+)\\/([a-zA-z]+)";
regex_t regexCompiled;
regmatch_t groupArray[maxGroups];
int rc;
if ((rc = regcomp(&regexCompiled, regexString, REG_EXTENDED)) != 0)
{
char buffer[1024];
regerror(rc, &regexCompiled, buffer, sizeof(buffer));
printf("Could not compile regular expression (%d: %s).\n", rc, buffer);
return 1;
}
if ((rc = regexec(&regexCompiled, source, maxGroups, groupArray, 0)) != 0)
{
char buffer[1024];
regerror(rc, &regexCompiled, buffer, sizeof(buffer));
printf("Could not execute regular expression (%d: %s).\n", rc, buffer);
return 1;
}
printf("Match successful:\n");
for (size_t i = 0; i < maxGroups; i++)
{
int so = groupArray[i].rm_so;
int eo = groupArray[i].rm_eo;
printf("%zu: %d..%d [%.*s]\n", i, so, eo, eo - so, &source[so]);
}
regfree(&regexCompiled);
return 0;
}
and the output is:
Match successful:
0: 0..64 [change#/devices/soc/799999.i2c/i2c-3/3-0015/power_supply/battery]
1: 0..6 [change]
2: 8..43 [devices/soc/799999.i2c/i2c-3/3-0015]
3: 44..56 [power_supply]
4: 57..64 [battery]

Segmentation fault multithreading with file open

I created a program to get all files in a directory, find the individual checksums and then find the total checksums using multithreading.
I am receiving a segmentation fault so I ran gdb and saw that the error is on line 60 where open() is. After researching the seg fault on SO, and on other forums, I attempted to implement a few different approaches such as changing open() to fopen() with a FILE *handle rather than an int. That change proved incorrect.
After hours of debugging and searching, I am clueless and would greatly appreciate any insight.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h> ///Compile with -pthread or -lpthread
#include <sys/stat.h>
#define BUFFER_SIZE (1<<16)
void cleanup();
void get_filenames();
void* get_checksum();
char **filenames;
int file_cnt;
DIR *dir;
//int handle;
FILE *handle;
unsigned int checksum;
unsigned char* ptr;
int length;
int count;
unsigned char* buffer;
int* sum;
unsigned int total = 0;
int main(int argc, char *argv[]){
int i;
pthread_t* file;
atexit(cleanup);
get_filenames();
printf("There are %d files:\n", file_cnt);
file = calloc(sizeof(pthread_t), file_cnt);
sum = calloc(sizeof(int), file_cnt);
for(i=0; i<file_cnt; i++){
printf("%s\n", filenames[i]);
pthread_create(&(file[i]), NULL, get_checksum, (void*)&filenames[i]);
}
for(i=0; i<file_cnt; i++){
total += sum[i];
}
printf("total is: %u\n", total);
return EXIT_SUCCESS;
}
void* get_checksum(void* a){
int b = *((int *)a);
//handle = open(filenames[b], O_RDONLY); //SEG FAULT HERE
handle = fopen(filenames[b], "r"); //SEG FAULT HERE
if( handle == NULL ){
printf( "Can't open file: %s\n", filenames[b]);
exit(1);
}
buffer = malloc(BUFFER_SIZE);
if( buffer == NULL ){
printf( "Can't get enough memory\n" );
exit(1);
}
checksum = 0;
do{
//length = read( handle, buffer, BUFFER_SIZE );
length = read( handle, buffer, (sizeof(char)));
if( length == -1 ){
printf( "Error reading file: %s\n", filenames[b]);
//return NULL;
exit(1);
}
ptr = buffer;
count = length;
while( count-- ){
checksum = checksum + (unsigned int)( *ptr++ );
sum[b] = checksum;
}
} while( length );
printf("Checksum= %d\nTimes at: %d\n", checksum, (int)clock());
}
void cleanup() {
if(filenames && file_cnt > 0) {
while(file_cnt-- > 0) {
if(filenames[file_cnt]) {
free(filenames[file_cnt]);
}
}
free(filenames);
}
if(dir) {
closedir(dir);
}
return;
}
void get_filenames() {
struct dirent *dir_entry;
if((dir = opendir(".")) == NULL) {
fprintf(stderr, "Couldn't open the directory entry for reading\n");
exit(1);
}
errno = 0;
file_cnt = 0;
while((dir_entry = readdir(dir)) != NULL) {
char **new_filenames = filenames;
static int realative_dirs = 0;
if(realative_dirs < 2 &&
(strcmp(".", dir_entry->d_name) == 0 || strcmp("..", dir_entry->d_name) == 0)
) {
realative_dirs++;
continue;
}
new_filenames = (char **)realloc(filenames, sizeof(char **) * (file_cnt + 1));
if(new_filenames == NULL) {
free(filenames[file_cnt]);
fprintf(stderr, "Could not allocate reference for filename[%d]\n", file_cnt);
exit(1);
}
filenames = new_filenames;
filenames[file_cnt] = (char *)calloc(strlen(dir_entry->d_name) + 1, sizeof(char));
if(filenames[file_cnt] == NULL) {
fprintf(stderr, "Could not allocate memory for filename[%d]'s string: \"%s\"\n",
file_cnt, dir_entry->d_name);
exit(1);
}
strcpy(filenames[file_cnt], dir_entry->d_name);
file_cnt++;
}
if(errno != 0) {
fprintf(stderr, "An error occured getting the filenam list\n");
exit(1);
}
return;
}
Below is the output and gdb debugging:
There are 24 files:
.windows
.xscreensaver
.alias
.cshrc
Segmentation fault
(gdb) run
Starting program: /home/nolooking/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
There are 24 files:
.windows
[New Thread 0x7ffff781e700 (LWP 15957)]
.xscreensaver
[New Thread 0x7ffff701d700 (LWP 15958)]
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff781e700 (LWP 15957)]
0x0000000000400d53 in get_checksum (a=0x60b610) at checksum.c:60
60 handle = open(filenames[b], O_RDONLY);
(gdb) backtrace
#0 0x0000000000400d53 in get_checksum (a=0x60b610) at checksum.c:60
#1 0x00007ffff7bc6374 in start_thread () from /lib64/libpthread.so.0
#2 0x00007ffff7907c3d in clone () from /lib64/libc.so.6
(gdb) quit
A debugging session is active.
UPDATE:
I took the advice of one user in the comments who suggested that I use:
handle=fopen((char*)a, "r");. I can successfully print out the file names when the if statement if(handle==NULL) is commented out. When I include that if statement I receive the following output:
There are 24 files:
.windows
.xscreensaver
.alias
.cshrc
Can't open file: p▒`
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <sys/stat.h>
#define BUFFER_SIZE (1<<16)
void cleanup();
void get_filenames();
void* get_checksum();
char **filenames;
int file_cnt;
DIR *dir;
//int handle;
FILE *handle;
unsigned int checksum;
unsigned char* ptr;
int length;
int count;
unsigned char* buffer;
int* sum;
unsigned int total = 0;
int main(int argc, char *argv[]){
int i;
pthread_t* file;
atexit(cleanup);
get_filenames();
printf("There are %d files:\n", file_cnt);
file = calloc(sizeof(pthread_t), file_cnt);
sum = calloc(sizeof(int), file_cnt);
for(i=0; i<file_cnt; i++){
printf("%s\n", filenames[i]);
pthread_create(&(file[i]), NULL, get_checksum, (void*)&filenames[i]);
}
for(i=0; i<file_cnt; i++){
total += sum[i];
}
printf("total is: %u\n", total);
return EXIT_SUCCESS;
}
void* get_checksum(void* a){
int b = *((int *)a);
handle = fopen(((char*)a), "r");
if( handle == NULL ){
printf( "Can't open file: %s\n", ((char*)a));
exit(1);
}
buffer = malloc(BUFFER_SIZE);
if( buffer == NULL ){
printf( "Can't get enough memory\n" );
exit(1);
}
checksum = 0;
do{
length = read( handle, buffer, BUFFER_SIZE );
if( length == -1 ){
printf( "Error reading file: %s\n", ((char*)a));
//return NULL;
exit(1);
}
ptr = buffer;
count = length;
while( count-- ){
checksum = checksum + (unsigned int)( *ptr++ );
//sum[a] = checksum;
}
} while( length );
printf("Checksum= %d\nTimes at: %d\n", checksum, (int)clock());
}
void cleanup() {
if(filenames && file_cnt > 0) {
while(file_cnt-- > 0) {
if(filenames[file_cnt]) {
free(filenames[file_cnt]);
}
}
free(filenames);
}
if(dir) {
closedir(dir);
}
return;
}
void get_filenames() {
struct dirent *dir_entry;
if((dir = opendir(".")) == NULL) {
fprintf(stderr, "Couldn't open the directory entry for reading\n");
exit(1);
}
errno = 0;
file_cnt = 0;
while((dir_entry = readdir(dir)) != NULL) {
char **new_filenames = filenames;
static int realative_dirs = 0;
if(realative_dirs < 2 &&
(strcmp(".", dir_entry->d_name) == 0 || strcmp("..", dir_entry->d_name) == 0)
) {
realative_dirs++;
continue;
}
new_filenames = (char **)realloc(filenames, sizeof(char **) * (file_cnt + 1));
if(new_filenames == NULL) {
free(filenames[file_cnt]);
fprintf(stderr, "Could not allocate reference for filename[%d]\n", file_cnt);
exit(1);
}
filenames = new_filenames;
filenames[file_cnt] = (char *)calloc(strlen(dir_entry->d_name) + 1, sizeof(char));
if(filenames[file_cnt] == NULL) {
fprintf(stderr, "Could not allocate memory for filename[%d]'s string: \"%s\"\n",
file_cnt, dir_entry->d_name);
exit(1);
}
strcpy(filenames[file_cnt], dir_entry->d_name);
file_cnt++;
}
if(errno != 0) {
fprintf(stderr, "An error occured getting the filenam list\n");
exit(1);
}
return;
}
Why I am receiving that output once I uncomment the if statement?
Change this
pthread_create(&(file[i]), NULL, get_checksum, (void*)&filenames[i]);
to be
pthread_create(&(file[i]), NULL, get_checksum, (void*)i);
and this
int b = *((int *)a);
to be
int b = (int)a;
Also you cannot call read() on a FILE* as it is returned by fopen(). Use fread() instead.
Don't use &i. I'll explain in a bit. The argument you're passing to the thread is wrong a is not an integer. It's meant to be a pointer to a string...
Change the thread create to this...
pthread_create(&(file[i]), NULL, get_checksum, filenames[i]);
then print the string as follows...
void* get_checksum(void *a){
char *file_name = (char *)a;
printf("filename=%s\n", file_name);
You're passing the string as a pointer to the called function. In your code you're trying to use this as an index into the array.
If you want to pass the index as an integer beware... this won't work..
pthread_create(&(file[i]), NULL, get_checksum, &i);
This is multithreaded and the value pointed to by &i is changing as the loop runs. Pass the pointer to the string and do not under any circumstances change filenames as the threads run.
I think your problem is simply because you are passing &filenames[i] instead of simply &i.
Then in void* get_checksum(void* a) you are trying to use a char* as an int.
The code would be more like :
for(i=0; i<file_cnt; i++){
printf("%s\n", filenames[i]);
pthread_create(&(file[i]), NULL, get_checksum, (void*)&i);
}
and in void* get_checksum(void* a) :
int b = *((int *)a);
handle = fopen(filenames[b], "r");
if( handle == NULL ){
printf( "Can't open file: %s\n", filenames[b]);
exit(1);
}

in strtok how to use char* as a arguement

In my program, i am allocating dyanamic memory to a variable buffer of type 'char *' using malloc. Then if I using strtok(buffer,"+"); it is giving Segmentation fault. I got the reason for this Stackoverflow and same problem Stackoverflow. but neither post giving me a desired solution. As I can't use static memory or array type according to my program.
My problem is In strtok, in arguements if I use char array then working properly and when use char * then give error. How to use char * in strtok arguements.
char *buffer;
int len;
connection_t * conn;
long addr = 0;
FILE *fptr;
if (!ptr) pthread_exit(0);
conn = (connection_t *)ptr;
const char *s = "+";
char *token;
/* read length of message */
read(conn->sock, &len, sizeof(int));
if (len > 0)
{
addr = (long)((struct sockaddr_in *)&conn->address)->sin_addr.s_addr;
buffer = (char *)malloc((len+1)*sizeof(char));
buffer[len] = 0;
/* read message */
read(conn->sock, buffer, len);
printf("%s and %d \n",buffer, addr);
/* get the first token */
token = strtok(buffer,"+");
last line showing segmentation fault
given the comments, and including error checking, the posted code needs to look similar to:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main( void )
{
char *buffer;
int len;
int sock;
long addr = 0;
//FILE *fptr;
const char *s = "+";
char *token;
struct sockaddr_in address;
ssize_t bytecount;
if( 0 > (sock = socket( AF_INET, SOCK_STREAM, 0) ) )
{
perror( "socket failed");
exit( EXIT_FAILURE );
}
// 'address' needs to be setup here
// 'bind()' needs to be called here
// 'connect()' needs to be called here
addr = ((struct sockaddr_in *)&address)->sin_addr.s_addr;
/* read length of message */
bytecount = read(sock, &len, sizeof(int));
if( sizeof(int) != bytecount )
{
fprintf( stderr, "read requested %d bytes but only got: %d bytes\n",
(int)sizeof(int),
(int)bytecount);
exit( EXIT_FAILURE );
}
if (len > 0)
{
if( NULL == (buffer = malloc( (size_t)(len+1)) ) )
{ // then malloc failed
perror( "malloc for buffer failed");
exit( EXIT_FAILURE );
}
if( len == (bytecount = read( sock, buffer, (size_t)len ) ) )
{ // then correct number of bytes read
buffer[bytecount] = '\0';
printf("%s and %ld\n", buffer, addr);
/* get the first token */
token = strtok(buffer, s);
printf( "token: %s\n", token);
}
}
}
otherwise we are only guessing as to the root of the problem.
Please update the posted code and let us know the result

Change inode ctime in Linux

utimensat() updates ctime when restoring atime and/or mtime, but I need to restore all 3 timestamps. I solved this in a tricky way, by saving the current clock, moving system clock to the needed ctime, calling utimensat(), restoring current clock.
It does the job, but I understand this is a bad solution, so I'm looking for a better one, all in (root) userspace without kernel mods.
Here is the code I wrote to verify utimensat() behaviour and test the solution.
/* Test utimensat() behaviour, restore also Change timestamp
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MYFILE "/home/user1/Work/myfile.txt"
static int get_timestamps(struct stat *sb, const char *descr) {
sleep(1);
if (stat(MYFILE, sb) == -1) {
perror("stat(" MYFILE ") ERROR");
return(errno);
}
char *a = ctime(&sb->st_atime);
char *m = ctime(&sb->st_mtime);
char *c = ctime(&sb->st_ctime);
printf("%s\n", descr);
printf("Last file access: %.*s.%lu\n", (int)strlen(a)-1, a, sb->st_atim.tv_nsec);
printf("Last file modification: %.*s.%lu\n", (int)strlen(m)-1, m, sb->st_mtim.tv_nsec);
printf("Last status change: %.*s.%lu\n\n", (int)strlen(c)-1, c, sb->st_ctim.tv_nsec);
return(0);
}
int main(int argc, char **argv) {
int rc = 0;
struct stat sb_original;
struct stat sb;
// Get file stats
rc = get_timestamps(&sb_original, "Initial");
if (rc) return(rc);
// Read file
FILE *myfile = fopen(MYFILE, "r");
if (myfile == NULL) {
perror("fopen(" MYFILE ") ERROR");
return(errno);
}
char buffer[10];
(void)fread(buffer, 1, 1, myfile);
(void)fclose(myfile);
rc = get_timestamps(&sb, "After fopen(); fread(); fclose()");
if (rc) return(rc);
system("touch " MYFILE);
rc = get_timestamps(&sb, "After touch");
if (rc) return(rc);
// Restore original Last Access timestamp updated after fopen(); fread(); fclose()
if (sb.st_ino) {
int have_sudo = 0;
struct timespec ts[2], tsctime, tsnow;
ts[0].tv_sec = sb_original.st_atim.tv_sec;
ts[0].tv_nsec = sb_original.st_atim.tv_nsec;
ts[1].tv_sec = sb_original.st_mtim.tv_sec;
ts[1].tv_nsec = sb_original.st_mtim.tv_nsec;
tsctime.tv_sec = sb_original.st_mtim.tv_sec;
tsctime.tv_nsec = sb_original.st_mtim.tv_nsec;
if (clock_gettime(CLOCK_REALTIME, &tsnow) < 0) {
perror("clock_gettime(CLOCK_REALTIME) ERROR");
return(errno);
}
/* ##### Fixme: is there a better way to restore all 3 timestamps? */
// Bad solution but does the job ;)
if (clock_settime(CLOCK_REALTIME, &tsctime) < 0) {
perror("clock_settime(CLOCK_REALTIME,ctime) ERROR");
if (errno != EPERM)
return(errno);
have_sudo = 1;
}
if (utimensat(0, MYFILE, ts, 0) < 0) { // This updates Change timestamp!
perror("utimensat(" MYFILE ") ERROR");
return(errno);
}
if (have_sudo && clock_settime(CLOCK_REALTIME, &tsnow) < 0) {
perror("clock_settime(CLOCK_REALTIME,now) ERROR");
return(errno);
}
rc = get_timestamps(&sb, "After utimensat()");
if (rc) return(rc);
}
return(0);
}

Convert Linux C Char Array to Int

need some advice on this one as im struggling abit and cannot figure it out.
i have a file that gets updated on a PC to indicate a system ran and what time it ran. i am writing a very simple linux console app (will eventually be a nagios plugin). that reads this file and responds depending on what it found within the file.
i am a total newbie to programming on Linux and using C so please be patient and if you would explain any answers it would really be appreciated.
basically i want to convert a char array containing 5 characters into an integer, however the 5th char in the array is always a letter. so technically all i want to-do is convert the first 4 chars in the array to a integer... how?? ive tried multiple ways with no success, my problem is that presently i do not have a good grasp of the language so have no real ideas on what it can and cannot do.
here is the source to my program.
basically the buf array will be holding a string taken from the file that will look something like this
3455Y (the number will be random but always 4 chars long).
Sorry for the poor formatting of the code, but i cannot get this stupid window for love nor money to format it correctly....
include <fcntl.h>
include <unistd.h>
include <stdio.h>
include <stdlib.h>
include <time.h>
include <string.h>
define COPYMODE 0644
int main(int argc, char *argv[])
{
int i, nRead, fd;
int source;
int STATE_OK = 0;
int STATE_WARNING = 1;
int STATE_CRITICAL = 2;
int STATE_UNKNOWN = 3;
int system_paused = 0;
char buf[5];
int testnumber;
if((fd = open(argv[1], O_RDONLY)) == -1)
{
printf("failed open : %s", argv[1]);
return STATE_UNKNOWN;
}
else
{
nRead = read(fd, buf, 5);
}
close(source);
if (buf[4] == 'P')
{
printf("Software Paused");
return STATE_WARNING;
}
else
{
return STATE_OK;
}
time_t ltime; /* calendar time */
struct tm *Tm;
ltime=time(NULL); /* get current cal time */
Tm=localtime(&ltime);
int test;
test = Tm->tm_hour + Tm->tm_min;
printf("%d", test);
printf("%d", strtoi(buf));
}
You can use sscanf to do the job:
int num = 0;
sscanf(buf, "%4d", &num);
Then num should hold the number from the line in the file.
You can use atoi
atoi requires one char * argument and returns an int.
If the string is empty, or first character isn't a number or a minus sign, then atoi returns 0.If atoi encounters a non-number character, it returns the number formed up until that point
int num = atoi(buf);
if you want to convert the first four characters of a string to an integer do this:
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdint.h>
uint8_t convertFirstFourChars(char * str, uint32_t *value){
char tmp[5] = {0};
strncpy((char *) tmp, str, 4);
*value = strtoul(tmp);
return errno;
}
then call / test this function like this
#include <stdint.h>
#include <stdio.h>
int main(int argc, char **argv){
char test1[5] = "1234A";
char test2[5] = "ABCDE";
uint32_t val = 0;
if(convertFirstFourChars((char *) test1, &val) == 0){
printf("conversion of %s succeeded, value = %ld\n", test1, val);
}
else{
printf("conversion of %s failed!\n", test1);
}
if(convertFirstFourChars((char *) test2, &val) == 0){
printf("conversion succeeded of %s, value = %ld\n", test2, val);
}
else{
printf("conversion of %s failed!\n", test2);
}
return 0;
}
FWIW, don't use atoi(...) because it converts any string to an integer regardless of its validity as a number. atoi("foo") === 0.
this is as much of your code as I was able to recover from the formatting:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <time.h>
#define COPYMODE 0644
int main(int argc, char *argv[])
{
int i, nRead, fd;
int source;
int STATE_OK = 0;
int STATE_WARNING = 1;
int STATE_CRITICAL = 2;
int STATE_UNKNOWN = 3;
int system_paused = 0;
char buf[5];
int testnumber;
if((fd = open(argv[1], O_RDONLY)) == -1)
{
printf("failed open : %s", argv[1]);
return STATE_UNKNOWN;
}
else
{
nRead = read(fd, buf, 5);
}
close(source);
if (buf[4] == 'P')
{
printf("Software Paused");
return STATE_WARNING;
} else {
return STATE_OK;
}
time_t ltime; /* calendar time /
struct tm Tm;
ltime=time(NULL); / get current cal time */
Tm=localtime(&ltime);
int test;
test = Tm->tm_hour + Tm->tm_min;
printf("%d", test);
printf("%d", strtoi(buf));
}
this is the version that does what you specified:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <time.h>
#define COPYMODE 0644
int main(int argc, char *argv[])
{
int i, nRead, fd;
int source;
int STATE_OK = 0;
int STATE_WARNING = 1;
int STATE_CRITICAL = 2;
int STATE_UNKNOWN = 3;
int system_paused = 0;
char buf[5];
int testnumber;
if((fd = open(argv[1], O_RDONLY)) == -1)
{
printf("failed open : %s", argv[1]);
return STATE_UNKNOWN;
}
else
{
nRead = read(fd, buf, 5);
}
close(source);
if (buf[4] == 'P')
{
printf("Software Paused");
return STATE_WARNING;
}/* else {
return STATE_OK;
buf[4] = 0;
} */
time_t ltime; /* calendar time */
struct tm *Tm;
ltime=time(NULL); /* get current cal time */
Tm=localtime(&ltime);
int test;
test = Tm->tm_hour + Tm->tm_min;
printf("%d\n", test);
printf("%d\n", atoi(buf));
}
The biggest problem with your code was the if statement with the returns in each branch, insuring that nothing after the if statement was ever executed.

Resources