Convert Linux C Char Array to Int - c

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.

Related

On linux in C how to generate file of size X?

So I want to make a file named genData.c that when executed for example: ./genData filename.txt will write 1 character to that file 1000 times.
In essence creating a 1kb file.
I would like to be able to modify the for loop, say 100000 times, to generate a 1MB file and so on.
Here is what I have tried and it compiles but when executed causes a segmentation fault.
Any suggestions? Sorry C is a language I've never dabbled in.
#include <stdio.h>
int main (int argc, char *argv) {
char ch = 'A';
FILE *fp;
fp = fopen(argv[1], "wb");
int i;
for (i = 0; i < 1000; i++) {
fwrite(&ch, sizeof(char), 1, fp);
}
fclose(fp);
return 0;
}
If you compile with warnings, you get a hint as to the exact problem:
test.c:3:5: warning: second argument of ‘main’ should be ‘char **’ [-Wmain]
int main (int argc, char *argv) {
^
All your troubles start downstream of this error. Fix this argument, and your code will work.
In the future, get into the habit of compiling with warnings turned on:
$ gcc -Wall foo.c
...
This will help catch typos and other oddities that will cause problems.
Since you tagged it Linux, this is how you can do it with the system-level functions (this should be a correct, most efficient way to do it):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sysexits.h>
#include <fcntl.h>
#include <string.h>
ssize_t /* Write "n" bytes to a descriptor */
writen(int fd, const void *ptr, size_t n);
int
main (int argc, char** argv) {
char buf[1000];
memset(buf, 'A', sizeof(buf));
int fd;
if((fd = open(argv[1], O_WRONLY|O_CREAT, 0666))<0){
perror(argv[1]);
exit(EX_NOPERM);
}
ssize_t left = writen(fd, buf, sizeof(buf));
if(left)
perror("write error\n");
return !!left;
}
ssize_t /* Write "n" bytes to a descriptor */
writen(int fd, const void *ptr, size_t n) {
size_t nleft;
ssize_t nwritten;
nleft = n;
while (nleft > 0) {
if ((nwritten = write(fd, ptr, nleft)) < 0) {
if (nleft == n)
return(-1); /* error, return -1 */
else
break; /* error, return amount written so far */
} else if (nwritten == 0) {
break;
}
nleft -= nwritten;
ptr += nwritten;
}
return(n - nleft); /* return >= 0 */
}
#include <stdio.h>
#include <stdlib.h>
#define SIZE_OF_FILE 1024
int main(int argc, char *argv[])
{
FILE *fdest;
char ch = '\n';
if(argc != 2)
exit(EXIT_FAILURE);
fdest = fopen(argv[1], "wb");
if (fdest == NULL)
exit(EXIT_FAILURE);
fseek(fdest, SIZE_OF_FILE - 1, SEEK_CUR);
fwrite(&ch, sizeof(char), 1, fdest);
fclose(fdest);
return 0;
}
In essence creating a 1kb file
if the only purpose is creating a file with sizeof x, it is more simple i belive.

DBus : transmit a Data Array but crash

I would like to transmit a data array from one application to the other via DBus.
My code as below:
server.c:
/* server.c */
#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
DBusHandlerResult filter_func(DBusConnection *connection,
DBusMessage *message, void *usr_data)
{
DBusMessage *reply;
dbus_bool_t handled = false;
char *pReadData;
unsigned char len;
unsigned char i;
DBusError dberr;
dbus_error_init(&dberr);
printf("pReadData = %x\n", (unsigned int)pReadData);
if(FALSE == dbus_message_get_args(message, &dberr, DBUS_TYPE_ARRAY,
DBUS_TYPE_BYTE, &pReadData, &len, DBUS_TYPE_INVALID) && 0 != len)
{
//printf("len = %d\n");
//printf("receiver data error\n");
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
if(0 == len)
return DBUS_HANDLER_RESULT_HANDLED;
printf("len = %d, ", len);
for( i = 0; i < len; i++)
printf("%#2x ", (unsigned char)pReadData[i]);
printf("\n");
handled = true;
printf("pReadData = %x\n", (unsigned int)pReadData);
/*if one free pReadData, it will crash!*/
//dbus_free_string_array((char**)&pReadData);
return (handled ? DBUS_HANDLER_RESULT_HANDLED :
DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
}/*filter_func*/
int main(int argc, char *argv[])
{
DBusError dberr;
DBusConnection *dbconn;
dbus_error_init(&dberr);
dbconn = dbus_bus_get(DBUS_BUS_SESSION, &dberr);
if (!dbus_connection_add_filter(dbconn, filter_func, NULL, NULL)) {
return -1;
}
dbus_bus_add_match(dbconn, "type='signal',interface='gaiger.Drstein.Demonstration'", &dberr);
while(dbus_connection_read_write_dispatch(dbconn, -1)) {
/* loop */
}
return 0;
}/*main*/
And client.c
#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int db_send(DBusConnection *dbconn)
{
DBusMessage *dbmsg;
char *pSendData;
unsigned char len;
unsigned char i;
pSendData = (char *)malloc(256);
dbmsg = dbus_message_new_signal("/client/signal/Object",
"gaiger.Drstein.Demonstration", "Test");
len = 6;
for(i = 0; i < len; i++)
pSendData[i] = (unsigned char)i;
if (!dbus_message_append_args(dbmsg, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
&pSendData, len, DBUS_TYPE_INVALID))
{
return -1;
}
if (!dbus_connection_send(dbconn, dbmsg, NULL)) {
return -1;
}
dbus_connection_flush(dbconn);
printf("send message : len = %d, ", len );
for( i = 0; i < len; i++)
printf("%#x ", (unsigned char)pSendData[i]);
printf("\n");
dbus_message_unref(dbmsg);
free(pSendData);
return 0;
}/**/
int main(int argc, char *argv[])
{
unsigned int i;
DBusError dberr;
DBusConnection *dbconn;
dbus_error_init(&dberr);
dbconn = dbus_bus_get(DBUS_BUS_SESSION, &dberr);
#if(1)
for(i = 0; i < 3; i++)
db_send(dbconn);
#else
while(dbus_connection_read_write_dispatch(dbconn, -1)) {
db_send(dbconn);
}
#endif
dbus_connection_unref(dbconn);
return 0;
}
The code works in Ubuntu 14.4, x86-64, but it crash in printing received data in Fedora 21, x86-32, virtual machine.
For the line :
if(FALSE == dbus_message_get_args(message, &dberr, DBUS_TYPE_ARRAY,
DBUS_TYPE_BYTE, &pReadData, &len, DBUS_TYPE_INVALID) && 0 != len)
I know the pointer pReadData would be allocated by dbus itself, the address value after this line is 0x90000 in Fedora 21, it is very odd number.
How should I do to avoid crash but print received data values in Fedora 21 x86 32bit?
Thank your help.
The documentation for dbus_message_get_args says to look at dbus_message_iter_get_fixed_array, and there we see that the len argument is a pointer to an integer (since in DBus "Arrays have a maximum length defined to be 2 to the 26th power or 67108864 (64 MiB).") but you are passing a pointer to an unsigned char. Use int len; on line 15 of the server.
Also you should not assume that an int and a pointer are the same size, and instead use a long to print the pointer.
printf("pReadData = %lx\n", (unsigned long)pReadData);

Low Level IO with Crypt

I am trying to compare a encrypted string that is taken from each line of a file to AAAA-ZZZZ until it finds its match of the password. I am guaranteed that the user password is of 4 characters. What I am trying to do is take in the file using LowLevel IO and output to a new file with the decrypted passwords of each line. I am not the best at C programming yet so please be gentle. I need direction on how to create an array or list going from AAAA all the way to ZZZZ and then comparing each to the decrypted version of the file line.
How to decrypt the file line by line and save it to a char []
How to compare each line to another char [] until password is found
For Example:
if the line is $1$6gMKIopE$I.zkP2EvrXHDmApzYoV.B. and the next line is $1$pkMKIcvE$WQfqzTNmcQr7fqsNq7K2p0. Assuming the resulting password after decryption is ABSZ and TAZE the new file will result it ABSZ on the first line and TAZE for the second line.
This is what I have so far:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void pdie(const char *);
void die(const char *);
#define BUFFER_SIZE 1024
int main(void)
{
char *pass;
int rfd;
int wfd;
char buffer[BUFFER_SIZE];
char *bp;
int bufferChars;
int writtenChars;
if ((rfd = open("pass.txt", O_RDONLY, 0)) < 0)
pdie("Open failed");
if ((wfd = open("passout.txt", O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0)
pdie("Open failed");
while (1)
{
if ((bufferChars = read(rfd, buffer, BUFFER_SIZE)) > 0)
{
printf("%s", buffer);
bp = buffer;
pass = crypt(getpass(all(4,4,'a','z')), *bp);
printf(pass);
while (bufferChars > 0)
{
if ((writtenChars = write(wfd, bp, bufferChars)) < 0)
pdie("Write failed");
bufferChars -= writtenChars;
bp += writtenChars;
}
}
else if (bufferChars == 0)
break;
else
pdie("Read failed");
}
close(rfd);
close(wfd);
return 0;
}
void pdie(const char *mesg) {
perror(mesg);
exit(1);
}
void die(const char *mesg) {
fputs(mesg, stderr);
fputc('\n', stderr);
exit(1);
}
int inc(char *c,char begin, char end){
if(c[0]==0) return 0;
if(c[0] == end){ // This make the algorithm to stop at char 'f'
c[0]=begin; // but you can put any other char
return inc(c+sizeof(char), begin, end);
}
c[0]++;
return 1;
}
int all(int a, int n,char begin, char end){
int i,j;
char *c = malloc((n+1)*sizeof(char));
for(i=a;i<=n;i++){
for(j=0;j<i;j++) c[j]=begin;
c[i]=0;
do {
printf("%s\n",c);
} while(inc(c,begin,end));
}
free(c);
}
here is the file:
$1$6gMKIopE$I.zkP2EvrXHDmApzYoV.B.
$1$pkMKIcvE$WQfqzTNmcQr7fqsNq7K2p0
$1$0lMKIuvE$7mOnlu6RZ/cUFRBidK7PK.

Writing to a Named Pipe not showing the full content of a string

I am trying to read data from 2 named pipe and write it to another named pipe concatenating the content from 2 inputs. But why my output only shows the string from first input?
Here is my code:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#define MAX_REC_SIZE 1024
int open_fifo(char *name, int mode) {
mode = mode == O_RDONLY ? (O_RDONLY | O_NONBLOCK): mode;
int fd;
if (access(name, F_OK) == -1) {
if(mkfifo(name, 0777) != 0) {
fprintf(stderr, "Could not create fifo %s\n", name);
exit(EXIT_FAILURE);
}
}
fd = open(name, mode);;
return fd;
}
void read_fifo(int fd, char *out_r) {
memset (out_r, '\0', MAX_REC_SIZE);
do {
if(read(fd, out_r, MAX_REC_SIZE) > 0) {
out_r = strtok(out_r, "\n");
return;
}
} while (1);
}
void write_fifo(int fd, char *out_w) {
write(fd, out_w, sizeof(out_w));
}
int main()
{
int pipe_fd[3], i;
char *pipe_nm[] = {"./in_pipe_1", "./in_pipe_2", "./out_pipe_1"};
int read_mode = O_RDONLY;
int write_mode = O_WRONLY;
char out[MAX_REC_SIZE];
char out_store[MAX_REC_SIZE];
for(i=0; i<3; i++) {
pipe_fd[i] = open_fifo(pipe_nm[i], i == 2 ? write_mode : read_mode);
}
read_fifo(pipe_fd[0], out);
strcpy(out_store, out);
read_fifo(pipe_fd[1], out);
strcat(out_store, out);
strcat(out_store, "\n");
write_fifo(pipe_fd[2], out_store);
return 0;
}
A suspicious part of your code is:
write(fd, out_w, sizeof(out_w))
Here, out_w is not an array, and the sizeof operator would yield the size of a char * pointer, not the length of the block.
You should pass the length of out_store to your write_fifo function.
Also, I'm not really sure what your intent is when using the strtok function.

C programming print a certain amount of bytes to file [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
C programming print a certain amount of bytes to screen
I would like to read partSize amount of bytes from one file, which can be of any type, and print that same exact amount that was read to a new file which already exists. The program I wrote seems to write less than it is suppose to and gives a segmentation fault.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#define PERMS 0777
#include <errno.h>
int main()
{
int createDescriptor;
int openDescriptorOriginal;
int closeCreateDescriptor;
char fileNameOriginal[15]="picture.jpg";
//char fileNameOriginal[15]="myFile.txt";
//char fileNameNew[15]="NEWFILE.txt";
char fileName[15]="NEWFILE.jpg";
int parts;
int partSize;
parts=2;
int bytesRemaining;
int partNumber;
char BUFFER[512];
int readDescriptor;
int openDescriptor;
if ((openDescriptorOriginal = open(fileNameOriginal, O_RDONLY )) == -1)
{
printf("Error opening %s", fileNameOriginal);
exit(EXIT_FAILURE);
}
struct stat buf;
int r = fstat(openDescriptorOriginal, &buf);
if(r)
{
fprintf(stderr, "error: fstat: %s\n",(char *)strerror(errno));
exit(1);
}
int originalFileSize=buf.st_size;
printf("The file is %d Bytes large.\n",originalFileSize);
partSize=((originalFileSize+parts)-1)/parts;
printf("Each part is %.9f Kilobytes large.\n",(double)partSize/1024 );
partNumber=1;
printf("Part number: %d\n", partNumber);
if ((openDescriptor = open(fileName, O_WRONLY )) == -1)
{
printf("Error creating %s\n", fileName);
exit(EXIT_FAILURE);
}
ssize_t count, total;
total = 0;
char *bufff = BUFFER;
while (partSize) {
count = read(openDescriptorOriginal, bufff, partSize);
if (count < 0) {
// handle error
break;
}
if (count == 0)
break;
bufff += count;
total += count;
partSize -= count;
}
write (openDescriptor, BUFFER, total);
printf("\n");
return 0;
}
Some initial problems:
add the CREAT flag to your open() in case the file isn't there.
partSize should not be adjusted
Take out the line where you adjust partSize and it should work.
int bytesReceived;
.... open files ....
while ((bytesReceived = read(openDescriptorOriginal, BUFFER, sizeof(BUFFER)) > 0) {
if (bytesReceived != write(openDescriptor, BUFFER, bytesReceived) {
printError(...);
}
}

Resources