/* Note: buf must be large enough (MAX_LINE bytes in size) */ char *lc_possession(Locale *lc, char *name, char *obj, char *buf, int buflen) { int l, j; if (buf == NULL || buflen <= 0) return NULL; if (name == NULL || !*name) { cstrcpy(buf, "(NULL)", buflen); return buf; } cstrcpy(buf, name, buflen); l = j = strlen(buf)-1; if (l < buflen-3) { buf[++l] = '\''; if (buf[j] != 'z' && buf[j] != 'Z' && buf[j] != 's' && buf[j] != 'S') buf[++l] = 's'; buf[++l] = ' '; buf[++l] = 0; if (obj != NULL && buflen - l > strlen(obj)) cstrcat(buf, obj, buflen); } return buf; }
int http_request_header_fields_parse(struct http_request_r *r) { int i,m; int request_header_fields_length; int crlf_pos[100]={0}; int colon_pos[100]={0}; struct http_request_fields *f[100],*p; m=0; for(i=r->request_header_fields_pos;i<r->content_pos;i++) { if(r->buf[i]==':') { colon_pos[m]=i; } if(r->buf[i]=='\r' && r->buf[i+1]=='\n') { crlf_pos[m]=i; m++; } if(r->buf[i]=='\r' && r->buf[i+1]=='\n' && r->buf[i+2]=='\r' && r->buf[i+3]=='\n') { break; } } for(i=0;i<m;i++) { if(1) { f[i] = (struct http_request_fields *)malloc(sizeof(struct http_request_fields)); memset(f[i],0,sizeof(struct http_request_fields)); f[i]->key = (char *)malloc(128); memset(f[i]->key,0,128); f[i]->val = (char *)malloc(128); memset(f[i]->val,0,128); if(i==0){ cstrcpy(f[i]->key,r->buf,r->request_header_fields_pos,colon_pos[i]-r->request_header_fields_pos); }else{ cstrcpy(f[i]->key,r->buf,crlf_pos[i-1]+2,colon_pos[i]-(crlf_pos[i-1]+2)); } cstrcpy(f[i]->val,r->buf,colon_pos[i]+1,crlf_pos[i]-colon_pos[i]); // printf("%s:%s\n",f[i]->key,f[i]->val); } } }
/* this is not really a locale, but hey ... maybe there is some freaky language out there that wants to output something like this in a different way I wrote the former function out and turned into this math-like looking formula stuff. This one actually produces better output. Note: buf must be large enough, MAX_LINE should do */ char *lc_print_total_time(Locale *lc, unsigned long total, char *buf, int buflen) { int div[5] = { SECS_IN_WEEK, SECS_IN_DAY, SECS_IN_HOUR, SECS_IN_MIN, 1 }; int v[5]; int i, l, elems; char *one[5] = { "week", "day", "hour", "minute", "second" }; char *more[5] = { "weeks", "days", "hours", "minutes", "seconds" }; if (buf == NULL || buflen <= 0) return NULL; elems = 0; for(i = 0; i < 5; i++) { v[i] = total / div[i]; total %= div[i]; if (v[i] > 0) elems++; } if (!elems) { cstrcpy(buf, "0 seconds", buflen); return buf; } buf[0] = 0; l = 0; for(i = 0; i < 5; i++) { if (v[i] > 0) { l += bufprintf(buf+l, buflen - l, "%d %s", v[i], (v[i] == 1) ? one[i] : more[i]); elems--; if (!elems) break; l += bufprintf(buf+l, buflen - l, (elems == 1) ? ", and " : ", "); } } return buf; }
/* Print a large number with dots or comma's We use a silly trick to do this ; walk the string in a reverse order and insert comma's into the string representation Note: buf must be large enough, MAX_NUMBER will do */ char *lc_print_number(unsigned long ul, int sep, char *buf, int buflen) { char buf2[MAX_NUMBER]; int i, j = 0, n = 0; if (buf == NULL || buflen <= 0) return NULL; buf[0] = 0; bufprintf(buf2, sizeof(buf2), "%lu", ul); i = strlen(buf2)-1; if (i < 0) return buf; while(i >= 0 && j < buflen-1) { buf[j++] = buf2[i--]; if (j >= buflen-1) break; n++; if (i >= 0 && n >= 3) { n = 0; buf[j++] = sep; /* usually dot or comma */ } } buf[j] = 0; cstrcpy(buf2, buf, MAX_NUMBER); i = strlen(buf2)-1; j = 0; while(i >= 0 && j <= buflen-1) buf[j++] = buf2[i--]; buf[j] = 0; return buf; }
int save_Room(Room *r) { char filename[MAX_PATHLEN]; File *f; if (r == NULL) return -1; if (!(r->flags & ROOM_DIRTY)) { /* if the room is not dirty, don't save it this is a performance improvement for demand loaded rooms; Home> and Mail> */ if (!PARAM_HAVE_RESIDENT_INFO) { destroy_StringIO(r->info); r->info = NULL; } return 0; } r->flags &= ROOM_ALL; /* this automatically clears ROOM_DIRTY */ if (r->number == MAIL_ROOM || r->number == HOME_ROOM) { char name[MAX_LINE], *p; cstrcpy(name, r->name, MAX_LINE); if ((p = cstrchr(name, '\'')) == NULL) return -1; *p = 0; if (r->number == MAIL_ROOM) bufprintf(filename, sizeof(filename), "%s/%c/%s/MailData", PARAM_USERDIR, *name, name); else if (r->number == HOME_ROOM) bufprintf(filename, sizeof(filename), "%s/%c/%s/HomeData", PARAM_USERDIR, *name, name); load_roominfo(r, name); } else { bufprintf(filename, sizeof(filename), "%s/%u/RoomData", PARAM_ROOMDIR, r->number); load_roominfo(r, NULL); } path_strip(filename); if ((f = Fcreate(filename)) == NULL) return -1; if (save_Room_version1(f, r)) { Fcancel(f); return -1; } if (Fclose(f)) return -1; if (!PARAM_HAVE_RESIDENT_INFO) { destroy_StringIO(r->info); r->info = NULL; } return 0; }
/* strcat() with bounds check buflen is the size of the entire buffer, starting from 'dest' */ char *cstrcat(char *dest, char *src, int buflen) { int len; if (dest == NULL || src == NULL || buflen <= 0) return NULL; len = strlen(dest); return cstrcpy(dest+len, src, buflen - len); }
char *cstrerror(int err, char *buf, int maxlen) { if (buf == NULL || maxlen < 0) return NULL; #ifdef HAVE_STRERROR cstrcpy(buf, strerror(err), maxlen); #else bufprintf(buf, maxlen, "error %d", err); #endif return buf; }
void deepcopy_GString(GString *g, GString *copy) { if (g->size > 0) { if ((copy->str = (char *)Malloc(g->size)) == NULL) return; cstrcpy(copy->str, g->str, g->size); } else copy->str = NULL; copy->size = g->size; copy->len = g->len; }
int http_request_line_parse(struct http_request_r *r) { int i,n,k,m; n = strlen(r->buf); k = 0; int pos[3]={0}; for(i=0;i<n;i++) { if(r->buf[i]==' ') { pos[k]=i; k++; } if(r->buf[i]=='\r' && r->buf[i+1]=='\n') { pos[k]=i; break; } } r->method = (char *)malloc(12); memset(r->method,0,12); cstrcpy(r->method,r->buf,0,pos[0]); r->request_uri = (char *)malloc(128); memset(r->request_uri,0,128); cstrcpy(r->request_uri,r->buf,pos[0]+1,pos[1]-pos[0]-1); r->protocol = (char *)malloc(12); memset(r->protocol,0,12); cstrcpy(r->protocol,r->buf,pos[1]+1,pos[2]-pos[1]-1); r->request_header_fields_pos = pos[2]+2; }
int gstrcat(GString *g, char *s) { int l; if (s == NULL || !*s) return 0; l = g->len + strlen(s)+1; if (g->size < l && grow_GString(g, l) == -1) return -1; cstrcpy(g->str + g->len, s, g->size - g->len); g->len = l-1; return 0; }
/* rm -rf : first empty directory, then remove directory */ int rm_rf_trashdir(char *dirname) { char buf[MAX_PATHLEN], *bufp; DIR *dirp; struct dirent *direntp; if (dirname == NULL || !*dirname) return -1; /* safety check */ bufprintf(buf, sizeof(buf), "%s/", PARAM_TRASHDIR); path_strip(buf); if (strncmp(buf, dirname, strlen(buf)) || cstrstr(dirname, "..") != NULL) return -1; cstrcpy(buf, dirname, MAX_PATHLEN); bufp = buf+strlen(buf)-1; if (*bufp != '/') { bufp++; *bufp = '/'; bufp++; *bufp = 0; } if ((dirp = opendir(buf)) == NULL) return -1; while((direntp = readdir(dirp)) != NULL) { /* check for '.' and '..' directory */ if (direntp->d_name[0] == '.' && (!direntp->d_name[1] || (direntp->d_name[1] == '.' && !direntp->d_name[2]))) continue; cstrcpy(bufp, direntp->d_name, MAX_PATHLEN); unlink(buf); /* note: trash/ is not cached ; it's ok not to use unlink_file() */ } closedir(dirp); return remove_dir(dirname); }
int main() { int length1 = __VERIFIER_nondet_int(); int length2 = __VERIFIER_nondet_int(); if (length1 < 1) { length1 = 1; } if (length2 < 1) { length2 = 1; } if (length1 < length2) return 0; char* nondetArea = (char*) alloca(length1 * sizeof(char)); char* nondetString = (char*) alloca(length2 * sizeof(char)); nondetString[length2-1] = '\0'; cstrcpy(nondetArea,nondetString); return 0; }
int crypt_password(char *password, char *crypted, int max) { char salt[24], *pw; make_salt(salt); pthread_mutex_lock(&crypt_lock); if ((pw = crypt(password, salt)) == NULL) { pthread_mutex_unlock(&crypt_lock); *crypted = 0; return -1; } cstrcpy(crypted, pw, max); pthread_mutex_unlock(&crypt_lock); return 0; }
/* expand the <center> tag into a buffer This tag doesn't go well together with other tags */ void expand_center(char *str, char *dest, int bufsize, int width) { char *p; int l, n; if (str == NULL || dest == NULL || bufsize <= 0) return; if ((p = cstristr(str, "<center>")) == NULL) { cstrncpy(dest, str, bufsize); return; } l = p - str; if (l >= bufsize) { cstrncpy(dest, str, bufsize); return; } if (l > 0) cstrncpy(dest, str, l); else l = 0; dest[l] = 0; p += 8; n = width/2 - color_strlen(p)/2 - l; while(n > 0 && l < bufsize-1) { dest[l] = ' '; l++; n--; } dest[l] = 0; n = strlen(p); if (l + n >= bufsize) { n = bufsize - l; if (n > 0) cstrncpy(dest+l, p, n); } else cstrcpy(dest+l, p, bufsize - l); while((p = cstristr(dest, "<center>")) != NULL) /* filter out duplicate codes */ memmove(p, p+8, strlen(p+8)+1); }
/* the symbol table is loaded from 'nm' output All platforms have their own 'nm' output format, but luckily some support POSIX format (although often poorly supported). POSIX.2 format is <symbol> <type> <address> [<size>] The symbol apperently may be empty on some systems The address may be empty, when type is 'U' The size is optional */ int load_SymbolTable(char *filename) { AtomicFile *f; char buf[MAX_LONGLINE], namebuf[MAX_LONGLINE], type; unsigned long addr; SymbolTable *st; listdestroy_SymbolTable(symbol_table); symbol_table = NULL; if ((f = openfile(filename, "r")) == NULL) return 1; while(fgets(buf, MAX_LONGLINE, f->f) != NULL) { cstrip_line(buf); if (!*buf) continue; addr = 0UL; type = '#'; cstrcpy(namebuf, "<unknown>", MAX_LONGLINE); if (*buf == ' ') sscanf(buf, " %c %lx", &type, &addr); else sscanf(buf, "%s %c %lx", namebuf, &type, &addr); if ((st = new_SymbolTable()) == NULL) { closefile(f); listdestroy_SymbolTable(symbol_table); symbol_table = NULL; return -1; } st->name = cstrdup(namebuf); st->type = type; st->addr = addr; symbol_table = add_SymbolTable(&symbol_table, st); } closefile(f); symbol_table = rewind_SymbolTable(symbol_table); return 0; }
void MainView_Start(void) { Menu_Start(); cstrcpy(entries[0].text, "Ajustar Hora"); cstrcpy(entries[1].text, "Ajustar Captura"); cstrcpy(entries[2].text, "Ajustar Nivel"); cstrcpy(entries[3].text, "Configuracion"); cstrcpy(entries[4].text, "Temp Actual"); cstrcpy(entries[5].text, "Borrar Memoria"); cstrcpy(entries[6].text, "Conectar a PC"); entries[0].callback = &DateTimeView_Callback; entries[1].callback = &RegTimeView_Callback; entries[2].callback = &LevelView_Callback; entries[3].callback = &ConfigView_Callback; entries[4].callback = &TempView_Callback; entries[5].callback = &DeletView_Callback; entries[6].callback = &PCView_Callback; menu.currentIndex = 0; menu.nOptions = 7; menu.entries = entries; }
void enter_emote(User *usr) { char name[MAX_NAME], line[MAX_LINE], *p, *endp; XMsg *x; int sent; if ((x = new_XMsg()) == NULL) { Put(usr, "<red>Due to an error, you can not send messages now\n"); return; } if (edit_recipients(usr, multi_x_access) == -1) { destroy_XMsg(x); return; } if (usr->recipients.len <= 0) { destroy_XMsg(x); return; } check_recipients(usr); if (usr->recipients.len <= 0) { destroy_XMsg(x); return; } /* enter the message text */ Print(usr, "<cyan>* <white>%s <yellow>", usr->name); if (edit_line(usr, line, MAX_LINE) == -1 || !line[0]) { Put(usr, "<red>Message not sent\n"); destroy_XMsg(x); return; } ctrim_line(line); if (!line[0]) { Put(usr, "<red>Message not sent\n"); destroy_XMsg(x); return; } if (add_XMsg_line(x, line) == -1) { Put(usr, "<red>Due to an error, you can not send messages now\n"); destroy_XMsg(x); return; } check_recipients(usr); if (usr->recipients.len <= 0) { destroy_XMsg(x); return; } set_XMsg(x, XMSG_EMOTE, usr->name, usr->recipients.str, time(NULL)); sent = 0; p = usr->recipients.str; while((endp = cstrchr(p, ',')) != NULL) { *endp = 0; cstrcpy(name, p, MAX_NAME); *endp = ','; endp++; p = endp; sent += send_xmsg(usr, x, name); } cstrcpy(name, p, MAX_NAME); sent += send_xmsg(usr, x, name); if (sent) send_xmsg_bcc(usr, x); /* remember message as sent in 'this' user */ else destroy_XMsg(x); }
void enter_xmsg(User *usr) { char name[MAX_NAME], *p, *endp; XMsg *x; GString gstr; int sent; if ((x = new_XMsg()) == NULL) { Put(usr, "<red>Due to an error, you can not send messages now\n"); return; } if (edit_recipients(usr, multi_x_access) == -1) { destroy_XMsg(x); return; } if (usr->recipients.len <= 0) { destroy_XMsg(x); return; } check_recipients(usr); if (usr->recipients.len <= 0) { destroy_XMsg(x); return; } /* enter the message text */ Put(usr, "<green>"); init_GString(&gstr); if (edit_lines(usr, &gstr, ">", MAX_X_LINES) == -1) { Put(usr, "<red>Message not sent\n"); destroy_XMsg(x); deinit_GString(&gstr); return; } if (gstr.len <= 0) { Put(usr, "<red>Message not sent\n"); destroy_XMsg(x); deinit_GString(&gstr); return; } ctrim_line(gstr.str); if (add_XMsg_line(x, gstr.str) == -1) { Put(usr, "<red>Due to an error, you can not send messages now\n"); destroy_XMsg(x); deinit_GString(&gstr); return; } deinit_GString(&gstr); check_recipients(usr); if (usr->recipients.len <= 0) { destroy_XMsg(x); return; } set_XMsg(x, XMSG_X, usr->name, usr->recipients.str, time(NULL)); sent = 0; p = usr->recipients.str; while((endp = cstrchr(p, ',')) != NULL) { *endp = 0; cstrcpy(name, p, MAX_NAME); *endp = ','; endp++; p = endp; sent += send_xmsg(usr, x, name); } cstrcpy(name, p, MAX_NAME); sent += send_xmsg(usr, x, name); if (sent) send_xmsg_bcc(usr, x); /* remember message as sent in 'this' user */ else destroy_XMsg(x); }
/* create a directory listing in a StringQueue flags can be IGNORE_SYMLINKS|IGNORE_HIDDEN|NO_SLASHES|NO_DIRS */ StringQueue *listdir(char *dirname, int flags) { StringQueue *l; StringList *sl; DIR *dir; struct dirent *entry; char fullpath[MAX_PATHLEN], *path, errbuf[MAX_LINE]; struct stat statbuf; int max, n; if (dirname == NULL || !*dirname) return NULL; if ((dir = opendir(dirname)) == NULL) { log_err("listdir(): opendir(%s) failed %s", dirname, cstrerror(errno, errbuf, MAX_LINE)); return NULL; } if ((l = new_StringQueue()) == NULL) { closedir(dir); return NULL; } cstrcpy(fullpath, dirname, MAX_PATHLEN); max = strlen(fullpath); path = fullpath + max; *path = '/'; path++; *path = 0; max = MAX_PATHLEN - max - 1; while((entry = readdir(dir)) != NULL) { if ((flags & IGNORE_HIDDEN) && entry->d_name[0] == '.') /* skip hidden files */ continue; cstrcpy(path, entry->d_name, max); if (lstat(fullpath, &statbuf) < 0) { log_err("listdir(): lstat(%s) failed: %s", fullpath, cstrerror(errno, errbuf, MAX_LINE)); continue; } switch(statbuf.st_mode & S_IFMT) { case S_IFREG: break; case S_IFDIR: /* for directories, append a slash */ if (flags & NO_DIRS) { *path = 0; break; } if (!(flags & NO_SLASHES)) { n = strlen(path); path[n++] = '/'; path[n] = 0; } break; case S_IFLNK: if (flags & IGNORE_SYMLINKS) *path = 0; break; default: /* no fifo's, sockets, device files, etc. */ *path = 0; } if (!*path) continue; if ((sl = new_StringList(path)) == NULL) { log_err("listdir(): out of memory for directory %s", dirname); break; } (void)add_StringQueue(l, sl); } closedir(dir); sort_StringQueue(l, alphasort_StringList); return l; }
/* load all rooms definitions at startup Note that room #1 and room #2 are 'shadow' rooms for Mail> and Home> the BBS cannot work without room #0, #1, and #2 */ int init_Room(void) { char buf[MAX_PATHLEN], *bufp; DIR *dirp; struct dirent *direntp; struct stat statbuf; Room *newroom; unsigned int u; int load_room_flags, len; printf("\n"); listdestroy_Room(AllRooms); AllRooms = Lobby_room = NULL; load_room_flags = LOAD_ROOM_ALL; if (!PARAM_HAVE_RESIDENT_INFO) load_room_flags &= ~LOAD_ROOM_INFO; bufprintf(buf, sizeof(buf), "%s/", PARAM_ROOMDIR); path_strip(buf); len = strlen(buf); bufp = buf+len; if ((dirp = opendir(buf)) == NULL) return -1; while((direntp = readdir(dirp)) != NULL) { if (is_numeric(direntp->d_name)) { /* only do numeric directories */ cstrcpy(bufp, direntp->d_name, MAX_PATHLEN - len); if (stat(buf, &statbuf)) continue; if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { u = (unsigned int)cstrtoul(bufp, 10); printf("loading room %3u ... ", u); fflush(stdout); if ((newroom = load_Room(u, load_room_flags)) != NULL) { (void)prepend_Room(&AllRooms, newroom); room_readdir(newroom); printf("%s>\n", newroom->name); } else { printf("FAILED!\n"); closedir(dirp); listdestroy_Room(AllRooms); AllRooms = Lobby_room = NULL; return -1; } } } } closedir(dirp); if (PARAM_HAVE_CATEGORY) (void)sort_Room(&AllRooms, room_sort_by_category); else (void)sort_Room(&AllRooms, room_sort_by_number); /* find the Lobby> It should be first, but you never know... */ if (Lobby_room == NULL) { Room *rm; for(rm = AllRooms; rm != NULL; rm = rm->next) { if (!rm->number) { Lobby_room = rm; break; } } } if (Lobby_room == NULL) { printf("Failed to find the Lobby> (room 0)\n" "Please create room definition file '%s/0/RoomData'\n", PARAM_ROOMDIR); listdestroy_Room(AllRooms); AllRooms = NULL; return -1; } printf("\n"); return 0; }
int http_request_ext_path(struct http_request_r *r) { int i=0,n=0,period_pos=0,query_pos=0,file_end_pos=0; char ch; r->path = (char *)malloc(100); memset(r->path,0,100); r->ext = (char *)malloc(10); memset(r->ext,0,10); n = strlen(r->request_uri); for(i=0;i<n;i++) { ch = r->request_uri[i]; if(ch=='.') { period_pos=i; } if(ch=='?') { query_pos=i; break; } } strcpy(r->path,"/data/tests/web/"); if(query_pos>0) { file_end_pos = query_pos-1; } else { file_end_pos = n; } if(file_end_pos<2) { strcpy(r->path+strlen(r->path),"index.html"); printf("%s\n",r->path); strcpy(r->ext,"html"); } else { strncpy(r->path+strlen(r->path),r->request_uri,file_end_pos); if(period_pos>0) { cstrcpy(r->ext,r->request_uri,period_pos+1,file_end_pos-period_pos-1); } else { strcpy(r->ext,""); } } printf("%d %d %s\n",file_end_pos,period_pos,r->ext); }
/* prints the entries in raw_list to create a menu in columns this routine looks a lot like the one that formats the wide who-list flags is FORMAT_NUMBERED|FORMAT_NO_UNDERSCORES */ void print_columns(User *usr, StringList *raw_list, int flags) { int term_width, total, cols, rows, i, j, buflen, len, max_width, idx; StringList *sl, *sl_cols[16]; char buf[MAX_LINE*4], format[MAX_LINE], filename[MAX_PATHLEN], *p; if (usr == NULL || raw_list == NULL) return; term_width = usr->display->term_width; if (term_width >= MAX_LONGLINE) term_width = MAX_LONGLINE; total = 0; max_width = 10; for(sl = raw_list; sl != NULL; sl = sl->next) { len = strlen(sl->str); if (len > max_width) max_width = len; total++; } if (flags & FORMAT_NUMBERED) bufprintf(format, sizeof(format), "%c%%3d %c%%-%ds", (char)color_by_name("green"), (char)color_by_name("yellow"), max_width); else bufprintf(format, sizeof(format), "%c%%-%ds", (char)color_by_name("yellow"), max_width); cols = term_width / (max_width+6); if (cols < 1) cols = 1; else if (cols > 15) cols = 15; rows = total / cols; if (total % cols) rows++; memset(sl_cols, 0, sizeof(StringList *) * cols); /* fill in array of pointers to columns */ sl = raw_list; for(i = 0; i < cols; i++) { sl_cols[i] = sl; for(j = 0; j < rows; j++) { if (sl == NULL) break; sl = sl->next; } } /* make the menu text */ for(j = 0; j < rows; j++) { idx = j + 1; buf[0] = 0; buflen = 0; for(i = 0; i < cols; i++) { if (sl_cols[i] == NULL || sl_cols[i]->str == NULL) continue; cstrcpy(filename, sl_cols[i]->str, MAX_PATHLEN); if (flags & FORMAT_NO_UNDERSCORES) { p = filename; while((p = cstrchr(p, '_')) != NULL) *p = ' '; } if (flags & FORMAT_NUMBERED) buflen += bufprintf(buf+buflen, sizeof(buf) - buflen, format, idx, filename); else buflen += bufprintf(buf+buflen, sizeof(buf) - buflen, format, filename); idx += rows; if ((i+1) < cols) { buf[buflen++] = ' '; buf[buflen++] = ' '; buf[buflen] = 0; } sl_cols[i] = sl_cols[i]->next; } buf[buflen++] = '\n'; buf[buflen] = 0; Put(usr, buf); } }
int main() { char* s2; char* s1; cstrcpy(s1, s2); return 0; }
/* convert key code to long color code some key codes do not have a long equivalent flags can be USR_SHORT_DL_COLORS, which means that the color codes should be represented in short format */ int short_color_to_long(char c, char *buf, int max_len, int flags) { int i; if (buf == NULL || max_len <= 0) return -1; buf[0] = 0; switch(c) { case KEY_CTRL('Q'): /* don't auto-color this string */ break; case KEY_CTRL('X'): break; case KEY_CTRL('A'): cstrcpy(buf, "<beep>", max_len); break; case KEY_CTRL('L'): /* clear screen */ break; case KEY_CTRL('Z'): case KEY_CTRL('R'): case KEY_CTRL('G'): case KEY_CTRL('Y'): case KEY_CTRL('B'): case KEY_CTRL('M'): case KEY_CTRL('C'): case KEY_CTRL('W'): for(i = 0; i < NUM_COLORS; i++) { if (color_table[i].key == c) { if (flags & USR_SHORT_DL_COLORS) { /* black is Ctrl-Z, but actually has to entered as Ctrl-K see also edit_color() in edit.c (this is confusing, but black is blacK, while the K is for hotkeys) */ if (c == KEY_CTRL('Z')) c = KEY_CTRL('K'); bufprintf(buf, max_len, "^%c", c + 'A' - 1); } else { bufprintf(buf, max_len, "<%s>", color_table[i].name); cstrlwr(buf); } break; } } break; case KEY_CTRL('K'): cstrcpy(buf, "<hotkey>", max_len); break; case KEY_CTRL('N'): cstrcpy(buf, "<normal>", max_len); break; case KEY_CTRL('D'): cstrcpy(buf, "<default>", max_len); break; default: if (c >= ' ' && c <= '~' && max_len >= 2) { buf[0] = c; buf[1] = 0; } } return 0; }