[BACK]Return to tput.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tput

Diff for /src/usr.bin/tput/tput.c between version 1.7 and 1.8

version 1.7, 1999/03/06 20:27:42 version 1.8, 1999/06/29 19:39:40
Line 1 
Line 1 
 /*      $OpenBSD$       */  /*      $OpenBSD$       */
 /*      $NetBSD: tput.c,v 1.8 1995/08/31 22:11:37 jtc Exp $     */  
   
   /*
    * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    * 1. Redistributions of source code must retain the above copyright
    *    notice, this list of conditions and the following disclaimer.
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in the
    *    documentation and/or other materials provided with the distribution.
    * 3. The name of the author may not be used to endorse or promote products
    *    derived from this software without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
    * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
    * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
    * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
    * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    */
 /*-  /*-
  * Copyright (c) 1980, 1988, 1993   * Copyright (c) 1980, 1988, 1993
  *      The Regents of the University of California.  All rights reserved.   *      The Regents of the University of California.  All rights reserved.
Line 47 
Line 72 
 static char rcsid[] = "$OpenBSD$";  static char rcsid[] = "$OpenBSD$";
 #endif /* not lint */  #endif /* not lint */
   
 #include <termios.h>  #include <sys/param.h>
   
   #include <ctype.h>
 #include <err.h>  #include <err.h>
 #include <curses.h>  #include <curses.h>
   #include <term.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
   #include <termios.h>
 #include <unistd.h>  #include <unistd.h>
 #include <string.h>  #include <string.h>
   
 static void   prlongname __P((char *));  #include <sys/wait.h>
 static void   setospeed __P((void));  
 static void   outc __P((int));  static void   init __P((void));
 static void   usage __P((void));  
 static char **process __P((char *, char *, char **));  static char **process __P((char *, char *, char **));
   static void   reset __P((void));
   static void   usage __P((void));
   
   extern char  *__progname;
   
 int  int
 main(argc, argv)  main(argc, argv)
         int argc;          int argc;
         char **argv;          char **argv;
 {  {
         extern char *optarg;          int ch, exitval, n, Sflag;
         extern int optind;          size_t len;
         int ch, exitval, n;          char *p, *term, *str;
         char *argv0, *cptr, *p, *term, buf[1024], tbuf[1024];          char **oargv;
   
           oargv = argv;
         term = NULL;          term = NULL;
         while ((ch = getopt(argc, argv, "T:")) != -1)          Sflag = exitval = 0;
           while ((ch = getopt(argc, argv, "ST:")) != -1)
                 switch(ch) {                  switch(ch) {
                 case 'T':                  case 'T':
                         term = optarg;                          term = optarg;
                         break;                          break;
                   case 'S':
                           Sflag = 1;
                           break;
                 case '?':                  case '?':
                 default:                  default:
                         usage();                          usage();
                 }                  }
         if ((argv0 = (char *)strrchr(argv[0], '/')) != NULL)  
                 argv0++;  
         else  
                 argv0 = argv[0];  
         argc -= optind;          argc -= optind;
         argv += optind;          argv += optind;
   
           if (Sflag && argc > 0)
                   usage();
   
         if (!term && !(term = getenv("TERM")))          if (!term && !(term = getenv("TERM")))
 errx(2, "no terminal type specified and no TERM environmental variable.");                  errx(2, "No value for $TERM and no -T specified");
         if (tgetent(tbuf, term) != 1)  
                 err(2, "tgetent failure");          /*
         setospeed();           * NOTE: tgetent() will call setupterm() and set ospeed for us
         if (strcmp(argv0, "clear") == 0) {           * (this is ncurses-specific behavior)
                 *argv = "clear";           */
           if (tgetent(NULL, term) != 1)
                   errx(3, "Unknown terminal type `%s'", term);
   
           if (strcmp(__progname, "clear") == 0) {
                   if (Sflag)
                           usage();
                   argv = oargv;
                   *argv = __progname;
                 *(argv+1) = NULL;                  *(argv+1) = NULL;
         }          }
         for (exitval = 0; (p = *argv) != NULL; ++argv) {          if (Sflag) {
                   char **av;
   
                   /* Build new argv based on stdin */
                   argc = n = 0;
                   av = NULL;
                   while ((str = fgetln(stdin, &len)) != NULL) {
                           if (str[len-1] != '\n')
                                   errx(1, "premature EOF");
                           str[len-1] = '\0';
                           /* grow av as needed */
                           if (argc + 1 >= n) {
                                   n += 64;
                                   av = (char **)realloc(av, sizeof(char *) * n);
                                   if (av == NULL)
                                           errx(1, "out of memory");
                           }
                           while ((p = strsep(&str, " \t")) != NULL) {
                                   if (*p != '\0' &&
                                       (av[argc++] = strdup(p)) == NULL)
                                           errx(1, "out of memory");
                           }
                   }
                   if (argc > 0) {
                           av[argc] = NULL;
                           argv = av;
                   }
           }
           while ((p = *argv++)) {
                 switch (*p) {                  switch (*p) {
                 case 'c':  
                         if (!strcmp(p, "clear"))  
                                 p = "cl";  
                         break;  
                 case 'i':                  case 'i':
                         if (!strcmp(p, "init"))                          if (!strcmp(p, "init")) {
                                 p = "is";                                  init();
                                   continue;
                           }
                         break;                          break;
                 case 'l':                  case 'l':
                         if (!strcmp(p, "longname")) {                          if (!strcmp(p, "longname")) {
                                 prlongname(tbuf);                                  puts(longname());
                                 continue;                                  continue;
                         }                          }
                         break;                          break;
                 case 'r':                  case 'r':
                         if (!strcmp(p, "reset"))                          if (!strcmp(p, "reset")) {
                                 p = "rs";                                  reset();
                                   continue;
                           }
                         break;                          break;
                 }                  }
                 cptr = buf;  
                 if (tgetstr(p, &cptr))                  /* First try as terminfo */
                         argv = process(p, buf, argv);                  if ((str = tigetstr(p)) && str != (char *)-1)
                           argv = process(p, str, argv);
                   else if ((n = tigetnum(p)) != -2)
                           (void)printf("%d\n", n);
                   else if ((n = tigetflag(p)) != -1)
                           exitval = !n;
                   /* Then fall back on termcap */
                   else if ((str = tgetstr(p, NULL)))
                           argv = process(p, str, argv);
                 else if ((n = tgetnum(p)) != -1)                  else if ((n = tgetnum(p)) != -1)
                         (void)printf("%d\n", n);                          (void)printf("%d\n", n);
                 else                  else if ((exitval = tgetflag(p)) != 0)
                         exitval = !tgetflag(p);                          exitval = !exitval;
                   else {
                           warnx("Unknown terminfo capability `%s'", p);
                           exitval = 4;
                   }
   
                 if (argv == NULL)                  if (*argv == NULL)
                         break;                          break;
         }          }
         exit(argv ? exitval : 2);          exit(*argv ? exitval : 2);
 }  }
   
 static void  
 prlongname(buf)  
         char *buf;  
 {  
         int savech;  
         char *p, *savep;  
   
         for (p = buf; *p && *p != ':'; ++p)  
                 continue;  
         savech = *(savep = p);  
         for (*p = '\0'; p >= buf && *p != '|'; --p)  
                 continue;  
         (void)printf("%s\n", p + 1);  
         *savep = savech;  
 }  
   
 static char **  static char **
 process(cap, str, argv)  process(cap, str, argv)
         char *cap, *str, **argv;          char *cap, *str, **argv;
 {  {
         static char errfew[] =          char *cp, *s, *nargv[9];
             "not enough arguments (%d) for capability `%s'";          int arg_need, popcount, i;
         static char errmany[] =  
             "too many arguments (%d) for capability `%s'";  
         static char erresc[] =  
             "unknown %% escape `%c' for capability `%s'";  
         char *cp;  
         int arg_need, arg_rows, arg_cols;  
   
         /* Count how many values we need for this capability. */          /* Count how many values we need for this capability. */
         for (cp = str, arg_need = 0; *cp != '\0'; cp++)          for (cp = str, arg_need = popcount = 0; *cp != '\0'; cp++) {
                 if (*cp == '%')                  if (*cp == '%') {
                             switch (*++cp) {                          switch (*++cp) {
                             case 'd':                          case '%':
                             case '2':                                  cp++;
                             case '3':                                  break;
                             case '.':                          case 'i':
                             case '+':                                  if (popcount < 2)
                                     arg_need++;                                          popcount = 2;
                                     break;                                  break;
                             case '%':                          case 'p':
                             case '>':                                  cp++;
                             case 'i':                                  if (isdigit(cp[1]) && popcount < cp[1] - '0')
                             case 'r':                                          popcount = cp[1] - '0';
                             case 'n':                                  break;
                             case 'B':                          case 'd':
                             case 'D':                          case 's':
                                     break;                          case '0':
                             default:                          case '1':
                                 /*                          case '2':
                                  * hpux has lot's of them, but we complain                          case '3':
                                  */                          case '4':
                                  errx(2, erresc, *cp, cap);                          case '5':
                             }                          case '6':
                           case '7':
                           case '8':
                           case '9':
                           case '.':
                           case '+':
                                   arg_need++;
                                   break;
                           default:
                                   break;
                           }
                   }
           }
           arg_need = MAX(arg_need, popcount);
           if (arg_need > 9)
                   errx(2, "too many arguments (%d) for capability `%s'",
                       arg_need, cap);
   
           for (i = 0; i < arg_need; i++) {
                   long l;
   
         /* And print them. */                  if (argv[i] == NULL)
         switch (arg_need) {                          errx(2, "not enough arguments (%d) for capability `%s'",
         case 0:                              arg_need, cap);
                 (void)tputs(str, 1, outc);  
                 break;  
         case 1:  
                 arg_cols = 0;  
   
                 if (*++argv == NULL || *argv[0] == '\0')                  /* convert ascii representation of numbers to longs */
                         errx(2, errfew, 1, cap);                  if (isdigit(argv[i][0]) && (l = strtol(argv[i], &cp, 10)) >= 0
                 arg_rows = atoi(*argv);                      && l < LONG_MAX && *cp == '\0')
                           nargv[i] = (char *)l;
                   else
                           nargv[i] = argv[i];
           }
   
                 (void)tputs(tgoto(str, arg_cols, arg_rows), 1, outc);          s = tparm(str, nargv[0], nargv[1], nargv[2], nargv[3],
                 break;              nargv[4], nargv[5], nargv[6], nargv[7], nargv[8]);
         case 2:          putp(s);
                 if (*++argv == NULL || *argv[0] == '\0')          fflush(stdout);
                         errx(2, errfew, 2, cap);  
                 arg_rows = atoi(*argv);  
   
                 if (*++argv == NULL || *argv[0] == '\0')          return (argv + arg_need);
                         errx(2, errfew, 2, cap);  
                 arg_cols = atoi(*argv);  
   
                 (void) tputs(tgoto(str, arg_cols, arg_rows), arg_rows, outc);  
                 break;  
   
         default:  
                 errx(2, errmany, arg_need, cap);  
         }  
         return (argv);  
 }  }
   
 static void  static void
 setospeed()  init()
 {  {
 #undef ospeed          FILE *ifile;
         extern short ospeed;          size_t len;
         struct termios t;          char *buf;
           int waitinfo;
   
         if (tcgetattr(STDOUT_FILENO, &t) != -1)          /* XXX - should we check for existence before exec()'ing? */
                 ospeed = 0;          if (init_prog && !issetugid()) {
         else                  switch (vfork()) {
                 ospeed = cfgetospeed(&t);                  case -1:
                           err(4, "vfork");
                           break;
                   case 0:
                           /* child */
                           execl(init_prog, init_prog, NULL);
                           _exit(127);
                           break;
                   default:
                           wait(&waitinfo);
                           /* XXX - interpret waitinfo? */
                           break;
                   }
           }
           if (init_1string)
                   putp(init_1string);
           if (init_2string)
                   putp(init_2string);
           if (init_file && !issetugid() && (ifile = fopen(init_file, "r"))) {
                   while ((buf = fgetln(ifile, &len)) != NULL) {
                           if (buf[len-1] != '\n')
                                   errx(1, "premature EOF reading %s", init_file);
                           buf[len-1] = '\0';
                           putp(buf);
                   }
                   fclose(ifile);
           }
           if (init_3string)
                   putp(init_3string);
           /* XXX - do tabs and margins */
           fflush(stdout);
 }  }
   
 static void  static void
 outc(c)  reset()
         int c;  
 {  {
         (void)putchar(c);          FILE *rfile;
           size_t len;
           char *buf;
   
           if (reset_1string)
                   putp(reset_1string);
           if (reset_2string)
                   putp(reset_2string);
           /* XXX - cat reset_file */
           if (reset_file && !issetugid() && (rfile = fopen(reset_file, "r"))) {
                   while ((buf = fgetln(rfile, &len)) != NULL) {
                           if (buf[len-1] != '\n')
                                   errx(1, "premature EOF reading %s", reset_file);
                           buf[len-1] = '\0';
                           putp(buf);
                   }
                   fclose(rfile);
           }
           if (reset_3string)
                   putp(reset_3string);
           /* XXX - do tabs and margins */
           fflush(stdout);
 }  }
   
 static void  static void
 usage()  usage()
 {  {
         (void)fprintf(stderr, "usage: tput [-T term] attribute ...\n");  
           if (strcmp(__progname, "clear") == 0)
                   (void)fprintf(stderr, "usage: %s [-T term]\n", __progname);
           else
                   (void)fprintf(stderr,
                       "usage: %s [-T term] attribute [attribute-args] ...\n"
                       "       %s [-T term] -S\n", __progname, __progname);
         exit(1);          exit(1);
 }  }

Legend:
Removed from v.1.7  
changed lines
  Added in v.1.8