@@ -184,6 +184,33 @@ char kdb_getchar(void)
184
184
unreachable ();
185
185
}
186
186
187
+ /**
188
+ * kdb_position_cursor() - Place cursor in the correct horizontal position
189
+ * @prompt: Nil-terminated string containing the prompt string
190
+ * @buffer: Nil-terminated string containing the entire command line
191
+ * @cp: Cursor position, pointer the character in buffer where the cursor
192
+ * should be positioned.
193
+ *
194
+ * The cursor is positioned by sending a carriage-return and then printing
195
+ * the content of the line until we reach the correct cursor position.
196
+ *
197
+ * There is some additional fine detail here.
198
+ *
199
+ * Firstly, even though kdb_printf() will correctly format zero-width fields
200
+ * we want the second call to kdb_printf() to be conditional. That keeps things
201
+ * a little cleaner when LOGGING=1.
202
+ *
203
+ * Secondly, we can't combine everything into one call to kdb_printf() since
204
+ * that renders into a fixed length buffer and the combined print could result
205
+ * in unwanted truncation.
206
+ */
207
+ static void kdb_position_cursor (char * prompt , char * buffer , char * cp )
208
+ {
209
+ kdb_printf ("\r%s" , kdb_prompt_str );
210
+ if (cp > buffer )
211
+ kdb_printf ("%.*s" , (int )(cp - buffer ), buffer );
212
+ }
213
+
187
214
/*
188
215
* kdb_read
189
216
*
@@ -220,8 +247,7 @@ static char *kdb_read(char *buffer, size_t bufsize)
220
247
int count ;
221
248
int i ;
222
249
int diag , dtab_count ;
223
- int key , buf_size , ret ;
224
-
250
+ int key , ret ;
225
251
226
252
diag = kdbgetintenv ("DTABCOUNT" , & dtab_count );
227
253
if (diag )
@@ -243,18 +269,11 @@ static char *kdb_read(char *buffer, size_t bufsize)
243
269
switch (key ) {
244
270
case 8 : /* backspace */
245
271
if (cp > buffer ) {
246
- if (cp < lastchar ) {
247
- memcpy (tmpbuffer , cp , lastchar - cp );
248
- memcpy (cp - 1 , tmpbuffer , lastchar - cp );
249
- }
250
- * (-- lastchar ) = '\0' ;
251
- -- cp ;
252
- kdb_printf ("\b%s \r" , cp );
253
- tmp = * cp ;
254
- * cp = '\0' ;
255
- kdb_printf (kdb_prompt_str );
256
- kdb_printf ("%s" , buffer );
257
- * cp = tmp ;
272
+ memmove (cp - 1 , cp , lastchar - cp + 1 );
273
+ lastchar -- ;
274
+ cp -- ;
275
+ kdb_printf ("\b%s " , cp );
276
+ kdb_position_cursor (kdb_prompt_str , buffer , cp );
258
277
}
259
278
break ;
260
279
case 10 : /* linefeed */
@@ -269,22 +288,16 @@ static char *kdb_read(char *buffer, size_t bufsize)
269
288
return buffer ;
270
289
case 4 : /* Del */
271
290
if (cp < lastchar ) {
272
- memcpy (tmpbuffer , cp + 1 , lastchar - cp - 1 );
273
- memcpy (cp , tmpbuffer , lastchar - cp - 1 );
274
- * (-- lastchar ) = '\0' ;
275
- kdb_printf ("%s \r" , cp );
276
- tmp = * cp ;
277
- * cp = '\0' ;
278
- kdb_printf (kdb_prompt_str );
279
- kdb_printf ("%s" , buffer );
280
- * cp = tmp ;
291
+ memmove (cp , cp + 1 , lastchar - cp );
292
+ lastchar -- ;
293
+ kdb_printf ("%s " , cp );
294
+ kdb_position_cursor (kdb_prompt_str , buffer , cp );
281
295
}
282
296
break ;
283
297
case 1 : /* Home */
284
298
if (cp > buffer ) {
285
- kdb_printf ("\r" );
286
- kdb_printf (kdb_prompt_str );
287
299
cp = buffer ;
300
+ kdb_position_cursor (kdb_prompt_str , buffer , cp );
288
301
}
289
302
break ;
290
303
case 5 : /* End */
@@ -300,11 +313,10 @@ static char *kdb_read(char *buffer, size_t bufsize)
300
313
}
301
314
break ;
302
315
case 14 : /* Down */
303
- memset (tmpbuffer , ' ' ,
304
- strlen (kdb_prompt_str ) + (lastchar - buffer ));
305
- * (tmpbuffer + strlen (kdb_prompt_str ) +
306
- (lastchar - buffer )) = '\0' ;
307
- kdb_printf ("\r%s\r" , tmpbuffer );
316
+ case 16 : /* Up */
317
+ kdb_printf ("\r%*c\r" ,
318
+ (int )(strlen (kdb_prompt_str ) + (lastchar - buffer )),
319
+ ' ' );
308
320
* lastchar = (char )key ;
309
321
* (lastchar + 1 ) = '\0' ;
310
322
return lastchar ;
@@ -314,33 +326,19 @@ static char *kdb_read(char *buffer, size_t bufsize)
314
326
++ cp ;
315
327
}
316
328
break ;
317
- case 16 : /* Up */
318
- memset (tmpbuffer , ' ' ,
319
- strlen (kdb_prompt_str ) + (lastchar - buffer ));
320
- * (tmpbuffer + strlen (kdb_prompt_str ) +
321
- (lastchar - buffer )) = '\0' ;
322
- kdb_printf ("\r%s\r" , tmpbuffer );
323
- * lastchar = (char )key ;
324
- * (lastchar + 1 ) = '\0' ;
325
- return lastchar ;
326
329
case 9 : /* Tab */
327
330
if (tab < 2 )
328
331
++ tab ;
329
- p_tmp = buffer ;
330
- while (* p_tmp == ' ' )
331
- p_tmp ++ ;
332
- if (p_tmp > cp )
333
- break ;
334
- memcpy (tmpbuffer , p_tmp , cp - p_tmp );
335
- * (tmpbuffer + (cp - p_tmp )) = '\0' ;
336
- p_tmp = strrchr (tmpbuffer , ' ' );
337
- if (p_tmp )
338
- ++ p_tmp ;
339
- else
340
- p_tmp = tmpbuffer ;
341
- len = strlen (p_tmp );
342
- buf_size = sizeof (tmpbuffer ) - (p_tmp - tmpbuffer );
343
- count = kallsyms_symbol_complete (p_tmp , buf_size );
332
+
333
+ tmp = * cp ;
334
+ * cp = '\0' ;
335
+ p_tmp = strrchr (buffer , ' ' );
336
+ p_tmp = (p_tmp ? p_tmp + 1 : buffer );
337
+ strscpy (tmpbuffer , p_tmp , sizeof (tmpbuffer ));
338
+ * cp = tmp ;
339
+
340
+ len = strlen (tmpbuffer );
341
+ count = kallsyms_symbol_complete (tmpbuffer , sizeof (tmpbuffer ));
344
342
if (tab == 2 && count > 0 ) {
345
343
kdb_printf ("\n%d symbols are found." , count );
346
344
if (count > dtab_count ) {
@@ -352,46 +350,51 @@ static char *kdb_read(char *buffer, size_t bufsize)
352
350
}
353
351
kdb_printf ("\n" );
354
352
for (i = 0 ; i < count ; i ++ ) {
355
- ret = kallsyms_symbol_next (p_tmp , i , buf_size );
353
+ ret = kallsyms_symbol_next (tmpbuffer , i , sizeof ( tmpbuffer ) );
356
354
if (WARN_ON (!ret ))
357
355
break ;
358
356
if (ret != - E2BIG )
359
- kdb_printf ("%s " , p_tmp );
357
+ kdb_printf ("%s " , tmpbuffer );
360
358
else
361
- kdb_printf ("%s... " , p_tmp );
362
- * ( p_tmp + len ) = '\0' ;
359
+ kdb_printf ("%s... " , tmpbuffer );
360
+ tmpbuffer [ len ] = '\0' ;
363
361
}
364
362
if (i >= dtab_count )
365
363
kdb_printf ("..." );
366
364
kdb_printf ("\n" );
367
365
kdb_printf (kdb_prompt_str );
368
366
kdb_printf ("%s" , buffer );
367
+ if (cp != lastchar )
368
+ kdb_position_cursor (kdb_prompt_str , buffer , cp );
369
369
} else if (tab != 2 && count > 0 ) {
370
- len_tmp = strlen (p_tmp );
371
- strncpy (p_tmp + len_tmp , cp , lastchar - cp + 1 );
372
- len_tmp = strlen (p_tmp );
373
- strncpy (cp , p_tmp + len , len_tmp - len + 1 );
374
- len = len_tmp - len ;
375
- kdb_printf ("%s" , cp );
376
- cp += len ;
377
- lastchar += len ;
370
+ /* How many new characters do we want from tmpbuffer? */
371
+ len_tmp = strlen (tmpbuffer ) - len ;
372
+ if (lastchar + len_tmp >= bufend )
373
+ len_tmp = bufend - lastchar ;
374
+
375
+ if (len_tmp ) {
376
+ /* + 1 ensures the '\0' is memmove'd */
377
+ memmove (cp + len_tmp , cp , (lastchar - cp ) + 1 );
378
+ memcpy (cp , tmpbuffer + len , len_tmp );
379
+ kdb_printf ("%s" , cp );
380
+ cp += len_tmp ;
381
+ lastchar += len_tmp ;
382
+ if (cp != lastchar )
383
+ kdb_position_cursor (kdb_prompt_str ,
384
+ buffer , cp );
385
+ }
378
386
}
379
387
kdb_nextline = 1 ; /* reset output line number */
380
388
break ;
381
389
default :
382
390
if (key >= 32 && lastchar < bufend ) {
383
391
if (cp < lastchar ) {
384
- memcpy (tmpbuffer , cp , lastchar - cp );
385
- memcpy (cp + 1 , tmpbuffer , lastchar - cp );
386
- * ++ lastchar = '\0' ;
392
+ memmove (cp + 1 , cp , lastchar - cp + 1 );
393
+ lastchar ++ ;
387
394
* cp = key ;
388
- kdb_printf ("%s\r " , cp );
395
+ kdb_printf ("%s" , cp );
389
396
++ cp ;
390
- tmp = * cp ;
391
- * cp = '\0' ;
392
- kdb_printf (kdb_prompt_str );
393
- kdb_printf ("%s" , buffer );
394
- * cp = tmp ;
397
+ kdb_position_cursor (kdb_prompt_str , buffer , cp );
395
398
} else {
396
399
* ++ lastchar = '\0' ;
397
400
* cp ++ = key ;
0 commit comments