+
+// Copy a string - truncating it if necessary.
+char *
+strtcpy(char *dest, const char *src, size_t len)
+{
+ char *d = dest;
+ while (--len && *src != '\0')
+ *d++ = *src++;
+ *d = '\0';
+ return dest;
+}
+
+// locate first occurance of character c in the string s
+char *
+strchr(const char *s, int c)
+{
+ for (; *s; s++)
+ if (*s == c)
+ return (char*)s;
+ return NULL;
+}
+
+// Remove any trailing blank characters (spaces, new lines, carriage returns)
+void
+nullTrailingSpace(char *buf)
+{
+ int len = strlen(buf);
+ char *end = &buf[len-1];
+ while (end >= buf && *end <= ' ')
+ *(end--) = '\0';
+}
+
+/****************************************************************
+ * Keyboard calls
+ ****************************************************************/
+
+// See if a keystroke is pending in the keyboard buffer.
+static int
+check_for_keystroke(void)
+{
+ struct bregs br;
+ memset(&br, 0, sizeof(br));
+ br.flags = F_IF;
+ br.ah = 1;
+ call16_int(0x16, &br);
+ return !(br.flags & F_ZF);
+}
+
+// Return a keystroke - waiting forever if necessary.
+static int
+get_raw_keystroke(void)
+{
+ struct bregs br;
+ memset(&br, 0, sizeof(br));
+ br.flags = F_IF;
+ call16_int(0x16, &br);
+ return br.ah;
+}
+
+// Read a keystroke - waiting up to 'msec' milliseconds.
+int
+get_keystroke(int msec)
+{
+ u32 end = calc_future_timer(msec);
+ for (;;) {
+ if (check_for_keystroke())
+ return get_raw_keystroke();
+ if (check_timer(end))
+ return -1;
+ wait_irq();
+ }
+}