1
\$\begingroup\$

The daemon program is associated with a message queue with a predefined key, to be blocked later when waiting for messages.

The two programs implement a producer-consumer problem.

The process sends a message to the queue, and the daemon wakes up to write the message it receives in a file. daemon creates a queue and sends a message to the message queue. The daemon runs for 10 seconds and stops

How can I improve the program? Please criticize the implementation

daemon:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define MSGSZ 128
// Declare the message structure.
typedef struct msgbuf {
    long mtype;
    char mtext[MSGSZ];
} message_buf;

static void skeleton_daemon()
{
pid_t pid;
    pid = fork();
    printf(" fork pid=%d\n",pid);
    if (pid < 0){
    printf("fail fork\n");
        exit(EXIT_FAILURE);}
    
    if (pid > 0){
    printf(" succes exit parent pid=%d\n",pid);
        exit(EXIT_SUCCESS);}
    
    if (setsid() < 0){
    printf(" child fail\n");
        exit(EXIT_FAILURE);}
  // Catch, ignore and handle signals 
    // Implement a working signal handler 
    
    signal(SIGCHLD, SIG_IGN);
    signal(SIGHUP, SIG_IGN);
       // Fork 
    pid = fork();
    /* daca error */
    if (pid < 0){
    printf(" child 2 fail\n");
        exit(EXIT_FAILURE);}
    
    if (pid > 0){
    printf(" child 2 succes, parent exit pid=%d\n",pid);
        exit(EXIT_SUCCESS);}
    
    // Set new file permissions
    umask(0);
    
    // Change the working directory to the root directory
// or another appropriated directory
    //chdir("/");
    // Close all open file descriptors 
    int x;
    for (x = sysconf(_SC_OPEN_MAX); x>=0; x--)
    {
        close (x);
    }
    
}

int main()
{
time_t T = time(NULL);

    skeleton_daemon();
    FILE *fp; 
    char *timp;
    char *sir;
    while (1)
    {
    int msqid;
    key_t key;
    message_buf rbuf;
    key = 1234;
    if ((msqid = msgget(key, 0666)) >= 0) {
    // Incoming message type 1.
    if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) >= 0) {
    timp = ctime(&T);
    fp = fopen( "file.txt" , "a" );
   fwrite( timp, 1 , 24 , fp );
   sir = rbuf.mtext;
    fwrite( sir , 1 , sizeof(sir) , fp );
   fclose(fp);
    }
    }
   // code demon.
       sleep (10);
        break;
    }
   T = time(NULL);
   timp = ctime(&T);
   char str[] = " daemon finished. \n";
   fp = fopen( "file.txt" , "a" );
   fwrite( timp, 1 , 24 , fp );
   fwrite(str , 1 , sizeof(str) -1, fp );
   fclose(fp);
    // message failure, can be read if demonization failed
    printf(" this is not a demon\n");
    return EXIT_SUCCESS;

}

sender:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MSGSZ 128   

// The structure of the message is declared

typedef struct msgbuf {
    long mtype;
    char mtext[MSGSZ];
} message_buf;

main() 
{
    int msqid;
    int msgflg = IPC_CREAT | 0666;
    key_t key;
    message_buf sbuf;
    size_t buf_length;

    key = 1234;

    (void)fprintf(stderr, "\nmsgget: Calling msgget(%#1x,\%#o)\n", key, msgflg);
    
    if ((msqid = msgget(key, 0666 | IPC_CREAT))){;//msgflg)) < 0) {
        perror("msgget");
        exit(1);
    }
    else
        (void)fprintf(stderr, "msgget: msgget succeeded: msgqid = %d\n", msqid);

    // The type 1 message is being sent
    sbuf.mtype = 1;
    (void) fprintf(stderr, "msggeet: msgget succeeded: msqid = %d\n", msqid);
    (void) strcpy(sbuf.mtext, "Did you get this?");
    (void) fprintf(stderr, "msgget: msgget succeeded: msqid = %d\n", msqid);

    buf_length = strlen(sbuf.mtext) + 1;

    //The message is being sent.
    if((msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT)) < 0){
        printf("%d, %d, %s, %d\n", msqid, sbuf.mtype, sbuf.mtext, buf_length);
        perror("msgsnd");
        exit(1);
    }
    else
        printf("Message: \"%s\" Sent\n", sbuf.mtext);

    exit(0);
}
```
\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

Use Header Files For Common Code

The 2 programs share some common code, this code should be in a header file that is used by both programs. If the code isn't in a header file used by both, then both the structure and the constants can get out of sync between the 2 programs. The Key value should be a constant defined in the header file as well. This code should be in the header file:

#define MSGSZ 128   

// The structure of the message is declared

typedef struct msgbuf {
    long mtype;
    char mtext[MSGSZ];
} message_buf;

Daemons Should Not Call Exit

Daemons are services which are part of an operating system, they should never terminate, they are expected to run all the time. The exception to this is that they do need to respond to signals. When they receive a signal they do need to release the resources they are managing so the code needs to handle the signal.

The call to sleep() is also questionable, 10 seconds is too long a time for a daemon to sleep.

Consistency

The daemon uses the EXIT status constants provided by the system, the other program does not. This is inconsistent.

Indentation

The code is not consistently indented, this is a real problem in the daemon.

Posted Code

static void skeleton_daemon()
{
pid_t pid;
    pid = fork();
    printf(" fork pid=%d\n",pid);
    if (pid < 0){
    printf("fail fork\n");
        exit(EXIT_FAILURE);}
    
    if (pid > 0){
    printf(" succes exit parent pid=%d\n",pid);
        exit(EXIT_SUCCESS);}
    
    if (setsid() < 0){
    printf(" child fail\n");
        exit(EXIT_FAILURE);}
  // Catch, ignore and handle signals 
    // Implement a working signal handler 
    
    signal(SIGCHLD, SIG_IGN);
    signal(SIGHUP, SIG_IGN);
       // Fork 
    pid = fork();
    /* daca error */
    if (pid < 0){
    printf(" child 2 fail\n");
        exit(EXIT_FAILURE);}
    
    if (pid > 0){
    printf(" child 2 succes, parent exit pid=%d\n",pid);
        exit(EXIT_SUCCESS);}
    
    // Set new file permissions
    umask(0);
    
    // Change the working directory to the root directory
// or another appropriated directory
    //chdir("/");
    // Close all open file descriptors 
    int x;
    for (x = sysconf(_SC_OPEN_MAX); x>=0; x--)
    {
        close (x);
    }
    
}

int main()
{
time_t T = time(NULL);

    skeleton_daemon();
    FILE *fp; 
    char *timp;
    char *sir;
    while (1)
    {
    int msqid;
    key_t key;
    message_buf rbuf;
    key = 1234;
    if ((msqid = msgget(key, 0666)) >= 0) {
    // Incoming message type 1.
    if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) >= 0) {
    timp = ctime(&T);
    fp = fopen( "file.txt" , "a" );
   fwrite( timp, 1 , 24 , fp );
   sir = rbuf.mtext;
    fwrite( sir , 1 , sizeof(sir) , fp );
   fclose(fp);
    }
    }
   // code demon.
       sleep (10);
        break;
    }
   T = time(NULL);
   timp = ctime(&T);
   char str[] = " daemon finished. \n";
   fp = fopen( "file.txt" , "a" );
   fwrite( timp, 1 , 24 , fp );
   fwrite(str , 1 , sizeof(str) -1, fp );
   fclose(fp);
    // message failure, can be read if demonization failed
    printf(" this is not a demon\n");
    return EXIT_SUCCESS;

}

int main()
{
    time_t T = time(NULL);

    skeleton_daemon();
    FILE* fp;
    char* timp;
    char* sir;
    while (1)
    {
        int msqid;
        key_t key;
        message_buf rbuf;
        key = 1234;
        if ((msqid = msgget(key, 0666)) >= 0) {
            // Incoming message type 1.
            if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) >= 0) {
                timp = ctime(&T);
                fp = fopen("file.txt", "a");
                fwrite(timp, 1, 24, fp);
                sir = rbuf.mtext;
                fwrite(sir, 1, sizeof(sir), fp);
                fclose(fp);
            }
        }
        // code demon.
        sleep(10);
        break;
    }
    T = time(NULL);
    timp = ctime(&T);
    char str[] = " daemon finished. \n";
    fp = fopen("file.txt", "a");
    fwrite(timp, 1, 24, fp);
    fwrite(str, 1, sizeof(str) - 1, fp);
    fclose(fp);
    // message failure, can be read if demonization failed
    printf(" this is not a demon\n");
    return EXIT_SUCCESS;

}

How My IDE Autoindented

static void skeleton_daemon()
{
    pid_t pid;
    pid = fork();
    printf(" fork pid=%d\n", pid);
    if (pid < 0) {
        printf("fail fork\n");
        exit(EXIT_FAILURE);
    }

    if (pid > 0) {
        printf(" succes exit parent pid=%d\n", pid);
        exit(EXIT_SUCCESS);
    }

    if (setsid() < 0) {
        printf(" child fail\n");
        exit(EXIT_FAILURE);
    }
    // Catch, ignore and handle signals 
      // Implement a working signal handler 

    signal(SIGCHLD, SIG_IGN);
    signal(SIGHUP, SIG_IGN);
    // Fork 
    pid = fork();
    /* daca error */
    if (pid < 0) {
        printf(" child 2 fail\n");
        exit(EXIT_FAILURE);
    }

    if (pid > 0) {
        printf(" child 2 succes, parent exit pid=%d\n", pid);
        exit(EXIT_SUCCESS);
    }

    // Set new file permissions
    umask(0);

    // Change the working directory to the root directory
// or another appropriated directory
    //chdir("/");
    // Close all open file descriptors 
    int x;
    for (x = sysconf(_SC_OPEN_MAX); x >= 0; x--)
    {
        close(x);
    }

}
\$\endgroup\$
1
  • \$\begingroup\$ If you down vote my answer, please be provide a comment as to why you down vote my answer. I'm not perfect to be sure. I don't argue with people that leave comments or down vote my answers. \$\endgroup\$
    – pacmaninbw
    Jun 7, 2022 at 21:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.