From 9fd3ac4a263b844c1730cdabc6365e7ef01ee22e Mon Sep 17 00:00:00 2001 From: Jack-Benny Persson Date: Fri, 29 Mar 2019 05:43:54 +0100 Subject: [PATCH] Bokens exempelprogram --- daemon-ex1.c | 60 ++++++++++++++++++++++++++ daemon-sig-ex1.c | 96 +++++++++++++++++++++++++++++++++++++++++ daemon-sig-ex2.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++ fifo-ex1.c | 74 +++++++++++++++++++++++++++++++ my-msg-recv-rm.c | 45 +++++++++++++++++++ my-msg-recv.c | 45 +++++++++++++++++++ my-msg-send.c | 53 +++++++++++++++++++++++ sig-client.c | 61 ++++++++++++++++++++++++++ simple-ls-ver1.c | 100 ++++++++++++++++++++++++++++++++++++++++++ simple-ls-ver2.c | 75 ++++++++++++++++++++++++++++++++ 10 files changed, 719 insertions(+) create mode 100644 daemon-ex1.c create mode 100644 daemon-sig-ex1.c create mode 100644 daemon-sig-ex2.c create mode 100644 fifo-ex1.c create mode 100644 my-msg-recv-rm.c create mode 100644 my-msg-recv.c create mode 100644 my-msg-send.c create mode 100644 sig-client.c create mode 100644 simple-ls-ver1.c create mode 100644 simple-ls-ver2.c diff --git a/daemon-ex1.c b/daemon-ex1.c new file mode 100644 index 0000000..aa97f1b --- /dev/null +++ b/daemon-ex1.c @@ -0,0 +1,60 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include + +int main(void) +{ + pid_t process_id = 0; + pid_t sid = 0; + + /* Skapa barn/child process */ + process_id = fork(); + + /* Hantera eventuellt fel vid fork() */ + if (process_id < 0) + { + fprintf(stderr, "fork failed!\n"); + exit(1); + } + + /* Förälderprocessen/parent process. + Avsluta den eftersom allt arbete kommer att + utföras av demonen. Skriv också ut demonens PID */ + else if (process_id > 0) + { + printf("Daemon process: %d \n", process_id); + exit(0); + } + + /* Sätt umask till 000 så att alla kan komma eventuella + filer skapade av demonen. Anpassas efter vad demonen + ska användas till */ + umask(0); + /* Starta en ny session */ + sid = setsid(); + + if(sid < 0) + { + /* Avsluta ifall det inte gick att skapa en ny + session */ + fprintf(stderr, "Failure to set new session\n"); + exit(1); + } + + /* Ändra aktuell katalog till / */ + chdir("/"); + + /* Stäng stdin, stdout och stderr. Dessa behövs inte + i en demonprocess */ + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + /* Här börjar demonens arbete... */ + for(;;) + { + sleep(5); + } +} diff --git a/daemon-sig-ex1.c b/daemon-sig-ex1.c new file mode 100644 index 0000000..60265a3 --- /dev/null +++ b/daemon-sig-ex1.c @@ -0,0 +1,96 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include + +void sigHandler(int sig); + +int main(void) +{ + pid_t process_id = 0; + pid_t sid = 0; + FILE *fp; + char pidfile[] = "/tmp/daemon-sig-ex.pid"; + + /* Skapa barn/child process */ + process_id = fork(); + + /* Hantera eventuellt fel vid fork() */ + if (process_id < 0) + { + fprintf(stderr, "fork misslyckades!\n"); + exit(1); + } + + /* Förälderprocessen/parent process. + Avsluta den eftersom allt arbete kommer att + utföras av demonen. Skriv också ut demonens PID */ + else if (process_id > 0) + { + printf("Demonens PID: %d \n", process_id); + fp = fopen(pidfile, "w"); + fprintf(fp, "%d", process_id); + fclose(fp); + exit(0); + } + + /* Sätt umask till 000 så att alla kan komma eventuella + filer skapade av demonen. Anpassas efter vad demonen + ska användas till */ + umask(0); + /* Starta en ny session */ + sid = setsid(); + + if(sid < 0) + { + /* Avsluta ifall det inte gick att skapa en ny + session */ + fprintf(stderr, "Misslyckades att skapa en ny session\n"); + exit(1); + } + + /* Ändra aktuell katalog till / */ + chdir("/"); + + /* Stäng stdin, stdout och stderr. Dessa behövs inte + i en demonprocess */ + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + /* Registrera signalhanterarna, en för varje signal + som vi vill fånga upp */ + signal(SIGUSR1, sigHandler); + signal(SIGTERM, sigHandler); + + /* Demonens arbete... */ + for(;;) + { + sleep(5); + } + return 0; +} + +void sigHandler(int sig) +{ + if (sig == SIGUSR1) + { + /* Skriv till syslog-demonen */ + syslog(LOG_DAEMON, "Tog emot SIGUSR1"); + } + else if (sig == SIGTERM) + { + /* Samma som ovan */ + syslog(LOG_DAEMON, "Tog emot SIGTERM"); + } + else + { + syslog(LOG_DAEMON, "Någonting hände med demonen..."); + } + /* Signalhanteraren återställs efter första signalen, + vi måste därför sätta den igen */ + signal(sig, sigHandler); +} diff --git a/daemon-sig-ex2.c b/daemon-sig-ex2.c new file mode 100644 index 0000000..30aedf8 --- /dev/null +++ b/daemon-sig-ex2.c @@ -0,0 +1,110 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include + +char pidfile[] = "/tmp/daemon-sig-ex.pid"; + +void sigHandler(int sig); +void shutDown(int sig); + +int main(void) +{ + pid_t process_id = 0; + pid_t sid = 0; + FILE *fp; + + /* Skapa barn/child process */ + process_id = fork(); + + /* Hantera eventuellt fel vid fork() */ + if (process_id < 0) + { + fprintf(stderr, "fork misslyckades!\n"); + exit(1); + } + + /* Förälderprocessen/parent process. + Avsluta den eftersom allt arbete kommer att + utföras av demonen. Skriv också ut demonens PID */ + else if (process_id > 0) + { + printf("Demonens PID: %d \n", process_id); + fp = fopen(pidfile, "w"); + fprintf(fp, "%d", process_id); + fclose(fp); + exit(0); + } + + /* Sätt umask till 000 så att alla kan komma eventuella + filer skapade av demonen. Anpassas efter vad demonen + ska användas till */ + umask(0); + /* Starta en ny session */ + sid = setsid(); + + if(sid < 0) + { + /* Avsluta ifall det inte gick att skapa en ny + session */ + fprintf(stderr, "Misslyckades att skapa en ny session\n"); + exit(1); + } + + /* Ändra aktuell katalog till / */ + chdir("/"); + + /* Stäng stdin, stdout och stderr. Dessa behövs inte + i en demonprocess */ + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + /* Registrera signalhanterarna, en för varje signal + som vi vill fånga upp */ + signal(SIGUSR1, sigHandler); + signal(SIGTERM, sigHandler); + signal(SIGABRT, shutDown); + signal(SIGQUIT, shutDown); + signal(SIGINT, shutDown); + + /* Demonens arbete... */ + for(;;) + { + sleep(5); + } + return 0; +} + +void sigHandler(int sig) +{ + if (sig == SIGUSR1) + { + /* Skriv till syslog-demonen */ + syslog(LOG_DAEMON, "Tog emot SIGUSR1"); + } + else if (sig == SIGTERM) + { + /* Samma som ovan */ + syslog(LOG_DAEMON, "Tog emot SIGTERM"); + } + else + { + syslog(LOG_DAEMON, "Någonting hände med demonen..."); + } + /* Signalhanteraren återställs efter första signalen, + vi måste därför sätta den igen */ + signal(sig, sigHandler); +} + +void shutDown(int sig) +{ + syslog(LOG_DAEMON, "Demonens avslutas"); + /* Ta bort PID-filen efter oss */ + if ( unlink(pidfile) == -1 ) + syslog(LOG_DAEMON, "Kunde inte ta bort PID-filen"); + exit(0); +} diff --git a/fifo-ex1.c b/fifo-ex1.c new file mode 100644 index 0000000..596b1c6 --- /dev/null +++ b/fifo-ex1.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define FIFONAM "/tmp/testfifo" + +/* Skapa fifofd i det globala scopet så att + vi kan stänga den ifrån signalhanteraren. */ +int fifofd; + +void cleanUp(int signum); + +int main(void) +{ + char msg[] = "Ett meddelande till klienterna\n"; + + /* Registrera signalhanterare för vanliga "avsluts-signaler" */ + signal(SIGINT, cleanUp); + signal(SIGQUIT, cleanUp); + signal(SIGABRT, cleanUp); + signal(SIGTERM, cleanUp); + /* Skapa FIFOn. S_IWUSR och S_IRUSR är detsamma som för + open() och creat() */ + if ( mkfifo(FIFONAM, S_IWUSR | S_IRUSR) != 0) + { + if (errno == EEXIST) + { + fprintf(stderr, "FIFOn finns redan, använder den\n"); + } + else + { + perror("mkfifo"); + return 1; + } + } + + /* Kör i en oändlig loop */ + while(1) + { + fifofd = open(FIFONAM, O_WRONLY); + if (fifofd < 0) + { + perror("open"); + return 1; + } + + write(fifofd, msg, sizeof(msg)); + sleep(1); /* Vänta en sekund mellan varje körning */ + } + /* Hit bör vi aldrig komma, men fall i fall så städar vi upp */ + unlink(FIFONAM); + close(fifofd); + return 0; +} + +void cleanUp(int signum) +{ + /* Ständ fildeskriptorn */ + if ( close(fifofd) == -1 ) + perror("cleanUp - close"); + + /* Radera FIFO-filen från systemet & avsluta programmet */ + if ( unlink(FIFONAM) == -1 ) + { + perror("cleanUp - unlink"); + exit(1); + } + exit(0); +} diff --git a/my-msg-recv-rm.c b/my-msg-recv-rm.c new file mode 100644 index 0000000..4500059 --- /dev/null +++ b/my-msg-recv-rm.c @@ -0,0 +1,45 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include + +#define MAX 100 + +int main(void) +{ + /* Struktur som krävs av msgsnd & msgrcv */ + struct msgbuf + { + long mtype; + char mtext[MAX]; + }; + + int id; + key_t key = 12345; + struct msgbuf msg; + msg.mtext[0] = '\0'; + + /* Kalla msgget för att få ett ID-nummer till kön. + Observera att vi här utelämnar IPC_CREAT. */ + if ( (id = msgget(key, 0660)) < 0 ) + { + fprintf(stderr, "Could not open message queue\n"); + perror("msgget"); + return 1; + } + + /* Ta emot meddelandet och spara det i msg */ + if ( msgrcv(id, &msg, MAX, 1, 0) < 0 ) + { + fprintf(stderr, "Could not receive messages\n"); + perror("msgrcv"); + return 1; + } + + /* Skriv ut meddelandet */ + printf("%s\n", msg.mtext); + msgctl(id, IPC_RMID, 0); + return 0; +} diff --git a/my-msg-recv.c b/my-msg-recv.c new file mode 100644 index 0000000..9d8e9cd --- /dev/null +++ b/my-msg-recv.c @@ -0,0 +1,45 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include + +#define MAX 100 + +int main(void) +{ + /* Struktur som krävs av msgsnd & msgrcv */ + struct msgbuf + { + long mtype; + char mtext[MAX]; + }; + + int id; + key_t key = 12345; + struct msgbuf msg; + msg.mtext[0] = '\0'; + + /* Kalla msgget för att få ett ID-nummer till kön. + Observera att vi här utelämnar IPC_CREAT. */ + if ( (id = msgget(key, 0660)) < 0 ) + { + fprintf(stderr, "Could not open message queue\n"); + perror("msgget"); + return 1; + } + + /* Ta emot meddelandet och spara det i msg */ + if ( msgrcv(id, &msg, MAX, 1, 0) < 0 ) + { + fprintf(stderr, "Could not receive messages\n"); + perror("msgrcv"); + return 1; + } + + /* Skriv ut meddelandet */ + printf("%s\n", msg.mtext); + + return 0; +} diff --git a/my-msg-send.c b/my-msg-send.c new file mode 100644 index 0000000..dfeb4a2 --- /dev/null +++ b/my-msg-send.c @@ -0,0 +1,53 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include + +#define MAX 100 + +int main(void) +{ + /* Struktur som krävs av msgsnd & msgrcv */ + struct msgbuf + { + long mtype; + char mtext[MAX]; + }; + + /* Variabler vi behöver */ + int id; + key_t key = 12345; + struct msgbuf msg; + size_t msglen; + msg.mtext[0] = '\0'; + + /* Kalla msgget för att få ett ID-nummer till kön. + IPC_CREAT är flaggan för att skapa en kö. 0660 + är rättigheterna för kön */ + if ( (id = msgget(key, IPC_CREAT | 0660)) < 0 ) + { + fprintf(stderr, "Could not create message queue\n"); + perror("msgget"); + return 1; + } + + /* Komponera ett testmeddelande. mtype är till för att + identifiera just detta meddelandet i kön. mtext är + det faktiska innehållet och msglen är längden på + meddelandet */ + msg.mtype = 1; + strcat(msg.mtext, "Hejsan svejsan"); + msglen = strlen(msg.mtext) + 1; + + /* Skicka meddelandet */ + if ( msgsnd(id, &msg, msglen, IPC_NOWAIT) < 0 ) + { + fprintf(stderr, "Could not send message\n"); + perror("msgsend"); + return 1; + } + + return 0; +} diff --git a/sig-client.c b/sig-client.c new file mode 100644 index 0000000..7a20af1 --- /dev/null +++ b/sig-client.c @@ -0,0 +1,61 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include + +void printUsage(char *arg); + +int main(int argc, char* argv[]) +{ + FILE *fp; + int opt; + pid_t process_id; + char pidfile[] = "/tmp/daemon-sig-ex.pid"; + + /* Kontrollera ifall PID-filen finns */ + if ( (fp = fopen(pidfile, "r")) == 0 ) + { + fprintf(stderr, "Ingen PID-fil, körs verkligen demonen?\n"); + return 1; + } + /* Läs in PID till process_id variabeln */ + fscanf(fp, "%d", &process_id); + + /* Om inga argument angavs, skriv ut demonens PID */ + if (argc == 1) + printf("Demonen körs med PID: %d\n", process_id); + + /* Behandla argument till programmet */ + while ((opt = getopt(argc, argv, "utqh")) != -1) + { + switch (opt) + { + case 'u': + kill(process_id, SIGUSR1); + break; + case 't': + kill(process_id, SIGTERM); + break; + case 'q': + kill(process_id, SIGQUIT); + break; + case 'h': + printUsage(argv[0]); + return 0; + default: + printUsage(argv[0]); + return 1; + } + } + return 0; +} + +void printUsage(char *arg) +{ + fprintf(stderr, "Usage: %s [-u] [-t] [-q] [-h]\n" + "-u = send SIGUSR1 to daemon\n" + "-t = send SIGTERM to daemon\n" + "-q = send SIGQUIT to quit the daemon\n" + "-h = display help\n", arg); +} diff --git a/simple-ls-ver1.c b/simple-ls-ver1.c new file mode 100644 index 0000000..c8b3d7e --- /dev/null +++ b/simple-ls-ver1.c @@ -0,0 +1,100 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include + +void printUsage(char *arg); + +int main(int argc, char **argv) +{ + int typ; + char opt[5] = { 0 }; + + /* Skapa pekare och struct */ + DIR *d; + struct dirent *dir; + struct stat s; + + /* Läs in aktuell katalog */ + d = opendir("."); + /* Om 'd' INTE är sant (! = inte sant) */ + if (!d) + { + printf("Kan inte läsa aktuell katalog\n"); + return 1; + } + + /* Behandla arugment */ + if (argc == 1) + { + strncpy(opt, "-a", 2); + } + else if (argc == 2) + { + strncpy(opt, argv[1], 2); + + /* Hjälptext */ + if ( strcmp(opt, "-h") == 0 ) + printUsage(argv[0]); + + /* Visa endast filer */ + else if ( strcmp(opt, "-f") == 0 ) + { + typ = S_IFREG; + } + + /* Visa endast kataloger */ + else if ( strcmp(opt, "-d") == 0 ) + { + typ = S_IFDIR; + } + + /* Visa alla filer */ + else if ( strcmp(opt, "-a") == 0 ) + { + ; + } + + /* Om vi angav ett felaktigt argument */ + else + { + printUsage(argv[0]); + return 1; + } + } + /* Om vi angav fel antal argument */ + else + { + printUsage(argv[0]); + return 1; + } + + /* Skriv ut innehållet i katalogen */ + while ((dir = readdir(d)) != NULL) + { + if ( strcmp(opt, "-a") == 0 ) + { + printf("%s\n", dir->d_name); + } + else + { + stat(dir->d_name, &s); + /* Se kapitlet om 'Bitvisa operationer' */ + if ((s.st_mode & S_IFMT) == typ) + printf("%s\n", dir->d_name); + } + } + + /* Stäng "d" och returnera noll */ + closedir(d); + return 0; +} + +void printUsage(char *arg) +{ + printf("Usage: %s [-a] [-f] [-d]\n" + " -a to list all types (default)\n" + " -f to list only files\n" + " -d to list only directories\n", arg); +} diff --git a/simple-ls-ver2.c b/simple-ls-ver2.c new file mode 100644 index 0000000..5517699 --- /dev/null +++ b/simple-ls-ver2.c @@ -0,0 +1,75 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include + +void printUsage(char *arg); + +int main(int argc, char **argv) +{ + int opt; + int typ = -1; + char *path = "."; + + /* Skapa pekare och struct */ + DIR *d; + struct dirent *dir; + struct stat s; + + /* Behandla argument med getopt */ + while ((opt = getopt(argc, argv, "hafdp:")) != -1) + { + switch (opt) + { + case 'a': + typ = -1; + break; + case 'f': + typ = S_IFREG; + break; + case 'd': + typ = S_IFDIR; + break; + case 'p': + path = optarg; + break; + case 'h': + printUsage(argv[0]); + return 0; + default: + printUsage(argv[0]); + return 1; + } + } + + /* Byt katalog med chdir() för att stat() ska + se filerna i rätt katalog */ + chdir(path); + + d = opendir(path); + while ((dir = readdir(d)) != NULL) + { + if ( typ == -1 ) + { + printf("%s\n", dir->d_name); + } + else + { + stat(dir->d_name, &s); + /* Se kapitlet om 'Bitvisa operationer' */ + if ((s.st_mode & S_IFMT) == typ) + printf("%s\n", dir->d_name); + } + } + return 0; +} + +void printUsage(char *arg) +{ + printf("Usage: %s [-a] [-f] [-d] [-p path]\n" + " -a to list all types (default)\n" + " -f to list only files\n" + " -d to list only directories\n" + " -p to specify a directory\n", arg); +}