1 /* 2 * ReactOS log2lines 3 * Written by Jan Roeloffzen 4 * 5 * - Cli for escape commands 6 */ 7 8 #include <stdio.h> 9 #include <string.h> 10 #include <stdlib.h> 11 12 #include "util.h" 13 #include "cmd.h" 14 #include "options.h" 15 #include "log2lines.h" 16 #include "help.h" 17 18 /* When you edit the cmd line and/or use the history instead of just typing, 19 * a bunch of editing BS and space characters 20 * is inserted, so the string looks right on the console but still 21 * contains the original string, plus other garbage: 22 */ 23 static char 24 *backSpaceEdit(char *s) 25 { 26 char c; 27 char *edit = s; 28 char *text = s; 29 30 while (( c = *edit++ )) 31 { 32 switch (c) 33 { 34 case KDBG_BS_CHAR: 35 if (text > s) 36 text --; 37 break; 38 default: 39 *text++ = c; 40 } 41 } 42 *text = '\0'; 43 44 return s; 45 } 46 47 static int 48 handle_switch(FILE *outFile, int *sw, char *arg, char *desc) 49 { 50 int changed =0; 51 int x = 0; 52 53 if (arg && (strcmp(arg,"") != 0)) 54 { 55 x = atoi(arg); 56 if (x != *sw) 57 { 58 *sw = x; 59 changed = 1; 60 } 61 } 62 if (desc) 63 { 64 esclog(outFile, "%s is %d (%s)\n", desc, *sw, changed ? "changed":"unchanged"); 65 if (!arg) 66 esclog(outFile, "(readonly)\n"); 67 } 68 69 return changed; 70 } 71 72 static int 73 handle_switch_str(FILE *outFile, char *sw, char *arg, char *desc) 74 { 75 int changed =0; 76 77 if (arg) 78 { 79 if (strcmp(arg,"") != 0) 80 { 81 if (strcmp(arg,KDBG_ESC_OFF) == 0) 82 { 83 if (*sw) 84 changed = 1; 85 *sw = '\0'; 86 } 87 else if (strcmp(arg, sw) != 0) 88 { 89 strcpy(sw, arg); 90 changed = 1; 91 } 92 } 93 } 94 if (desc) 95 { 96 esclog(outFile, "%s is \"%s\" (%s)\n", desc, sw, changed ? "changed":"unchanged"); 97 if (!arg) 98 esclog(outFile, "(readonly)\n"); 99 } 100 101 return changed; 102 } 103 104 static int 105 handle_switch_pstr(FILE *outFile, char **psw, char *arg, char *desc) 106 { 107 int changed =0; 108 109 if (arg) 110 { 111 if (strcmp(arg,"") != 0) 112 { 113 if (strcmp(arg,KDBG_ESC_OFF) == 0) 114 { 115 if (*psw) 116 changed = 1; 117 free(*psw); 118 *psw = NULL; 119 } 120 else 121 { 122 if (!*psw) 123 { 124 *psw = malloc(LINESIZE); 125 **psw = '\0'; 126 } 127 128 if (strcmp(arg, *psw) != 0) 129 { 130 strcpy(*psw, arg); 131 changed = 1; 132 } 133 } 134 } 135 } 136 if (desc) 137 { 138 esclog(outFile, "%s is \"%s\" (%s)\n", desc, *psw, changed ? "changed":"unchanged"); 139 if (!arg) 140 esclog(outFile, "(readonly)\n"); 141 } 142 143 return changed; 144 } 145 146 static int 147 handle_address_cmd(FILE *outFile, char *arg) 148 { 149 PLIST_MEMBER plm; 150 char Image[NAMESIZE]; 151 DWORD Offset; 152 int cnt; 153 char *s; 154 155 if(( s = strchr(arg, ':') )) 156 { 157 *s = ' '; 158 if ( (cnt = sscanf(arg,"%20s %x", Image, &Offset)) == 2) 159 { 160 if (( plm = entry_lookup(&cache, Image) )) 161 { 162 if (plm->RelBase != INVALID_BASE) 163 esclog(outFile, "Address: 0x%lx\n", plm->RelBase + Offset) 164 else 165 esclog(outFile, "Relocated base missing for '%s' ('mod' will update)\n", Image); 166 } 167 else 168 esclog(outFile, "Image '%s' not found\n", Image); 169 } 170 else 171 esclog(outFile, "usage: `a <Image>:<offset>\n"); 172 } 173 else 174 esclog(outFile, "':' expected\n"); 175 176 return 1; 177 } 178 179 char 180 handle_escape_cmd(FILE *outFile, char *Line, char *path, char *LineOut) 181 { 182 char cmd; 183 char sep = '\n'; 184 char *arg; 185 char *l = Line; 186 int res = 1; 187 int cnt = 0; 188 int changed = 0; 189 190 l = backSpaceEdit(l); 191 if (l[1] != KDBG_ESC_CHAR) 192 return l[1]; //for reprocessing as not escaped 193 194 log(outFile, "\n"); 195 196 l += 2; //skip space+escape character 197 if ( (cnt=sscanf(l,"%c%c",&cmd,&sep)) < 1) 198 { 199 esclog(outFile, "Command expected\n"); 200 res = 0; 201 } 202 203 if (res && cnt==2 && sep != ' ') 204 { 205 esclog(outFile, "' ' expected\n"); 206 res = 0; 207 } 208 l++; //skip cmd 209 while ( *l == ' ')l++; //skip more spaces 210 arg = l; 211 opt_cli = 1; 212 switch (cmd) 213 { 214 case 'a': 215 handle_address_cmd(outFile, arg); 216 break; 217 case 'h': 218 usage(1); 219 break; 220 case 'b': 221 if (handle_switch(outFile, &opt_buffered, arg, "-b Logfile buffering")) 222 set_LogFile(&logFile); //re-open same logfile 223 break; 224 case 'c': 225 handle_switch(outFile, &opt_console, NULL, "-c Console option"); 226 break; 227 case 'd': 228 handle_switch_str(outFile, opt_dir, NULL, "-d Directory option"); 229 break; 230 case 'l': 231 if (handle_switch_str(outFile, opt_logFile, arg, "-l logfile") || (strcmp(opt_mod,"a")!=0)) 232 { 233 opt_mod = "a"; 234 set_LogFile(&logFile); //open new logfile 235 } 236 break; 237 case 'L': 238 if (handle_switch_str(outFile, opt_logFile, arg, "-L logfile") || (strcmp(opt_mod,"w")!=0)) 239 { 240 opt_mod = "w"; 241 set_LogFile(&logFile); //open new logfile 242 } 243 break; 244 case 'm': 245 handle_switch(outFile, &opt_Mark, arg, "-m mark (*)"); 246 break; 247 case 'M': 248 handle_switch(outFile, &opt_Mark, arg, "-M Mark (?)"); 249 break; 250 case 'P': 251 handle_switch_str(outFile, opt_Pipe, NULL, "-P Pipeline option"); 252 break; 253 case 'q': 254 opt_quit = 1; 255 esclog(outFile, "Bye!\n"); 256 break; 257 case 'r': 258 handle_switch(outFile, &opt_raw, arg, "-r Raw"); 259 break; 260 case 'R': 261 changed = handle_switch_pstr(outFile, &opt_Revision, arg, NULL); 262 opt_Revision_check = 0; 263 if (opt_Revision) 264 { 265 opt_Revision_check = 1; 266 if (strstr(opt_Revision, "check") == opt_Revision) 267 { 268 esclog(outFile, "-R is \"%s\" (%s)\n", opt_Revision, changed ? "changed":"unchanged"); 269 } 270 else if (strstr(opt_Revision, "regscan") == opt_Revision) 271 { 272 char *s = strchr(opt_Revision, ','); 273 274 revinfo.range = DEF_RANGE; 275 if (s) 276 { 277 *s++ = '\0'; 278 revinfo.range = atoi(s); 279 } 280 regscan(outFile); 281 } 282 else if (strstr(opt_Revision, "regclear") == opt_Revision) 283 { 284 list_clear(&sources); 285 summ.regfound = 0; 286 esclog(outFile, "cleared regression scan results\n"); 287 } 288 } 289 break; 290 case 's': 291 if (strcmp(arg,"clear") == 0) 292 { 293 memset(&summ, 0, sizeof(SUMM)); 294 esclog(outFile, "Statistics cleared\n"); 295 } 296 else 297 stat_print(outFile, &summ); 298 break; 299 case 'S': 300 cnt = sscanf(arg, "%d+%d", &opt_Source, &opt_SrcPlus); 301 if (opt_Source) 302 { 303 handle_switch(outFile, &opt_undo, "1", "-u Undo"); 304 handle_switch(outFile, &opt_redo, "1", "-U Undo and reprocess"); 305 opt_Revision_check = 1; 306 } 307 esclog(outFile, "-S Sources option is %d+%d,\"%s\"\n", opt_Source, opt_SrcPlus, opt_SourcesPath); 308 esclog(outFile, "(Setting source tree not implemented)\n"); 309 break; 310 case 't': 311 handle_switch(outFile, &opt_twice, arg, "-t Translate twice"); 312 break; 313 case 'T': 314 handle_switch(outFile, &opt_twice, arg, NULL); 315 handle_switch(outFile, &opt_Twice, arg, "-T Translate for (address-1)"); 316 break; 317 case 'u': 318 handle_switch(outFile, &opt_undo, arg, "-u undo"); 319 break; 320 case 'U': 321 handle_switch(outFile, &opt_undo, arg, NULL); 322 handle_switch(outFile, &opt_redo, arg, "-U Undo and reprocess"); 323 break; 324 case 'v': 325 handle_switch(outFile, &opt_verbose, arg, "-v Verbosity"); 326 break; 327 case 'z': 328 handle_switch_str(outFile, opt_7z, NULL, "-z 7z path"); 329 break; 330 default: 331 if (strchr(optchars, cmd)) 332 esclog(outFile, "Command not implemented in cli: %c %s\n",cmd, arg) 333 else 334 esclog(outFile, "Unknown command: %c %s\n",cmd, arg); 335 } 336 opt_cli = 0; 337 338 memset(Line, '\0', LINESIZE); // flushed 339 340 return KDBG_ESC_CHAR; //handled escaped command 341 } 342 343 /* EOF */ 344