Why I dont see a msg from message queue? - c

I would like to understand how message queues in Unix work. I wrote a simple code which sends a short message to queue and then I can read that message. But my code shows :
And I dont know why - and I cant see a message I send to queue. Heres my code:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
struct mymsgbuf {
long mtype;
char mtext[1024];
}msg;
int send_message(int qid, struct mymsgbuf *buffer )
{
int result = -1, length = 0;
length = sizeof(struct mymsgbuf) - sizeof(long);
if((result = msgsnd(qid, buffer, length, 0)) == -1)
return -1;
return result;
}
int read_message(int qid, long type, struct mymsgbuf *buffer)
{
int result, length;
length = sizeof(struct mymsgbuf) - sizeof(long);
if((result = msgrcv(qid, buffer, length, type, 0)) == -1)
return -1;
printf("Type: %ld Text: %s\n", buffer->mtype, buffer->mtext);
return result;
}
int main(int argc, char **argv)
{
int buffsize = 1024;
int qid = msgget(ftok(".", 0), IPC_CREAT | O_EXCL);
if (qid == -1)
{
perror("msgget");
exit(1);
}
msg.mtype = 1;
strcpy(msg.mtext, "my simple msg");
if((send_message(qid, &msg)) == -1)
{
perror("msgsnd");
exit(1);
}
if((read_message(qid, 1, &msg) == -1))
{
perror("msgrcv");
exit(1);
}
return 0;
}
When I changed a line with msgget for this line:
int qid = msgget(ftok(".", 0), IPC_CREAT | O_EXCL | 0600);
it shows:

From the documentation for msgget:
The low-order 9 bits of msg_perm.mode shall be set equal to the low-order 9 bits of msgflg.
You need to add some permissions to your queue, at least read and write. Do something like:
int qid = msgget(ftok(".", 0), IPC_CREAT | O_EXCL | 0600);

Related

C Programming in Linux, Creating A Simple Database, no data is being inserted into the database

I was working on a C programming database tutorial (linked here- https://www.youtube.com/watch?v=SEenaPQXxFs )
When I go to run my code and insert new data into the database it does generate a data file, but no data is stored in the data file/database at all- im not really sure why its not working, and as far as I can tell no errors populate.
The code I was working on is as follows
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
//give structure to record
typedef struct
{
unsigned int key; //primary key assingment
char fname[16]; // defines length allowed for names
char lname[16]; //same but for last name
unsigned int age;
} person_rec; //gives name to definition
int open_record(char *filename) //function to open record
{
int fd;
fd = open(filename, O_CREAT | O_APPEND, 0644);
if(fd == -1)
perror("open_record");
return fd;
}
void close_record(int fd) //close record
{
close(fd);
}
int insert_record(int fd, person_rec *rec) //unkkown
{
int ret;
ret = write(fd, rec, sizeof(person_rec));
return ret;
}
//function to delete and print
int get_record(int fd, person_rec *rec, int key)
{
int ret;
while( ( ret = read(fd, rec, sizeof(person_rec)) ) != -1)
{
if(ret == 0)
{
memset(rec, 0, sizeof(person_rec)); //clear any errors by resetting size
break;
return ret;
}
else if (key == rec->key)
return ret;
}
memset(rec, 0, sizeof(person_rec)); //clear record if error due to -1 size
return ret;
}
//delete function
int delete_record(int fd, int key)
{
int ret;
person_rec rec;
off_t pos;
pos = lseek(fd, 0, SEEK_SET);
while( ( ret = read(fd, &rec, sizeof(person_rec)) ) != -1)
{
if(ret == 0)
{
return ret;
}
else if (key == rec.key)
{
lseek(fd, pos, SEEK_SET);
rec.key = 0;
ret = write(fd, &rec, sizeof(person_rec));
return ret;
}
pos = lseek(fd, 0, SEEK_CUR);
}
return ret;
}
int main(int argc, char *argv[]) //main function/uses all prior defined function to make database ect
{
int fd;
person_rec rec;
fd = open_record("data1");
if(argc > 1)
{
/* insert */
if(argc > 5 && !strcmp(argv[1], "insert"))
{
rec.key = atoi(argv[2]);
strcpy(rec.fname, argv[3]);
strcpy(rec.lname, argv[4]);
rec.age = atoi(argv[5]);
insert_record(fd, &rec);
}
/* delete */
if(argc > 2 && !strcmp(argv[1], "delete"))
delete_record(fd, atoi(argv[2]));
/*print */
if(argc > 2 && !strcmp(argv[1], "print"))
{
get_record(fd, &rec, atoi(argv[2]));
printf("key = %d\n", rec.key);
printf("First = %s\n", rec.fname);
printf("Last = %s\n", rec.lname);
printf("Age = %d\n", rec.age);
}
}
return 0;
}
From the open man page:
The argument flags must include one of the following access modes: O_RDONLY, O_WRONLY, or O_RDWR.
So:
fd = open(filename, O_CREAT | O_APPEND, 0644);
should be:
fd = open(filename, O_CREAT | O_APPEND | O_RDWR, 0644);
I don't see any call to fclose() or fflush() to empty buffer to disk. Add fflush() after every write or fclose() before exiting the program.

List and filter file using c REGEX expression [duplicate]

This question already has answers here:
When using regex in C, \d does not work but [0-9] does
(4 answers)
Closed 3 years ago.
In the following code, I am trying to filter out using regex ONLY, the file called test.jpg, what am I doing wrong as the code below is not filtering this out?
I know there are simpler ways, but eventually I would like to change the regex to ^(image_)\\d{3,6}_201412\\d{2}_\\d{6}\\.(jpg)
and also my folder contains 100,000+ files, so I can only use the c getdents function which is super fast compared to any other way
I get the following output:
**************found*******
image_0179_20141212_060714.jpg
#define _GNU_SOURCE
#include <dirent.h> /* Defines DT_* constants */
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <string.h>
#include <regex.h>
#include <stdio.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct linux_dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[];
};
#define BUF_SIZE 1024*1024*5
int
main(int argc, char *argv[])
{
int fd, nread;
char buf[BUF_SIZE];
struct linux_dirent *d;
int bpos;
char d_type;
regex_t reg;
regmatch_t pmatch[40];
#define NAME "image_0179_20141212_060714.jpg"
const char *pattern = "^(image_)\\d{3,6}_201412\\d{2}_\\d{6}\\.(jpg)";
regcomp(&reg, pattern, REG_ICASE | REG_EXTENDED);
int retval = 0;
char buffer[1024] = "";
fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY);
if (fd == -1)
handle_error("open");
for ( ; ; )
{
nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
if (nread == -1)
handle_error("getdents");
if (nread == 0)
break;
for (bpos = 0; bpos < nread;)
{
d = (struct linux_dirent *) (buf + bpos);
d_type = *(buf + bpos + d->d_reclen - 1);
if( d->d_ino != 0 && d_type == DT_REG )
{
//printf("%s\n", (char *)d->d_name );
if (strstr(d->d_name, NAME) != NULL)
{
printf("**************found*******\n");
printf("%s\n", (char *)d->d_name );
};
retval = regexec(&reg, d->d_name, 2, pmatch, 0);
//printf("%d\n",retval);
if(retval==0)
{
printf("**************found regex*******\n");
printf("%s\n", (char *)d->d_name );
}
}
bpos += d->d_reclen;
}
}
regfree(&reg);
exit(EXIT_SUCCESS);
}
use the following regex instead
^image_[0-9]{3,6}_201412[0-9]{2}_[0-9]{6}\.jpg$

System V Message Queues - getting message that already exists

I've been working on a project and one of the tasks that I have to do is passing the string received from another process through a pipe to yet another process but this time I have to use a message queue.
I've managed to learn how msgqueue works and made a simple working program but, the thing is, it works when receiving a string from stdin through fgets.
My question is:
Can I pass a string that is already saved in other variable (for example
char s[20] = "message test"; ) to the msgqueues mtext?
My simple program looks like that:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
struct msgbuf {
long mtype;
char string[20];
};
struct msgbuf mbuf;
int open_queue( key_t keyval ) {
int qid;
if((qid = msgget( keyval, IPC_CREAT | 0660 )) == -1)
return(-1);
return(qid);
}
int send_message( int qid){
int result, size;
size = sizeof mbuf.string;
if((result = msgsnd( qid, &mbuf, size, 0)) == -1)
return(-1);
return(result);
}
int remove_queue( int qid ){
if( msgctl( qid, IPC_RMID, 0) == -1)
return(-1);
return(0);
}
int read_message( int qid, long type){
int result, size;
size = sizeof mbuf.string;
if((result = msgrcv( qid, &mbuf, size, type, 0)) == -1)
return(-1);
return(result);
}
int main(void){
int qid;
key_t msgkey;
msgkey = ftok(".", 'm');
if(( qid = open_queue( msgkey)) == -1) {
perror("openErr");
exit(1);
}
mbuf.mtype = 1;
fgets(mbuf.string, sizeof mbuf.string, stdin);
if((send_message( qid)) == -1) {
perror("sendErr");
exit(1);
}
mbuf.mtype = 1;
if((read_message(qid, mbuf.mtype))== -1){
perror("recERR");
exit(1);
}
printf("Queue: %s\n", mbuf.string);
remove_queue(qid);
return 0;
}
Your code uses fgets() to fill the buffer mbuf.string with input read from stdin. You can instead use something like strcpy(mbuf.string, "message test") where you can pass in a variable or use a hard coded string.
I recommend using the POSIX message queue API as the System V API is deprecated.

Linux : Check if message queue is empty

i want to know if a queue message is empty or not . i have used msg_ctl() as follows it doesn't work :
struct msqid_ds buf;
int num_messages;
rc = msgctl(msqid, IPC_STAT, &buf);
and i've used this peek function :
int peek_message( int qid, long type )
{
int result, length;
if((result = msgrcv( qid, NULL, 0, type, IPC_NOWAIT)) == -1) {
if(errno==E2BIG)
return(1);
}
return(0);
}
in both cases i get the same result before and after sending a message to the queue.
the message gets to the queue successfully , i've tested that with reading what i've sent.
I wrote the sample code that does seem to work properly:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <errno.h>
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
int main(void) {
int msqid;
//msqid = msgget(IPC_PRIVATE, (IPC_CREAT | IPC_EXCL | 0600));
msqid = msgget((key_t)1235, 0600 | IPC_CREAT);
printf("Using message queue %d\n", msqid);
struct msqid_ds buf;
int rc = msgctl(msqid, IPC_STAT, &buf);
uint msg = (uint)(buf.msg_qnum);
printf("# messages before post: %u\n", msg);
printf("Posting message to queue...\n");
struct msgbuf qmsg;
qmsg.mtype = 100;
qmsg.mtext[0] = 'T';
int res = msgsnd(msqid, &qmsg, 1, MSG_NOERROR);
rc = msgctl(msqid, IPC_STAT, &buf);
msg = (uint)(buf.msg_qnum);
printf("# messages after post: %u\n", msg);
return 0;
}
Maybe that will be helpful to you? The number of messages on the queue does seem to increment correctly when using this code.

Why does the following prints 'Resource temporarily unavailable'?

Why does the following code print ‘read(): Resource temporarily unavailable’ 80% of the time? That is the EAGAIN code, which is the same as WOULD BLOCK which means there is no data waiting to be read, but select is returning 1 saying there is data (tested in Linux):
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/errno.h>
int main(int argc, char** argv)
{
int fd = open("/dev/lp0", O_RDWR | O_NONBLOCK);
int ret = 0;
int status = 0;
char buffer[1024];
char teststr[] = "This is a test\n";
char XMIT_STATUS_OFFLINE[] = {0x10,0x04,0x02};
char XMIT_STATUS_ERROR[] = {0x10,0x04,0x03};
char XMIT_STATUS_ROLL[] = {0x10,0x04,0x04};
char XMIT_STATUS_SLIP[] = {0x10,0x04,0x05};
fd_set rfds;
FD_ZERO( &rfds );
FD_SET( fd, &rfds );
struct timeval sleep;
sleep.tv_sec = 5;
sleep.tv_usec = 0;
/* Offline status */
ret = write(fd, XMIT_STATUS_OFFLINE, sizeof(XMIT_STATUS_OFFLINE));
//printf("write() returned %d\n", ret);
do {
ret = select( fd + 1, &rfds, NULL, NULL, &sleep );
} while (ret < 0 && (errno == EINTR));
ret = read(fd, buffer, 1024);
if(ret == -1) {
perror("read(): ");
} else {
status = buffer[0];
if((status & 0x04) != 0)
{
printf("The cover is open.\n");
} else {
printf("OFFLINE is good.\n");
}
}
close(fd);
return 0;
}
Your select call will return 0 after the 5 second timeout elapses if no data is available. Your code will ignore this and try to read from the device anyways. Check for ret == 0 and that will fix your problem.

Resources