/** * Copyright 2015 University of Applied Sciences Western Switzerland / Fribourg * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Module: MA-CSEL1 - Building Embedded Systems under Linux * * Abstract: Introduction to the Embedded Linux Development Environment * * Purpose: This module implements a simple application to be launched from * /etc/inttab. * -->> tracing with syslog * * Autĥor: Daniel Gachet * Date: 28.08.2015 */ #define _XOPEN_SOURCE 600 #define _DEFAULT_SOURCE #include #include #include #include #include #include #include #include #include #include #include #define UNUSED(x) (void)(x) static int signal_catched = 0; static void catch_signal (int signal) { syslog (LOG_INFO, "signal=%d catched\n", signal); signal_catched++; } int main(int argc, char* argv[]) { UNUSED(argc); UNUSED(argv); // daemon's steps 1 to 3 skipt // 4. capture all required signals struct sigaction act = {.sa_handler = catch_signal,}; sigaction (SIGHUP, &act, NULL); // 1 - hangup sigaction (SIGINT, &act, NULL); // 2 - terminal interrupt sigaction (SIGQUIT, &act, NULL); // 3 - terminal quit sigaction (SIGABRT, &act, NULL); // 6 - abort sigaction (SIGTERM, &act, NULL); // 15 - termination sigaction (SIGTSTP, &act, NULL); // 19 - terminal stop signal // 5. update file mode creation mask umask(0027); // 6. change working directory to appropriate place if (chdir ("/") == -1) { syslog (LOG_ERR, "ERROR while changing to working directory"); exit (1); } // 7. close all open file descriptors for (int fd = sysconf(_SC_OPEN_MAX); fd >= 0; fd--) { close (fd); } // 8. redirect stdin, stdout and stderr to /dev/null if (open ("/dev/null", O_RDWR) != STDIN_FILENO) { syslog (LOG_ERR, "ERROR while opening '/dev/null' for stdin"); exit (1); } if (dup2 (STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO) { syslog (LOG_ERR, "ERROR while opening '/dev/null' for stdout"); exit (1); } if (dup2 (STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) { syslog (LOG_ERR, "ERROR while opening '/dev/null' for stderr"); exit (1); } // 9. option: open syslog for message logging openlog (NULL, LOG_NDELAY | LOG_PID, LOG_DAEMON); syslog (LOG_INFO, "Daemon has started..."); // 10. option: get effective user and group id for appropriate's one struct passwd* pwd = getpwnam ("daemon"); if (pwd == 0) { syslog (LOG_ERR, "ERROR while reading daemon password file entry"); exit (1); } // 11. option: change root directory if (chroot (".") == -1) { syslog (LOG_ERR, "ERROR while changing to new root directory"); exit (1); } // 12. option: change effective user and group id for appropriate's one if (setegid (pwd->pw_gid) == -1) { syslog (LOG_ERR, "ERROR while setting new effective group id"); exit (1); } if (seteuid (pwd->pw_uid) == -1) { syslog (LOG_ERR, "ERROR while setting new effective user id"); exit (1); } // 13. implement daemon body... int t = 30; do { t = sleep(t); } while (t > 0); syslog (LOG_INFO, "daemon stopped. Number of signals catched=%d\n", signal_catched); closelog(); return 0; }