/* * Display the current state of the queue. Format = 1 if long format. */ void displayq(int format) { struct queue *q; int i, rank, nitems, fd, ret, len; char *cp, *ecp, *p; struct queue **queue; struct winsize win; struct stat statb; FILE *fp; termwidth = 80; if (isatty(STDOUT_FILENO)) { if ((p = getenv("COLUMNS")) != NULL) termwidth = atoi(p); else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 && win.ws_col > 0) termwidth = win.ws_col; } if (termwidth < 60) termwidth = 60; lflag = format; totsize = 0; if ((i = cgetent(&bp, printcapdb, printer)) == -2) fatal("can't open printer description file"); else if (i == -1) fatal("unknown printer"); else if (i == -3) fatal("potential reference loop detected in printcap file"); if (cgetstr(bp, DEFLP, &LP) < 0) LP = _PATH_DEFDEVLP; if (cgetstr(bp, "rp", &RP) < 0) RP = DEFLP; if (cgetstr(bp, "sd", &SD) < 0) SD = _PATH_DEFSPOOL; if (cgetstr(bp,"lo", &LO) < 0) LO = DEFLOCK; if (cgetstr(bp, "st", &ST) < 0) ST = DEFSTAT; cgetstr(bp, "rm", &RM); if ((cp = checkremote()) != NULL) printf("Warning: %s\n", cp); /* * Print out local queue * Find all the control files in the spooling directory */ PRIV_START; if (chdir(SD) < 0) fatal("cannot chdir to spooling directory"); PRIV_END; if ((nitems = getq(&queue)) < 0) fatal("cannot examine spooling area"); PRIV_START; ret = stat(LO, &statb); PRIV_END; if (ret >= 0) { if (statb.st_mode & S_IXUSR) { if (remote) printf("%s: ", host); printf("Warning: %s is down: ", printer); PRIV_START; fd = safe_open(ST, O_RDONLY|O_NOFOLLOW, 0); PRIV_END; if (fd >= 0 && flock(fd, LOCK_SH) == 0) { while ((i = read(fd, line, sizeof(line))) > 0) (void)fwrite(line, 1, i, stdout); (void)close(fd); /* unlocks as well */ } else putchar('\n'); } if (statb.st_mode & S_IXGRP) { if (remote) printf("%s: ", host); printf("Warning: %s queue is turned off\n", printer); } } if (nitems) { PRIV_START; fd = safe_open(LO, O_RDONLY|O_NOFOLLOW, 0); PRIV_END; if (fd < 0 || (fp = fdopen(fd, "r")) == NULL) { if (fd >= 0) close(fd); nodaemon(); } else { /* get daemon pid */ cp = current; ecp = cp + sizeof(current) - 1; while ((i = getc(fp)) != EOF && i != '\n') { if (cp < ecp) *cp++ = i; } *cp = '\0'; i = atoi(current); if (i <= 0) { ret = -1; } else { PRIV_START; ret = kill(i, 0); PRIV_END; } if (ret < 0 && errno != EPERM) { nodaemon(); } else { /* read current file name */ cp = current; ecp = cp + sizeof(current) - 1; while ((i = getc(fp)) != EOF && i != '\n') { if (cp < ecp) *cp++ = i; } *cp = '\0'; /* * Print the status file. */ if (remote) printf("%s: ", host); PRIV_START; fd = safe_open(ST, O_RDONLY|O_NOFOLLOW, 0); PRIV_END; if (fd >= 0 && flock(fd, LOCK_SH) == 0) { while ((i = read(fd, line, sizeof(line))) > 0) (void)fwrite(line, 1, i, stdout); (void)close(fd); /* unlocks as well */ } else putchar('\n'); } (void)fclose(fp); } /* * Now, examine the control files and print out the jobs to * be done for each user. */ if (!lflag) header(); /* The currently printed job is treated specially. */ if (!remote && current[0] != '\0') inform(current, 0); for (i = 0, rank = 1; i < nitems; i++) { q = queue[i]; if (remote || strcmp(current, q->q_name) != 0) inform(q->q_name, rank++); free(q); } } free(queue); if (!remote) { if (nitems == 0) puts("no entries"); return; } /* * Print foreign queue * Note that a file in transit may show up in either queue. */ if (nitems) putchar('\n'); (void)snprintf(line, sizeof(line), "%c%s", format + '\3', RP); cp = line; cp += strlen(cp); for (i = 0; i < requests && cp - line < sizeof(line) - 1; i++) { len = line + sizeof(line) - cp; if (snprintf(cp, len, " %d", requ[i]) >= len) { cp += strlen(cp); break; } cp += strlen(cp); } for (i = 0; i < users && cp - line < sizeof(line) - 1; i++) { len = line + sizeof(line) - cp; if (snprintf(cp, len, " %s", user[i]) >= len) { cp += strlen(cp); break; } } if (cp-line < sizeof(line) - 1) strlcat(line, "\n", sizeof(line)); else line[sizeof(line) - 2] = '\n'; fd = getport(RM, 0); if (fd < 0) { if (from != host) printf("%s: ", host); (void)printf("connection to %s is down\n", RM); } else { struct sigaction osa, nsa; char *visline; int n = 0; i = strlen(line); if (write(fd, line, i) != i) fatal("Lost connection"); memset(&nsa, 0, sizeof(nsa)); nsa.sa_handler = alarmer; sigemptyset(&nsa.sa_mask); nsa.sa_flags = 0; (void)sigaction(SIGALRM, &nsa, &osa); alarm(wait_time); if ((visline = (char *)malloc(4 * sizeof(line) + 1)) == NULL) fatal("Out of memory"); while ((i = read(fd, line, sizeof(line))) > 0) { n = strvisx(visline, line, i, VIS_SAFE|VIS_NOSLASH); (void)fwrite(visline, 1, n, stdout); alarm(wait_time); } /* XXX some LPR implementations may not end stream with '\n' */ if (n > 0 && visline[n-1] != '\n') putchar('\n'); alarm(0); (void)sigaction(SIGALRM, &osa, NULL); free(visline); (void)close(fd); } }
/* * Display the current state of the queue. Format = 1 if long format. */ void displayq(int format) { struct queue *q; int i, nitems, fd, ret; char *cp, *ecp; struct queue **queue; struct stat statb; FILE *fp; lflag = format; totsize = 0; rank = -1; getprintcap(printer); /* * Print out local queue * Find all the control files in the spooling directory */ seteuid(euid); if (chdir(SD) < 0) fatal("cannot chdir to spooling directory"); seteuid(uid); if ((nitems = getq(&queue)) < 0) fatal("cannot examine spooling area\n"); seteuid(euid); ret = stat(LO, &statb); seteuid(uid); if (ret >= 0) { if (statb.st_mode & S_IXUSR) { if (remote) printf("%s: ", host); printf("Warning: %s is down: ", printer); seteuid(euid); fd = open(ST, O_RDONLY); seteuid(uid); if (fd >= 0) { (void)flock(fd, LOCK_SH); while ((i = read(fd, line, sizeof(line))) > 0) (void)fwrite(line, 1, (size_t)i, stdout); (void)close(fd); /* unlocks as well */ } else putchar('\n'); } if (statb.st_mode & S_IXGRP) { if (remote) printf("%s: ", host); printf("Warning: %s queue is turned off\n", printer); } } if (nitems) { seteuid(euid); fp = fopen(LO, "r"); seteuid(uid); if (fp == NULL) nodaemon(); else { /* get daemon pid */ cp = current; ecp = cp + sizeof(current) - 1; while ((i = getc(fp)) != EOF && i != '\n') { if (cp < ecp) *cp++ = i; } *cp = '\0'; i = atoi(current); if (i <= 0) { ret = -1; } else { seteuid(euid); ret = kill(i, 0); seteuid(uid); } if (ret < 0) { nodaemon(); } else { /* read current file name */ cp = current; ecp = cp + sizeof(current) - 1; while ((i = getc(fp)) != EOF && i != '\n') { if (cp < ecp) *cp++ = i; } *cp = '\0'; /* * Print the status file. */ if (remote) printf("%s: ", host); seteuid(euid); fd = open(ST, O_RDONLY); seteuid(uid); if (fd >= 0) { (void)flock(fd, LOCK_SH); while ((i = read(fd, line, sizeof(line))) > 0) (void)fwrite(line, 1, (size_t)i, stdout); (void)close(fd); /* unlocks as well */ } else putchar('\n'); } (void)fclose(fp); } /* * Now, examine the control files and print out the jobs to * be done for each user. */ if (!lflag) header(); for (i = 0; i < nitems; i++) { q = queue[i]; inform(q->q_name); } } freeq(queue, nitems); if (!remote) { if (nitems == 0) puts("no entries"); return; } /* * Print foreign queue * Note that a file in transit may show up in either queue. */ if (nitems) putchar('\n'); (void)snprintf(line, sizeof(line), "%c%s", format + '\3', RP); cp = line; ecp = line + sizeof(line); for (i = 0; i < requests && (size_t)(cp - line + 11) < sizeof(line) - 2; i++) { cp += strlen(cp); (void)snprintf(cp, ecp - cp, " %d", requ[i]); } for (i = 0; i < users && cp - line + 1 + strlen(user[i]) < sizeof(line) - 2; i++) { cp += strlen(cp); if ((size_t)(cp - line) > sizeof(line) - 2) break; *cp++ = ' '; /* truncation may happen */ (void)strlcpy(cp, user[i], ecp - cp); } (void)strlcat(line, "\n", sizeof(line)); fd = getport(RM); if (fd < 0) { if (from != host) printf("%s: ", host); (void)printf("connection to %s is down\n", RM); } else { struct sigaction osa, nsa; i = strlen(line); if (write(fd, line, (size_t)i) != i) fatal("Lost connection"); nsa.sa_handler = alarmer; sigemptyset(&nsa.sa_mask); sigaddset(&nsa.sa_mask, SIGALRM); nsa.sa_flags = 0; (void)sigaction(SIGALRM, &nsa, &osa); alarm(wait_time); while ((i = read(fd, line, sizeof(line))) > 0) { (void)fwrite(line, 1, (size_t)i, stdout); alarm(wait_time); } alarm(0); (void)sigaction(SIGALRM, &osa, NULL); (void)close(fd); } }