* POTFILES.in: add gnome/gcustom-layout.c file
[midnight-commander.git] / os2 / util.os2.c
blob48fb057eabfb9aef17313609b62294f36fb43e87
1 /* Various utilities - OS/2 versions
2 Copyright (C) 1994, 1995, 1996 the Free Software Foundation.
4 Written 1994, 1995, 1996 by:
5 Juan Grigera, Miguel de Icaza, Janne Kukonlehto, Dugan Porter,
6 Jakub Jelinek, Mauricio Plaza.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22 #define INCL_DOS
23 #define INCL_PM
24 #define INCL_DOSPROCESS
25 #define INCL_DOSFILEMGR
26 #define INCL_DOSDEVICES /* Device values */
27 #define INCL_DOSDATETIME
28 #define INCL_DOSERRORS
29 #include "config.h"
30 #include <os2.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <config.h>
36 #include <ctype.h>
37 #include <sys/stat.h>
38 #include <errno.h>
39 #include <io.h>
40 #include <fcntl.h>
41 #include <signal.h> /* my_system */
42 #include <limits.h> /* INT_MAX */
43 #include <sys/time.h> /* select: timeout */
44 #include <sys/param.h>
45 #include <sys/stat.h>
46 #include <stdarg.h>
47 #include <process.h>
48 #include <fs.h>
49 #include <util.h>
51 #ifdef __BORLANDC__
52 #define ENOTEMPTY ERROR_DIR_NOT_EMPTY
53 #endif
55 char *
56 get_owner (int uid)
58 return "none";
61 char *
62 get_group (int gid)
64 return "none";
67 /* Pipes are guaranteed to be able to hold at least 4096 bytes */
68 /* More than that would be unportable */
69 #define MAX_PIPE_SIZE 4096
71 static int error_pipe[2]; /* File descriptors of error pipe */
72 static int old_error; /* File descriptor of old standard error */
74 /* Creates a pipe to hold standard error for a later analysis. */
75 /* The pipe can hold 4096 bytes. Make sure no more is written */
76 /* or a deadlock might occur. */
77 void
78 open_error_pipe (void)
80 return;
83 void
84 close_error_pipe (int error, char *text)
86 return;
89 void
90 check_error_pipe (void)
92 char error[MAX_PIPE_SIZE];
93 int len = 0;
94 if (old_error >= 0){
95 while (len < MAX_PIPE_SIZE)
97 int rvalue;
99 rvalue = read (error_pipe[0], error + len, 1);
100 len ++;
101 if (rvalue <= 0)
102 break;
104 error[len] = 0;
105 close (error_pipe[0]);
107 if (len > 0)
108 message (0, " Warning ", error);
112 static int
113 StartWindowsProg (char *name, SHORT type)
115 #if 0 /* FIXME: PM DDL's should be loaded (or not loaded) at run time */
116 PROGDETAILS pDetails;
118 memset(&pDetails, 0, sizeof(PROGDETAILS)) ;
119 pDetails.Length = sizeof(pDetails);
120 pDetails.pszExecutable = name; /* program name */
121 pDetails.pszStartupDir = NULL; /* default directory for new app. */
122 pDetails.pszParameters = NULL; /* command line */
123 pDetails.progt.fbVisible = SHE_VISIBLE ;
124 pDetails.pszEnvironment = NULL;
126 switch (type) {
127 case 0:
128 /* Win Standard */
129 pDetails.progt.progc = PROG_31_ENHSEAMLESSCOMMON ;
130 break;
131 case 1:
132 /* Win 3.1 Protect */
133 pDetails.progt.progc = PROG_31_ENHSEAMLESSCOMMON ;
134 break;
135 case 2:
136 /* Win 3.1 Enh. Protect */
137 pDetails.progt.progc = PROG_31_ENHSEAMLESSCOMMON ;
138 break;
139 default:
140 pDetails.progt.progc = PROG_31_ENHSEAMLESSCOMMON ;
141 break;
143 WinStartApp(NULLHANDLE,
144 &pDetails,
145 NULL,
146 NULL,
147 SAF_INSTALLEDCMDLINE|SAF_STARTCHILDAPP) ;
148 #endif
149 return 0;
153 static int
154 os2_system (int as_shell_command, const char *shell, const char *command, char *parm);
157 as_shell_command = 1: If a program is started during input line, CTRL-O
158 or RETURN
159 = 0: F3, F4
161 int
162 my_system (int as_shell_command, const char *shell, const char *command)
164 char *sh; /* This is the shell -- always! */
165 char *cmd; /* This is the command (only the command) */
166 char *parm; /* This is the parameter (can be more than one) */
167 register int length, i;
168 char temp[4096]; /* That's enough! */
170 sh = get_default_shell();
171 if (strcmp(sh, shell)) {
173 Not equal -- That means: shell is the program and command is the
174 parameter
176 cmd = (char *) shell;
177 parm = (char *) command;
178 } else {
179 /* look into the command and take out the program */
180 if (command) {
181 strcpy(temp, command);
182 length = strlen(command);
183 for (i=length-1; i>=0; i--) {
184 if (command[i] == ' ') {
185 temp[i] = (char) 0;
186 length--;
187 } else
188 break;
190 if (i==-1) {
191 /* only blanks */
192 return -1;
194 if (parm = strchr(temp, (char) ' ')) {
195 *parm = (char) 0;
196 parm++;
198 cmd = (char *) temp;
199 } else {
200 /* command is NULL */
201 cmd = parm = NULL;
204 /* .ado: Konvertierung wenn shell <> get_default_shell */
205 os2_system (as_shell_command, sh, cmd, parm);
208 static int
209 ux_startp (const char *shell, const char *command, const char *parm)
211 if (parm) {
212 spawnlp (P_WAIT,
213 (char *) shell,
214 (char *) shell,
215 "/c",
216 (char *) command,
217 (char *) parm,
218 (char *) 0);
219 } else {
220 spawnlp (P_WAIT,
221 (char *) shell,
222 (char *) shell,
223 "/c",
224 (char *) command,
225 (char *) 0);
227 return 0;
231 static int
232 os2_system (int as_shell_command, const char *shell, const char *command, char *parm)
234 register int i, j;
235 ULONG AppType = 0; /* Application type flags (returned) */
236 APIRET rc = NO_ERROR; /* Return Code */
237 char pathValue[5] = "PATH"; /* For DosSearchPath */
238 UCHAR searchResult[MC_MAXPATHLEN * 2 + 1]; /* For DosSearchPath */
240 char *cmdString;
241 char *postFix[3];
242 char *line;
243 /* ------------------------------------------------------- */
244 STARTDATA StartData;
245 CHAR ObjBuf[100];
246 ULONG SessionID;
247 PID pid;
249 if (command == NULL) {
250 /* .ado: just start a shell, we don't need the parameter */
251 spawnl (P_WAIT,
252 (char *) shell,
253 (char *) shell,
254 (char *) command, (char *) 0);
255 return 0;
258 memset(&StartData, 0, sizeof(StartData)) ;
259 StartData.Length = sizeof(StartData);
260 StartData.Related = SSF_RELATED_CHILD;
261 StartData.FgBg = SSF_FGBG_BACK;
262 StartData.TraceOpt = SSF_TRACEOPT_NONE;
263 StartData.PgmTitle = NULL;
264 StartData.TermQ = NULL;
265 StartData.InheritOpt = SSF_INHERTOPT_PARENT;
266 StartData.IconFile = 0;
267 StartData.PgmHandle = 0;
268 StartData.PgmControl = SSF_CONTROL_VISIBLE ;
269 StartData.ObjectBuffer = ObjBuf;
270 StartData.ObjectBuffLen = 100;
271 StartData.PgmInputs = parm;
273 postFix[0] = ".exe";
274 postFix[1] = ".cmd";
275 postFix[2] = ".bat";
277 i = strlen(command);
278 if (command[i-1] == ' ') {
279 /* The user has used ALT-RETURN */
280 i--;
282 cmdString = (char *) malloc(i+1);
283 for (j=0; j<i; j++) {
284 cmdString[j] = command[j];
286 cmdString[j] = (char) 0;
288 if ((i < 5) || ((i > 4) && (cmdString[i-4]) != '.')) {
289 /* without Extension */
290 line = (char *) malloc(i+5);
291 rc = 1;
292 for (i=0; (i<3 && rc); i++) {
293 /* Search for the file */
294 strcpy(line, cmdString);
295 strcat(line, postFix[i]);
296 rc = DosSearchPath((SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT | SEARCH_CUR_DIRECTORY),
297 (PSZ) pathValue,
298 line,
299 searchResult,
300 sizeof(searchResult));
302 free (line);
303 } else {
304 /* Just search */
305 rc = DosSearchPath((SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT | SEARCH_CUR_DIRECTORY),
306 (PSZ) pathValue,
307 cmdString,
308 searchResult,
309 sizeof(searchResult));
311 free(cmdString);
312 if (rc != 0) {
313 /* Internal command or the program was written with absolut path */
314 return ux_startp(shell, command, parm);
317 /* Application to be started */
318 StartData.PgmName = searchResult;
319 StartData.Environment = NULL;
320 rc = DosQueryAppType(searchResult, &AppType);
321 if (rc == NO_ERROR) {
322 StartData.SessionType = PROG_WINDOWABLEVIO;
323 if ((AppType & 0x00000007) == FAPPTYP_WINDOWAPI) {
324 /* Window API */
325 StartData.SessionType = PROG_PM;
326 return DosStartSession(&StartData, &SessionID, &pid);
328 if ((AppType & 0x00000007) == FAPPTYP_WINDOWCOMPAT) {
329 /* Window compat */
330 return ux_startp(shell, command, parm);
332 if (AppType & 0x0000ffff & FAPPTYP_DOS) {
333 /* PC/DOS Format */
334 StartData.SessionType = PROG_WINDOWEDVDM;
335 return DosStartSession(&StartData, &SessionID, &pid);
337 if (AppType & 0x0000ffff & FAPPTYP_WINDOWSREAL) {
338 /* Windows real mode app */
339 return StartWindowsProg(searchResult, 0);
341 if (AppType & 0x0000ffff & FAPPTYP_WINDOWSPROT) {
342 /* Windows Protect mode app*/
343 return StartWindowsProg(searchResult, 1);
345 if (AppType & 0x0000ffff & FAPPTYP_WINDOWSPROT31) {
346 /* Windows 3.1 Protect mode app*/
347 return StartWindowsProg(searchResult, 2);
349 rc = DosStartSession(&StartData, &SessionID, &pid) ;
350 } else {
351 /* It's not a known exe type or it's a CMD/BAT file */
352 i = strlen(searchResult);
353 if ((toupper(searchResult[--i]) == 'T') &&
354 (toupper(searchResult[--i]) == 'A') &&
355 (toupper(searchResult[--i]) == 'B') &&
356 (searchResult[--i] == '.') ) {
357 StartData.SessionType = PROG_WINDOWEDVDM;
358 rc = DosStartSession(&StartData, &SessionID, &pid) ;
359 } else {
360 rc = ux_startp (shell, command, parm);
363 return rc;
366 char *tilde_expand (char *directory)
368 return strdup (directory);
372 /* Canonicalize path, and return a new path. Do everything in situ.
373 The new path differs from path in:
374 Multiple BACKSLASHs are collapsed to a single BACKSLASH.
375 Leading `./'s and trailing `/.'s are removed.
376 Trailing BACKSLASHs are removed.
377 Non-leading `../'s and trailing `..'s are handled by removing
378 portions of the path. */
379 char *
380 canonicalize_pathname (char *path)
382 int i, start;
383 char stub_char;
385 stub_char = (*path == PATH_SEP) ? PATH_SEP : '.';
387 /* Walk along path looking for things to compact. */
388 i = 0;
389 for (;;) {
390 if (!path[i])
391 break;
393 while (path[i] && path[i] != PATH_SEP)
394 i++;
396 start = i++;
398 /* If we didn't find any slashes, then there is nothing left to do. */
399 if (!path[start])
400 break;
402 /* Handle multiple BACKSLASHs in a row. */
403 while (path[i] == PATH_SEP)
404 i++;
406 if ((start + 1) != i) {
407 strcpy (path + start + 1, path + i);
408 i = start + 1;
411 /* Handle backquoted BACKSLASH. */
412 /* if (start > 0 && path[start - 1] == '\\')
413 continue; */
415 /* Check for trailing BACKSLASH. */
416 if (start && !path[i]) {
417 zero_last:
418 path[--i] = '\0';
419 break;
422 /* Check for `../', `./' or trailing `.' by itself. */
423 if (path[i] == '.') {
424 /* Handle trailing `.' by itself. */
425 if (!path[i + 1])
426 goto zero_last;
428 /* Handle `./'. */
429 if (path[i + 1] == PATH_SEP) {
430 strcpy (path + i, path + i + 1);
431 i = start;
432 continue;
435 /* Handle `../' or trailing `..' by itself.
436 Remove the previous ?/ part with the exception of
437 ../, which we should leave intact. */
438 if (path[i + 1] == '.' && (path[i + 2] == PATH_SEP || !path[i + 2])) {
439 while (--start > -1 && path[start] != PATH_SEP);
440 if (!strncmp (path + start + 1, "..\\", 3))
441 continue;
442 strcpy (path + start + 1, path + i + 2);
443 i = start;
444 continue;
449 if (!*path) {
450 *path = stub_char;
451 path[1] = '\0';
453 return path;
457 void
458 my_statfs (struct my_statfs *myfs_stats, char *path)
460 PFSALLOCATE pBuf;
461 PFSINFO pFsInfo;
462 ULONG lghBuf;
464 ULONG diskNum = 0;
465 ULONG logical = 0;
467 UCHAR szDeviceName[3] = "A:";
468 ULONG ulOrdinal = 0; /* Ordinal of entry in name list */
469 PBYTE pszFSDName = NULL; /* pointer to FS name */
470 APIRET rc = NO_ERROR; /* Return code */
471 BYTE fsqBuffer[sizeof(FSQBUFFER2) + (3 * CCHMAXPATH)] = {0};
472 ULONG cbBuffer = sizeof(fsqBuffer); /* Buffer length) */
473 PFSQBUFFER2 pfsqBuffer = (PFSQBUFFER2) fsqBuffer;
475 int i, len = 0;
477 /* ------------------------------------------------------------------ */
479 lghBuf = sizeof(FSALLOCATE);
480 pBuf = (PFSALLOCATE) malloc(lghBuf);
482 /* Get the free number of Bytes */
483 rc = DosQueryFSInfo(0L, FSIL_ALLOC, (PVOID) pBuf, lghBuf);
484 /* KBytes available */
485 myfs_stats->avail = pBuf->cSectorUnit * pBuf->cUnitAvail * pBuf->cbSector / 1024;
486 /* KBytes total */
487 myfs_stats->total = pBuf->cSectorUnit * pBuf->cUnit * pBuf->cbSector / 1024;
488 myfs_stats->nfree = pBuf->cUnitAvail;
489 myfs_stats->nodes = pBuf->cbSector;
491 lghBuf = sizeof(FSINFO);
492 pFsInfo = (PFSINFO) malloc(lghBuf);
493 rc = DosQueryFSInfo(0L,
494 FSIL_VOLSER,
495 (PVOID) pFsInfo,
496 lghBuf);
497 /* Get name */
498 myfs_stats->device = strdup(pFsInfo->vol.szVolLabel); /* Label of the Disk */
500 /* Get the current disk for DosQueryFSAttach */
501 rc = DosQueryCurrentDisk(&diskNum, &logical);
503 szDeviceName[0] = (UCHAR) (diskNum + (ULONG) 'A' - 1);
504 /* Now get the type of the disk */
505 rc = DosQueryFSAttach(szDeviceName,
506 0L,
507 FSAIL_QUERYNAME,
508 pfsqBuffer,
509 &cbBuffer);
511 pszFSDName = pfsqBuffer->szName + pfsqBuffer->cbName + 1;
512 myfs_stats->mpoint = strdup(pszFSDName); /* FAT, HPFS ... */
514 myfs_stats->type = pBuf->idFileSystem;
515 /* What is about 3 ?*/
516 if (myfs_stats->type == 0) {
517 myfs_stats->typename = (char *) malloc(11);
518 strcpy(myfs_stats->typename, "Local Disk");
519 } else {
520 myfs_stats->typename = (char *) malloc(13);
521 strcpy(myfs_stats->typename, "Other Device");
524 free(pBuf);
525 free(pFsInfo);
528 int
529 gettimeofday (struct timeval* tvp, void *p)
531 DATETIME pdt = {0};
532 if (p != NULL) /* what is "p"? */
533 return 0;
535 /* Since MC only calls this func from get_random_hint we return
536 * some value, not exactly the "correct" one
538 DosGetDateTime(&pdt);
539 tvp->tv_usec = (pdt.hours * 60 + pdt.minutes) * 60 + pdt.seconds;
540 /* Number of milliseconds since Windows started */
541 tvp->tv_sec = tvp->tv_usec * 1000 + pdt.hundredths * 10;
542 return 0;
545 /* FAKE functions */
547 int
548 look_for_exe(const char* pathname)
550 int j;
551 char *p;
552 int lgh = strlen(pathname);
554 if (lgh < 4) {
555 return 0;
556 } else {
557 p = (char *) pathname;
558 for (j=0; j<lgh-4; j++) {
559 p++;
561 if (!stricmp(p, ".exe") ||
562 !stricmp(p, ".bat") ||
563 !stricmp(p, ".com") ||
564 !stricmp(p, ".cmd")) {
565 return 1;
568 return 0;
571 int
572 lstat (const char* pathname, struct stat *buffer)
574 int rc = stat (pathname, buffer);
575 #ifdef __BORLANDC__
576 if (rc == 0) {
577 if (!(buffer->st_mode & S_IFDIR)) {
578 if (!look_for_exe(pathname)) {
579 buffer->st_mode &= !S_IXUSR & !S_IXGRP & !S_IXOTH;
583 #endif
584 return rc;
587 int
588 getuid ()
590 return 0;
593 int
594 getgid ()
596 return 0;
599 int
600 readlink (char* path, char* buf, int size)
602 return -1;
605 int
606 symlink (char *n1, char *n2)
608 return -1;
611 int
612 link (char *p1, char *p2)
614 return -1;
617 int
618 chown (char *path, int owner, int group)
620 return -1;
623 int
624 mknod (char *path, int mode, int dev)
626 return -1;
629 void
630 init_uid_gid_cache (void)
632 return;
635 int
636 mc_doublepopen (int inhandle, int inlen, pid_t *the_pid, char *command, ...)
638 return 0;
641 int
642 mc_doublepclose (int pipe, pid_t pid)
644 return 0;
647 /*hacks to get it compile, remove these after vfs works */
648 char *
649 vfs_get_current_dir (void)
651 return NULL;
654 int
655 vfs_current_is_extfs (void)
657 return 0;
660 int
661 vfs_file_is_ftp (char *filename)
663 return 0;
667 mc_utime (char *path, void *times)
669 return 0;
673 void
674 extfs_run (char *file)
676 return;
680 geteuid(void)
682 return 0;
687 mc_chdir(char *pathname)
689 APIRET ret;
690 register int lgh = strlen(pathname);
692 /* Set the current drive */
693 if (lgh == 0) {
694 return -1;
695 } else {
696 /* First set the default drive */
697 if (lgh > 1) {
698 if (pathname[1] == ':') {
699 ret = DosSetDefaultDisk(toupper(pathname[0]) - 'A' + 1);
702 /* After that, set the current dir! */
703 ret = DosSetCurrentDir(pathname);
705 return ret;
709 mc_chmod(char *pathName, int unxmode)
711 /* OS/2 does not need S_REG */
712 int os2Mode = unxmode & 0x0FFF;
713 return chmod(pathName, os2Mode);
716 static int
717 conv_os2_unx_rc(int os2rc)
719 int errCode;
720 switch (os2rc) {
721 case ERROR_FILE_NOT_FOUND:
722 case ERROR_PATH_NOT_FOUND:
723 case ERROR_FILENAME_EXCED_RANGE:
724 errCode = ENOENT;
725 break;
726 case ERROR_NOT_DOS_DISK:
727 case ERROR_SHARING_VIOLATION:
728 case ERROR_SHARING_BUFFER_EXCEEDED:
729 case ERROR_ACCESS_DENIED:
730 errCode = EACCES;
731 break;
732 case ERROR_INVALID_PARAMETER:
733 errCode = EINVAL;
734 break;
735 default:
736 errCode = EINVAL;
737 break;
739 return errCode;
743 mc_open (char *file, int flags, int pmode)
745 return open(file, (flags | O_BINARY), pmode);
749 mc_unlink(char *pathName)
751 /* Use OS/2 API to delete a file, if the file is set as read-only,
752 the file will be deleted without asking the user! */
753 APIRET rc;
754 rc = DosDelete(pathName);
755 if (!rc) {
756 return 0;
758 if (rc == ERROR_ACCESS_DENIED) {
759 chmod(pathName, (S_IREAD|S_IWRITE));
760 rc = DosDelete(pathName);
761 if (rc) {
762 errno = conv_os2_unx_rc(rc) ;
763 return -1;
764 } else {
765 return 0;
767 } else {
768 errno = conv_os2_unx_rc(rc) ;
769 return -1;
774 strncasecmp (char *s, char *d, int count)
776 register char result;
778 while (count > 0){
779 if (result = (0x20 | *s) - (0x20 | *d))
780 break;
781 if (!*s)
782 return 0;
783 s++;
784 d++;
785 count--;
787 return result;
790 FILE *
791 _popen(const char *cmd, const char *mode)
793 return NULL;
797 _pclose(FILE *file)
799 return 1;
802 char *
803 get_default_editor (void)
805 char *tmp;
806 APIRET rc;
807 char pathValue[5] = "PATH";
808 UCHAR searchResult[MC_MAXPATHLEN + 1];
810 /* EPM is not always be installed */
811 rc = DosSearchPath((SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT | SEARCH_CUR_DIRECTORY),
812 (PSZ) pathValue,
813 "EPM.EXE",
814 searchResult,
815 sizeof(searchResult));
816 if (rc != 0) {
817 /* The system editor is always there */
818 return strdup("e.exe");
819 } else {
820 /* Let it be searched from my_system */
821 return strdup("epm.exe");
825 /* get_default_shell
826 Get the default shell for the current hardware platform
827 TODO: Get the value of %OS2_SHELL% or %SHELL%: which one?
829 char *
830 get_default_shell()
832 return getenv ("COMSPEC");
836 getpid (void)
838 return 0;
842 errno_dir_not_empty (int err)
844 if (err == ENOTEMPTY)
845 return 1;
846 return 0;
849 char *
850 get_mc_lib_dir ()
852 char *mchome = getenv("MCHOME");
853 if (!mchome) {
854 return "D:\\mc";
855 } else {
856 return mchome;
860 int get_user_rights (struct stat *buf)
862 return 2;
864 void init_groups (void)
867 void delete_groups (void)