Advertisement
tyree731

recall_input.cxx

Oct 21st, 2021
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.06 KB | None | 0 0
  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <inttypes.h>
  5. #include <iostream>
  6. #include <sstream>
  7. #include <string>
  8. #include <sys/stat.h>
  9. #include <unistd.h>
  10.  
  11. #define __NEW_STARLET 1
  12. #include <descrip.h>
  13. #include <efndef.h>
  14. #include <gen64def.h>
  15. #include <iledef.h>
  16. #include <iosbdef.h>
  17. #include <jpidef.h>
  18. #include <lib$routines.h>
  19. #include <lnmdef.h>
  20. #include <prvdef.h>
  21. #include <psldef.h>
  22. #include <ssdef.h>
  23. #include <starlet.h>
  24. #include <stsdef.h>
  25.  
  26. static const char* kCookieLogicalName = "RECALL_INPUT_COOKIE";
  27.  
  28. extern "C" int set_process_level_executive(int16_t* new_process_level)
  29. {
  30.   static const unsigned long PPD$L_PRC       = 0x00000008;
  31.   static const unsigned long PRC_W_PROCLEVEL = 0x00000038;
  32.  
  33.   typedef struct prcdef {
  34.     char filler[PRC_W_PROCLEVEL];
  35.     int16_t prc_w_proclevel;
  36.   } PRCDEF;
  37.  
  38.   typedef struct clidata {
  39.     char filler[PPD$L_PRC];
  40. #pragma pointer_size save
  41. #pragma pointer_size 32
  42.     PRCDEF *p_prc;
  43. #pragma pointer_size restore
  44.   } CLIDATA;
  45.  
  46.   extern void *CTL$AG_CLIDATA;
  47.  
  48.   CLIDATA *p_clidata;
  49.   p_clidata = (CLIDATA *)&CTL$AG_CLIDATA;
  50.   PRCDEF *p_prc;
  51.   p_prc = p_clidata->p_prc;
  52.  
  53.   const int16_t old_process_level = p_prc->prc_w_proclevel;
  54.   p_prc->prc_w_proclevel = *new_process_level;
  55.   return old_process_level;
  56. }
  57.  
  58. extern "C" bool set_process_level(int16_t  new_process_level
  59.                                 , int16_t& old_process_level)
  60. {
  61.   struct {
  62.     uint64_t count;
  63.     int16_t* new_process_level;
  64.   } arguments = {1, &new_process_level};
  65.  
  66.   const int status = static_cast<unsigned short>(
  67.     sys$cmexec_64(reinterpret_cast<int(*)(__unknown_params)>(&set_process_level_executive)
  68.                 , reinterpret_cast<unsigned __int64*>(&arguments))
  69.   );
  70.  
  71.   if (status == SS$_NOCMEXEC) {
  72.     return false;
  73.   }
  74.  
  75.   old_process_level = static_cast<unsigned short>(status);
  76.   return true;
  77. }
  78.  
  79. extern "C" void set_process_level_noreturn(int16_t new_process_level)
  80. {
  81.   int16_t unused = 0;
  82.   (void)set_process_level(new_process_level, unused);
  83. }
  84.  
  85. inline void initialize_descriptor(const char* name
  86.                                 , struct dsc64$descriptor_s& descriptor)
  87. {
  88.   descriptor.dsc64$w_mbo      = 1;
  89.   descriptor.dsc64$b_dtype    = DSC64$K_DTYPE_T;
  90.   descriptor.dsc64$b_class    = DSC64$K_CLASS_S;;
  91.   descriptor.dsc64$l_mbmo     = -1;
  92.   descriptor.dsc64$q_length   = strnlen(name, LNM$C_NAMLENGTH);
  93.   descriptor.dsc64$pq_pointer = const_cast<char*>(name);
  94. }
  95.  
  96. #define ILE3_64_BUF(code,bsize,baddr,ret) {1,(code),-1,bsize,baddr,ret}
  97. #define ILE3_64_END() {0,0,0,0,0,0}
  98.  
  99. bool check_magic_cookie()
  100. {
  101.   const unsigned int flag = LNM$M_CASE_BLIND;
  102.  
  103.   struct dsc64$descriptor_s table;
  104.   initialize_descriptor("LNM$PROCESS", table);
  105.   struct dsc64$descriptor_s logical;
  106.   initialize_descriptor(kCookieLogicalName, logical);
  107.  
  108.   char buffer[LNM$C_NAMLENGTH + 1] = {0};
  109.   size_t buffer_length = sizeof(buffer);
  110.  
  111.   uint64_t length = 0;
  112.   ILEB_64 items[2] = {
  113.     ILE3_64_BUF(LNM$_STRING, buffer_length - 1, buffer, &length)
  114.   , ILE3_64_END()
  115.   };
  116.  
  117.   unsigned char exec_mode = PSL$C_EXEC;
  118.   const int status = sys$trnlnm(const_cast<unsigned int*>(&flag), &table
  119.                               , &logical, &exec_mode, items);
  120.   return ($VMS_STATUS_SUCCESS(status));
  121. }
  122.  
  123. bool destroy_magic_cookie()
  124. {
  125.   struct dsc64$descriptor_s table;
  126.   initialize_descriptor("LNM$PROCESS", table);
  127.   struct dsc64$descriptor_s logical;
  128.   initialize_descriptor(kCookieLogicalName, logical);
  129.  
  130.   unsigned char exec_mode = PSL$C_EXEC;
  131.   return ($VMS_STATUS_SUCCESS(sys$dellnm(&table, &logical, &exec_mode)));
  132. }
  133.  
  134. bool create_magic_cookie()
  135. {
  136.   struct dsc64$descriptor_s table;
  137.   initialize_descriptor("LNM$PROCESS", table);
  138.   struct dsc64$descriptor_s logical;
  139.   initialize_descriptor(kCookieLogicalName, logical);
  140.  
  141.   static const char* kLogicalValue = "1";
  142.   unsigned char exec_mode = PSL$C_EXEC;
  143.   ILEB_64 items[2] = {
  144.     ILE3_64_BUF(LNM$_STRING, strlen(kLogicalValue), const_cast<char*>(kLogicalValue), 0)
  145.   , ILE3_64_END()
  146.   };
  147.  
  148.   return ($VMS_STATUS_SUCCESS(sys$crelnm(NULL, &table, &logical, &exec_mode, items)));
  149. }
  150.  
  151. inline bool file_exists(const std::string& filename)
  152. {
  153.   struct stat unused;
  154.   return (stat(filename.c_str(), &unused) == 0);
  155. }
  156.  
  157. inline bool is_number(const char* input)
  158. {
  159.   const size_t input_size = strlen(input);
  160.   for (int i = 0; i < input_size; ++i) {
  161.     if (!isdigit(input[i])) {
  162.       return false;
  163.     }
  164.   }
  165.   return true;
  166. }
  167.  
  168. std::string get_process_name()
  169. {
  170.   char process_name[FILENAME_MAX + 1] = {0};
  171.  
  172.   uint64_t length = 0;
  173.   ILEB_64 items[] = {
  174.     ILE3_64_BUF(JPI$_IMAGNAME, sizeof(process_name) - 1, process_name, &length)
  175.   , ILE3_64_END()
  176.   };
  177.  
  178.   _iosb iosb;
  179.   const int status = sys$getjpiw(EFN$C_ENF, NULL, 0, items, &iosb, 0, 0);
  180.   if ($VMS_STATUS_SUCCESS(status) && $VMS_STATUS_SUCCESS(iosb.iosb$w_status)) {
  181.     return std::string(process_name, length);
  182.   }
  183.   return std::string();
  184. }
  185.  
  186. extern "C" int snprintf(char *__s, __size_t __n, const char *__format, ...);
  187.  
  188. void display_error(const char* type, const char* message)
  189. {
  190.   std::stringstream str;
  191.   str << "%RECALLINPUT-E-" << type << ", " << message;
  192.   std::cerr << str.str() << std::endl;
  193. }
  194.  
  195. void display_fnf_error(const char* filename)
  196. {
  197.   std::stringstream str;
  198.   str << "error opening " << filename << " as input";
  199.   display_error("FNF", str.str().c_str());
  200. }
  201.  
  202. int main(int argc, char** argv)
  203. {
  204.   if (argc != 2) {
  205.     display_error("USAGE", "mcr tools:recall_input.exe <filename>");
  206.     return EXIT_FAILURE;
  207.   }
  208.  
  209.   if (is_number(argv[1])) {
  210.     if (!check_magic_cookie()) {
  211.       display_fnf_error(argv[1]);
  212.       return EXIT_FAILURE;
  213.     }
  214.  
  215.     set_process_level_noreturn(atoi(argv[1]));
  216.     (void)destroy_magic_cookie();
  217.     return EXIT_SUCCESS;
  218.   }
  219.  
  220.   const std::string filename = argv[1];
  221.   if (!file_exists(filename)) {
  222.     display_fnf_error(filename.c_str());
  223.     return EXIT_FAILURE;
  224.   }
  225.  
  226.   const std::string this_process = get_process_name();
  227.   if (this_process.empty()) {
  228.     display_error("JPIERR", "error getting this process' name");
  229.     return EXIT_FAILURE;
  230.   }
  231.  
  232.   int16_t old_process_level = 0;
  233.   if (!set_process_level(0, old_process_level)) {
  234.     display_error("NOPRIV", "error escalating to CMEXEC privileges");
  235.     return EXIT_FAILURE;
  236.   }
  237.  
  238.   if (!create_magic_cookie()) {
  239.     display_error("COOKIE", "error creating internal cookie");
  240.     set_process_level_noreturn(old_process_level);
  241.     return EXIT_FAILURE;
  242.   }
  243.  
  244.   char command[256] = {0};
  245.   const int full_command_size =
  246.     snprintf(command, sizeof(command) - 1
  247.            , "pipe recall/input=%s ; mcr %s %d"
  248.            , filename.c_str(), this_process.c_str(), old_process_level);
  249.   if (full_command_size >= sizeof(command)) {
  250.     display_error("CMDLNGTH", "error constructing internal recall command due"
  251.                               " to filename being too long");
  252.     set_process_level_noreturn(old_process_level);
  253.     return EXIT_FAILURE;
  254.   }
  255.  
  256.   $DESCRIPTOR64(command_descriptor, command);
  257.   lib$do_command(&command_descriptor);
  258.   return EXIT_FAILURE;
  259. }
  260.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement