1 /*
2 * IBM/3270 Driver -- Copyright (C) 2000 UTS Global LLC
3 *
4 * tubttyrcl.c -- Linemode Command-recall functionality
5 *
6 *
7 *
8 *
9 *
10 * Author: Richard Hitt
11 */
12 #include "tubio.h"
13
14 int
tty3270_rcl_init(tub_t * tubp)15 tty3270_rcl_init(tub_t *tubp)
16 {
17 return tty3270_rcl_resize(tubp, 20);
18 }
19
20 int
tty3270_rcl_resize(tub_t * tubp,int newrclk)21 tty3270_rcl_resize(tub_t *tubp, int newrclk)
22 {
23 char *(*newrclb)[];
24
25 if (newrclk > 1000)
26 return -EINVAL;
27 if (newrclk <= 0) {
28 tty3270_rcl_purge(tubp),
29 kfree(tubp->tty_rclbufs);
30 tubp->tty_rclbufs = NULL;
31 return 0;
32 }
33 if ((newrclb = (char *(*)[])kmalloc(
34 newrclk * sizeof (char *), GFP_KERNEL)) == NULL)
35 return -ENOMEM;
36 memset(newrclb, 0, newrclk * sizeof (char *));
37 if (tubp->tty_rclbufs != NULL) {
38 int i, j, k;
39 char *data;
40
41 i = tubp->tty_rclp;
42 j = newrclk;
43 k = tubp->tty_rclk;
44 while (j-- && k--) {
45 if ((data = (*tubp->tty_rclbufs)[i]) == NULL)
46 break;
47 (*newrclb)[j] = data;
48 (*tubp->tty_rclbufs)[i] = NULL;
49 if (--i < 0)
50 i = tubp->tty_rclk - 1;
51 }
52 tty3270_rcl_purge(tubp);
53 kfree(tubp->tty_rclbufs);
54 }
55 tubp->tty_rclbufs = newrclb;
56 tubp->tty_rclk = newrclk;
57 tubp->tty_rclp = newrclk - 1;
58 tty3270_rcl_sync(tubp);
59 return 0;
60 }
61
62 int
tty3270_rcl_set(tub_t * tubp,char * buf,int count)63 tty3270_rcl_set(tub_t *tubp, char *buf, int count)
64 {
65 #define RCL_SIZ "recallsize="
66 #define L_RCL_SIZ (strlen(RCL_SIZ))
67 int newsize;
68 int len;
69 int rc;
70 char *rcl_siz = RCL_SIZ;
71 int l_rcl_siz = L_RCL_SIZ;
72
73 if (count < l_rcl_siz || strncmp(buf, rcl_siz, l_rcl_siz) != 0)
74 return 0;
75 if ((len = count - l_rcl_siz) == 0)
76 return count;
77 newsize = simple_strtoul(buf + l_rcl_siz, 0, 0);
78 rc = tty3270_rcl_resize(tubp, newsize);
79 return rc < 0? rc: count;
80 }
81
82 void
tty3270_rcl_fini(tub_t * tubp)83 tty3270_rcl_fini(tub_t *tubp)
84 {
85 if (tubp->tty_rclbufs != NULL) {
86 tty3270_rcl_purge(tubp);
87 kfree(tubp->tty_rclbufs);
88 tubp->tty_rclbufs = NULL;
89 }
90 }
91
92 void
tty3270_rcl_purge(tub_t * tubp)93 tty3270_rcl_purge(tub_t *tubp)
94 {
95 int i;
96 char *buf;
97
98 if (tubp->tty_rclbufs == NULL)
99 return;
100 for (i = 0; i < tubp->tty_rclk; i++) {
101 if ((buf = (*tubp->tty_rclbufs)[i]) == NULL)
102 continue;
103 kfree(buf);
104 (*tubp->tty_rclbufs)[i] = NULL;
105 }
106 }
107
108 int
tty3270_rcl_get(tub_t * tubp,char * buf,int len,int inc)109 tty3270_rcl_get(tub_t *tubp, char *buf, int len, int inc)
110 {
111 int iter;
112 int i;
113 char *data;
114
115 if (tubp->tty_rclbufs == NULL)
116 return 0;
117 if (tubp->tty_rclk <= 0) /* overcautious */
118 return 0;
119 if (inc != 1 && inc != -1) /* overcautious */
120 return 0;
121
122 if ((i = tubp->tty_rclb) == -1) {
123 i = tubp->tty_rclp;
124 if (inc == 1)
125 i++;
126 } else {
127 i += inc;
128 }
129 for (iter = tubp->tty_rclk; iter; iter--, i += inc) {
130 if (i < 0)
131 i = tubp->tty_rclk - 1;
132 else if (i >= tubp->tty_rclk)
133 i = 0;
134 if ((*tubp->tty_rclbufs)[i] != NULL)
135 break;
136 }
137 if (iter < 0 || (data = (*tubp->tty_rclbufs)[i]) == NULL)
138 return 0;
139 tubp->tty_rclb = i;
140 if ((len = MIN(len - 1, strlen(data))) <= 0)
141 return 0;
142 memcpy(buf, data, len);
143 buf[len] = '\0';
144 return len;
145 }
146
147 void
tty3270_rcl_put(tub_t * tubp,char * data,int len)148 tty3270_rcl_put(tub_t *tubp, char *data, int len)
149 {
150 char *buf, **bufp;
151 int i;
152
153 if (tubp->tty_rclbufs == NULL)
154 return;
155
156 if (tubp->tty_rclk <= 0) /* overcautious */
157 return;
158
159 /* If input area is invisible, don't log */
160 if (tubp->tty_inattr == TF_INPUTN)
161 return;
162
163 /* If this & most recent cmd text match, don't log */
164 if ((buf = (*tubp->tty_rclbufs)[tubp->tty_rclp]) != NULL &&
165 strlen(buf) == len && memcmp(buf, data, len) == 0) {
166 tty3270_rcl_sync(tubp);
167 return;
168 }
169
170 /* Don't stack zero-length commands */
171 if (len == 0) {
172 tty3270_rcl_sync(tubp);
173 return;
174 }
175
176 i = tubp->tty_rclp;
177 if (++i == tubp->tty_rclk)
178 i = 0;
179 bufp = &(*tubp->tty_rclbufs)[i];
180 if (*bufp == NULL || strlen(*bufp) < len + 1) {
181 if (*bufp) {
182 kfree(*bufp);
183 *bufp = NULL;
184 }
185 if ((*bufp = kmalloc(len + 1, GFP_ATOMIC)) == NULL)
186 return;
187 }
188 memcpy(*bufp, data, len);
189 (*bufp)[len] = '\0';
190 tubp->tty_rclp = i;
191 tty3270_rcl_sync(tubp);
192 }
193
194 void
tty3270_rcl_sync(tub_t * tubp)195 tty3270_rcl_sync(tub_t *tubp)
196 {
197 tubp->tty_rclb = -1;
198 }
199
200