1*48289Sbostic /*-
2*48289Sbostic * Copyright (c) 1983 The Regents of the University of California.
3*48289Sbostic * All rights reserved.
4*48289Sbostic *
5*48289Sbostic * %sccs.include.proprietary.c%
6*48289Sbostic */
78789Smckusick
8*48289Sbostic #ifndef lint
9*48289Sbostic char copyright[] =
10*48289Sbostic "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
11*48289Sbostic All rights reserved.\n";
12*48289Sbostic #endif /* not lint */
13*48289Sbostic
14*48289Sbostic #ifndef lint
15*48289Sbostic static char sccsid[] = "@(#)pr.c 4.9 (Berkeley) 04/18/91";
16*48289Sbostic #endif /* not lint */
17*48289Sbostic
181063Sbill /*
191063Sbill * print file with headings
201063Sbill * 2+head+2+page[56]+5
211063Sbill */
221063Sbill
231063Sbill #include <stdio.h>
241063Sbill #include <signal.h>
251063Sbill #include <sys/types.h>
261063Sbill #include <sys/stat.h>
271063Sbill
281063Sbill /* Making putcp a macro sped things up by 14%. */
291063Sbill #define putcp(c) if (page >= fpage) putchar(c)
301063Sbill
311063Sbill int ncol = 1;
321063Sbill char *header;
331063Sbill int col;
341063Sbill int icol;
351063Sbill FILE *file;
361063Sbill char *bufp;
3717505Sralph #define BUFS 9000 /* at least 66 * 132 */
381063Sbill char buffer[BUFS]; /* for multi-column output */
391063Sbill char obuf[BUFSIZ];
401063Sbill #define FF 014
411063Sbill int line;
421063Sbill char *colp[72];
431063Sbill int nofile;
441063Sbill char isclosed[10];
451063Sbill FILE *ifile[10];
461063Sbill char **lastarg;
471063Sbill int peekc;
481063Sbill int fpage;
491063Sbill int page;
501063Sbill int colw;
511063Sbill int nspace;
521063Sbill int width = 72;
531063Sbill int length = 66;
541063Sbill int plength = 61;
551063Sbill int margin = 10;
561063Sbill int ntflg;
571063Sbill int fflg;
581063Sbill int mflg;
591063Sbill int tabc;
601063Sbill char *tty;
611063Sbill int mode;
621063Sbill char *ttyname();
631063Sbill char *ctime();
641063Sbill
main(argc,argv)651063Sbill main(argc, argv)
661063Sbill char **argv;
671063Sbill {
681063Sbill int nfdone;
6946845Sbostic void onintr();
701063Sbill
711063Sbill setbuf(stdout, obuf);
721063Sbill if (signal(SIGINT, SIG_IGN) != SIG_IGN)
731063Sbill signal(SIGINT, onintr);
741063Sbill lastarg = &argv[argc-1];
751063Sbill fixtty();
761063Sbill for (nfdone=0; argc>1; argc--) {
771063Sbill argv++;
781063Sbill if (**argv == '-') {
791063Sbill switch (*++*argv) {
808789Smckusick case 'h': /* define page header */
811063Sbill if (argc>=2) {
821063Sbill header = *++argv;
831063Sbill argc--;
841063Sbill }
851063Sbill continue;
861063Sbill
878789Smckusick case 't': /* don't print page headers */
881063Sbill ntflg++;
891063Sbill continue;
901063Sbill
918789Smckusick case 'f': /* use form feeds */
921063Sbill fflg++;
931063Sbill plength = 60;
941063Sbill continue;
951063Sbill
968789Smckusick case 'l': /* length of page */
971063Sbill length = atoi(++*argv);
981063Sbill continue;
991063Sbill
1008789Smckusick case 'w': /* width of page */
1011063Sbill width = atoi(++*argv);
1021063Sbill continue;
1031063Sbill
1048789Smckusick case 's': /* col separator */
1051063Sbill if (*++*argv)
1061063Sbill tabc = **argv;
1071063Sbill else
1081063Sbill tabc = '\t';
1091063Sbill continue;
1101063Sbill
1118789Smckusick case 'm': /* all files at once */
1121063Sbill mflg++;
1131063Sbill continue;
1141063Sbill
1151063Sbill default:
1168789Smckusick if (numeric(*argv)) { /* # of cols */
1178789Smckusick if ((ncol = atoi(*argv)) == 0) {
1188789Smckusick fprintf(stderr, "can't print 0 cols, using 1 instead.\n");
1198789Smckusick ncol = 1;
1208789Smckusick }
1218789Smckusick } else {
1228789Smckusick fprintf(stderr, "pr: bad key %s\n", *argv);
1238789Smckusick exit(1);
1248789Smckusick }
1251063Sbill continue;
1261063Sbill }
1278789Smckusick } else if (**argv == '+') { /* start at page ++*argv */
1281063Sbill fpage = atoi(++*argv);
1291063Sbill } else {
1301063Sbill print(*argv, argv);
1311063Sbill nfdone++;
1321063Sbill if (mflg)
1331063Sbill break;
1341063Sbill }
1351063Sbill }
1361063Sbill if (nfdone==0)
1371063Sbill print((char *)0, (char **)0);
1381063Sbill done();
1391063Sbill }
1401063Sbill
done()1411063Sbill done()
1421063Sbill {
1431063Sbill
1441063Sbill if (tty)
1451063Sbill chmod(tty, mode);
1461063Sbill exit(0);
1471063Sbill }
1481063Sbill
1498789Smckusick /* numeric -- returns 1 if str is numeric, elsewise 0 */
numeric(str)1508789Smckusick numeric(str)
1518789Smckusick char *str;
1528789Smckusick {
1538789Smckusick for (; *str ; str++) {
1548789Smckusick if (*str > '9' || *str < '0') {
1558789Smckusick return(0);
1568789Smckusick }
1578789Smckusick }
1588789Smckusick return(1);
1598789Smckusick }
1608789Smckusick
16146845Sbostic void
onintr()1621063Sbill onintr()
1631063Sbill {
1641063Sbill
1651063Sbill if (tty)
1661063Sbill chmod(tty, mode);
1671063Sbill _exit(1);
1681063Sbill }
1691063Sbill
fixtty()1701063Sbill fixtty()
1711063Sbill {
1721063Sbill struct stat sbuf;
1731063Sbill
1741063Sbill tty = ttyname(1);
1751063Sbill if (tty == 0)
1761063Sbill return;
1771063Sbill stat(tty, &sbuf);
1781063Sbill mode = sbuf.st_mode&0777;
1791063Sbill chmod(tty, 0600);
1801063Sbill }
1811063Sbill
1828789Smckusick /* print -- print file */
print(fp,argp)1831063Sbill print(fp, argp)
1841063Sbill char *fp;
1851063Sbill char **argp;
1861063Sbill {
1871063Sbill struct stat sbuf;
1881063Sbill register sncol;
1891063Sbill register char *sheader;
1901063Sbill register char *cbuf;
1911063Sbill char linebuf[150], *cp;
1921063Sbill
1931063Sbill if (ntflg)
1941063Sbill margin = 0;
1951063Sbill else
1961063Sbill margin = 10;
1971063Sbill if (length <= margin)
1981063Sbill length = 66;
1991063Sbill if (width <= 0)
2001063Sbill width = 72;
2011063Sbill if (ncol>72 || ncol>width) {
2021063Sbill fprintf(stderr, "pr: No room for columns.\n");
2031063Sbill done();
2041063Sbill }
2051063Sbill if (mflg) {
2061063Sbill mopen(argp);
2071063Sbill ncol = nofile;
2081063Sbill }
2091063Sbill colw = width/(ncol==0? 1 : ncol);
2101063Sbill sncol = ncol;
2111063Sbill sheader = header;
2121063Sbill plength = length-5;
2131063Sbill if (ntflg)
2141063Sbill plength = length;
2151063Sbill if (--ncol<0)
2161063Sbill ncol = 0;
2171063Sbill if (mflg)
2181063Sbill fp = 0;
2191063Sbill if (fp) {
2201063Sbill if((file=fopen(fp, "r"))==NULL) {
2211063Sbill if (tty==NULL)
22212095Smckusick perror(fp);
2231063Sbill ncol = sncol;
2241063Sbill header = sheader;
2251063Sbill return;
2261063Sbill }
2271063Sbill stat(fp, &sbuf);
2281063Sbill } else {
2291063Sbill file = stdin;
2301063Sbill time(&sbuf.st_mtime);
2311063Sbill }
2321063Sbill if (header == 0)
2331063Sbill header = fp?fp:"";
2341063Sbill cbuf = ctime(&sbuf.st_mtime);
2351063Sbill cbuf[16] = '\0';
2361063Sbill cbuf[24] = '\0';
2371063Sbill page = 1;
2381063Sbill icol = 0;
2391063Sbill colp[ncol] = bufp = buffer;
2401063Sbill if (mflg==0)
2411063Sbill nexbuf();
2421063Sbill while (mflg&&nofile || (!mflg)&&tpgetc(ncol)>0) {
2431063Sbill if (mflg==0) {
2441063Sbill colp[ncol]--;
2451063Sbill if (colp[ncol] < buffer)
24630276Sbostic colp[ncol] = &buffer[BUFS - 1];
2471063Sbill }
2481063Sbill line = 0;
2491063Sbill if (ntflg==0) {
2501063Sbill if (fflg) {
2511063Sbill /* Assume a ff takes two blank lines at the
2521063Sbill top of the page. */
2531063Sbill line = 2;
25432417Sbostic (void)sprintf(linebuf, "%s %s %s Page %d\n\n\n",
2551063Sbill cbuf+4, cbuf+20, header, page);
2561063Sbill } else
25732417Sbostic (void)sprintf(linebuf, "\n\n%s %s %s Page %d\n\n\n",
2581063Sbill cbuf+4, cbuf+20, header, page);
2591063Sbill for(cp=linebuf;*cp;) put(*cp++);
2601063Sbill }
2611063Sbill putpage();
2621063Sbill if (ntflg==0) {
2631063Sbill if (fflg)
2641063Sbill put('\f');
2651063Sbill else
2661063Sbill while(line<length)
2671063Sbill put('\n');
2681063Sbill }
2691063Sbill page++;
2701063Sbill }
2711063Sbill fclose(file);
2721063Sbill ncol = sncol;
2731063Sbill header = sheader;
2741063Sbill }
2751063Sbill
mopen(ap)2761063Sbill mopen(ap)
2771063Sbill char **ap;
2781063Sbill {
2791063Sbill register char **p, *p1;
2801063Sbill
2811063Sbill p = ap;
2821063Sbill while((p1 = *p) && p++ <= lastarg) {
2831063Sbill if((ifile[nofile]=fopen(p1, "r")) == NULL){
2841063Sbill isclosed[nofile] = 1;
2851063Sbill nofile--;
2861063Sbill }
2871063Sbill else
2881063Sbill isclosed[nofile] = 0;
2891063Sbill if(++nofile>=10) {
2901063Sbill fprintf(stderr, "pr: Too many args\n");
2911063Sbill done();
2921063Sbill }
2931063Sbill }
2941063Sbill }
2951063Sbill
putpage()2961063Sbill putpage()
2971063Sbill {
2981063Sbill register int lastcol, i, c;
2991063Sbill int j;
3001063Sbill
3011063Sbill if (ncol==0) {
3021063Sbill while (line<plength) {
3031063Sbill while((c = tpgetc(0)) && c!='\n' && c!=FF)
3041063Sbill putcp(c);
30511274Slayer if (c==0) break;
3061063Sbill putcp('\n');
3071063Sbill line++;
3081063Sbill if (c==FF)
3091063Sbill break;
3101063Sbill }
3111063Sbill return;
3121063Sbill }
3131063Sbill colp[0] = colp[ncol];
3141063Sbill if (mflg==0) for (i=1; i<=ncol; i++) {
3151063Sbill colp[i] = colp[i-1];
3161063Sbill for (j = margin; j<length; j++)
3171063Sbill while((c=tpgetc(i))!='\n')
3181063Sbill if (c==0)
3191063Sbill break;
3201063Sbill }
3211063Sbill while (line<plength) {
3221063Sbill lastcol = colw;
3231063Sbill for (i=0; i<ncol; i++) {
3241063Sbill while ((c=pgetc(i)) && c!='\n')
3251063Sbill if (col<lastcol || tabc!=0)
3261063Sbill put(c);
3271063Sbill if (c==0)
3281063Sbill continue;
3291063Sbill if (tabc)
3301063Sbill put(tabc);
3311063Sbill else while (col<lastcol)
3321063Sbill put(' ');
3331063Sbill lastcol += colw;
3341063Sbill }
3351063Sbill while ((c = pgetc(ncol)) && c!='\n')
3361063Sbill put(c);
3371063Sbill put('\n');
3381063Sbill }
3391063Sbill }
3401063Sbill
nexbuf()3411063Sbill nexbuf()
3421063Sbill {
3431063Sbill register int n;
3441063Sbill register char *rbufp;
3451063Sbill
3461063Sbill rbufp = bufp;
3471063Sbill n = &buffer[BUFS] - rbufp;
3481063Sbill if (n>512)
3491063Sbill n = 512;
3501063Sbill if((n=fread(rbufp,1,n,file)) <= 0){
3511063Sbill fclose(file);
3521063Sbill *rbufp = 0376;
3531063Sbill }
3541063Sbill else {
3551063Sbill rbufp += n;
3561063Sbill if (rbufp >= &buffer[BUFS])
3571063Sbill rbufp = buffer;
3581063Sbill *rbufp = 0375;
3591063Sbill }
3601063Sbill bufp = rbufp;
3611063Sbill }
3621063Sbill
tpgetc(ai)3631063Sbill tpgetc(ai)
3641063Sbill {
3651063Sbill register char **p;
3661063Sbill register int c, i;
3671063Sbill
3681063Sbill i = ai;
3691063Sbill if (mflg) {
3701063Sbill if((c=getc(ifile[i])) == EOF) {
3711063Sbill if (isclosed[i]==0) {
3721063Sbill isclosed[i] = 1;
3731063Sbill if (--nofile <= 0)
3741063Sbill return(0);
3751063Sbill }
3761063Sbill return('\n');
3771063Sbill }
3781063Sbill if (c==FF && ncol>0)
3791063Sbill c = '\n';
3801063Sbill return(c);
3811063Sbill }
3821063Sbill loop:
3831063Sbill c = **(p = &colp[i]) & 0377;
3841063Sbill if (c == 0375) {
3851063Sbill nexbuf();
3861063Sbill c = **p & 0377;
3871063Sbill }
3881063Sbill if (c == 0376)
3891063Sbill return(0);
3901063Sbill (*p)++;
3911063Sbill if (*p >= &buffer[BUFS])
3921063Sbill *p = buffer;
3931063Sbill if (c==0)
3941063Sbill goto loop;
3951063Sbill return(c);
3961063Sbill }
3971063Sbill
pgetc(i)3981063Sbill pgetc(i)
3991063Sbill {
4001063Sbill register int c;
4011063Sbill
4021063Sbill if (peekc) {
4031063Sbill c = peekc;
4041063Sbill peekc = 0;
4051063Sbill } else
4061063Sbill c = tpgetc(i);
4071063Sbill if (tabc)
4081063Sbill return(c);
4091063Sbill switch (c) {
4101063Sbill
4111063Sbill case '\t':
4121063Sbill icol++;
4131063Sbill if ((icol&07) != 0)
4141063Sbill peekc = '\t';
4151063Sbill return(' ');
4161063Sbill
4171063Sbill case '\n':
4181063Sbill icol = 0;
4191063Sbill break;
4201063Sbill
4211063Sbill case 010:
4221063Sbill case 033:
4231063Sbill icol--;
4241063Sbill break;
4251063Sbill }
4261063Sbill if (c >= ' ')
4271063Sbill icol++;
4281063Sbill return(c);
4291063Sbill }
put(ac)4301063Sbill put(ac)
4311063Sbill {
4321063Sbill register int ns, c;
4331063Sbill
4341063Sbill c = ac;
4351063Sbill if (tabc) {
4361063Sbill putcp(c);
4371063Sbill if (c=='\n')
4381063Sbill line++;
4391063Sbill return;
4401063Sbill }
4411063Sbill switch (c) {
4421063Sbill
4431063Sbill case ' ':
4441063Sbill nspace++;
4451063Sbill col++;
4461063Sbill return;
4471063Sbill
4481063Sbill case '\n':
4491063Sbill col = 0;
4501063Sbill nspace = 0;
4511063Sbill line++;
4521063Sbill break;
4531063Sbill
4541063Sbill case 010:
4551063Sbill case 033:
4561063Sbill if (--col<0)
4571063Sbill col = 0;
4581063Sbill if (--nspace<0)
4591063Sbill nspace = 0;
4601063Sbill
4611063Sbill }
4621063Sbill while(nspace) {
4631063Sbill if (nspace>2 && col > (ns=((col-nspace)|07))) {
4641063Sbill nspace = col-ns-1;
4651063Sbill putcp('\t');
4661063Sbill } else {
4671063Sbill nspace--;
4681063Sbill putcp(' ');
4691063Sbill }
4701063Sbill }
4711063Sbill if (c >= ' ')
4721063Sbill col++;
4731063Sbill putcp(c);
4741063Sbill }
475