Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.sbin / pcvt / userkeys / vt220keys.c
1 /*
2  *      Trivial program to load VT220 Function keys with strings,
3  *      note that the values only get sent when the key is shifted
4  *      (shoulda been an option to flip the shift set like the Z19!)
5  *
6  *      Typing no args gives help, basically pairs of keyname/value
7  *      strings.
8  *
9  *      Author, Author: Barry Shein, Boston University
10  *
11  * HISTORY
12   {1}   30-Oct-85  Kenneth J. Lester (ken) at ektools
13
14         Added the necessary code to read an initialization file.  This
15         should make it easier to used this program.  Also added code
16         that will set-up the terminal in vt200 (this saves the user the
17         trouble of checking if the set-up is in vt200).
18
19         Restructed  the  main  function  to  use   getopt,  for  argument
20         processing.
21
22         Alterated usage function  to include  new "i"  option (init file)
23
24
25         -hm     minor modifications for pcvt 2.0 release
26
27 $FreeBSD: src/usr.sbin/pcvt/userkeys/vt220keys.c,v 1.5.6.1 2001/05/12 10:11:42 kris Exp $
28 */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <ctype.h>
34
35 /*
36  *      The default toupper() macro is stupid, will toupper anything
37  */
38
39 #ifdef toupper
40 #undef toupper
41 #endif
42 #define toupper(c) (islower(c) ? ((c)-' ') : c)
43
44 #define VT200_7BIT 1
45 #define ESC 033
46 #define INITFILE ".vt220rc"
47
48 struct keynames {
49   char *name ;
50   char *string ;
51 } keys[] = {
52   "F6", "17",
53   "F7", "18",
54   "F8", "19",
55   "F9", "20",
56   "F10", "21",
57   "F11", "23",
58   "ESC", "23",
59   "F12", "24",
60   "BS", "24",
61   "F13", "25",
62   "LF", "25",
63   "F14", "26",
64   "HELP", "28",
65   "DO", "29",
66   "F17", "31",
67   "F18", "32",
68   "F19", "33",
69   "F20", "34",
70     NULL, NULL
71 };
72
73 char prog[BUFSIZ];
74
75 main(argc,argv)
76         int argc;
77         char *argv[];
78 {
79         /* these are defined in the getopt routine                       */
80         extern char *optarg;    /* argument give to an option            */
81         extern int  optind;     /* argv index after option processing    */
82
83         int option;             /* option character returned by getopt   */
84         int initf = 0;          /* read initialization file              */
85         int lockf = 0;          /* lock keys after loading strings       */
86         int clearf = 0;         /* clear all keys before loading strings */
87
88         strlcpy(prog, *argv, sizeof(prog));  /* store program name       */
89
90         if(argc == 1) usage();  /* program requires options              */
91
92         /* get options */
93         while ((option = getopt(argc, argv, "cli")) != -1)
94         switch(option)
95         {
96                 case 'c' :
97                         clearf++;
98                         break;
99                 case 'l' :
100                         lockf++;
101                         break;
102                 case 'i' :
103                         initf++;
104                         break;
105                 case '?' :
106                         usage();
107           }
108
109         if (VT200_7BIT)
110                 printf("\033[62;1\"p");    /* vt200 7 bits */
111         else
112                 printf("\033[62;2\"p");    /* vt200 8 bits */
113
114         if(clearf) clearkeys();
115
116         if (initf) getinit();
117
118         /* process {key, key string} pairs.  Note optind is index to argv
119            for first pair.  By adding 1 to optind insures that a pair exists
120            i.e. the last key has a key string.                             */
121
122         while(optind + 1 < argc)
123         {
124                 dokey(argv[optind], argv[optind+1]);
125                 optind += 2;
126         }
127
128         if(lockf) lockkeys();
129
130         exit(0);
131 }
132
133 /****************************************************************************/
134
135 /*
136  *      Load the VT220 SHIFT-FNKEY value, the basic pattern is
137  *              "\EP1;1|"+KEYNAME+"/"+VAL_AS_HEX+"\E\\"
138  *      that is, literally what is in quotes (w/o quotes) then the
139  *      name of the key from the keytable above (a numeric string)
140  *      then a slash, then the string value as hex pairs then ESC-BACKSLASH
141  *
142  *      Note: you can gang together key defns with semicolons but that
143  *      would complicate things, especially error handling, so do it all
144  *      for each pair, who cares, really.
145  */
146
147 dokey(nm,val) char *nm, *val;
148 {
149         register char *scr;
150         register struct keynames *kp;
151
152         for(scr = nm; *scr = toupper(*scr); scr++)
153                         ;
154         for(kp = keys; kp->name != NULL; kp++)
155           if(strcmp(nm,kp->name) == 0) {
156             printf("%cP1;1|%s/",ESC,kp->string);
157             while(*val) printf("%02x",*val++);
158             printf("%c\\",ESC);
159             fflush(stdout);
160             return;
161         }
162         fprintf(stderr,"Bad key name: %s\n",nm);
163         usage();        /* bad key name, give up */
164 }
165
166 /****************************************************************************/
167
168 clearkeys()
169 {
170         printf("%cP0;1|%c\\",ESC,ESC);
171         fflush(stdout);
172 }
173
174 /****************************************************************************/
175
176 lockkeys()
177 {
178         printf("%cP1;0|%c\\",ESC,ESC);
179         fflush(stdout);
180 }
181
182 /****************************************************************************/
183
184 usage()
185 {
186         int i;
187
188         fprintf(stderr,"Usage: %s [-cil] [keyname string keyname string...]\n\n",prog);
189         fprintf(stderr,"The following options are available\n");
190         fprintf(stderr,"\t-c\tclears keys first\n");
191         fprintf(stderr,"\t-l\t[sets then] locks further setting\n");
192         fprintf(stderr,"\t-i\tfirst read initialization file $HOME/%s\n",INITFILE);
193         fprintf(stderr,"(note that the only way to unlock is via Set-Up)\n\n");
194         fprintf(stderr,"Keyname is one of:\n\t");
195         for(i=0; keys[i].name != NULL; i++)
196                 fprintf(stderr,"%s ",keys[i].name);
197         fprintf(stderr,"\nKeyname is SHIFTED function key that sends the string\n\n");
198         fprintf(stderr,"Strings may need quoting to protect from shell\n");
199         fprintf(stderr,"You must specify an option or key,string pairs\n\n");
200         exit(1);
201 }
202
203 /****************************************************************************/
204
205 /* This routine process the INITFILE.  This file expects lines in the format
206
207                 <ws> keyname ws string
208
209    Where ws is white space (spaces or tabs) and <ws> is optional white space.
210    The string may include spaces or tabs and need not be quoted.  If the
211    string has the sequence of "\n" then a newline character is included in
212    the string.
213
214    examples:
215
216         F6      ls -lg\n
217         F7      uulog -s
218
219 */
220
221 #include <sys/types.h>
222 #include <sys/stat.h>
223
224 getinit()
225 {
226         char *home;             /* user's home directory                */
227         char path[BUFSIZ];      /* full path name of init file          */
228         char buf[BUFSIZ];       /* buffer to hold 1 line from init file */
229         char key[BUFSIZ];       /* buffer, to hold specified fcn key    */
230         char keystr[BUFSIZ];    /* string associated with fcn key       */
231         char *ptr;              /* pointer to transverse buf            */
232         int i, j;               /* array indices                        */
233         int statflag;           /* whether init file is regular & readable */
234         struct stat statbuf;    /* stat of the init file                */
235         FILE *fp;               /* file pointer to init file            */
236
237         /* construct full path name for init file */
238         home = getenv("HOME");
239         snprintf(path, sizeof(path), "%s/%s", home, INITFILE);
240
241         /* check status if init file    */
242         if (stat(path, &statbuf) != -1)
243         {
244             statflag = statbuf.st_mode & S_IFREG && statbuf.st_mode & S_IREAD;
245             if (!statflag || (fp = fopen(path, "r")) == NULL)
246             {
247                 fprintf(stderr, "couldn't open initalization file: %s\n", path);
248                 exit(1);
249             }
250
251             /* process lines from init file */
252             while (fgets(buf, BUFSIZ, fp) != NULL)
253             {
254                 /* variable initializations */
255                 i = 0; j = 0;
256                 key[0] = '\0'; keystr[0] = '\0';
257                 ptr = buf;
258
259                 while (*ptr == ' ' || *ptr == '\t') ptr++; /*skip whitespace*/
260
261                 if (*ptr == '\n') break;   /* we hit an emtpy line          */
262
263                 while (!isspace(*ptr) && *ptr != '\0')     /* get keyname   */
264                     key[i++] = *ptr++;
265                 key[i] = '\0'; /* place EOS in buffer */
266
267                 while (*ptr == ' ' || *ptr == '\t') ptr++; /*skip whitespace*/
268
269                 while (*ptr != '\n' && *ptr != '\0')       /* get string    */
270                 {
271                     /* check if string is to include newline i.e. \n        */
272                     if (*ptr == '\\' && *(ptr+1) == 'n')
273                     {
274                           keystr[j] = '\012';
275                           ptr++;
276                     }
277                     else
278                           keystr[j] = *ptr;
279                     j++; ptr++;
280                 }
281                 keystr[j] = '\0';     /* place EOS in buffer  */
282                 dokey(key, keystr);   /* load key with string */
283             }
284         }
285         else
286         {
287             fprintf(stderr, "init file %s not found\n\n", path);
288             usage();
289         }
290 }