Пример #1
0
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");
}
Пример #2
0
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);
				}
			}
		}
	}
}
Пример #3
0
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);
				}
			}	
		}
	}
}
Пример #4
0
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);
				}
			}
		}
	}
}
Пример #5
0
/*
 * 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");
}
Пример #6
0
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;
    }
}
Пример #7
0
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;
    }
}
Пример #8
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);
}
Пример #9
0
void
block_write(const char *buf, int n)
{
    set_block();
    if (write(psfd, buf, n) != n)
        log_sys("block_write: write error");
}
Пример #10
0
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 */
}
Пример #11
0
/*
 * 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);
}
Пример #12
0
void
clear_alrm(void)
{
	alarm(0);
	if (signal(SIGALRM, SIG_IGN) == SIG_ERR)
		log_sys("clear_alrm: signal error");
	alrm_flag = 0;
}
Пример #13
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);
}
Пример #14
0
static void
open_mailfp(void)
{
    if (mailfp == NULL) {
        if ( (mailfp = fopen(tmpnam(temp_file), "w")) == NULL)
            log_sys("open_mailfp: fopen error");
    }
}
Пример #15
0
/* 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;
}
Пример #16
0
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);
    }
}
Пример #17
0
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");
	}
}
Пример #18
0
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");
}
Пример #19
0
/*
 * 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);
}
Пример #20
0
/*
 * 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);
}
Пример #21
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);
}
Пример #22
0
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() */
}
Пример #23
0
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);
}
Пример #24
0
void
sig_unblock(void)
{
	if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
		log_sys("SIG_SETMASK error");
}
Пример #25
0
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);
                }
            }
        }
    }
}
Пример #26
0
void
tty_flush(void)        /* flush (empty) tty input and output queues */
{
    if (tcflush(psfd, TCIOFLUSH) < 0)
        log_sys("tty_flush: tcflush error");
}
Пример #27
0
/*
 * 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);
}
Пример #28
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);
}