consio.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #include "rar.hpp"
  2. #ifndef GUI
  3. #include "log.cpp"
  4. #endif
  5. static int KbdAnsi(char *Addr,int Size);
  6. #if !defined(GUI) && !defined(SILENT)
  7. static void RawPrint(char *Msg,MESSAGE_TYPE MessageType);
  8. static uint GetKey();
  9. #endif
  10. static MESSAGE_TYPE MsgStream=MSG_STDOUT;
  11. static bool Sound=false;
  12. const int MaxMsgSize=2*NM+2048;
  13. void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound)
  14. {
  15. ::MsgStream=MsgStream;
  16. ::Sound=Sound;
  17. }
  18. #if !defined(GUI) && !defined(SILENT)
  19. void mprintf(const char *fmt,...)
  20. {
  21. if (MsgStream==MSG_NULL || MsgStream==MSG_ERRONLY)
  22. return;
  23. char Msg[MaxMsgSize];
  24. va_list argptr;
  25. va_start(argptr,fmt);
  26. vsnprintf(Msg,ASIZE(Msg),fmt,argptr);
  27. // Different vsnprintf implementation can return either -1 or >=MaxMsgSize
  28. // if string is truncated. So we do not check exit code and always zero
  29. // terminate the string for safety. It is faster than check for error.
  30. Msg[ASIZE(Msg)-1] = 0;
  31. RawPrint(Msg,MsgStream);
  32. va_end(argptr);
  33. }
  34. #endif
  35. #if !defined(GUI) && !defined(SILENT)
  36. void eprintf(const char *fmt,...)
  37. {
  38. if (MsgStream==MSG_NULL)
  39. return;
  40. safebuf char Msg[MaxMsgSize];
  41. va_list argptr;
  42. va_start(argptr,fmt);
  43. vsnprintf(Msg,ASIZE(Msg),fmt,argptr);
  44. // Different vsnprintf implementation can return either -1 or >=MaxMsgSize
  45. // if string is truncated. So we do not check exit code and always zero
  46. // terminate the string for safety. It is faster than check for error.
  47. Msg[ASIZE(Msg)-1] = 0;
  48. RawPrint(Msg,MSG_STDERR);
  49. va_end(argptr);
  50. }
  51. #endif
  52. #if !defined(GUI) && !defined(SILENT)
  53. void RawPrint(char *Msg,MESSAGE_TYPE MessageType)
  54. {
  55. File OutFile;
  56. switch(MessageType)
  57. {
  58. case MSG_STDOUT:
  59. OutFile.SetHandleType(FILE_HANDLESTD);
  60. break;
  61. case MSG_STDERR:
  62. case MSG_ERRONLY:
  63. OutFile.SetHandleType(FILE_HANDLEERR);
  64. break;
  65. default:
  66. return;
  67. }
  68. #ifdef _WIN_ALL
  69. CharToOemA(Msg,Msg);
  70. char OutMsg[MaxMsgSize];
  71. size_t OutPos=0;
  72. for (size_t I=0;Msg[I]!=0;I++)
  73. {
  74. if (Msg[I]=='\n' && (I==0 || Msg[I-1]!='\r') && OutPos<ASIZE(OutMsg)-1)
  75. OutMsg[OutPos++]='\r';
  76. if (OutPos<ASIZE(OutMsg)-1)
  77. OutMsg[OutPos++]=Msg[I];
  78. }
  79. OutMsg[OutPos]=0;
  80. strcpy(Msg,OutMsg);
  81. #endif
  82. #if defined(_UNIX) || defined(_EMX)
  83. char OutMsg[MaxMsgSize],*OutPos=OutMsg;
  84. for (size_t I=0;Msg[I]!=0;I++)
  85. if (Msg[I]!='\r')
  86. *(OutPos++)=Msg[I];
  87. *OutPos=0;
  88. strcpy(Msg,OutMsg);
  89. #endif
  90. OutFile.Write(Msg,strlen(Msg));
  91. }
  92. #endif
  93. #ifndef SILENT
  94. void Alarm()
  95. {
  96. #ifndef SFX_MODULE
  97. if (Sound)
  98. putchar('\007');
  99. #endif
  100. }
  101. #endif
  102. #ifndef SILENT
  103. #ifndef GUI
  104. void GetPasswordText(wchar *Str,uint MaxLength)
  105. {
  106. if (MaxLength==0)
  107. return;
  108. #ifdef _WIN_ALL
  109. HANDLE hConIn=GetStdHandle(STD_INPUT_HANDLE);
  110. HANDLE hConOut=GetStdHandle(STD_OUTPUT_HANDLE);
  111. DWORD ConInMode,ConOutMode;
  112. DWORD Read=0;
  113. GetConsoleMode(hConIn,&ConInMode);
  114. GetConsoleMode(hConOut,&ConOutMode);
  115. SetConsoleMode(hConIn,ENABLE_LINE_INPUT);
  116. SetConsoleMode(hConOut,ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT);
  117. ReadConsoleW(hConIn,Str,MaxLength-1,&Read,NULL);
  118. Str[Read]=0;
  119. SetConsoleMode(hConIn,ConInMode);
  120. SetConsoleMode(hConOut,ConOutMode);
  121. #else
  122. char StrA[MAXPASSWORD];
  123. #if defined(_EMX) || defined(_BEOS) || defined(__sparc) || defined(sparc) || defined (__VMS)
  124. fgets(StrA,ASIZE(StrA)-1,stdin);
  125. #else
  126. strncpyz(StrA,getpass(""),ASIZE(StrA));
  127. #endif
  128. CharToWide(StrA,Str,MaxLength);
  129. #endif
  130. Str[MaxLength-1]=0;
  131. RemoveLF(Str);
  132. }
  133. #endif
  134. #endif
  135. #ifndef SILENT
  136. bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,wchar *Password,uint MaxLength)
  137. {
  138. Alarm();
  139. while (true)
  140. {
  141. char PromptStr[NM+256];
  142. #if defined(_EMX) || defined(_BEOS)
  143. strcpy(PromptStr,St(MAskPswEcho));
  144. #else
  145. strcpy(PromptStr,St(MAskPsw));
  146. #endif
  147. if (Type!=PASSWORD_GLOBAL)
  148. {
  149. strcat(PromptStr,St(MFor));
  150. char *NameOnly=PointToName(FileName);
  151. if (strlen(PromptStr)+strlen(NameOnly)<ASIZE(PromptStr))
  152. strcat(PromptStr,NameOnly);
  153. }
  154. eprintf("\n%s: ",PromptStr);
  155. GetPasswordText(Password,MaxLength);
  156. if (*Password==0 && Type==PASSWORD_GLOBAL)
  157. return(false);
  158. if (Type==PASSWORD_GLOBAL)
  159. {
  160. eprintf(St(MReAskPsw));
  161. wchar CmpStr[MAXPASSWORD];
  162. GetPasswordText(CmpStr,ASIZE(CmpStr));
  163. if (*CmpStr==0 || wcscmp(Password,CmpStr)!=0)
  164. {
  165. eprintf(St(MNotMatchPsw));
  166. memset(Password,0,MaxLength*sizeof(*Password));
  167. memset(CmpStr,0,sizeof(CmpStr));
  168. continue;
  169. }
  170. memset(CmpStr,0,sizeof(CmpStr));
  171. }
  172. break;
  173. }
  174. return(true);
  175. }
  176. #endif
  177. #if !defined(GUI) && !defined(SILENT)
  178. uint GetKey()
  179. {
  180. char Str[80];
  181. bool EndOfFile;
  182. #if defined(__GNUC__) || defined(sun)
  183. EndOfFile=(fgets(Str,sizeof(Str),stdin)==NULL);
  184. #else
  185. File SrcFile;
  186. SrcFile.SetHandleType(FILE_HANDLESTD);
  187. EndOfFile=(SrcFile.Read(Str,sizeof(Str))==0);
  188. #endif
  189. if (EndOfFile)
  190. {
  191. // Looks like stdin is a null device. We can enter to infinite loop
  192. // calling Ask(), so let's better exit.
  193. ErrHandler.Exit(USER_BREAK);
  194. }
  195. return(Str[0]);
  196. }
  197. #endif
  198. #if !defined(GUI) && !defined(SILENT)
  199. int Ask(const char *AskStr)
  200. {
  201. const int MaxItems=10;
  202. char Item[MaxItems][40];
  203. int ItemKeyPos[MaxItems],NumItems=0;
  204. for (const char *NextItem=AskStr;NextItem!=NULL;NextItem=strchr(NextItem+1,'_'))
  205. {
  206. char *CurItem=Item[NumItems];
  207. strncpyz(CurItem,NextItem+1,ASIZE(Item[0]));
  208. char *EndItem=strchr(CurItem,'_');
  209. if (EndItem!=NULL)
  210. *EndItem=0;
  211. int KeyPos=0,CurKey;
  212. while ((CurKey=CurItem[KeyPos])!=0)
  213. {
  214. bool Found=false;
  215. for (int I=0;I<NumItems && !Found;I++)
  216. if (loctoupper(Item[I][ItemKeyPos[I]])==loctoupper(CurKey))
  217. Found=true;
  218. if (!Found && CurKey!=' ')
  219. break;
  220. KeyPos++;
  221. }
  222. ItemKeyPos[NumItems]=KeyPos;
  223. NumItems++;
  224. }
  225. for (int I=0;I<NumItems;I++)
  226. {
  227. eprintf(I==0 ? (NumItems>4 ? "\n":" "):", ");
  228. int KeyPos=ItemKeyPos[I];
  229. for (int J=0;J<KeyPos;J++)
  230. eprintf("%c",Item[I][J]);
  231. eprintf("[%c]%s",Item[I][KeyPos],&Item[I][KeyPos+1]);
  232. }
  233. eprintf(" ");
  234. int Ch=GetKey();
  235. #if defined(_WIN_ALL)
  236. OemToCharBuff((LPCSTR)&Ch,(LPTSTR)&Ch,1);
  237. #endif
  238. Ch=loctoupper(Ch);
  239. for (int I=0;I<NumItems;I++)
  240. if (Ch==Item[I][ItemKeyPos[I]])
  241. return(I+1);
  242. return(0);
  243. }
  244. #endif
  245. int KbdAnsi(char *Addr,size_t Size)
  246. {
  247. int RetCode=0;
  248. #ifndef GUI
  249. for (size_t I=0;I<Size;I++)
  250. if (Addr[I]==27 && Addr[I+1]=='[')
  251. {
  252. for (size_t J=I+2;J<Size;J++)
  253. {
  254. if (Addr[J]=='\"')
  255. return(2);
  256. if (!IsDigit(Addr[J]) && Addr[J]!=';')
  257. break;
  258. }
  259. RetCode=1;
  260. }
  261. #endif
  262. return(RetCode);
  263. }
  264. void OutComment(char *Comment,size_t Size)
  265. {
  266. #ifndef GUI
  267. if (KbdAnsi(Comment,Size)==2)
  268. return;
  269. const size_t MaxOutSize=0x400;
  270. for (size_t I=0;I<Size;I+=MaxOutSize)
  271. {
  272. char Msg[MaxOutSize+1];
  273. size_t CopySize=Min(MaxOutSize,Size-I);
  274. strncpy(Msg,Comment+I,CopySize);
  275. Msg[CopySize]=0;
  276. mprintf("%s",Msg);
  277. }
  278. mprintf("\n");
  279. #endif
  280. }