~ubuntu-branches/debian/wheezy/tweak/wheezy

« back to all changes in this revision

Viewing changes to .pc/02_avoid_buffer_overflows/keytab.c

  • Committer: Package Import Robot
  • Author(s): Daniel Kahn Gillmor
  • Date: 2012-03-04 19:37:53 UTC
  • Revision ID: package-import@ubuntu.com-20120304193753-jnid7ekl6wkag63d
Tags: 3.01-8
* debian/control: bump Standards-Version to 3.9.3 (no changes needed),
  change Vcs- fields.
* debian/rules: minimize, move to dh 8
* convert source format to '3.0 (quilt)' (dropping dpatch build-dep)
* drop halibut build-dep in favor of shipping upstream's man page and
  documentation directly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "tweak.h"
 
2
 
 
3
#include <stdio.h>
 
4
#include <stdlib.h>
 
5
#include <string.h>
 
6
#include <ctype.h>
 
7
 
 
8
typedef union keytab keytab;
 
9
 
 
10
union keytab {
 
11
    enum {ACTION, EXTENDED} type;
 
12
    struct {
 
13
        int type;
 
14
        keyact action;
 
15
    } a;
 
16
    struct {
 
17
        int type;
 
18
        keytab *extended[256];
 
19
    } e;
 
20
};
 
21
 
 
22
keytab *base[256] = { NULL256 };
 
23
 
 
24
/*
 
25
 * Bind a key sequence to an action.
 
26
 */
 
27
void bind_key (char *sequence, int len, keyact action) {
 
28
    keytab *(*table)[256];
 
29
    int k, i;
 
30
 
 
31
    table = &base;
 
32
    while (--len) {
 
33
        k = (unsigned char) *sequence++;
 
34
        if ( !(*table)[k] ) {
 
35
            /*
 
36
             * We must create an EXTENDED entry.
 
37
             */
 
38
            (*table)[k] = malloc(sizeof(base[0]->e));
 
39
            (*table)[k]->type = EXTENDED;
 
40
            for (i=0; i<256; i++)
 
41
                (*table)[k]->e.extended[i] = NULL;
 
42
        } else if ( (*table)[k]->type == ACTION ) {
 
43
            /*
 
44
             * A subsequence is already bound: fail.
 
45
             */
 
46
            return;
 
47
        }
 
48
        table = &(*table)[k]->e.extended;
 
49
    }
 
50
    k = (unsigned char) *sequence;
 
51
    if ( !(*table)[k] ) {
 
52
        /*
 
53
         * We can bind the key.
 
54
         */
 
55
        (*table)[k] = malloc(sizeof(base[0]->a));
 
56
        (*table)[k]->type = ACTION;
 
57
        (*table)[k]->a.action = action;
 
58
    }
 
59
}
 
60
 
 
61
/*
 
62
 * Format an ASCII code into a printable description of the key stroke.
 
63
 */
 
64
static void strkey (char *s, int k) {
 
65
    k &= 255;                          /* force unsigned */
 
66
    if (k==27)
 
67
        strcpy(s, " ESC");
 
68
    else if (k<32 || k==127)
 
69
        sprintf(s, " ^%c", k ^ 64);
 
70
    else if (k<127)
 
71
        sprintf(s, " %c", k);
 
72
    else
 
73
        sprintf(s, " <0x%2X>", k);
 
74
}
 
75
 
 
76
/*
 
77
 * Get and process a key stroke.
 
78
 */
 
79
void proc_key (void) {
 
80
    keytab *kt;
 
81
 
 
82
#if defined(unix) && !defined(GO32)
 
83
    if (update_required)
 
84
        update();
 
85
    safe_update = TRUE;
 
86
#endif
 
87
    last_char = display_getkey();
 
88
#if defined(unix) && !defined(GO32)
 
89
    safe_update = FALSE;
 
90
#endif
 
91
    strcpy(message, "Unknown key sequence");
 
92
    strkey(message+strlen(message), last_char);
 
93
    kt = base[(unsigned char) last_char];
 
94
    if (!kt) {
 
95
        display_beep();
 
96
        while (display_input_to_flush())
 
97
            strkey(message+strlen(message), display_getkey());
 
98
        return;
 
99
    }
 
100
 
 
101
    while (kt->type == EXTENDED) {
 
102
#if defined(unix) && !defined(GO32)
 
103
        if (update_required)
 
104
            update();
 
105
        safe_update = TRUE;
 
106
#endif
 
107
        last_char = display_getkey();
 
108
#if defined(unix) && !defined(GO32)
 
109
        safe_update = FALSE;
 
110
#endif
 
111
        strkey(message+strlen(message), last_char);
 
112
        kt = kt->e.extended[(unsigned char) last_char];
 
113
        if (!kt) {
 
114
            display_beep();
 
115
            while (display_input_to_flush())
 
116
                strkey(message+strlen(message), display_getkey());
 
117
            return;
 
118
        }
 
119
    }
 
120
    message[0] = '\0';                 /* clear the "unknown" message */
 
121
    (*kt->a.action)();
 
122
}