void tty_open(void) { struct termios term; if ( (psfd = open(DEF_DEVICE, O_RDWR)) < 0) log_sys("tty_open: open error"); if (tcgetattr(psfd, &term) < 0) /* fetch attributes */ log_sys("tty_open: tcgetattr error"); term.c_cflag = CS8 | /* 8-bit data */ CREAD | /* enable receiver */ CLOCAL; /* ignore modem status lines */ /* no parity, 1 stop bit */ term.c_oflag &= ~OPOST; /* turn off post processing */ term.c_iflag = IXON | IXOFF | /* Xon/Xoff flow control */ IGNBRK | /* ignore breaks */ ISTRIP | /* strip input to 7 bits */ IGNCR; /* ignore received CR */ term.c_lflag = 0; /* everything off in local flag: disables canonical mode, disables signal generation, disables echo */ term.c_cc[VMIN] = 1; /* 1 byte at a time, no timer */ term.c_cc[VTIME] = 0; cfsetispeed(&term, DEF_BAUD); cfsetospeed(&term, DEF_BAUD); if (tcsetattr(psfd, TCSANOW, &term) < 0) /* set attributes */ log_sys("tty_open: tcsetattr error"); }
void loop (void) { int i, n, maxfd, maxi, listenfd, clifd, nread; char buf[MAXLINE]; uid_t uid; fd_set rset, allset; FD_ZERO (&allset); /* obtain fd to listen for client requests on */ if ((listenfd = serv_listen (CS_OPEN)) < 0) { log_sys ("serv_listen error"); } FD_SET (listenfd, &allset); maxfd = listenfd; maxi = -1; for (;;) { rset = allset; /* rset gets modified each time around */ if ((n = select (maxfd + 1, &rset, NULL, NULL, NULL)) < 0) { log_sys ("select error"); } if (FD_ISSET (listenfd, &rset)) { /* accept new client request */ if ((clifd = serv_accept (listenfd, &uid)) < 0) { log_sys ("serv_accept error: %d", clifd); } i = client_add (clifd, uid); FD_SET (clifd, &allset); if (clifd > maxfd) { maxfd = clifd; /* max fd for select() */ } if (i > maxi) { maxi = i; /* max index in client[] array */ } log_msg ("new connection: uid %d, fd %d", uid, clifd); } for (i = 0; i <= maxi; i++) { /* go through client[] array */ if ((clifd = client[i].fd) < 0) { continue; } if (FD_ISSET (clifd, &rset)) { /* read argument buffer from client */ if ((nread = read (clifd, buf, MAXLINE)) < 0) { log_sys ("read error on fd %d", clifd); } else if (nread == 0) { log_msg ("closed: uid %d, fd %d", client[i].uid, clifd); client_del (clifd); /* client has closed cxn */ FD_CLR (clifd, &allset); close (clifd); } else { /* process client's request */ request (buf, nread, clifd, client[i].uid); } } } } }
void loop(void) { int listenfd, clifd; int rval, i, nr; int maxi, maxfd; uid_t uid; fd_set rset, allset; char buf[MAXLINE]; /* obtain fd to listen for client request on */ if ((listenfd = serv_listen(CS_OPEN)) < 0) log_sys("serv_listen error"); FD_ZERO(&allset); FD_SET(listenfd, &allset); maxfd = listenfd; maxi = -1; for (;;) { rset = allset; /* rset get modified each time around */ rval = select(maxfd + 1, &rset, NULL, NULL, NULL); if (rval < 0) log_sys("select error"); if (FD_ISSET(listenfd, &rset)) { /* accept new client request */ if ((clifd = serv_accept(listenfd, &uid)) < 0) log_sys("serv_accept error"); i = client_add(clifd, uid); FD_SET(clifd, &allset); if (i > maxi) maxi = i; if (clifd > maxfd) maxfd = clifd; log_msg("new connection: uid %d, fd %d", uid, clifd); continue; } for (i = 0; i <= maxi; i++) { if (client[i].fd == -1) continue; if (FD_ISSET(client[i].fd, &rset)) { /* read argument buffer from client */ if ((nr = read(client[i].fd, buf, MAXLINE)) < 0) { log_sys("read error on fd %d", clifd); } else if (nr == 0) { log_msg("closed: uid %d, fd %d", client[i].uid, clifd); client_del(client[i].fd); /* client has closed cxn */ FD_CLR(clifd, &allset); close(clifd); } else { /* process client's request */ handler_request(buf, nr, clifd, client[i].uid); } } } } }
void loop(void) { int i, maxi, listenfd, clifd, nread; char buf[MAXLINE]; uid_t uid; struct pollfd *pollfd; if ((pollfd = malloc(open_max() * sizeof(struct pollfd))) == NULL) err_sys("malloc error"); /* obtain fd to listen for client requests on */ if ((listenfd = serv_listen(CS_OPEN)) < 0) log_sys("serv_listen error"); client_add(listenfd, 0); /* we use [0] for listenfd */ pollfd[0].fd = listenfd; pollfd[0].events = POLLIN; maxi = 0; for ( ; ; ) { if (poll(pollfd, maxi + 1, -1) < 0) log_sys("poll error"); if (pollfd[0].revents & POLLIN) { /* accept new client request */ if ((clifd = serv_accept(listenfd, &uid)) < 0) log_sys("serv_accept error: %d", clifd); i = client_add(clifd, uid); pollfd[i].fd = clifd; pollfd[i].events = POLLIN; if (i > maxi) maxi = i; log_msg("new connection: uid %d, fd %d", uid, clifd); } for (i = 1; i <= maxi; i++) { if ((clifd = client[i].fd) < 0) continue; if (pollfd[i].revents & POLLHUP) { goto hungup; } else if (pollfd[i].revents & POLLIN) { /* read argument buffer from client */ if ((nread = read(clifd, buf, MAXLINE)) < 0) { log_sys("read error on fd %d", clifd); } else if (nread == 0) { hungup: log_msg("closed: uid %d, fd %d", client[i].uid, clifd); client_del(clifd); /* client has closed conn */ pollfd[i].fd = -1; close(clifd); } else { /* process client's request */ request(buf, nread, clifd, client[i].uid); } } } } }
/* * Update the job ID file with the next job number. * Doesn't handle wrap-around of job number. * * LOCKING: none. */ void update_jobno(void) { char buf[32]; if (lseek(jobfd, 0, SEEK_SET) == -1) log_sys("can't seek in job file"); sprintf(buf, "%d", nextjob); if (write(jobfd, buf, strlen(buf)) < 0) log_sys("can't update job file"); }
void set_block(void) /* turn off nonblocking flag */ { /* called only by block_write() below */ int val; if (block_flag == 0) { if ( (val = fcntl(psfd, F_GETFL, 0)) < 0) log_sys("set_block: fcntl F_GETFL error"); val &= ~O_NONBLOCK; if (fcntl(psfd, F_SETFL, val) < 0) log_sys("set_block: fcntl F_SETFL error"); block_flag = 1; } }
void set_nonblock(void) /* set descriptor nonblocking */ { int val; if (block_flag) { if ( (val = fcntl(psfd, F_GETFL, 0)) < 0) log_sys("set_nonblock: fcntl F_GETFL error"); val |= O_NONBLOCK; if (fcntl(psfd, F_SETFL, val) < 0) log_sys("set_nonblock: fcntl F_SETFL error"); block_flag = 0; } }
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); }
void block_write(const char *buf, int n) { set_block(); if (write(psfd, buf, n) != n) log_sys("block_write: write error"); }
void handle_request(char *buf, int nread, int clifd, uid_t uid) { int newfd; if (buf[nread - 1] != 0) { snprintf(errmsg, MAXLINE - 1, "request from uid %d not null terminated: %*.*s\n", uid, nread, nread, buf); send_err(clifd, -1, errmsg); return; } log_msg("request: %s, from uid %d", buf, uid); /* parse the arguments, set options */ if (buf_args(buf, cli_args) < 0) { send_err(clifd, -1, errmsg); log_msg(errmsg); return; } if ((newfd = open(pathname, oflag)) < 0) { snprintf(errmsg, MAXLINE - 1, "can't open %s: %s\n", pathname, strerror(errno)); send_err(clifd, -1, errmsg); log_msg(errmsg); return; } /* send the desrciptor */ if (send_fd(clifd, newfd) < 0) log_sys("send_fd error"); log_msg("send fd %d over fd %d for %s", newfd, clifd, pathname); close(newfd); /* we're done with desrciptor */ }
/* * Given a keyword, scan the configuration file for a match * and return the string value corresponding to the keyword. * * LOCKING: none. */ static char * scan_configfile(char *keyword) { int n, match; FILE *fp; char keybuf[MAXKWLEN], pattern[MAXFMTLEN]; char line[MAXCFGLINE]; static char valbuf[MAXCFGLINE]; if ((fp = fopen(CONFIG_FILE, "r")) == NULL) log_sys("can't open %s", CONFIG_FILE); sprintf(pattern, "%%%ds %%%ds", MAXKWLEN-1, MAXCFGLINE-1); match = 0; while (fgets(line, MAXCFGLINE, fp) != NULL) { n = sscanf(line, pattern, keybuf, valbuf); if (n == 2 && strcmp(keyword, keybuf) == 0) { match = 1; break; } } fclose(fp); if (match != 0) return(valbuf); else return(NULL); }
void clear_alrm(void) { alarm(0); if (signal(SIGALRM, SIG_IGN) == SIG_ERR) log_sys("clear_alrm: signal error"); alrm_flag = 0; }
void /* Establish the signal handler and set the alarm. */ set_alrm(unsigned int nsec) { alrm_flag = 0; if (signal_intr(SIGALRM, sig_alrm) == SIG_ERR) log_sys("set_alrm: signal_intr error"); alarm(nsec); }
static void open_mailfp(void) { if (mailfp == NULL) { if ( (mailfp = fopen(tmpnam(temp_file), "w")) == NULL) log_sys("open_mailfp: fopen error"); } }
/* Output the buffer that out_char() has been storing into. * We have our own output function, so that we never block on a write * to the printer. Each time we output our buffer to the printer, * we also see if the printer has something to send us. If so, * we call proc_input_char() to process each character. */ static void out_buf(void) { char *wptr, *rptr, ibuf[IBSIZE]; int wcnt, nread, nwritten; fd_set rfds, wfds; FD_ZERO(&wfds); FD_ZERO(&rfds); set_nonblock(); /* don't want the write() to block */ wptr = outbuf; /* ptr to first char to output */ wcnt = outptr - wptr; /* #bytes to output */ while (wcnt > 0) { FD_SET(psfd, &wfds); FD_SET(psfd, &rfds); if (intr_flag) handle_intr(); while (select(psfd + 1, &rfds, &wfds, NULL, NULL) < 0) { if (errno == EINTR) { if (intr_flag) handle_intr(); /* no return */ } else log_sys("out_buf: select error"); } if (FD_ISSET(psfd, &rfds)) { /* printer is readable */ if ( (nread = read(psfd, ibuf, IBSIZE)) < 0) log_sys("out_buf: read error"); rptr = ibuf; while (--nread >= 0) proc_input_char(*rptr++); } if (FD_ISSET(psfd, &wfds)) { /* printer is writeable */ if ( (nwritten = write(psfd, wptr, wcnt)) < 0) log_sys("out_buf: write error"); wcnt -= nwritten; wptr += nwritten; } } outptr = outbuf; /* reset buffer pointer and count */ outcnt = OBSIZE; }
void close_mailfp(void) { char command[1024]; if (mailfp != NULL) { if (fclose(mailfp) == EOF) log_sys("close_mailfp: fclose error"); sprintf(command, MAILCMD, loginname, hostname, temp_file); system(command); unlink(temp_file); } }
void do_acct(void) { FILE *fp; if (end_page > start_page && acct_file != NULL && (fp = fopen(acct_file, "a")) != NULL) { fprintf(fp, "%7.2f %s:%s\n", (double)(end_page - start_page), hostname, loginname); if (fclose(fp) == EOF) log_sys("do_acct: fclose error"); } }
void DEBUG_NONL(char *fmt, ...) /* debug output, NO newline at end */ { va_list args; char line[MAXLINE]; int n; if (Debug == 0) return; va_start(args, fmt); vsprintf(line, fmt, args); va_end(args); n = strlen(line); if (writen(clifd, line, n) != n) log_sys("writen error"); }
/* * Read data from the printer, possibly increasing the buffer. * Returns offset of end of data in buffer or -1 on failure. * * LOCKING: none. */ ssize_t readmore(int sockfd, char **bpp, int off, int *bszp) { ssize_t nr; char *bp = *bpp; int bsz = *bszp; if (off >= bsz) { bsz += IOBUFSZ; if ((bp = realloc(*bpp, bsz)) == NULL) log_sys("readmore: can't allocate bigger read buffer"); *bszp = bsz; *bpp = bp; } if ((nr = tread(sockfd, &bp[off], bsz-off, 1)) < 0) return(off+nr); else return(-1); }
/* * Add a new job to the list of pending jobs. Then signal * the printer thread that a job is pending.. * * LOCKING: acquries and release joblock. */ void add_job(struct printreq *reqp, long jobid) { struct job *jp; if ((jp = malloc(sizeof(struct job))) == NULL) log_sys("malloc failed"); memcpy(&jp->req, reqp, sizeof(struct printreq)); jp->jobid = jobid; jp->next = NULL; pthread_mutex_lock(&joblock); jp->prev = jobtail; if (jobtail == NULL) jobhead = jp; else jobtail->next = jp; jobtail = jp; pthread_mutex_unlock(&joblock); pthread_cond_signal(&jobwait); }
/* * 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); }
void sig_chld(int signo) { int stat, errno_save; pid_t pid; errno_save = errno; /* log_msg() might change errno */ chld_flag = 1; if ( (pid = waitpid(-1, &stat, 0)) <= 0) log_sys("waitpid error"); if (WIFEXITED(stat) != 0) /* set client's childdone status for loop() */ client_sigchld(pid, WEXITSTATUS(stat)+1); else log_msg("child %d terminated abnormally: %04x", pid, stat); errno = errno_save; return; /* probably interrupts accept() in serv_accept() */ }
int send_str(int fd, char *ptr, char *phone, int echocheck) { char c, tempc; /* go though send string, converting escape sequences on the fly */ while ( (c = *ptr++) != 0) { if (c == '\\') { if (*ptr == 0) { sprintf(errmsg, "backslash at end of send string\n"); return(-1); } c = *ptr++; /* char following backslash */ switch (c) { case 'c': /* no CR, if at end of string */ if (*ptr == 0) goto returnok; continue; /* ignore if not at end of string */ case 'd': /* 2 second delay */ DEBUG_NONL("<delay>"); sleep(2); continue; case 'p': /* 0.25 second pause */ DEBUG_NONL("<pause>"); sleep_us(250000); /* {Ex sleepus} */ continue; case 'e': DEBUG_NONL("<echo check off>"); echocheck = 0; continue; case 'E': DEBUG_NONL("<echo check on>"); echocheck = 1; continue; case 'T': /* output phone number */ send_str(fd, phone, phone, echocheck); /* recursive */ continue; case 'r': c = '\r'; break; case 's': c = ' '; break; /* room for lots more case statements ... */ default: sprintf("errmsg, unknown send escape char: \\%s\n", ctl_str(c)); return(-1); } } DEBUG_NONL("%s", ctl_str(c)); if (write(fd, &c, 1) != 1) log_sys("write error"); if (echocheck) { /* wait for char to be echoed */ do { if (read(fd, &tempc, 1) != 1) log_sys("read error"); DEBUG_NONL("{%s}", ctl_str(tempc)); } while (tempc != c); } } c = '\r'; /* if no \c at end of string, CR written at end */ DEBUG_NONL("%s", ctl_str(c)); if (write(fd, &c, 1) != 1) log_sys("write error"); returnok: DEBUG(""); return(0); }
void sig_unblock(void) { if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) log_sys("SIG_SETMASK error"); }
void loop(void) { int i, listenfd, clifd, nread; char buf[MAXLINE]; uid_t uid; struct pollfd *pollfd; int numfd = 1; int maxfd = NALLOC; if ((pollfd = malloc(NALLOC * sizeof(struct pollfd))) == NULL) err_sys("malloc error"); for (i = 0; i < NALLOC; i++) { pollfd[i].fd = -1; pollfd[i].events = POLLIN; pollfd[i].revents = 0; } /* obtain fd to listen for client requests on */ if ((listenfd = serv_listen(CS_OPEN)) < 0) log_sys("serv_listen error"); client_add(listenfd, 0); /* we use [0] for listenfd */ pollfd[0].fd = listenfd; for ( ; ; ) { if (poll(pollfd, numfd, -1) < 0) log_sys("poll error"); if (pollfd[0].revents & POLLIN) { /* accept new client request */ if ((clifd = serv_accept(listenfd, &uid)) < 0) log_sys("serv_accept error: %d", clifd); client_add(clifd, uid); /* possibly increase the size of the pollfd array */ if (numfd == maxfd) pollfd = grow_pollfd(pollfd, &maxfd); pollfd[numfd].fd = clifd; pollfd[numfd].events = POLLIN; pollfd[numfd].revents = 0; numfd++; log_msg("new connection: uid %d, fd %d", uid, clifd); } for (i = 1; i < numfd; i++) { if (pollfd[i].revents & POLLHUP) { goto hungup; } else if (pollfd[i].revents & POLLIN) { /* read argument buffer from client */ if ((nread = read(pollfd[i].fd, buf, MAXLINE)) < 0) { log_sys("read error on fd %d", pollfd[i].fd); } else if (nread == 0) { hungup: /* the client closed the connection */ log_msg("closed: uid %d, fd %d", client[i].uid, pollfd[i].fd); client_del(pollfd[i].fd); close(pollfd[i].fd); if (i < (numfd-1)) { /* pack the array */ pollfd[i].fd = pollfd[numfd-1].fd; pollfd[i].events = pollfd[numfd-1].events; pollfd[i].revents = pollfd[numfd-1].revents; i--; /* recheck this entry */ } numfd--; } else { /* process client's request */ handle_request(buf, nread, pollfd[i].fd, client[i].uid); } } } } }
void tty_flush(void) /* flush (empty) tty input and output queues */ { if (tcflush(psfd, TCIOFLUSH) < 0) log_sys("tty_flush: tcflush error"); }
/* * Read and parse the response from the printer. Return 1 * if the request was successful, and 0 otherwise. * * LOCKING: none. */ int printer_status(int sfd, struct job *jp) { int i, success, code, len, found, bufsz, datsz; int32_t jobid; ssize_t nr; char *bp, *cp, *statcode, *reason, *contentlen; struct ipp_hdr *hp; /* * Read the HTTP header followed by the IPP response header. * They can be returned in multiple read attempts. Use the * Content-Length specifier to determine how much to read. */ success = 0; bufsz = IOBUFSZ; if ((bp = malloc(IOBUFSZ)) == NULL) log_sys("printer_status: can't allocate read buffer"); while ((nr = tread(sfd, bp, bufsz, 5)) > 0) { /* * Find the status. Response starts with "HTTP/x.y" * so we can skip the first 8 characters. */ cp = bp + 8; datsz = nr; while (isspace((int)*cp)) cp++; statcode = cp; while (isdigit((int)*cp)) cp++; if (cp == statcode) { /* Bad format; log it and move on */ log_msg(bp); } else { *cp++ = '\0'; reason = cp; while (*cp != '\r' && *cp != '\n') cp++; *cp = '\0'; code = atoi(statcode); if (HTTP_INFO(code)) continue; if (!HTTP_SUCCESS(code)) { /* probable error: log it */ bp[datsz] = '\0'; log_msg("error: %s", reason); break; } /* * HTTP request was okay, but still need to check * IPP status. Search for the Content-Length. */ i = cp - bp; for (;;) { while (*cp != 'C' && *cp != 'c' && i < datsz) { cp++; i++; } if (i >= datsz) { /* get more header */ if ((nr = readmore(sfd, &bp, i, &bufsz)) < 0) { goto out; } else { cp = &bp[i]; datsz += nr; } } if (strncasecmp(cp, "Content-Length:", 15) == 0) { cp += 15; while (isspace((int)*cp)) cp++; contentlen = cp; while (isdigit((int)*cp)) cp++; *cp++ = '\0'; i = cp - bp; len = atoi(contentlen); break; } else { cp++; i++; } } if (i >= datsz) { /* get more header */ if ((nr = readmore(sfd, &bp, i, &bufsz)) < 0) { goto out; } else { cp = &bp[i]; datsz += nr; } } found = 0; while (!found) { /* look for end of HTTP header */ while (i < datsz - 2) { if (*cp == '\n' && *(cp + 1) == '\r' && *(cp + 2) == '\n') { found = 1; cp += 3; i += 3; break; } cp++; i++; } if (i >= datsz) { /* get more header */ if ((nr = readmore(sfd, &bp, i, &bufsz)) < 0) { goto out; } else { cp = &bp[i]; datsz += nr; } } } if (datsz - i < len) { /* get more header */ if ((nr = readmore(sfd, &bp, i, &bufsz)) < 0) { goto out; } else { cp = &bp[i]; datsz += nr; } } hp = (struct ipp_hdr *)cp; i = ntohs(hp->status); jobid = ntohl(hp->request_id); if (jobid != jp->jobid) { /* * Different jobs. Ignore it. */ log_msg("jobid %d status code %d", jobid, i); break; } if (STATCLASS_OK(i)) success = 1; break; } } out: free(bp); if (nr < 0) { log_msg("jobid %d: error reading printer response: %s", jobid, strerror(errno)); } return(success); }
/* * 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); }