xref: /csrg-svn/usr.sbin/lpr/lpc/cmds.c (revision 15719)
1 #ifndef lint
2 static char sccsid[] = "@(#)cmds.c	4.9 (Berkeley) 12/16/83";
3 #endif
4 
5 /*
6  * lpc -- line printer control program -- commands:
7  */
8 
9 #include "lp.h"
10 #include <sys/time.h>
11 
12 /*
13  * kill an existing daemon and disable printing.
14  */
15 abort(argc, argv)
16 	char *argv[];
17 {
18 	register int c, status;
19 	register char *cp1, *cp2;
20 	char prbuf[100];
21 
22 	if (argc == 1) {
23 		printf("Usage: abort {all | printer ...}\n");
24 		return;
25 	}
26 	if (argc == 2 && !strcmp(argv[1], "all")) {
27 		printer = prbuf;
28 		while (getprent(line) > 0) {
29 			cp1 = prbuf;
30 			cp2 = line;
31 			while ((c = *cp2++) && c != '|' && c != ':')
32 				*cp1++ = c;
33 			*cp1 = '\0';
34 			abortpr();
35 		}
36 		return;
37 	}
38 	while (--argc) {
39 		printer = *++argv;
40 		if ((status = pgetent(line, printer)) < 0) {
41 			printf("cannot open printer description file\n");
42 			continue;
43 		} else if (status == 0) {
44 			printf("unknown printer %s\n", printer);
45 			continue;
46 		}
47 		abortpr();
48 	}
49 }
50 
51 abortpr()
52 {
53 	register FILE *fp;
54 	struct stat stbuf;
55 	int pid, fd;
56 
57 	bp = pbuf;
58 	if ((SD = pgetstr("sd", &bp)) == NULL)
59 		SD = DEFSPOOL;
60 	if ((LO = pgetstr("lo", &bp)) == NULL)
61 		LO = DEFLOCK;
62 	(void) sprintf(line, "%s/%s", SD, LO);
63 	printf("%s:\n", printer);
64 
65 	/*
66 	 * Turn on the owner execute bit of the lock file to disable printing.
67 	 */
68 	if (stat(line, &stbuf) >= 0) {
69 		if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
70 			printf("\tcannot disable printing\n");
71 		else
72 			printf("\tprinting disabled\n");
73 	} else if (errno == ENOENT) {
74 		if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
75 			printf("\tcannot create lock file\n");
76 		else {
77 			(void) close(fd);
78 			printf("\tprinting disabled\n");
79 			printf("\tno daemon to abort\n");
80 		}
81 		return;
82 	} else {
83 		printf("\tcannot stat lock file\n");
84 		return;
85 	}
86 	/*
87 	 * Kill the current daemon to stop printing now.
88 	 */
89 	if ((fp = fopen(line, "r")) == NULL) {
90 		printf("\tcannot open lock file\n");
91 		return;
92 	}
93 	if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) {
94 		(void) fclose(fp);	/* unlocks as well */
95 		printf("\tno daemon to abort\n");
96 		return;
97 	}
98 	(void) fclose(fp);
99 	if (kill(pid = atoi(line), SIGINT) < 0)
100 		printf("\tWarning: daemon (pid %d) not killed\n", pid);
101 	else
102 		printf("\tdaemon (pid %d) killed\n", pid);
103 }
104 
105 /*
106  * Remove all spool files and temporaries from the spooling area.
107  */
108 clean(argc, argv)
109 	char *argv[];
110 {
111 	register int c, status;
112 	register char *cp1, *cp2;
113 	char prbuf[100];
114 
115 	if (argc == 1) {
116 		printf("Usage: clean {all | printer ...}\n");
117 		return;
118 	}
119 	if (argc == 2 && !strcmp(argv[1], "all")) {
120 		printer = prbuf;
121 		while (getprent(line) > 0) {
122 			cp1 = prbuf;
123 			cp2 = line;
124 			while ((c = *cp2++) && c != '|' && c != ':')
125 				*cp1++ = c;
126 			*cp1 = '\0';
127 			cleanpr();
128 		}
129 		return;
130 	}
131 	while (--argc) {
132 		printer = *++argv;
133 		if ((status = pgetent(line, printer)) < 0) {
134 			printf("cannot open printer description file\n");
135 			continue;
136 		} else if (status == 0) {
137 			printf("unknown printer %s\n", printer);
138 			continue;
139 		}
140 		cleanpr();
141 	}
142 }
143 
144 select(d)
145 struct direct *d;
146 {
147 	int c = d->d_name[0];
148 
149 	if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f')
150 		return(1);
151 	return(0);
152 }
153 
154 /*
155  * Comparison routine for scandir. Sort by job number and machine, then
156  * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z.
157  */
158 sortq(d1, d2)
159 struct direct **d1, **d2;
160 {
161 	int c1, c2;
162 
163 	if (c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3))
164 		return(c1);
165 	c1 = (*d1)->d_name[0];
166 	c2 = (*d2)->d_name[0];
167 	if (c1 == c2)
168 		return((*d1)->d_name[2] - (*d2)->d_name[2]);
169 	if (c1 == 'c')
170 		return(-1);
171 	if (c1 == 'd' || c2 == 'c')
172 		return(1);
173 	return(-1);
174 }
175 
176 /*
177  * Remove incomplete jobs from spooling area.
178  */
179 cleanpr()
180 {
181 	register int i, n;
182 	register char *cp, *cp1, *lp;
183 	struct direct **queue;
184 	int nitems;
185 
186 	bp = pbuf;
187 	if ((SD = pgetstr("sd", &bp)) == NULL)
188 		SD = DEFSPOOL;
189 	printf("%s:\n", printer);
190 
191 	for (lp = line, cp = SD; *lp++ = *cp++; )
192 		;
193 	lp[-1] = '/';
194 
195 	nitems = scandir(SD, &queue, select, sortq);
196 	if (nitems < 0) {
197 		printf("\tcannot examine spool directory\n");
198 		return;
199 	}
200 	if (nitems == 0)
201 		return;
202 	i = 0;
203 	do {
204 		cp = queue[i]->d_name;
205 		if (*cp == 'c') {
206 			n = 0;
207 			while (i + 1 < nitems) {
208 				cp1 = queue[i + 1]->d_name;
209 				if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3))
210 					break;
211 				i++;
212 				n++;
213 			}
214 			if (n == 0) {
215 				strcpy(lp, cp);
216 				unlinkf(line);
217 			}
218 		} else {
219 			/*
220 			 * Must be a df with no cf (otherwise, it would have
221 			 * been skipped above) or a tf file (which can always
222 			 * be removed).
223 			 */
224 			strcpy(lp, cp);
225 			unlinkf(line);
226 		}
227      	} while (++i < nitems);
228 }
229 
230 unlinkf(name)
231 	char	*name;
232 {
233 	if (unlink(name) < 0)
234 		printf("\tcannot remove %s\n", name);
235 	else
236 		printf("\tremoved %s\n", name);
237 }
238 
239 /*
240  * Enable queuing to the printer (allow lpr's).
241  */
242 enable(argc, argv)
243 	char *argv[];
244 {
245 	register int c, status;
246 	register char *cp1, *cp2;
247 	char prbuf[100];
248 
249 	if (argc == 1) {
250 		printf("Usage: enable {all | printer ...}\n");
251 		return;
252 	}
253 	if (argc == 2 && !strcmp(argv[1], "all")) {
254 		printer = prbuf;
255 		while (getprent(line) > 0) {
256 			cp1 = prbuf;
257 			cp2 = line;
258 			while ((c = *cp2++) && c != '|' && c != ':')
259 				*cp1++ = c;
260 			*cp1 = '\0';
261 			enablepr();
262 		}
263 		return;
264 	}
265 	while (--argc) {
266 		printer = *++argv;
267 		if ((status = pgetent(line, printer)) < 0) {
268 			printf("cannot open printer description file\n");
269 			continue;
270 		} else if (status == 0) {
271 			printf("unknown printer %s\n", printer);
272 			continue;
273 		}
274 		enablepr();
275 	}
276 }
277 
278 enablepr()
279 {
280 	struct stat stbuf;
281 
282 	bp = pbuf;
283 	if ((SD = pgetstr("sd", &bp)) == NULL)
284 		SD = DEFSPOOL;
285 	if ((LO = pgetstr("lo", &bp)) == NULL)
286 		LO = DEFLOCK;
287 	(void) sprintf(line, "%s/%s", SD, LO);
288 	printf("%s:\n", printer);
289 
290 	/*
291 	 * Turn off the group execute bit of the lock file to enable queuing.
292 	 */
293 	if (stat(line, &stbuf) >= 0) {
294 		if (chmod(line, stbuf.st_mode & 0767) < 0)
295 			printf("\tcannot enable queuing\n");
296 		else
297 			printf("\tqueuing enabled\n");
298 	}
299 }
300 
301 /*
302  * Disable queuing.
303  */
304 disable(argc, argv)
305 	char *argv[];
306 {
307 	register int c, status;
308 	register char *cp1, *cp2;
309 	char prbuf[100];
310 
311 	if (argc == 1) {
312 		printf("Usage: disable {all | printer ...}\n");
313 		return;
314 	}
315 	if (argc == 2 && !strcmp(argv[1], "all")) {
316 		printer = prbuf;
317 		while (getprent(line) > 0) {
318 			cp1 = prbuf;
319 			cp2 = line;
320 			while ((c = *cp2++) && c != '|' && c != ':')
321 				*cp1++ = c;
322 			*cp1 = '\0';
323 			disablepr();
324 		}
325 		return;
326 	}
327 	while (--argc) {
328 		printer = *++argv;
329 		if ((status = pgetent(line, printer)) < 0) {
330 			printf("cannot open printer description file\n");
331 			continue;
332 		} else if (status == 0) {
333 			printf("unknown printer %s\n", printer);
334 			continue;
335 		}
336 		disablepr();
337 	}
338 }
339 
340 disablepr()
341 {
342 	register int fd;
343 	struct stat stbuf;
344 
345 	bp = pbuf;
346 	if ((SD = pgetstr("sd", &bp)) == NULL)
347 		SD = DEFSPOOL;
348 	if ((LO = pgetstr("lo", &bp)) == NULL)
349 		LO = DEFLOCK;
350 	(void) sprintf(line, "%s/%s", SD, LO);
351 	printf("%s:\n", printer);
352 	/*
353 	 * Turn on the group execute bit of the lock file to disable queuing.
354 	 */
355 	if (stat(line, &stbuf) >= 0) {
356 		if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0)
357 			printf("\tcannot disable queuing\n");
358 		else
359 			printf("\tqueuing disabled\n");
360 	} else if (errno == ENOENT) {
361 		if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0)
362 			printf("\tcannot create lock file\n");
363 		else {
364 			(void) close(fd);
365 			printf("\tqueuing disabled\n");
366 		}
367 		return;
368 	} else
369 		printf("\tcannot stat lock file\n");
370 }
371 
372 /*
373  * Exit lpc
374  */
375 quit(argc, argv)
376 	char *argv[];
377 {
378 	exit(0);
379 }
380 
381 /*
382  * Startup the daemon.
383  */
384 restart(argc, argv)
385 	char *argv[];
386 {
387 	register int c, status;
388 	register char *cp1, *cp2;
389 	char prbuf[100];
390 
391 	if (argc == 1) {
392 		printf("Usage: restart {all | printer ...}\n");
393 		return;
394 	}
395 	gethostname(host, sizeof(host));
396 	if (argc == 2 && !strcmp(argv[1], "all")) {
397 		printer = prbuf;
398 		while (getprent(line) > 0) {
399 			cp1 = prbuf;
400 			cp2 = line;
401 			while ((c = *cp2++) && c != '|' && c != ':')
402 				*cp1++ = c;
403 			*cp1 = '\0';
404 			startpr(0);
405 		}
406 		return;
407 	}
408 	while (--argc) {
409 		printer = *++argv;
410 		if ((status = pgetent(line, printer)) < 0) {
411 			printf("cannot open printer description file\n");
412 			continue;
413 		} else if (status == 0) {
414 			printf("unknown printer %s\n", printer);
415 			continue;
416 		}
417 		startpr(0);
418 	}
419 }
420 
421 /*
422  * Enable printing on the specified printer and startup the daemon.
423  */
424 start(argc, argv)
425 	char *argv[];
426 {
427 	register int c, status;
428 	register char *cp1, *cp2;
429 	char prbuf[100];
430 
431 	if (argc == 1) {
432 		printf("Usage: start {all | printer ...}\n");
433 		return;
434 	}
435 	gethostname(host, sizeof(host));
436 	if (argc == 2 && !strcmp(argv[1], "all")) {
437 		printer = prbuf;
438 		while (getprent(line) > 0) {
439 			cp1 = prbuf;
440 			cp2 = line;
441 			while ((c = *cp2++) && c != '|' && c != ':')
442 				*cp1++ = c;
443 			*cp1 = '\0';
444 			startpr(1);
445 		}
446 		return;
447 	}
448 	while (--argc) {
449 		printer = *++argv;
450 		if ((status = pgetent(line, printer)) < 0) {
451 			printf("cannot open printer description file\n");
452 			continue;
453 		} else if (status == 0) {
454 			printf("unknown printer %s\n", printer);
455 			continue;
456 		}
457 		startpr(1);
458 	}
459 }
460 
461 startpr(enable)
462 {
463 	struct stat stbuf;
464 
465 	bp = pbuf;
466 	if ((SD = pgetstr("sd", &bp)) == NULL)
467 		SD = DEFSPOOL;
468 	if ((LO = pgetstr("lo", &bp)) == NULL)
469 		LO = DEFLOCK;
470 	(void) sprintf(line, "%s/%s", SD, LO);
471 	printf("%s:\n", printer);
472 
473 	/*
474 	 * Turn off the owner execute bit of the lock file to enable printing.
475 	 */
476 	if (enable && stat(line, &stbuf) >= 0) {
477 		if (chmod(line, stbuf.st_mode & 0677) < 0)
478 			printf("\tcannot enable printing\n");
479 		else
480 			printf("\tprinting enabled\n");
481 	}
482 	if (!startdaemon(printer))
483 		printf("\tcouldn't start daemon\n");
484 	else
485 		printf("\tdaemon started\n");
486 }
487 
488 /*
489  * Print the status of each queue listed or all the queues.
490  */
491 status(argc, argv)
492 	char *argv[];
493 {
494 	register int c, status;
495 	register char *cp1, *cp2;
496 	char prbuf[100];
497 
498 	if (argc == 1) {
499 		printer = prbuf;
500 		while (getprent(line) > 0) {
501 			cp1 = prbuf;
502 			cp2 = line;
503 			while ((c = *cp2++) && c != '|' && c != ':')
504 				*cp1++ = c;
505 			*cp1 = '\0';
506 			prstat();
507 		}
508 		return;
509 	}
510 	while (--argc) {
511 		printer = *++argv;
512 		if ((status = pgetent(line, printer)) < 0) {
513 			printf("cannot open printer description file\n");
514 			continue;
515 		} else if (status == 0) {
516 			printf("unknown printer %s\n", printer);
517 			continue;
518 		}
519 		prstat();
520 	}
521 }
522 
523 /*
524  * Print the status of the printer queue.
525  */
526 prstat()
527 {
528 	struct stat stbuf;
529 	register int fd, i;
530 	register struct direct *dp;
531 	DIR *dirp;
532 
533 	bp = pbuf;
534 	if ((SD = pgetstr("sd", &bp)) == NULL)
535 		SD = DEFSPOOL;
536 	if ((LO = pgetstr("lo", &bp)) == NULL)
537 		LO = DEFLOCK;
538 	if ((ST = pgetstr("st", &bp)) == NULL)
539 		ST = DEFSTAT;
540 	printf("%s:\n", printer);
541 	(void) sprintf(line, "%s/%s", SD, LO);
542 	if (stat(line, &stbuf) >= 0) {
543 		printf("\tqueuing is %s\n",
544 			(stbuf.st_mode & 010) ? "disabled" : "enabled");
545 		printf("\tprinting is %s\n",
546 			(stbuf.st_mode & 0100) ? "disabled" : "enabled");
547 	} else {
548 		printf("\tqueuing is enabled\n");
549 		printf("\tprinting is enabled\n");
550 	}
551 	if ((dirp = opendir(SD)) == NULL) {
552 		printf("\tcannot examine spool directory\n");
553 		return;
554 	}
555 	i = 0;
556 	while ((dp = readdir(dirp)) != NULL) {
557 		if (*dp->d_name == 'c' && dp->d_name[1] == 'f')
558 			i++;
559 	}
560 	closedir(dirp);
561 	if (i == 0)
562 		printf("\tno entries\n");
563 	else if (i == 1)
564 		printf("\t1 entry in spool area\n");
565 	else
566 		printf("\t%d entries in spool area\n", i);
567 	fd = open(line, O_RDONLY);
568 	if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) {
569 		(void) close(fd);	/* unlocks as well */
570 		printf("\tno daemon present\n");
571 		return;
572 	}
573 	(void) close(fd);
574 	putchar('\t');
575 	(void) sprintf(line, "%s/%s", SD, ST);
576 	fd = open(line, O_RDONLY);
577 	if (fd >= 0) {
578 		(void) flock(fd, LOCK_SH);
579 		while ((i = read(fd, line, sizeof(line))) > 0)
580 			(void) fwrite(line, 1, i, stdout);
581 		(void) close(fd);	/* unlocks as well */
582 	}
583 }
584 
585 /*
586  * Stop the specified daemon after completing the current job and disable
587  * printing.
588  */
589 stop(argc, argv)
590 	char *argv[];
591 {
592 	register int c, status;
593 	register char *cp1, *cp2;
594 	char prbuf[100];
595 
596 	if (argc == 1) {
597 		printf("Usage: stop {all | printer ...}\n");
598 		return;
599 	}
600 	if (argc == 2 && !strcmp(argv[1], "all")) {
601 		printer = prbuf;
602 		while (getprent(line) > 0) {
603 			cp1 = prbuf;
604 			cp2 = line;
605 			while ((c = *cp2++) && c != '|' && c != ':')
606 				*cp1++ = c;
607 			*cp1 = '\0';
608 			stoppr();
609 		}
610 		return;
611 	}
612 	while (--argc) {
613 		printer = *++argv;
614 		if ((status = pgetent(line, printer)) < 0) {
615 			printf("cannot open printer description file\n");
616 			continue;
617 		} else if (status == 0) {
618 			printf("unknown printer %s\n", printer);
619 			continue;
620 		}
621 		stoppr();
622 	}
623 }
624 
625 stoppr()
626 {
627 	register int fd;
628 	struct stat stbuf;
629 
630 	bp = pbuf;
631 	if ((SD = pgetstr("sd", &bp)) == NULL)
632 		SD = DEFSPOOL;
633 	if ((LO = pgetstr("lo", &bp)) == NULL)
634 		LO = DEFLOCK;
635 	(void) sprintf(line, "%s/%s", SD, LO);
636 	printf("%s:\n", printer);
637 
638 	/*
639 	 * Turn on the owner execute bit of the lock file to disable printing.
640 	 */
641 	if (stat(line, &stbuf) >= 0) {
642 		if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
643 			printf("\tcannot disable printing\n");
644 		else
645 			printf("\tprinting disabled\n");
646 	} else if (errno == ENOENT) {
647 		if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
648 			printf("\tcannot create lock file\n");
649 		else {
650 			(void) close(fd);
651 			printf("\tprinting disabled\n");
652 		}
653 	} else
654 		printf("\tcannot stat lock file\n");
655 }
656 
657 struct	queue **queue;
658 int	nitems;
659 time_t	mtime;
660 
661 /*
662  * Put the specified jobs at the top of printer queue.
663  */
664 topq(argc, argv)
665 	char *argv[];
666 {
667 	register int n, i;
668 	struct stat stbuf;
669 	register char *cfname;
670 	int status, changed;
671 
672 	if (argc < 3) {
673 		printf("Usage: topq printer [jobnum ...] [user ...]\n");
674 		return;
675 	}
676 
677 	--argc;
678 	printer = *++argv;
679 	status = pgetent(line, printer);
680 	if (status < 0) {
681 		printf("cannot open printer description file\n");
682 		return;
683 	} else if (status == 0) {
684 		printf("%s: unknown printer\n", printer);
685 		return;
686 	}
687 	bp = pbuf;
688 	if ((SD = pgetstr("sd", &bp)) == NULL)
689 		SD = DEFSPOOL;
690 	if ((LO = pgetstr("lo", &bp)) == NULL)
691 		LO = DEFLOCK;
692 	printf("%s:\n", printer);
693 
694 	if (chdir(SD) < 0) {
695 		printf("\tcannot chdir to %s\n", SD);
696 		return;
697 	}
698 	nitems = getq(&queue);
699 	if (nitems == 0)
700 		return;
701 	changed = 0;
702 	mtime = queue[0]->q_time;
703 	for (i = argc; --i; ) {
704 		if (doarg(argv[i]) == 0) {
705 			printf("\tjob %s is not in the queue\n", argv[i]);
706 			continue;
707 		} else
708 			changed++;
709 	}
710 	for (i = 0; i < nitems; i++)
711 		free(queue[i]);
712 	free(queue);
713 	if (!changed) {
714 		printf("\tqueue order unchanged\n");
715 		return;
716 	}
717 	/*
718 	 * Turn on the public execute bit of the lock file to
719 	 * get lpd to rebuild the queue after the current job.
720 	 */
721 	if (changed && stat(LO, &stbuf) >= 0)
722 		(void) chmod(LO, (stbuf.st_mode & 0777) | 01);
723 }
724 
725 /*
726  * Reposition the job by changing the modification time of
727  * the control file.
728  */
729 touch(q)
730 	struct queue *q;
731 {
732 	struct timeval tvp[2];
733 
734 	tvp[0].tv_sec = tvp[1].tv_sec = --mtime;
735 	tvp[0].tv_usec = tvp[1].tv_usec = 0;
736 	return(utimes(q->q_name, tvp));
737 }
738 
739 /*
740  * Checks if specified job name is in the printer's queue.
741  * Returns:  negative (-1) if argument name is not in the queue.
742  */
743 doarg(job)
744 	char *job;
745 {
746 	register struct queue **qq;
747 	register int jobnum, n;
748 	register char *cp, *machine;
749 	int cnt = 0;
750 	FILE *fp;
751 
752 	/*
753 	 * Look for a job item consisting of system name, colon, number
754 	 * (example: ucbarpa:114)
755 	 */
756 	if ((cp = index(job, ':')) != NULL) {
757 		machine = job;
758 		*cp++ = '\0';
759 		job = cp;
760 	} else
761 		machine = NULL;
762 
763 	/*
764 	 * Check for job specified by number (example: 112 or 235ucbarpa).
765 	 */
766 	if (isdigit(*job)) {
767 		jobnum = 0;
768 		do
769 			jobnum = jobnum * 10 + (*job++ - '0');
770 		while (isdigit(*job));
771 		for (qq = queue + nitems; --qq >= queue; ) {
772 			n = 0;
773 			for (cp = (*qq)->q_name+3; isdigit(*cp); )
774 				n = n * 10 + (*cp++ - '0');
775 			if (jobnum != n)
776 				continue;
777 			if (*job && strcmp(job, cp) != 0)
778 				continue;
779 			if (machine != NULL && strcmp(machine, cp) != 0)
780 				continue;
781 			if (touch(*qq) == 0) {
782 				printf("\tmoved %s\n", (*qq)->q_name);
783 				cnt++;
784 			}
785 		}
786 		return(cnt);
787 	}
788 	/*
789 	 * Process item consisting of owner's name (example: henry).
790 	 */
791 	for (qq = queue + nitems; --qq >= queue; ) {
792 		if ((fp = fopen((*qq)->q_name, "r")) == NULL)
793 			continue;
794 		while (getline(fp) > 0)
795 			if (line[0] == 'P')
796 				break;
797 		(void) fclose(fp);
798 		if (line[0] != 'P' || strcmp(job, line+1) != 0)
799 			continue;
800 		if (touch(*qq) == 0) {
801 			printf("\tmoved %s\n", (*qq)->q_name);
802 			cnt++;
803 		}
804 	}
805 	return(cnt);
806 }
807