|
|
1.1 ! root 1: /* VMS subprocess and command interface. ! 2: Copyright (C) 1987, 1988 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU Emacs. ! 5: ! 6: GNU Emacs is distributed in the hope that it will be useful, ! 7: but WITHOUT ANY WARRANTY. No author or distributor ! 8: accepts responsibility to anyone for the consequences of using it ! 9: or for whether it serves any particular purpose or works at all, ! 10: unless he says so in writing. Refer to the GNU Emacs General Public ! 11: License for full details. ! 12: ! 13: Everyone is granted permission to copy, modify and redistribute ! 14: GNU Emacs, but only under the conditions described in the ! 15: GNU Emacs General Public License. A copy of this license is ! 16: supposed to have been given to you along with GNU Emacs so you ! 17: can know your rights and responsibilities. It should be in a ! 18: file named COPYING. Among other things, the copyright notice ! 19: and this notice must be preserved on all copies. */ ! 20: ! 21: /* Written by Mukesh Prasad. */ ! 22: ! 23: /* ! 24: * INTERFACE PROVIDED BY EMACS FOR VMS SUBPROCESSES: ! 25: * ! 26: * Emacs provides the following functions: ! 27: * ! 28: * "spawn-subprocess", which takes as arguments: ! 29: * ! 30: * (i) an integer to identify the spawned subprocess in future ! 31: * operations, ! 32: * (ii) A function to process input from the subprocess, and ! 33: * (iii) A function to be called upon subprocess termination. ! 34: * ! 35: * First argument is required. If second argument is missing or nil, ! 36: * the default action is to insert all received messages at the current ! 37: * location in the current buffer. If third argument is missing or nil, ! 38: * no action is taken upon subprocess termination. ! 39: * The input-handler is called as ! 40: * (input-handler num string) ! 41: * where num is the identifying integer for the subprocess and string ! 42: * is a string received from the subprocess. exit-handler is called ! 43: * with the identifying integer as the argument. ! 44: * ! 45: * "send-command-to-subprocess" takes two arguments: ! 46: * ! 47: * (i) Subprocess identifying integer. ! 48: * (ii) String to send as a message to the subprocess. ! 49: * ! 50: * "stop-subprocess" takes the subprocess identifying integer as ! 51: * argument. ! 52: * ! 53: * Implementation is done by spawning an asynchronous subprocess, and ! 54: * communicating to it via mailboxes. ! 55: */ ! 56: ! 57: #ifdef VMS ! 58: ! 59: #include <stdio.h> ! 60: #include <ctype.h> ! 61: #undef NULL ! 62: ! 63: #include "config.h" ! 64: #include "lisp.h" ! 65: #include <descrip.h> ! 66: #include <dvidef.h> ! 67: #include <prvdef.h> ! 68: /* #include <clidef.h> */ ! 69: #include <iodef.h> ! 70: #include <ssdef.h> ! 71: #include <errno.h> ! 72: ! 73: #ifdef VMS4_4 /* I am being cautious; perhaps this exists in older versions */ ! 74: #include <jpidef.h> ! 75: #endif ! 76: ! 77: /* #include <syidef.h> */ ! 78: ! 79: #define CLI$M_NOWAIT 1 /* clidef.h is missing from C library */ ! 80: #define SYI$_VERSION 4096 /* syidef.h is missing from C library */ ! 81: #define JPI$_CLINAME 522 /* JPI$_CLINAME is missing from jpidef.h */ ! 82: #define JPI$_MASTER_PID 805 /* JPI$_MASTER_PID missing from jpidef.h */ ! 83: #define LIB$_NOSUCHSYM 1409892 /* libclidef.h missing */ ! 84: ! 85: #define MSGSIZE 160 /* Maximum size for mailbox operations */ ! 86: ! 87: #ifndef PRV$V_ACNT ! 88: ! 89: /* these defines added as hack for VMS 5.1-1. SJones, 8-17-89 */ ! 90: /* this is _really_ nasty and needs to be changed ASAP - should see about ! 91: using the union defined in SYS$LIBRARY:PRVDEF.H under v5 */ ! 92: ! 93: #define PRV$V_ACNT 0x09 ! 94: #define PRV$V_ALLSPOOL 0x04 ! 95: #define PRV$V_ALTPRI 0x0D ! 96: #define PRV$V_BUGCHK 0x17 ! 97: #define PRV$V_BYPASS 0x1D ! 98: #define PRV$V_CMEXEC 0x01 ! 99: #define PRV$V_CMKRNL 0x00 ! 100: #define PRV$V_DETACH 0x05 ! 101: #define PRV$V_DIAGNOSE 0x06 ! 102: #define PRV$V_DOWNGRADE 0x21 ! 103: #define PRV$V_EXQUOTA 0x13 ! 104: #define PRV$V_GROUP 0x08 ! 105: #define PRV$V_GRPNAM 0x03 ! 106: #define PRV$V_GRPPRV 0x22 ! 107: #define PRV$V_LOG_IO 0x07 ! 108: #define PRV$V_MOUNT 0x11 ! 109: #define PRV$V_NETMBX 0x14 ! 110: #define PRV$V_NOACNT 0x09 ! 111: #define PRV$V_OPER 0x12 ! 112: #define PRV$V_PFNMAP 0x1A ! 113: #define PRV$V_PHY_IO 0x16 ! 114: #define PRV$V_PRMCEB 0x0A ! 115: #define PRV$V_PRMGBL 0x18 ! 116: #define PRV$V_PRMJNL 0x25 ! 117: #define PRV$V_PRMMBX 0x0B ! 118: #define PRV$V_PSWAPM 0x0C ! 119: #define PRV$V_READALL 0x23 ! 120: #define PRV$V_SECURITY 0x26 ! 121: #define PRV$V_SETPRI 0x0D ! 122: #define PRV$V_SETPRV 0x0E ! 123: #define PRV$V_SHARE 0x1F ! 124: #define PRV$V_SHMEM 0x1B ! 125: #define PRV$V_SYSGBL 0x19 ! 126: #define PRV$V_SYSLCK 0x1E ! 127: #define PRV$V_SYSNAM 0x02 ! 128: #define PRV$V_SYSPRV 0x1C ! 129: #define PRV$V_TMPJNL 0x24 ! 130: #define PRV$V_TMPMBX 0x0F ! 131: #define PRV$V_UPGRADE 0x20 ! 132: #define PRV$V_VOLPRO 0x15 ! 133: #define PRV$V_WORLD 0x10 ! 134: #endif ! 135: ! 136: /* IO status block for mailbox operations. */ ! 137: struct mbx_iosb ! 138: { ! 139: short status; ! 140: short size; ! 141: int pid; ! 142: }; ! 143: ! 144: /* Structure for maintaining linked list of subprocesses. */ ! 145: struct process_list ! 146: { ! 147: int name; /* Numeric identifier for subprocess */ ! 148: int process_id; /* VMS process address */ ! 149: int process_active; /* 1 iff process has not exited yet */ ! 150: int mbx_chan; /* Mailbox channel to write to process */ ! 151: struct mbx_iosb iosb; /* IO status block for write operations */ ! 152: Lisp_Object input_handler; /* Input handler for subprocess */ ! 153: Lisp_Object exit_handler; /* Exit handler for subprocess */ ! 154: struct process_list * next; /* Linked list chain */ ! 155: }; ! 156: ! 157: /* Structure for privilege list. */ ! 158: struct privilege_list ! 159: { ! 160: char * name; ! 161: int mask; ! 162: }; ! 163: ! 164: /* Structure for finding VMS related information. */ ! 165: struct vms_objlist ! 166: { ! 167: char * name; /* Name of object */ ! 168: Lisp_Object (* objfn)(); /* Function to retrieve VMS object */ ! 169: }; ! 170: ! 171: static int exit_ast (); /* Called upon subprocess exit */ ! 172: static int create_mbx (); /* Creates mailbox */ ! 173: static void mbx_msg (); /* Writes null terminated string to mbx */ ! 174: static void write_to_mbx (); /* Writes message to string */ ! 175: static void start_mbx_input (); /* Queues I/O request to mailbox */ ! 176: ! 177: static int input_mbx_chan = 0; /* Channel to read subprocess input on */ ! 178: static char input_mbx_name[20]; ! 179: /* Storage for mailbox device name */ ! 180: static struct dsc$descriptor_s input_mbx_dsc; ! 181: /* Descriptor for mailbox device name */ ! 182: static struct process_list * process_list = 0; ! 183: /* Linked list of subprocesses */ ! 184: static char mbx_buffer[MSGSIZE]; ! 185: /* Buffer to read from subprocesses */ ! 186: static struct mbx_iosb input_iosb; ! 187: /* IO status block for mailbox reads */ ! 188: ! 189: int have_process_input, /* Non-zero iff subprocess input pending */ ! 190: process_exited; /* Non-zero iff suprocess exit pending */ ! 191: ! 192: /* List of privilege names and mask offsets */ ! 193: static struct privilege_list priv_list[] = { ! 194: ! 195: { "ACNT", PRV$V_ACNT }, ! 196: { "ALLSPOOL", PRV$V_ALLSPOOL }, ! 197: { "ALTPRI", PRV$V_ALTPRI }, ! 198: { "BUGCHK", PRV$V_BUGCHK }, ! 199: { "BYPASS", PRV$V_BYPASS }, ! 200: { "CMEXEC", PRV$V_CMEXEC }, ! 201: { "CMKRNL", PRV$V_CMKRNL }, ! 202: { "DETACH", PRV$V_DETACH }, ! 203: { "DIAGNOSE", PRV$V_DIAGNOSE }, ! 204: { "DOWNGRADE", PRV$V_DOWNGRADE }, /* Isn't VMS as low as you can go? */ ! 205: { "EXQUOTA", PRV$V_EXQUOTA }, ! 206: { "GRPPRV", PRV$V_GRPPRV }, ! 207: { "GROUP", PRV$V_GROUP }, ! 208: { "GRPNAM", PRV$V_GRPNAM }, ! 209: { "LOG_IO", PRV$V_LOG_IO }, ! 210: { "MOUNT", PRV$V_MOUNT }, ! 211: { "NETMBX", PRV$V_NETMBX }, ! 212: { "NOACNT", PRV$V_NOACNT }, ! 213: { "OPER", PRV$V_OPER }, ! 214: { "PFNMAP", PRV$V_PFNMAP }, ! 215: { "PHY_IO", PRV$V_PHY_IO }, ! 216: { "PRMCEB", PRV$V_PRMCEB }, ! 217: { "PRMGBL", PRV$V_PRMGBL }, ! 218: { "PRMJNL", PRV$V_PRMJNL }, ! 219: { "PRMMBX", PRV$V_PRMMBX }, ! 220: { "PSWAPM", PRV$V_PSWAPM }, ! 221: { "READALL", PRV$V_READALL }, ! 222: { "SECURITY", PRV$V_SECURITY }, ! 223: { "SETPRI", PRV$V_SETPRI }, ! 224: { "SETPRV", PRV$V_SETPRV }, ! 225: { "SHARE", PRV$V_SHARE }, ! 226: { "SHMEM", PRV$V_SHMEM }, ! 227: { "SYSGBL", PRV$V_SYSGBL }, ! 228: { "SYSLCK", PRV$V_SYSLCK }, ! 229: { "SYSNAM", PRV$V_SYSNAM }, ! 230: { "SYSPRV", PRV$V_SYSPRV }, ! 231: { "TMPJNL", PRV$V_TMPJNL }, ! 232: { "TMPMBX", PRV$V_TMPMBX }, ! 233: { "UPGRADE", PRV$V_UPGRADE }, ! 234: { "VOLPRO", PRV$V_VOLPRO }, ! 235: { "WORLD", PRV$V_WORLD }, ! 236: ! 237: }; ! 238: ! 239: static Lisp_Object ! 240: vms_account(), vms_cliname(), vms_owner(), vms_grp(), vms_image(), ! 241: vms_parent(), vms_pid(), vms_prcnam(), vms_terminal(), vms_uic_int(), ! 242: vms_uic_str(), vms_username(), vms_version_fn(), vms_trnlog(), ! 243: vms_symbol(), vms_proclist(); ! 244: ! 245: /* Table of arguments to Fvms_object, and the handlers that get the data. */ ! 246: ! 247: static struct vms_objlist vms_object [] = { ! 248: { "ACCOUNT", vms_account }, /* Returns account name as a string */ ! 249: { "CLINAME", vms_cliname }, /* Returns CLI name (string) */ ! 250: { "OWNER", vms_owner }, /* Returns owner process's PID (int) */ ! 251: { "GRP", vms_grp }, /* Returns group number of UIC (int) */ ! 252: { "IMAGE", vms_image }, /* Returns executing image (string) */ ! 253: { "PARENT", vms_parent }, /* Returns parent proc's PID (int) */ ! 254: { "PID", vms_pid }, /* Returns process's PID (int) */ ! 255: { "PRCNAM", vms_prcnam }, /* Returns process's name (string) */ ! 256: { "TERMINAL", vms_terminal }, /* Returns terminal name (string) */ ! 257: { "UIC", vms_uic_int }, /* Returns UIC as integer */ ! 258: { "UICGRP", vms_uic_str }, /* Returns UIC as string */ ! 259: { "USERNAME", vms_username }, /* Returns username (string) */ ! 260: { "VERSION", vms_version_fn },/* Returns VMS version (string) */ ! 261: { "LOGICAL", vms_trnlog }, /* Translates VMS logical name */ ! 262: { "DCL-SYMBOL", vms_symbol }, /* Translates DCL symbol */ ! 263: { "PROCLIST", vms_proclist }, /* Returns list of all PIDs on system */ ! 264: }; ! 265: ! 266: Lisp_Object Qdefault_subproc_input_handler; ! 267: ! 268: extern int process_ef; /* Event flag for subprocess operations */ ! 269: ! 270: DEFUN ("default-subprocess-input-handler", ! 271: Fdefault_subproc_input_handler, Sdefault_subproc_input_handler, ! 272: 2, 2, 0, ! 273: "Default input handler for input from spawned subprocesses.") ! 274: (name, input) ! 275: Lisp_Object name, input; ! 276: { ! 277: /* Just insert in current buffer */ ! 278: InsCstr (XSTRING (input)->data, XSTRING (input)->size); ! 279: InsCstr ("\n", 1); ! 280: } ! 281: ! 282: DEFUN ("spawn-subprocess", Fspawn_subprocess, Sspawn_subprocess, 1, 3, 0, ! 283: "Spawns an asynchronous VMS suprocess for command processing.") ! 284: (name, input_handler, exit_handler) ! 285: Lisp_Object name, input_handler, exit_handler; ! 286: { ! 287: int status; ! 288: char output_mbx_name[20]; ! 289: struct dsc$descriptor_s output_mbx_dsc; ! 290: struct process_list * ptr, * p; ! 291: ! 292: CHECK_NUMBER (name, 0); ! 293: if (! input_mbx_chan) ! 294: { ! 295: if (! create_mbx (&input_mbx_dsc, input_mbx_name, &input_mbx_chan, 1)) ! 296: return Qnil; ! 297: start_mbx_input (); ! 298: } ! 299: ptr = 0; ! 300: for (p = process_list; p; p = p->next) ! 301: if (p->name == XFASTINT (name)) ! 302: { ! 303: ptr = p; ! 304: if (p->process_active) ! 305: return Qt; ! 306: else ! 307: sys$dassgn (p->mbx_chan); ! 308: break; ! 309: } ! 310: if (! ptr) ! 311: ptr = xmalloc (sizeof (struct process_list)); ! 312: if (! create_mbx (&output_mbx_dsc, output_mbx_name, &ptr->mbx_chan, 2)) ! 313: { ! 314: free (ptr); ! 315: return Qnil; ! 316: } ! 317: if (NULL (input_handler)) ! 318: input_handler = Qdefault_subproc_input_handler; ! 319: ptr->input_handler = input_handler; ! 320: ptr->exit_handler = exit_handler; ! 321: message ("Creating subprocess..."); ! 322: status = lib$spawn (0, &output_mbx_dsc, &input_mbx_dsc, &CLI$M_NOWAIT, 0, ! 323: &ptr->process_id, 0, 0, exit_ast, &ptr->process_active); ! 324: if (! (status & 1)) ! 325: { ! 326: sys$dassgn (ptr->mbx_chan); ! 327: free (ptr); ! 328: error ("Unable to spawn subprocess"); ! 329: return Qnil; ! 330: } ! 331: ptr->name = XFASTINT (name); ! 332: ptr->next = process_list; ! 333: ptr->process_active = 1; ! 334: process_list = ptr; ! 335: message ("Creating subprocess...done"); ! 336: return Qt; ! 337: } ! 338: ! 339: static void ! 340: mbx_msg (ptr, msg) ! 341: struct process_list *ptr; ! 342: char *msg; ! 343: { ! 344: write_to_mbx (ptr, msg, strlen (msg)); ! 345: } ! 346: ! 347: DEFUN ("send-command-to-subprocess", ! 348: Fsend_command_to_subprocess, Ssend_command_to_subprocess, 2, 2, ! 349: "sSend command to subprocess: \nsSend subprocess %s command: ", ! 350: "Send to VMS subprocess named NAME the string COMMAND.") ! 351: (name, command) ! 352: Lisp_Object name, command; ! 353: { ! 354: struct process_list * ptr; ! 355: ! 356: CHECK_NUMBER (name, 0); ! 357: CHECK_STRING (command, 1); ! 358: for (ptr = process_list; ptr; ptr = ptr->next) ! 359: if (XFASTINT (name) == ptr->name) ! 360: { ! 361: write_to_mbx (ptr, XSTRING (command)->data, ! 362: XSTRING (command)->size); ! 363: return Qt; ! 364: } ! 365: return Qnil; ! 366: } ! 367: ! 368: DEFUN ("stop-subprocess", Fstop_subprocess, Sstop_subprocess, 1, 1, ! 369: "sStop subprocess: ", "Stop VMS subprocess named NAME.") ! 370: (name) ! 371: Lisp_Object name; ! 372: { ! 373: struct process_list * ptr; ! 374: ! 375: CHECK_NUMBER (name, 0); ! 376: for (ptr = process_list; ptr; ptr = ptr->next) ! 377: if (XFASTINT (name) == ptr->name) ! 378: { ! 379: ptr->exit_handler = Qnil; ! 380: if (sys$delprc (&ptr->process_id, 0) & 1) ! 381: ptr->process_active = 0; ! 382: return Qt; ! 383: } ! 384: return Qnil; ! 385: } ! 386: ! 387: static int ! 388: exit_ast (active) ! 389: int * active; ! 390: { ! 391: process_exited = 1; ! 392: *active = 0; ! 393: sys$setef (process_ef); ! 394: } ! 395: ! 396: /* Process to handle input on the input mailbox. ! 397: * Searches through the list of processes until the matching PID is found, ! 398: * then calls its input handler. ! 399: */ ! 400: ! 401: process_command_input () ! 402: { ! 403: struct process_list * ptr; ! 404: char * msg; ! 405: int msglen; ! 406: Lisp_Object expr; ! 407: ! 408: msg = mbx_buffer; ! 409: msglen = input_iosb.size; ! 410: /* Hack around VMS oddity of sending extraneous CR/LF characters for ! 411: * some of the commands (but not most). ! 412: */ ! 413: if (msglen > 0 && *msg == '\r') ! 414: { ! 415: msg++; ! 416: msglen--; ! 417: } ! 418: if (msglen > 0 && msg[msglen - 1] == '\n') ! 419: msglen--; ! 420: if (msglen > 0 && msg[msglen - 1] == '\r') ! 421: msglen--; ! 422: /* Search for the subprocess in the linked list. ! 423: */ ! 424: expr = Qnil; ! 425: for (ptr = process_list; ptr; ptr = ptr->next) ! 426: if (ptr->process_id == input_iosb.pid) ! 427: { ! 428: expr = Fcons (ptr->input_handler, ! 429: Fcons (make_number (ptr->name), ! 430: Fcons (make_string (msg, msglen), ! 431: Qnil))); ! 432: break; ! 433: } ! 434: have_process_input = 0; ! 435: start_mbx_input (); ! 436: if (! NULL (expr)) ! 437: Feval (expr); ! 438: } ! 439: ! 440: /* Searches process list for any processes which have exited. Calls their ! 441: * exit handlers and removes them from the process list. ! 442: */ ! 443: ! 444: process_exit () ! 445: { ! 446: struct process_list * ptr, * prev, * next; ! 447: ! 448: process_exited = 0; ! 449: prev = 0; ! 450: ptr = process_list; ! 451: while (ptr) ! 452: { ! 453: if (! ptr->process_active) ! 454: { ! 455: next = ptr->next; ! 456: if (prev) ! 457: prev->next = next; ! 458: else ! 459: process_list = next; ! 460: if (! NULL (ptr->exit_handler)) ! 461: Feval (Fcons (ptr->exit_handler, Fcons (make_number (ptr->name), ! 462: Qnil))); ! 463: sys$dassgn (ptr->mbx_chan); ! 464: free (ptr); ! 465: } ! 466: prev = ptr; ! 467: ptr = next; ! 468: } ! 469: } ! 470: ! 471: /* Called at emacs exit. ! 472: */ ! 473: ! 474: kill_vms_processes () ! 475: { ! 476: struct process_list * ptr; ! 477: ! 478: for (ptr = process_list; ptr; ptr = ptr->next) ! 479: if (ptr->process_active) ! 480: { ! 481: sys$dassgn (ptr->mbx_chan); ! 482: sys$delprc (&ptr->process_id, 0); ! 483: } ! 484: sys$dassgn (input_mbx_chan); ! 485: process_list = 0; ! 486: input_mbx_chan = 0; ! 487: } ! 488: ! 489: /* Creates a temporary mailbox and retrieves its device name in 'buf'. ! 490: * Makes the descriptor pointed to by 'dsc' refer to this device. ! 491: * 'buffer_factor' is used to allow sending messages asynchronously ! 492: * till some point. ! 493: */ ! 494: ! 495: static int ! 496: create_mbx (dsc, buf, chan, buffer_factor) ! 497: struct dsc$descriptor_s *dsc; ! 498: char *buf; ! 499: int *chan; ! 500: int buffer_factor; ! 501: { ! 502: int strval[2]; ! 503: int status; ! 504: ! 505: status = sys$crembx (0, chan, MSGSIZE, MSGSIZE * buffer_factor, 0, 0, 0); ! 506: if (! (status & 1)) ! 507: { ! 508: message ("Unable to create mailbox. Need TMPMBX privilege."); ! 509: return 0; ! 510: } ! 511: strval[0] = 16; ! 512: strval[1] = buf; ! 513: status = lib$getdvi (&DVI$_DEVNAM, chan, 0, 0, strval, ! 514: &dsc->dsc$w_length); ! 515: if (! (status & 1)) ! 516: return 0; ! 517: dsc->dsc$b_dtype = DSC$K_DTYPE_T; ! 518: dsc->dsc$b_class = DSC$K_CLASS_S; ! 519: dsc->dsc$a_pointer = buf; ! 520: return 1; ! 521: } /* create_mbx */ ! 522: ! 523: /* AST routine to be called upon receiving mailbox input. ! 524: * Sets flag telling keyboard routines that input is available. ! 525: */ ! 526: ! 527: static int ! 528: mbx_input_ast () ! 529: { ! 530: have_process_input = 1; ! 531: } ! 532: ! 533: /* Issue a QIO request on the input mailbox. ! 534: */ ! 535: static void ! 536: start_mbx_input () ! 537: { ! 538: sys$qio (process_ef, input_mbx_chan, IO$_READVBLK, &input_iosb, ! 539: mbx_input_ast, 0, mbx_buffer, sizeof (mbx_buffer), ! 540: 0, 0, 0, 0); ! 541: } ! 542: ! 543: /* Send a message to the subprocess input mailbox, without blocking if ! 544: * possible. ! 545: */ ! 546: static void ! 547: write_to_mbx (ptr, buf, len) ! 548: struct process_list *ptr; ! 549: char *buf; ! 550: int len; ! 551: { ! 552: sys$qiow (0, ptr->mbx_chan, IO$_WRITEVBLK | IO$M_NOW, &ptr->iosb, ! 553: 0, 0, buf, len, 0, 0, 0, 0); ! 554: } ! 555: ! 556: DEFUN ("setprv", Fsetprv, Ssetprv, 1, 3, 0, ! 557: "Set or reset a VMS privilege. First arg is privilege name.\n\ ! 558: Second arg is t or nil, indicating whether the privilege is to be\n\ ! 559: set or reset. Default is nil. Returns t if success, nil if not.\n\ ! 560: If third arg is non-nil, does not change privilege, but returns t\n\ ! 561: or nil depending upon whether the privilege is already enabled.") ! 562: (priv, value, getprv) ! 563: Lisp_Object priv, value, getprv; ! 564: { ! 565: int prvmask[2], prvlen, newmask[2]; ! 566: char * prvname; ! 567: int found, i; ! 568: struct privilege_list * ptr; ! 569: ! 570: CHECK_STRING (priv, 0); ! 571: priv = Fupcase (priv); ! 572: prvname = XSTRING (priv)->data; ! 573: prvlen = XSTRING (priv)->size; ! 574: found = 0; ! 575: prvmask[0] = 0; ! 576: prvmask[1] = 0; ! 577: for (i = 0; i < sizeof (priv_list) / sizeof (priv_list[0]); i++) ! 578: { ! 579: ptr = &priv_list[i]; ! 580: if (prvlen == strlen (ptr->name) && ! 581: bcmp (prvname, ptr->name, prvlen) == 0) ! 582: { ! 583: if (ptr->mask >= 32) ! 584: prvmask[1] = 1 << (ptr->mask % 32); ! 585: else ! 586: prvmask[0] = 1 << ptr->mask; ! 587: found = 1; ! 588: break; ! 589: } ! 590: } ! 591: if (! found) ! 592: error ("Unknown privilege name %s", XSTRING (priv)->data); ! 593: if (NULL (getprv)) ! 594: { ! 595: if (sys$setprv (NULL (value) ? 0 : 1, prvmask, 0, 0) == SS$_NORMAL) ! 596: return Qt; ! 597: return Qnil; ! 598: } ! 599: /* Get old priv value */ ! 600: if (sys$setprv (0, 0, 0, newmask) != SS$_NORMAL) ! 601: return Qnil; ! 602: if ((newmask[0] & prvmask[0]) ! 603: || (newmask[1] & prvmask[1])) ! 604: return Qt; ! 605: return Qnil; ! 606: } ! 607: ! 608: /* Retrieves VMS system information. */ ! 609: ! 610: #ifdef VMS4_4 /* I don't know whether these functions work in old versions */ ! 611: ! 612: DEFUN ("vms-system-info", Fvms_system_info, Svms_system_info, 1, 3, 0, ! 613: "Retrieve VMS process and system information.\n\ ! 614: The first argument (a string) specifies the type of information desired.\n\ ! 615: The other arguments depend on the type you select.\n\ ! 616: For information about a process, the second argument is a process ID\n\ ! 617: or a process name, with the current process as a default.\n\ ! 618: These are the possibilities for the first arg (upper or lower case ok):\n\ ! 619: account Returns account name\n\ ! 620: cliname Returns CLI name\n\ ! 621: owner Returns owner process's PID\n\ ! 622: grp Returns group number\n\ ! 623: parent Returns parent process's PID\n\ ! 624: pid Returns process's PID\n\ ! 625: prcnam Returns process's name\n\ ! 626: terminal Returns terminal name\n\ ! 627: uic Returns UIC number\n\ ! 628: uicgrp Returns formatted [UIC,GRP]\n\ ! 629: username Returns username\n\ ! 630: version Returns VMS version\n\ ! 631: logical Translates VMS logical name (second argument)\n\ ! 632: dcl-symbol Translates DCL symbol (second argument)\n\ ! 633: proclist Returns list of all PIDs on system (needs WORLD privilege)." ) ! 634: (type, arg1, arg2) ! 635: Lisp_Object type, arg1, arg2; ! 636: { ! 637: int i, typelen; ! 638: char * typename; ! 639: struct vms_objlist * ptr; ! 640: ! 641: CHECK_STRING (type, 0); ! 642: type = Fupcase (type); ! 643: typename = XSTRING (type)->data; ! 644: typelen = XSTRING (type)->size; ! 645: for (i = 0; i < sizeof (vms_object) / sizeof (vms_object[0]); i++) ! 646: { ! 647: ptr = &vms_object[i]; ! 648: if (typelen == strlen (ptr->name) ! 649: && bcmp (typename, ptr->name, typelen) == 0) ! 650: return (* ptr->objfn)(arg1, arg2); ! 651: } ! 652: error ("Unknown object type %s", typename); ! 653: } ! 654: ! 655: /* Given a reference to a VMS process, returns its process id. */ ! 656: ! 657: static int ! 658: translate_id (pid, owner) ! 659: Lisp_Object pid; ! 660: int owner; /* if pid is null/0, return owner. If this ! 661: * flag is 0, return self. */ ! 662: { ! 663: int status, code, id, i, numeric, size; ! 664: char * p; ! 665: int prcnam[2]; ! 666: ! 667: if (NULL (pid) ! 668: || XTYPE (pid) == Lisp_String && XSTRING (pid)->size == 0 ! 669: || XTYPE (pid) == Lisp_Int && XFASTINT (pid) == 0) ! 670: { ! 671: code = owner ? JPI$_OWNER : JPI$_PID; ! 672: status = lib$getjpi (&code, 0, 0, &id); ! 673: if (! (status & 1)) ! 674: error ("Cannot find %s: %s", ! 675: owner ? "owner process" : "process id", ! 676: vmserrstr (status)); ! 677: return (id); ! 678: } ! 679: if (XTYPE (pid) == Lisp_Int) ! 680: return (XFASTINT (pid)); ! 681: CHECK_STRING (pid, 0); ! 682: pid = Fupcase (pid); ! 683: size = XSTRING (pid)->size; ! 684: p = XSTRING (pid)->data; ! 685: numeric = 1; ! 686: id = 0; ! 687: for (i = 0; i < size; i++, p++) ! 688: if (isxdigit (*p)) ! 689: { ! 690: id *= 16; ! 691: if (*p >= '0' && *p <= '9') ! 692: id += *p - '0'; ! 693: else ! 694: id += *p - 'A' + 10; ! 695: } ! 696: else ! 697: { ! 698: numeric = 0; ! 699: break; ! 700: } ! 701: if (numeric) ! 702: return (id); ! 703: prcnam[0] = XSTRING (pid)->size; ! 704: prcnam[1] = XSTRING (pid)->data; ! 705: status = lib$getjpi (&JPI$_PID, 0, prcnam, &id); ! 706: if (! (status & 1)) ! 707: error ("Cannot find process id: %s", ! 708: vmserrstr (status)); ! 709: return (id); ! 710: } /* translate_id */ ! 711: ! 712: /* VMS object retrieval functions. */ ! 713: ! 714: static Lisp_Object ! 715: getjpi (jpicode, arg, numeric) ! 716: int jpicode; /* Type of GETJPI information */ ! 717: Lisp_Object arg; ! 718: int numeric; /* 1 if numeric value expected */ ! 719: { ! 720: int id, status, numval; ! 721: char str[128]; ! 722: int strdsc[2] = { sizeof (str), str }; ! 723: short strlen; ! 724: ! 725: id = translate_id (arg, 0); ! 726: status = lib$getjpi (&jpicode, &id, 0, &numval, strdsc, &strlen); ! 727: if (! (status & 1)) ! 728: error ("Unable to retrieve information: %s", ! 729: vmserrstr (status)); ! 730: if (numeric) ! 731: return (make_number (numval)); ! 732: return (make_string (str, strlen)); ! 733: } ! 734: ! 735: static Lisp_Object ! 736: vms_account (arg1, arg2) ! 737: Lisp_Object arg1, arg2; ! 738: { ! 739: return getjpi (JPI$_ACCOUNT, arg1, 0); ! 740: } ! 741: ! 742: static Lisp_Object ! 743: vms_cliname (arg1, arg2) ! 744: Lisp_Object arg1, arg2; ! 745: { ! 746: return getjpi (JPI$_CLINAME, arg1, 0); ! 747: } ! 748: ! 749: static Lisp_Object ! 750: vms_grp (arg1, arg2) ! 751: Lisp_Object arg1, arg2; ! 752: { ! 753: return getjpi (JPI$_GRP, arg1, 1); ! 754: } ! 755: ! 756: static Lisp_Object ! 757: vms_image (arg1, arg2) ! 758: Lisp_Object arg1, arg2; ! 759: { ! 760: return getjpi (JPI$_IMAGNAME, arg1, 0); ! 761: } ! 762: ! 763: static Lisp_Object ! 764: vms_owner (arg1, arg2) ! 765: Lisp_Object arg1, arg2; ! 766: { ! 767: return getjpi (JPI$_OWNER, arg1, 1); ! 768: } ! 769: ! 770: static Lisp_Object ! 771: vms_parent (arg1, arg2) ! 772: Lisp_Object arg1, arg2; ! 773: { ! 774: return getjpi (JPI$_MASTER_PID, arg1, 1); ! 775: } ! 776: ! 777: static Lisp_Object ! 778: vms_pid (arg1, arg2) ! 779: Lisp_Object arg1, arg2; ! 780: { ! 781: return getjpi (JPI$_PID, arg1, 1); ! 782: } ! 783: ! 784: static Lisp_Object ! 785: vms_prcnam (arg1, arg2) ! 786: Lisp_Object arg1, arg2; ! 787: { ! 788: return getjpi (JPI$_PRCNAM, arg1, 0); ! 789: } ! 790: ! 791: static Lisp_Object ! 792: vms_terminal (arg1, arg2) ! 793: Lisp_Object arg1, arg2; ! 794: { ! 795: return getjpi (JPI$_TERMINAL, arg1, 0); ! 796: } ! 797: ! 798: static Lisp_Object ! 799: vms_uic_int (arg1, arg2) ! 800: Lisp_Object arg1, arg2; ! 801: { ! 802: return getjpi (JPI$_UIC, arg1, 1); ! 803: } ! 804: ! 805: static Lisp_Object ! 806: vms_uic_str (arg1, arg2) ! 807: Lisp_Object arg1, arg2; ! 808: { ! 809: return getjpi (JPI$_UIC, arg1, 0); ! 810: } ! 811: ! 812: static Lisp_Object ! 813: vms_username (arg1, arg2) ! 814: Lisp_Object arg1, arg2; ! 815: { ! 816: return getjpi (JPI$_USERNAME, arg1, 0); ! 817: } ! 818: ! 819: static Lisp_Object ! 820: vms_version_fn (arg1, arg2) ! 821: Lisp_Object arg1, arg2; ! 822: { ! 823: char str[40]; ! 824: int status; ! 825: int strdsc[2] = { sizeof (str), str }; ! 826: short strlen; ! 827: ! 828: status = lib$getsyi (&SYI$_VERSION, 0, strdsc, &strlen, 0, 0); ! 829: if (! (status & 1)) ! 830: error ("Unable to obtain version: %s", vmserrstr (status)); ! 831: return (make_string (str, strlen)); ! 832: } ! 833: ! 834: static Lisp_Object ! 835: vms_trnlog (arg1, arg2) ! 836: Lisp_Object arg1, arg2; ! 837: { ! 838: char str[100]; ! 839: int status, symdsc[2]; ! 840: int strdsc[2] = { sizeof (str), str }; ! 841: short length, level; ! 842: ! 843: CHECK_STRING (arg1, 0); ! 844: symdsc[0] = XSTRING (arg1)->size; ! 845: symdsc[1] = XSTRING (arg1)->data; ! 846: status = lib$sys_trnlog (symdsc, &length, strdsc); ! 847: if (! (status & 1)) ! 848: error ("Unable to translate logical name: %s", vmserrstr (status)); ! 849: if (status == SS$_NOTRAN) ! 850: return (Qnil); ! 851: return (make_string (str, length)); ! 852: } ! 853: ! 854: static Lisp_Object ! 855: vms_symbol (arg1, arg2) ! 856: Lisp_Object arg1, arg2; ! 857: { ! 858: char str[100]; ! 859: int status, symdsc[2]; ! 860: int strdsc[2] = { sizeof (str), str }; ! 861: short length, level; ! 862: ! 863: CHECK_STRING (arg1, 0); ! 864: symdsc[0] = XSTRING (arg1)->size; ! 865: symdsc[1] = XSTRING (arg1)->data; ! 866: status = lib$get_symbol (symdsc, strdsc, &length, &level); ! 867: if (! (status & 1)) { ! 868: if (status == LIB$_NOSUCHSYM) ! 869: return (Qnil); ! 870: else ! 871: error ("Unable to translate symbol: %s", vmserrstr (status)); ! 872: } ! 873: return (make_string (str, length)); ! 874: } ! 875: ! 876: static Lisp_Object ! 877: vms_proclist (arg1, arg2) ! 878: Lisp_Object arg1, arg2; ! 879: { ! 880: Lisp_Object retval; ! 881: int id, status, pid; ! 882: ! 883: retval = Qnil; ! 884: pid = -1; ! 885: for (;;) ! 886: { ! 887: status = lib$getjpi (&JPI$_PID, &pid, 0, &id); ! 888: if (status == SS$_NOMOREPROC) ! 889: break; ! 890: if (! (status & 1)) ! 891: error ("Unable to get process ID: %s", vmserrstr (status)); ! 892: retval = Fcons (make_number (id), retval); ! 893: } ! 894: return (Fsort (retval, intern ("<"))); ! 895: } ! 896: ! 897: DEFUN ("shrink-to-icon", Fshrink_to_icon, Sshrink_to_icon, 0, 0, 0, ! 898: "If emacs is running in a workstation window, shrink to an icon.") ! 899: () ! 900: { ! 901: static char result[128]; ! 902: static $DESCRIPTOR (result_descriptor, result); ! 903: static $DESCRIPTOR (tt_name, "TT:"); ! 904: static int chan = 0; ! 905: static int buf = 0x9d + ('2'<<8) + ('2'<<16) + (0x9c<<24); ! 906: int status; ! 907: static int temp = JPI$_TERMINAL; ! 908: ! 909: status = lib$getjpi (&temp, 0, 0, 0, &result_descriptor, 0); ! 910: if (status != SS$_NORMAL) ! 911: error ("Unable to determine terminal type."); ! 912: if (result[0] != 'W' || result[1] != 'T') /* see if workstation */ ! 913: error ("Can't shrink-to-icon on a non workstation terminal"); ! 914: if (!chan) /* assign channel if not assigned */ ! 915: if ((status = sys$assign (&tt_name, &chan, 0, 0)) != SS$_NORMAL) ! 916: error ("Can't assign terminal, %d", status); ! 917: status = sys$qiow (0, chan, IO$_WRITEVBLK+IO$M_BREAKTHRU, 0, 0, 0, ! 918: &buf, 4, 0, 0, 0, 0); ! 919: if (status != SS$_NORMAL) ! 920: error ("Can't shrink-to-icon, %d", status); ! 921: } ! 922: ! 923: #endif /* VMS4_4 */ ! 924: ! 925: init_vmsfns () ! 926: { ! 927: process_list = 0; ! 928: input_mbx_chan = 0; ! 929: } ! 930: ! 931: syms_of_vmsfns () ! 932: { ! 933: defsubr (&Sdefault_subproc_input_handler); ! 934: defsubr (&Sspawn_subprocess); ! 935: defsubr (&Ssend_command_to_subprocess); ! 936: defsubr (&Sstop_subprocess); ! 937: defsubr (&Ssetprv); ! 938: #ifdef VMS4_4 ! 939: defsubr (&Svms_system_info); ! 940: defsubr (&Sshrink_to_icon); ! 941: #endif /* VMS4_4 */ ! 942: Qdefault_subproc_input_handler = intern ("default-subprocess-input-handler"); ! 943: staticpro (&Qdefault_subproc_input_handler); ! 944: } ! 945: #endif /* VMS */ ! 946:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.