/* * Deal with signals. * * LOCKING: acquires and releases configlock. */ void * signal_thread(void *arg) { int err, signo; for (;;) { err = sigwait(&mask, &signo); if (err != 0) log_quit("sigwait failed: %s", strerror(err)); switch (signo) { case SIGHUP: /* * Schedule to re-read the configuration file. */ pthread_mutex_lock(&configlock); reread = 1; pthread_mutex_unlock(&configlock); break; case SIGTERM: kill_workers(); log_msg("terminate with signal %s", strsignal(signo)); exit(0); default: kill_workers(); log_quit("unexpected signal %d", signo); } } }
int dial_next(Dialers *dialptr) /* pointers in structure are filled in */ { if (fpdial == NULL) { if ( (fpdial = fopen(DIALERS, "r")) == NULL) log_sys("can't open %s", DIALERS); diallineno = 0; } again: if (fgets(dialline, MAXLINE, fpdial) == NULL) return(-1); /* EOF */ diallineno++; if ( (dialptr->dialer = strtok(dialline, WHITE)) == NULL) { if (dialline[0] == '\n') goto again; /* ignore empty line */ log_quit("missing `dialer' in Dialers file, line %d", diallineno); } if (dialptr->dialer[0] == '#') goto again; /* ignore comment line */ if ( (dialptr->sub = strtok(NULL, WHITE)) == NULL) log_quit("missing `sub' in Dialers file, line %d", diallineno); if ( (dialptr->expsend = strtok(NULL, "\n")) == NULL) log_quit("missing `expsend' in Dialers file, line %d", diallineno); return(0); }
int main(int argc, char *argv[]) { int c; log_open("calld", LOG_PID, LOG_USER); opterr = 0; /* don't want getopt() writing to stderr */ while ((c = getopt(argc, argv, "d")) != EOF) { switch (c) { case 'd': /* debug */ log_to_stderr = 1; break; case '?': log_quit("unrecognized option: -%c", optopt); } } if (log_to_stderr == 0) daemonize("calld"); loop(); /* never returns */ return 0; }
int scheduler_init() { if(g_read_fd != CLEARED_SOCKET) { return -2; } /* convention : 0: read 1: write */ int sv[2]; if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) { int err = ERRNO_ERROR; log_quit("scheduler: socketpair error %r", err); return err; } g_read_fd = sv[0]; g_write_fd = sv[1]; threaded_queue_init(&scheduler_queue, SCHEDULER_MAX_TASKS); return g_read_fd; }
void ed_quit(Context_t *ctx) { buf_free(ctx->c_buffer); buf_free(ctx->cmd_buffer); ncs_close(ctx->scr); ncs_quit(); log_quit(); }
void client_sigchld(pid_t pid, int stat) { int i; for (i = 0; i < client_size; i++) { if (client[i].pid == pid) { client[i].childdone = stat; /* child's exit() status +1 */ return; } } log_quit("can't find client entry for pid %d", pid); }
void client_del(int fd) { int i; for (i = 0; i < client_size; i++) { if (client[i].fd == fd) { client[i].fd = -1; return; } } log_quit("can't find client entry for fd %d", fd); }
void scheduler_process() { scheduler_packet *packet; if(g_read_fd < 0) { return; } MALLOC_OR_DIE(scheduler_packet*, packet, sizeof (scheduler_packet), SCHDPAKT_TAG); int len = SCHEDULER_PACKET_LEN; u8* p = (u8*)packet; do { int n = read(g_read_fd, p, len); if(n < 0) { int err = errno; if(err == EINTR) { continue; } log_quit("scheduler: read error: %r", ERRNO_ERROR); free(packet); return; } len -= n; p += n; } while(len > 0); /* packet is the native-order pointer to the scheduler_task to add to the queue */ threaded_queue_enqueue(&scheduler_queue, packet); }
void scheduler_schedule_task(scheduler_task_callback* function, void* args) { scheduler_packet packet; u8* p = (u8*) & packet; ssize_t len = sizeof (scheduler_packet); ssize_t n; /* #ifndef NDEBUG log_debug("scheduler: scheduler_schedule_task(%P,%p)'", function, args); #endif */ packet.task = function; packet.args = args; if(g_write_fd < 0) { return; } do { n = write(g_write_fd, p, len); if(n <= 0) { int err = errno; if(err == EINTR) { continue; } log_quit("scheduler: write error: %r", err, ERRNO_ERROR); break; } len -= n; p += n; } while(len > 0); }
/* * Initialize the job ID file. Use a record lock to prevent * more than one printer daemon from running at a time. * * LOCKING: none, except for record-lock on job ID file. */ void init_request(void) { int n; char name[FILENMSZ]; sprintf(name, "%s/%s", SPOOLDIR, JOBFILE); jobfd = open(name, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); if (write_lock(jobfd, 0, SEEK_SET, 0) < 0) log_quit("daemon already running"); /* * Reuse the name buffer for the job counter. */ if ((n = read(jobfd, name, FILENMSZ)) < 0) log_sys("can't read job file"); if (n == 0) nextjob = 1; else nextjob = atol(name); }
int main(int argc, char *argv[]) { int err; pthread_t tid; struct sigaction sa; char *cmd; if(NULL == (cmd = strrchr(argv[0], '/'))) cmd = argv[0]; else cmd ++; syslog(LOG_ERR, "main thread id is %u.\n", (unsigned)pthread_self()); // daemonize(cmd); daemon(0, 0); if(already_running()) { syslog(LOG_ERR, "xdaemon already running.\n"); exit(1); } syslog(LOG_ERR, "main thread 2 id is %u.\n", (unsigned)pthread_self()); // /* sa.sa_handler = SIG_DFL; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if(sigaction(SIGHUP, &sa, NULL) < 0) log_quit("can't restore SIGHUP default"); sigfillset(&mask); if((err = pthread_sigmask(SIG_BLOCK, &mask, NULL)) != 0) log_exit(err, "SIG_BLOCK error"); err = pthread_create(&tid, NULL, thread_func, 0); if(err != 0) log_exit(err, "can't create thread"); //*/ test_func(); exit(0); }
/* * Main print server thread. Accepts connect requests from * clients and spawns additional threads to service requests. * * LOCKING: none. */ int main(int argc, char *argv[]) { pthread_t tid; struct addrinfo *ailist, *aip; int sockfd, err, i, n, maxfd; char *host; fd_set rendezvous, rset; struct sigaction sa; struct passwd *pwdp; if (argc != 1) err_quit("usage: printd"); daemonize("printd"); sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &sa, NULL) < 0) log_sys("sigaction failed"); sigemptyset(&mask); sigaddset(&mask, SIGHUP); sigaddset(&mask, SIGTERM); if ((err = pthread_sigmask(SIG_BLOCK, &mask, NULL)) != 0) log_sys("pthread_sigmask failed"); n = sysconf(_SC_HOST_NAME_MAX); if (n < 0) /* best guess */ n = HOST_NAME_MAX; if ((host = malloc(n)) == NULL) log_sys("malloc error"); if (gethostname(host, n) < 0) log_sys("gethostname error"); if ((err = getaddrlist(host, "print", &ailist)) != 0) { log_quit("getaddrinfo error: %s", gai_strerror(err)); exit(1); } FD_ZERO(&rendezvous); maxfd = -1; for (aip = ailist; aip != NULL; aip = aip->ai_next) { if ((sockfd = initserver(SOCK_STREAM, aip->ai_addr, aip->ai_addrlen, QLEN)) >= 0) { FD_SET(sockfd, &rendezvous); if (sockfd > maxfd) maxfd = sockfd; } } if (maxfd == -1) log_quit("service not enabled"); pwdp = getpwnam(LPNAME); if (pwdp == NULL) log_sys("can't find user %s", LPNAME); if (pwdp->pw_uid == 0) log_quit("user %s is privileged", LPNAME); if (setgid(pwdp->pw_gid) < 0 || setuid(pwdp->pw_uid) < 0) log_sys("can't change IDs to user %s", LPNAME); init_request(); init_printer(); err = pthread_create(&tid, NULL, printer_thread, NULL); if (err == 0) err = pthread_create(&tid, NULL, signal_thread, NULL); if (err != 0) log_exit(err, "can't create thread"); build_qonstart(); log_msg("daemon initialized"); for (;;) { rset = rendezvous; if (select(maxfd+1, &rset, NULL, NULL, NULL) < 0) log_sys("select failed"); for (i = 0; i <= maxfd; i++) { if (FD_ISSET(i, &rset)) { /* * Accept the connection and handle the request. */ if ((sockfd = accept(i, NULL, NULL)) < 0) log_ret("accept failed"); pthread_create(&tid, NULL, client_thread, (void *)((long)sockfd)); } } } exit(1); }
void daemonize(const char *cmd) { int i, fd0, fd1, fd2; pid_t pid; struct rlimit rl; struct sigaction sa; /* * Clear file creation mask. */ umask(0); /* * Get maximum number of file descriptors. */ if (getrlimit(RLIMIT_NOFILE, &rl) < 0) log_quit("%s:cannot get file limit", cmd); /* * Become a session leader tro lose controlling TTY. */ if ((pid = fork()) < 0) log_quit("%s:cannot fork", cmd); else if(pid != 0) /* parent */ exit(0); setsid(); /* * Ensure future opens won't allocate controlling TTYs. */ sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if(sigaction(SIGHUP, &sa, NULL) < 0) log_quit("%s:cannot igore SIGHUP", cmd); if((pid = fork()) < 0) log_quit("%s:cannot fork", cmd); else if(pid != 0) /* parent */ exit(0); /* * Change the current working directory to the root so * we won't jprevernt file systems from being unmounted */ if(chdir("/") < 0) log_quit("%s:can't chare dirctory to /", cmd); /* * Close all open file descriptions */ if(rl.rlim_max == RLIM_INFINITY) rl.rlim_max = 1024; for(i = 0; i < rl.rlim_max; i++) close(i); /* * Attach file descriptions 0, 1, and 2 to /dev/null. */ fd0 = open("/dev/null", O_RDWR); fd1 = dup(0); fd2 = dup(0); /* *Initialize the log file. */ openlog(cmd, LOG_CONS, LOG_DAEMON); if(fd0 != 0 || fd1 != 1 || fd2 != 2) { syslog(LOG_ERR, "unexpected file descriptors %d %d %d", fd0, fd1, fd2); exit(1); } }