Merge from trunk
[bpt/emacs.git] / src / dosfns.c
CommitLineData
1b94449f
RS
1/* MS-DOS specific Lisp utilities. Coded by Manabu Higashida, 1991.
2 Major changes May-July 1993 Morten Welinder (only 10% original code left)
0b5538bd 3 Copyright (C) 1991, 1993, 1996, 1997, 1998, 2001, 2002, 2003, 2004,
114f9c96 4 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
1b94449f
RS
5
6This file is part of GNU Emacs.
7
9ec0b715 8GNU Emacs is free software: you can redistribute it and/or modify
1b94449f 9it under the terms of the GNU General Public License as published by
9ec0b715
GM
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
1b94449f
RS
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
9ec0b715 19along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
1b94449f 20
48984716 21#include <config.h>
1b94449f
RS
22
23#ifdef MSDOS
24/* The entire file is within this conditional */
25
26#include <stdio.h>
27#include <dos.h>
d7306fe6 28#include <setjmp.h>
1b94449f
RS
29#include "lisp.h"
30#include "buffer.h"
31#include "termchar.h"
1b94449f 32#include "frame.h"
c06981c0 33#include "termhooks.h"
838a94b8
EZ
34#include "blockinput.h"
35#include "window.h"
1b94449f
RS
36#include "dosfns.h"
37#include "msdos.h"
e4441df0 38#include "dispextern.h"
83be827a 39#include "character.h"
76a76a57 40#include "coding.h"
e5c9f94c 41#include "process.h"
838a94b8 42#include <dpmi.h>
5f08dc78 43#include <go32.h>
50666766 44#include <dirent.h>
76a76a57 45#include <sys/vfs.h>
e5c9f94c
EZ
46#include <unistd.h>
47#include <grp.h>
48#include <crt0.h>
1b94449f 49
1b94449f 50DEFUN ("int86", Fint86, Sint86, 2, 2, 0,
8fc29035 51 doc: /* Call specific MS-DOS interrupt number INTERRUPT with REGISTERS.
7363986a
PJ
52Return the updated REGISTER vector.
53
54INTERRUPT should be an integer in the range 0 to 255.
55REGISTERS should be a vector produced by `make-register' and
56`set-register-value'. */)
5842a27b 57 (Lisp_Object interrupt, Lisp_Object registers)
1b94449f
RS
58{
59 register int i;
60 int no;
61 union REGS inregs, outregs;
1b94449f 62
b7826503 63 CHECK_NUMBER (interrupt);
e20104ba 64 no = (unsigned long) XINT (interrupt);
b7826503 65 CHECK_VECTOR (registers);
b058cb36 66 if (no < 0 || no > 0xff || XVECTOR (registers)-> size != 8)
1b94449f
RS
67 return Qnil;
68 for (i = 0; i < 8; i++)
b7826503 69 CHECK_NUMBER (XVECTOR (registers)->contents[i]);
1b94449f 70
e20104ba
EN
71 inregs.x.ax = (unsigned long) XFASTINT (XVECTOR (registers)->contents[0]);
72 inregs.x.bx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[1]);
73 inregs.x.cx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[2]);
74 inregs.x.dx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[3]);
75 inregs.x.si = (unsigned long) XFASTINT (XVECTOR (registers)->contents[4]);
76 inregs.x.di = (unsigned long) XFASTINT (XVECTOR (registers)->contents[5]);
77 inregs.x.cflag = (unsigned long) XFASTINT (XVECTOR (registers)->contents[6]);
78 inregs.x.flags = (unsigned long) XFASTINT (XVECTOR (registers)->contents[7]);
1b94449f
RS
79
80 int86 (no, &inregs, &outregs);
81
e20104ba
EN
82 XVECTOR (registers)->contents[0] = make_number (outregs.x.ax);
83 XVECTOR (registers)->contents[1] = make_number (outregs.x.bx);
84 XVECTOR (registers)->contents[2] = make_number (outregs.x.cx);
85 XVECTOR (registers)->contents[3] = make_number (outregs.x.dx);
86 XVECTOR (registers)->contents[4] = make_number (outregs.x.si);
87 XVECTOR (registers)->contents[5] = make_number (outregs.x.di);
88 XVECTOR (registers)->contents[6] = make_number (outregs.x.cflag);
89 XVECTOR (registers)->contents[7] = make_number (outregs.x.flags);
1b94449f 90
e20104ba 91 return registers;
1b94449f
RS
92}
93
5f08dc78 94DEFUN ("msdos-memget", Fdos_memget, Sdos_memget, 2, 2, 0,
7363986a
PJ
95 doc: /* Read DOS memory at offset ADDRESS into VECTOR.
96Return the updated VECTOR. */)
5842a27b 97 (Lisp_Object address, Lisp_Object vector)
5f08dc78
KS
98{
99 register int i;
100 int offs, len;
101 char *buf;
5f08dc78 102
b7826503 103 CHECK_NUMBER (address);
e20104ba 104 offs = (unsigned long) XINT (address);
b7826503 105 CHECK_VECTOR (vector);
e20104ba 106 len = XVECTOR (vector)-> size;
238a44a8 107 if (len < 1 || len > 2048 || offs < 0 || offs > 0xfffff - len)
5f08dc78
KS
108 return Qnil;
109 buf = alloca (len);
110 dosmemget (offs, len, buf);
b058cb36 111
5f08dc78 112 for (i = 0; i < len; i++)
e20104ba 113 XVECTOR (vector)->contents[i] = make_number (buf[i]);
5f08dc78 114
e20104ba 115 return vector;
5f08dc78
KS
116}
117
118DEFUN ("msdos-memput", Fdos_memput, Sdos_memput, 2, 2, 0,
7363986a 119 doc: /* Write DOS memory at offset ADDRESS from VECTOR. */)
5842a27b 120 (Lisp_Object address, Lisp_Object vector)
5f08dc78
KS
121{
122 register int i;
123 int offs, len;
124 char *buf;
5f08dc78 125
b7826503 126 CHECK_NUMBER (address);
e20104ba 127 offs = (unsigned long) XINT (address);
b7826503 128 CHECK_VECTOR (vector);
e20104ba 129 len = XVECTOR (vector)-> size;
238a44a8 130 if (len < 1 || len > 2048 || offs < 0 || offs > 0xfffff - len)
5f08dc78
KS
131 return Qnil;
132 buf = alloca (len);
133
134 for (i = 0; i < len; i++)
135 {
b7826503 136 CHECK_NUMBER (XVECTOR (vector)->contents[i]);
e20104ba 137 buf[i] = (unsigned char) XFASTINT (XVECTOR (vector)->contents[i]) & 0xFF;
5f08dc78
KS
138 }
139
140 dosmemput (buf, len, offs);
141 return Qt;
142}
143
144DEFUN ("msdos-set-keyboard", Fmsdos_set_keyboard, Smsdos_set_keyboard, 1, 2, 0,
7363986a
PJ
145 doc: /* Set keyboard layout according to COUNTRY-CODE.
146If the optional argument ALLKEYS is non-nil, the keyboard is mapped for
147all keys; otherwise it is only used when the ALT key is pressed.
148The current keyboard layout is available in dos-keyboard-code. */)
5842a27b 149 (Lisp_Object country_code, Lisp_Object allkeys)
5f08dc78 150{
b7826503 151 CHECK_NUMBER (country_code);
5f08dc78
KS
152 if (!dos_set_keyboard (XINT (country_code), !NILP (allkeys)))
153 return Qnil;
154 return Qt;
155}
156
87485d6f
MW
157#ifndef HAVE_X_WINDOWS
158/* Later we might want to control the mouse interface with this function,
159 e.g., with respect to non-80 column screen modes. */
160
7363986a
PJ
161DEFUN ("msdos-mouse-p", Fmsdos_mouse_p, Smsdos_mouse_p, 0, 0, 0,
162 doc: /* Report whether a mouse is present. */)
5842a27b 163 (void)
87485d6f
MW
164{
165 if (have_mouse)
166 return Qt;
167 else
168 return Qnil;
169}
87485d6f
MW
170#endif
171
ac3b0279 172DEFUN ("msdos-mouse-init", Fmsdos_mouse_init, Smsdos_mouse_init, 0, 0, "",
7363986a 173 doc: /* Initialize and enable mouse if available. */)
5842a27b 174 (void)
ac3b0279 175{
5f08dc78
KS
176 if (have_mouse)
177 {
178 have_mouse = 1;
179 mouse_init ();
180 return Qt;
181 }
ac3b0279
RS
182 return Qnil;
183}
184
185DEFUN ("msdos-mouse-enable", Fmsdos_mouse_enable, Smsdos_mouse_enable, 0, 0, "",
7363986a 186 doc: /* Enable mouse if available. */)
5842a27b 187 (void)
ac3b0279
RS
188{
189 if (have_mouse)
190 {
5f08dc78
KS
191 have_mouse = 1;
192 mouse_on ();
ac3b0279
RS
193 }
194 return have_mouse ? Qt : Qnil;
195}
196
197DEFUN ("msdos-mouse-disable", Fmsdos_mouse_disable, Smsdos_mouse_disable, 0, 0, "",
7363986a 198 doc: /* Disable mouse if available. */)
5842a27b 199 (void)
ac3b0279
RS
200{
201 mouse_off ();
202 if (have_mouse) have_mouse = -1;
203 return Qnil;
204}
205
7363986a 206DEFUN ("insert-startup-screen", Finsert_startup_screen, Sinsert_startup_screen, 0, 0, "",
cd53fb50 207 doc: /* Insert copy of screen contents prior to starting Emacs.
7363986a 208Return nil if startup screen is not available. */)
5842a27b 209 (void)
5f08dc78
KS
210{
211 char *s;
b058cb36
EZ
212 int rows, cols, i, j;
213
5f08dc78
KS
214 if (!dos_get_saved_screen (&s, &rows, &cols))
215 return Qnil;
b058cb36 216
5f08dc78
KS
217 for (i = 0; i < rows; i++)
218 {
219 for (j = 0; j < cols; j++)
220 {
65788bc2 221 insert_char (*s);
5f08dc78
KS
222 s += 2;
223 }
65788bc2 224 insert_char ('\n');
5f08dc78
KS
225 }
226
227 return Qt;
228}
87485d6f 229\f
5f08dc78 230/* country info */
31ade731
SM
231EMACS_INT dos_country_code;
232EMACS_INT dos_codepage;
233EMACS_INT dos_timezone_offset;
234EMACS_INT dos_decimal_point;
235EMACS_INT dos_keyboard_layout;
5f08dc78 236unsigned char dos_country_info[DOS_COUNTRY_INFO];
e089dc62
RS
237static unsigned char usa_country_info[DOS_COUNTRY_INFO] = {
238 0, 0, /* date format */
239 '$', 0, 0, 0, 0, /* currency string */
240 ',', 0, /* thousands separator */
241 '.', 0, /* decimal separator */
242 '/', 0, /* date separator */
243 ':', 0, /* time separator */
244 0, /* currency format */
245 2, /* digits after decimal in currency */
246 0, /* time format */
247 0, 0, 0, 0, /* address of case map routine, GPF if used */
248 ' ', 0, /* data-list separator (?) */
249 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* reserved */
250};
5f08dc78 251
31ade731
SM
252EMACS_INT dos_hyper_key;
253EMACS_INT dos_super_key;
254EMACS_INT dos_keypad_mode;
1b94449f 255
5f08dc78
KS
256Lisp_Object Vdos_version;
257Lisp_Object Vdos_display_scancodes;
838a94b8
EZ
258
259#ifndef HAVE_X_WINDOWS
260static unsigned dos_windows_version;
261Lisp_Object Vdos_windows_version;
262
263char parent_vm_title[50]; /* Ralf Brown says 30 is enough */
264int w95_set_virtual_machine_title (const char *);
265
266void
267restore_parent_vm_title (void)
268{
269 if (NILP (Vdos_windows_version))
270 return;
271 if ((dos_windows_version & 0xff) >= 4 && parent_vm_title[0])
272 w95_set_virtual_machine_title (parent_vm_title);
273 delay (50);
274}
275#endif /* !HAVE_X_WINDOWS */
b058cb36 276
1b94449f 277void
3a8ce822 278init_dosfns (void)
1b94449f
RS
279{
280 union REGS regs;
1b94449f 281 _go32_dpmi_registers dpmiregs;
e089dc62 282 unsigned long xbuf = _go32_info_block.linear_address_of_transfer_buffer;
1b94449f 283
87485d6f 284#ifndef SYSTEM_MALLOC
891ef8f7
EZ
285 extern void get_lim_data (void);
286
1b94449f 287 get_lim_data (); /* why the hell isn't this called elsewhere? */
87485d6f 288#endif
1b94449f
RS
289
290 regs.x.ax = 0x3000;
291 intdos (&regs, &regs);
292 Vdos_version = Fcons (make_number (regs.h.al), make_number (regs.h.ah));
293
e089dc62
RS
294 /* Obtain the country code via DPMI, use DJGPP transfer buffer. */
295 dpmiregs.x.ax = 0x3800;
7a2fd369 296 dpmiregs.x.ds = xbuf >> 4;
e089dc62
RS
297 dpmiregs.x.dx = 0;
298 dpmiregs.x.ss = dpmiregs.x.sp = dpmiregs.x.flags = 0;
299 _go32_dpmi_simulate_int (0x21, &dpmiregs);
300 if (dpmiregs.x.flags & 1)
301 {
302 dos_country_code = 1; /* assume USA if 213800 failed */
303 memcpy (dos_country_info, usa_country_info, DOS_COUNTRY_INFO);
304 }
1b94449f
RS
305 else
306 {
1b94449f 307 dos_country_code = dpmiregs.x.bx;
e089dc62 308 dosmemget (xbuf, DOS_COUNTRY_INFO, dos_country_info);
1b94449f 309 }
e089dc62 310
5f08dc78 311 dos_set_keyboard (dos_country_code, 0);
1b94449f
RS
312
313 regs.x.ax = 0x6601;
314 intdos (&regs, &regs);
315 if (regs.x.cflag)
316 /* Estimate code page from country code */
b058cb36 317 switch (dos_country_code)
1b94449f
RS
318 {
319 case 45: /* Denmark */
320 case 47: /* Norway */
321 dos_codepage = 865;
322 break;
323 default:
324 /* US */
325 dos_codepage = 437;
326 }
327 else
328 dos_codepage = regs.x.bx & 0xffff;
50666766 329
838a94b8
EZ
330#ifndef HAVE_X_WINDOWS
331 parent_vm_title[0] = '\0';
332
333 /* If we are running from DOS box on MS-Windows, get Windows version. */
334 dpmiregs.x.ax = 0x1600; /* enhanced mode installation check */
335 dpmiregs.x.ss = dpmiregs.x.sp = dpmiregs.x.flags = 0;
336 _go32_dpmi_simulate_int (0x2f, &dpmiregs);
337 /* We only support Windows-specific features when we run on Windows 9X
338 or on Windows 3.X/enhanced mode.
339
340 Int 2Fh/AX=1600h returns:
341
342 AL = 00: no Windows at all;
343 AL = 01: Windows/386 2.x;
344 AL = 80h: Windows 3.x in mode other than enhanced;
345 AL = FFh: Windows/386 2.x
346
347 We also check AH > 0 (Windows 3.1 or later), in case AL tricks us. */
348 if (dpmiregs.h.al > 2 && dpmiregs.h.al != 0x80 && dpmiregs.h.al != 0xff
349 && (dpmiregs.h.al > 3 || dpmiregs.h.ah > 0))
350 {
351 dos_windows_version = dpmiregs.x.ax;
352 Vdos_windows_version =
353 Fcons (make_number (dpmiregs.h.al), make_number (dpmiregs.h.ah));
354
355 /* Save the current title of this virtual machine, so we can restore
356 it before exiting. Otherwise, Windows 95 will continue to use
357 the title we set even after we are history, stupido... */
358 if (dpmiregs.h.al >= 4)
359 {
360 dpmiregs.x.ax = 0x168e;
361 dpmiregs.x.dx = 3; /* get VM title */
362 dpmiregs.x.cx = sizeof(parent_vm_title) - 1;
363 dpmiregs.x.es = __tb >> 4;
364 dpmiregs.x.di = __tb & 15;
365 dpmiregs.x.sp = dpmiregs.x.ss = dpmiregs.x.flags = 0;
366 _go32_dpmi_simulate_int (0x2f, &dpmiregs);
367 if (dpmiregs.x.ax == 1)
368 dosmemget (__tb, sizeof(parent_vm_title), parent_vm_title);
369 }
370 }
371 else
372 {
373 dos_windows_version = 0;
374 Vdos_windows_version = Qnil;
375 }
376#endif /* !HAVE_X_WINDOWS */
377
459f4042
RS
378 /* Without this, we never see hidden files.
379 Don't OR it with the previous value, so the value recorded at dump
380 time, possibly with `preserve-case' flags set, won't get through. */
381 __opendir_flags = __OPENDIR_FIND_HIDDEN;
382
383#if __DJGPP_MINOR__ == 0
384 /* Under LFN, preserve the case of files as recorded in the directory
385 (in DJGPP 2.01 and later this is automagically done by the library). */
50666766
RS
386 if (!NILP (Fmsdos_long_file_names ()))
387 __opendir_flags |= __OPENDIR_PRESERVE_CASE;
459f4042 388#endif /* __DJGPP_MINOR__ == 0 */
1b94449f
RS
389}
390\f
838a94b8 391#ifndef HAVE_X_WINDOWS
e4441df0
EZ
392
393/* Emulation of some X window features from xfns.c and xfaces.c. */
394
395/* Standard VGA colors, in the order of their standard numbering
396 in the default VGA palette. */
397static char *vga_colors[16] = {
398 "black", "blue", "green", "cyan", "red", "magenta", "brown",
399 "lightgray", "darkgray", "lightblue", "lightgreen", "lightcyan",
400 "lightred", "lightmagenta", "yellow", "white"
401};
402
403/* Given a color name, return its index, or -1 if not found. Note
404 that this only performs case-insensitive comparison against the
405 standard names. For anything more sophisticated, like matching
406 "gray" with "grey" or translating X color names into their MSDOS
2d764c78
EZ
407 equivalents, call the Lisp function Qtty_color_desc (defined
408 on lisp/term/tty-colors.el). */
e4441df0
EZ
409int
410msdos_stdcolor_idx (const char *name)
411{
412 int i;
413
414 for (i = 0; i < sizeof (vga_colors) / sizeof (vga_colors[0]); i++)
05131107 415 if (xstrcasecmp (name, vga_colors[i]) == 0)
e4441df0
EZ
416 return i;
417
f9d2fdc4 418 return
24480d5b
EZ
419 strcmp (name, unspecified_fg) == 0 ? FACE_TTY_DEFAULT_FG_COLOR
420 : strcmp (name, unspecified_bg) == 0 ? FACE_TTY_DEFAULT_BG_COLOR
f9d2fdc4 421 : FACE_TTY_DEFAULT_COLOR;
e4441df0
EZ
422}
423
424/* Given a color index, return its standard name. */
2d764c78 425Lisp_Object
e4441df0
EZ
426msdos_stdcolor_name (int idx)
427{
24480d5b
EZ
428 extern Lisp_Object Qunspecified;
429
430 if (idx == FACE_TTY_DEFAULT_FG_COLOR)
431 return build_string (unspecified_fg);
432 else if (idx == FACE_TTY_DEFAULT_BG_COLOR)
433 return build_string (unspecified_bg);
434 else if (idx >= 0 && idx < sizeof (vga_colors) / sizeof (vga_colors[0]))
435 return build_string (vga_colors[idx]);
436 else
437 return Qunspecified; /* meaning the default */
e4441df0
EZ
438}
439
838a94b8
EZ
440/* Support for features that are available when we run in a DOS box
441 on MS-Windows. */
442int
443ms_windows_version (void)
444{
445 return dos_windows_version;
446}
447
448/* Set the title of the current virtual machine, to appear on
449 the caption bar of that machine's window. */
450
451int
452w95_set_virtual_machine_title (const char *title_string)
453{
454 /* Only Windows 9X (version 4 and higher) support this function. */
455 if (!NILP (Vdos_windows_version)
456 && (dos_windows_version & 0xff) >= 4)
457 {
458 _go32_dpmi_registers regs;
459 dosmemput (title_string, strlen (title_string) + 1, __tb);
460 regs.x.ax = 0x168e;
461 regs.x.dx = 1;
462 regs.x.es = __tb >> 4;
463 regs.x.di = __tb & 15;
464 regs.x.sp = regs.x.ss = regs.x.flags = 0;
465 _go32_dpmi_simulate_int (0x2f, &regs);
466 return regs.x.ax == 1;
467 }
468 return 0;
469}
470
471/* Change the title of frame F to NAME.
472 If NAME is nil, use the frame name as the title.
473
474 If Emacs is not run from a DOS box on Windows 9X, this only
475 sets the name in the frame struct, but has no other effects. */
476
477void
3a8ce822 478x_set_title (struct frame *f, Lisp_Object name)
838a94b8
EZ
479{
480 /* Don't change the title if it's already NAME. */
481 if (EQ (name, f->title))
482 return;
483
484 update_mode_lines = 1;
485
486 f->title = name;
487
488 if (NILP (name))
489 name = f->name;
490
491 if (FRAME_MSDOS_P (f))
492 {
493 BLOCK_INPUT;
d5db4077 494 w95_set_virtual_machine_title (SDATA (name));
838a94b8
EZ
495 UNBLOCK_INPUT;
496 }
497}
498#endif /* !HAVE_X_WINDOWS */
499\f
76a76a57 500DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
7363986a
PJ
501 doc: /* Return storage information about the file system FILENAME is on.
502Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total
503storage of the file system, FREE is the free storage, and AVAIL is the
504storage available to a non-superuser. All 3 numbers are in bytes.
505If the underlying system call fails, value is nil. */)
5842a27b 506 (Lisp_Object filename)
76a76a57
EZ
507{
508 struct statfs stfs;
509 Lisp_Object encoded, value;
510
b7826503 511 CHECK_STRING (filename);
76a76a57
EZ
512 filename = Fexpand_file_name (filename, Qnil);
513 encoded = ENCODE_FILE (filename);
514
d5db4077 515 if (statfs (SDATA (encoded), &stfs))
76a76a57
EZ
516 value = Qnil;
517 else
518 value = list3 (make_float ((double) stfs.f_bsize * stfs.f_blocks),
519 make_float ((double) stfs.f_bsize * stfs.f_bfree),
520 make_float ((double) stfs.f_bsize * stfs.f_bavail));
521
522 return value;
523}
524\f
e5c9f94c
EZ
525/* System depended enumeration of and access to system processes a-la
526 ps(1). Here, we only return info about the running Emacs process.
527 (There are no other processes on DOS, right?) */
528
529Lisp_Object
3a8ce822 530list_system_processes (void)
e5c9f94c
EZ
531{
532 Lisp_Object proclist = Qnil;
533
534 proclist = Fcons (make_fixnum_or_float (getpid ()), proclist);
535
536 return proclist;
537}
538
539Lisp_Object
540system_process_attributes (Lisp_Object pid)
541{
542 int proc_id;
543 Lisp_Object attrs = Qnil;
544
545 CHECK_NUMBER_OR_FLOAT (pid);
546 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
547
548 if (proc_id == getpid ())
549 {
550 EMACS_INT uid, gid;
551 char *usr;
552 struct group *gr;
553 char cmd[FILENAME_MAX];
554 char *cmdline = NULL, *p, *q;
555 size_t cmdline_size = 0;
556 int i;
557 Lisp_Object cmd_str, decoded_cmd, tem;
558 double pmem;
891ef8f7 559 EXFUN (Fget_internal_run_time, 0);
693a2698 560#ifndef SYSTEM_MALLOC
e5c9f94c 561 extern unsigned long ret_lim_data ();
693a2698 562#endif
e5c9f94c
EZ
563
564 uid = getuid ();
565 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
566 usr = getlogin ();
567 if (usr)
568 attrs = Fcons (Fcons (Quser, build_string (usr)), attrs);
569 gid = getgid ();
570 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs);
571 gr = getgrgid (gid);
572 if (gr)
573 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
574 strcpy (cmd, basename (__crt0_argv[0]));
575 /* Command name is encoded in locale-coding-system; decode it. */
576 cmd_str = make_unibyte_string (cmd, strlen (cmd));
577 decoded_cmd = code_convert_string_norecord (cmd_str,
578 Vlocale_coding_system, 0);
579 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
580 /* Pretend we have 0 as PPID. */
581 attrs = Fcons (Fcons (Qppid, make_number (0)), attrs);
582 attrs = Fcons (Fcons (Qpgrp, pid), attrs);
583 attrs = Fcons (Fcons (Qttname, build_string ("/dev/tty")), attrs);
584 /* We are never idle! */
585 tem = Fget_internal_run_time ();
586 attrs = Fcons (Fcons (Qtime, tem), attrs);
587 attrs = Fcons (Fcons (Qthcount, make_number (1)), attrs);
588 attrs = Fcons (Fcons (Qstart,
589 Fsymbol_value (intern ("before-init-time"))),
590 attrs);
591 attrs = Fcons (Fcons (Qvsize,
592 make_fixnum_or_float ((unsigned long)sbrk(0)/1024)),
593 attrs);
594 attrs = Fcons (Fcons (Qetime, tem), attrs);
693a2698
EZ
595#ifndef SYSTEM_MALLOC
596 /* ret_lim_data is on vm-limit.c, which is not compiled in under
597 SYSTEM_MALLOC. */
e5c9f94c
EZ
598 pmem = (double)((unsigned long) sbrk (0)) / ret_lim_data () * 100.0;
599 if (pmem > 100)
693a2698 600#endif
e5c9f94c
EZ
601 pmem = 100;
602 attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs);
603 /* Pass 1: Count how much storage we need. */
604 for (i = 0; i < __crt0_argc; i++)
605 {
606 cmdline_size += strlen (__crt0_argv[i]) + 1; /* +1 for blank delim */
607 if (strpbrk (__crt0_argv[i], " \t\n\r\v\f"))
608 {
609 cmdline_size += 2;
610 for (p = __crt0_argv[i]; *p; p++)
611 {
612 if (*p == '"')
613 cmdline_size++;
614 }
615 }
616 }
617 /* Pass 2: Allocate storage and concatenate argv[]. */
618 cmdline = xmalloc (cmdline_size + 1);
619 for (i = 0, q = cmdline; i < __crt0_argc; i++)
620 {
621 if (strpbrk (__crt0_argv[i], " \t\n\r\v\f"))
622 {
623 *q++ = '"';
624 for (p = __crt0_argv[i]; *p; p++)
625 {
626 if (*p == '\"')
627 *q++ = '\\';
628 *q++ = *p;
629 }
630 *q++ = '"';
631 }
632 else
633 {
634 strcpy (q, __crt0_argv[i]);
635 q += strlen (__crt0_argv[i]);
636 }
637 *q++ = ' ';
638 }
639 /* Remove the trailing blank. */
640 if (q > cmdline)
641 q[-1] = '\0';
642
643 /* Command line is encoded in locale-coding-system; decode it. */
644 cmd_str = make_unibyte_string (cmdline, strlen (cmdline));
645 decoded_cmd = code_convert_string_norecord (cmd_str,
646 Vlocale_coding_system, 0);
647 xfree (cmdline);
648 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
649 }
650
651 return attrs;
652}
653\f
838a94b8
EZ
654void
655dos_cleanup (void)
656{
c06981c0
EZ
657 struct tty_display_info *tty;
658
838a94b8
EZ
659#ifndef HAVE_X_WINDOWS
660 restore_parent_vm_title ();
661#endif
6f855d64
EZ
662 /* Make sure the termscript file is committed, in case we are
663 crashing and some vital info was written there. */
c06981c0 664 if (FRAMEP (selected_frame))
6f855d64 665 {
c06981c0
EZ
666 struct frame *sf = XFRAME (selected_frame);
667
668 if (FRAME_LIVE_P (sf)
669 && (FRAME_MSDOS_P (sf) || FRAME_TERMCAP_P (sf)))
670 {
671 tty = CURTTY ();
672 if (tty->termscript)
673 {
674 fflush (tty->termscript);
675 fsync (fileno (tty->termscript));
676 }
677 }
6f855d64 678 }
838a94b8
EZ
679}
680
1b94449f
RS
681/*
682 * Define everything
683 */
3a8ce822
EZ
684void
685syms_of_dosfns (void)
1b94449f 686{
1b94449f 687 defsubr (&Sint86);
5f08dc78
KS
688 defsubr (&Sdos_memget);
689 defsubr (&Sdos_memput);
ac3b0279
RS
690 defsubr (&Smsdos_mouse_init);
691 defsubr (&Smsdos_mouse_enable);
5f08dc78
KS
692 defsubr (&Smsdos_set_keyboard);
693 defsubr (&Sinsert_startup_screen);
ac3b0279 694 defsubr (&Smsdos_mouse_disable);
76a76a57 695 defsubr (&Sfile_system_info);
87485d6f
MW
696#ifndef HAVE_X_WINDOWS
697 defsubr (&Smsdos_mouse_p);
87485d6f 698#endif
1b94449f
RS
699
700 DEFVAR_INT ("dos-country-code", &dos_country_code,
7363986a
PJ
701 doc: /* The country code returned by Dos when Emacs was started.
702Usually this is the international telephone prefix. */);
1b94449f
RS
703
704 DEFVAR_INT ("dos-codepage", &dos_codepage,
7363986a
PJ
705 doc: /* The codepage active when Emacs was started.
706The following are known:
707 437 United States
708 850 Multilingual (Latin I)
709 852 Slavic (Latin II)
710 857 Turkish
711 860 Portugal
712 861 Iceland
713 863 Canada (French)
714 865 Norway/Denmark */);
1b94449f 715
5f08dc78 716 DEFVAR_INT ("dos-timezone-offset", &dos_timezone_offset,
7363986a
PJ
717 doc: /* The current timezone offset to UTC in minutes.
718Implicitly modified when the TZ variable is changed. */);
b058cb36 719
1b94449f 720 DEFVAR_LISP ("dos-version", &Vdos_version,
7363986a 721 doc: /* The (MAJOR . MINOR) Dos version (subject to modification with setver). */);
5f08dc78 722
838a94b8
EZ
723#ifndef HAVE_X_WINDOWS
724 DEFVAR_LISP ("dos-windows-version", &Vdos_windows_version,
7363986a 725 doc: /* The (MAJOR . MINOR) Windows version for DOS session on MS-Windows. */);
838a94b8
EZ
726#endif
727
5f08dc78 728 DEFVAR_LISP ("dos-display-scancodes", &Vdos_display_scancodes,
7363986a
PJ
729 doc: /* *Controls whether DOS raw keyboard events are displayed as you type.
730When non-nil, the keyboard scan-codes are displayed at the bottom right
731corner of the display (typically at the end of the mode line).
732The output format is: scan code:char code*modifiers. */);
733
5f08dc78 734 Vdos_display_scancodes = Qnil;
b058cb36 735
5f08dc78 736 DEFVAR_INT ("dos-hyper-key", &dos_hyper_key,
7363986a
PJ
737 doc: /* *If set to 1, use right ALT key as hyper key.
738If set to 2, use right CTRL key as hyper key. */);
5f08dc78 739 dos_hyper_key = 0;
b058cb36 740
5f08dc78 741 DEFVAR_INT ("dos-super-key", &dos_super_key,
7363986a
PJ
742 doc: /* *If set to 1, use right ALT key as super key.
743If set to 2, use right CTRL key as super key. */);
5f08dc78 744 dos_super_key = 0;
b058cb36 745
5f08dc78 746 DEFVAR_INT ("dos-keypad-mode", &dos_keypad_mode,
7363986a
PJ
747 doc: /* *Controls what key code is returned by a key in the numeric keypad.
748The `numlock ON' action is only taken if no modifier keys are pressed.
749The value is an integer constructed by adding the following bits together:
750
751 0x00 Digit key returns digit (if numlock ON)
752 0x01 Digit key returns kp-digit (if numlock ON)
753 0x02 Digit key returns M-digit (if numlock ON)
754 0x03 Digit key returns edit key (if numlock ON)
755
756 0x00 Grey key returns char (if numlock ON)
757 0x04 Grey key returns kp-key (if numlock ON)
758
759 0x00 Digit key returns digit (if numlock OFF)
760 0x10 Digit key returns kp-digit (if numlock OFF)
761 0x20 Digit key returns M-digit (if numlock OFF)
762 0x30 Digit key returns edit key (if numlock OFF)
763
764 0x00 Grey key returns char (if numlock OFF)
765 0x40 Grey key returns kp-key (if numlock OFF)
766
767 0x200 ALT-0..ALT-9 in top-row produces shifted codes. */);
b3d5621c 768 dos_keypad_mode = 0x75;
b058cb36 769
5f08dc78 770 DEFVAR_INT ("dos-keyboard-layout", &dos_keyboard_layout,
7363986a
PJ
771 doc: /* Contains the country code for the current keyboard layout.
772Use msdos-set-keyboard to select another keyboard layout. */);
5f08dc78 773 dos_keyboard_layout = 1; /* US */
b058cb36 774
5f08dc78 775 DEFVAR_INT ("dos-decimal-point", &dos_decimal_point,
7363986a
PJ
776 doc: /* The character to produce when kp-decimal key is pressed.
777If non-zero, this variable contains the character to be returned when the
778decimal point key in the numeric keypad is pressed when Num Lock is on.
779If zero, the decimal point key returns the country code specific value. */);
5f08dc78 780 dos_decimal_point = 0;
1b94449f
RS
781}
782#endif /* MSDOS */
6b61353c
KH
783
784/* arch-tag: f5ea8847-a014-42c9-83f5-7738ad640b17
785 (do not change this comment) */