2 * Copyright (C) 1984-2022 Mark Nudelman
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Less License, as specified in the README file.
7 * For more information, see the README file.
12 * lesskey [-o output] [input]
14 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
17 * If no input file is specified, standard input is used.
18 * If no output file is specified, $HOME/.less is used.
20 * The .less file is used to specify (to "less") user-defined
21 * key bindings. Basically any sequence of 1 to MAX_CMDLEN
22 * keystrokes may be bound to an existing less function.
24 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
26 * The input file is an ascii file consisting of a
27 * sequence of lines of the form:
28 * string <whitespace> action [chars] <newline>
30 * "string" is a sequence of command characters which form
31 * the new user-defined command. The command
33 * 1. The actual character itself.
34 * 2. A character preceded by ^ to specify a
35 * control character (e.g. ^X means control-X).
36 * 3. A backslash followed by one to three octal digits
37 * to specify a character by its octal value.
38 * 4. A backslash followed by b, e, n, r or t
39 * to specify \b, ESC, \n, \r or \t, respectively.
40 * 5. Any character (other than those mentioned above) preceded
41 * by a \ to specify the character itself (characters which
42 * must be preceded by \ include ^, \, and whitespace.
43 * "action" is the name of a "less" action, from the table below.
44 * "chars" is an optional sequence of characters which is treated
45 * as keyboard input after the command is executed.
47 * Blank lines and lines which start with # are ignored,
48 * except for the special control lines:
49 * #command Signals the beginning of the command
51 * #line-edit Signals the beginning of the line-editing
53 * #env Signals the beginning of the environment
55 * #stop Stops command parsing in less;
56 * causes all default keys to be disabled.
58 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
60 * The output file is a non-ascii file, consisting of a header,
61 * one or more sections, and a trailer.
62 * Each section begins with a section header, a section length word
63 * and the section data. Normally there are three sections:
64 * CMD_SECTION Definition of command keys.
65 * EDIT_SECTION Definition of editing keys.
66 * END_SECTION A special section header, with no
67 * length word or section data.
69 * Section data consists of zero or more byte sequences of the form:
72 * string <0> <action|A_EXTRA> chars <0>
74 * "string" is the command string.
75 * "<0>" is one null byte.
76 * "<action>" is one byte containing the action code (the A_xxx value).
77 * If action is ORed with A_EXTRA, the action byte is followed
78 * by the null-terminated "chars" string.
80 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
96 char filetrailer
[] = {
101 char cmdsection
[1] = { CMD_SECTION
};
102 char editsection
[1] = { EDIT_SECTION
};
103 char varsection
[1] = { VAR_SECTION
};
104 char endsection
[1] = { END_SECTION
};
107 char *outfile
= NULL
;
109 extern char version
[];
114 fprintf(stderr
, "usage: lesskey [-o output] [input]\n");
119 lesskey_parse_error(s
)
122 fprintf(stderr
, "%s\n", s
);
130 return (int) strtol(buf
, ebuf
, 10);
140 p
= calloc(count
, size
);
143 fprintf(stderr
, "lesskey: cannot allocate %d bytes of memory\n", count
*size
);
148 mkpathname(dirname
, filename
)
154 pathname
= ecalloc(strlen(dirname
) + strlen(filename
) + 2, sizeof(char));
155 strcpy(pathname
, dirname
);
156 strcat(pathname
, PATHNAME_SEP
);
157 strcat(pathname
, filename
);
162 * Figure out the name of a default file (in the user's HOME directory).
171 if ((p
= getenv("HOME")) != NULL
&& *p
!= '\0')
172 pathname
= mkpathname(p
, filename
);
174 else if ((p
= getenv("INIT")) != NULL
&& *p
!= '\0')
175 pathname
= mkpathname(p
, filename
);
179 fprintf(stderr
, "cannot find $HOME - using current directory\n");
180 pathname
= mkpathname(".", filename
);
186 * Parse command line arguments.
189 parse_args(argc
, argv
)
200 /* Arg does not start with "-"; it's not an option. */
203 /* "-" means standard input. */
205 if (arg
[1] == '-' && arg
[2] == '\0')
207 /* "--" means end of options. */
215 if (strncmp(arg
, "--output", 8) == 0)
219 else if (arg
[8] == '=')
225 if (strcmp(arg
, "--version") == 0)
232 outfile
= &argv
[0][2];
234 if (*outfile
== '\0')
243 printf("lesskey version %s\n", version
);
252 * Open the input file, or use DEF_LESSKEYINFILE if none specified.
262 fputbytes(fd
, buf
, len
)
269 fwrite(buf
, sizeof(char), 1, fd
);
275 * Output an integer, in special KRADIX form.
284 if (val
>= KRADIX
*KRADIX
)
286 fprintf(stderr
, "error: cannot write %d, max %d\n",
291 fwrite(&c
, sizeof(char), 1, fd
);
293 fwrite(&c
, sizeof(char), 1, fd
);
301 struct lesskey_tables tables
;
306 if (getenv("HOME") == NULL
)
309 * If there is no HOME environment variable,
310 * try the concatenation of HOMEDRIVE + HOMEPATH.
312 char *drive
= getenv("HOMEDRIVE");
313 char *path
= getenv("HOMEPATH");
314 if (drive
!= NULL
&& path
!= NULL
)
316 char *env
= (char *) ecalloc(strlen(drive
) +
317 strlen(path
) + 6, sizeof(char));
318 strcpy(env
, "HOME=");
327 * Process command line arguments.
329 parse_args(argc
, argv
);
330 errors
= parse_lesskey(infile
, &tables
);
333 fprintf(stderr
, "%d errors; no output produced\n", errors
);
337 fprintf(stderr
, "NOTE: lesskey is deprecated.\n It is no longer necessary to run lesskey,\n when using less version 582 and later.\n");
340 * Write the output file.
341 * If no output file was specified, use "$HOME/.less"
344 outfile
= getenv("LESSKEY");
346 outfile
= homefile(LESSKEYFILE
);
347 if ((out
= fopen(outfile
, "wb")) == NULL
)
352 fprintf(stderr
, "Cannot open %s\n", outfile
);
358 fputbytes(out
, fileheader
, sizeof(fileheader
));
360 /* Command key section */
361 fputbytes(out
, cmdsection
, sizeof(cmdsection
));
362 fputint(out
, tables
.cmdtable
.buf
.end
);
363 fputbytes(out
, (char *)tables
.cmdtable
.buf
.data
, tables
.cmdtable
.buf
.end
);
364 /* Edit key section */
365 fputbytes(out
, editsection
, sizeof(editsection
));
366 fputint(out
, tables
.edittable
.buf
.end
);
367 fputbytes(out
, (char *)tables
.edittable
.buf
.data
, tables
.edittable
.buf
.end
);
369 /* Environment variable section */
370 fputbytes(out
, varsection
, sizeof(varsection
));
371 fputint(out
, tables
.vartable
.buf
.end
);
372 fputbytes(out
, (char *)tables
.vartable
.buf
.data
, tables
.vartable
.buf
.end
);
375 fputbytes(out
, endsection
, sizeof(endsection
));
376 fputbytes(out
, filetrailer
, sizeof(filetrailer
));