This commit was generated by cvs2svn to compensate for changes in r6453,
[chise/xemacs-chise.git.1] / src / mule-mcpath.c
1 /* Support for Non-ASCII Path Name
2    Copyright (C) 1985, 1986, 1992, 1993, 1995 Free Software Foundation, Inc.
3    Copyright (C) 1995 Sun Microsystems, Inc.
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING.  If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 /* Synched up with: Mule 2.3.   Not in FSF. */
23
24 /* mcpath.h should be included in config.h */
25 #include <config.h>
26 #include "lisp.h"
27
28 #include "sysfile.h"
29 #include "buffer.h"
30 #include "mule.h"
31
32 Lisp_Object Qpathname_coding_system = 0;
33
34 static void
35 mcpath_encode_code (struct Lisp_Coding_System *cp)
36 {
37   Lisp_Object coding_system;
38
39   coding_system = Fsymbol_value (Qpathname_coding_system);
40
41   mule_encode_code (coding_system, cp);
42   CODE_CNTL (cp) |= CC_END;
43 }
44
45 static int
46 mule_encode_path_1 (unsigned char *src, unsigned int srcsize,
47                     unsigned char *dst, unsigned int dstsize)
48 {
49   struct Lisp_Coding_System code;
50
51   mcpath_encode_code (&code);
52   if (CODE_TYPE (&code) > MULE_AUTOCONV)
53     {
54       unsigned char *buf;
55
56                                         /* get_conversion_buffer () is not */
57                                         /* re-entrant. */
58       buf = (unsigned char *) alloca (MULE_ENCODE_BUF_SIZE (srcsize, &code));
59       if (buf)
60         {
61           int len;
62           Lisp_Object dummy = Qnil;
63
64           len = mule_encode (&code, src, buf, srcsize, &dummy);
65           if (!CODE_CHAR (&code) && len <= dstsize)
66             {
67               memcpy (dst, buf, len);
68               return len;
69             }
70         }
71     }
72   return -1;                            /* use original */
73 }
74
75 static unsigned char *
76 mule_decode_path_1 (unsigned char *src, unsigned char *dst,
77                     unsigned int dstsize)
78 {
79   struct Lisp_Coding_System code;
80
81   mcpath_encode_code (&code);
82   if (CODE_TYPE (&code) > MULE_AUTOCONV)
83     {
84       int len;
85       unsigned char *buf;
86
87       len = strlen (src) + 1;           /* + 1 for '\0' */
88
89                                         /* get_conversion_buffer () is not */
90                                         /* re-entrant. */
91       buf = (unsigned char *) alloca (MULE_DECODE_BUF_SIZE (len, &code));
92       if (buf)
93         {
94           CODE_CNTL (&code) |= CC_END;
95           len = mule_decode (&code, src, buf, len);
96           if (!CODE_CHAR (&code) && len <= dstsize)
97             {
98               memcpy (dst, buf, len);   /* len should include '\0' */
99               return dst;
100             }
101         }
102     }
103   return src;
104 }
105
106 static unsigned char *
107 mule_decode_path (unsigned char *path, unsigned char ext_path[MC_MAXPATHLEN])
108 {
109   return
110     (Qpathname_coding_system
111      ? mule_decode_path_1 (path, ext_path, MC_MAXPATHLEN)
112      : path);                           /* in case of before initialization */
113 }
114
115 static unsigned char *
116 mule_encode_path (unsigned char *path, unsigned char *encode_buffer,
117                   unsigned int size)
118 {
119   int len;
120
121   len = mule_encode_path_1 (path, strlen (path), encode_buffer, size);
122   if (len > 0)
123     path = encode_buffer;
124 #ifdef MSDOS
125   /* convert the MSDOS style path delimiter to the UNIX style.  Note
126      that now the code is *internal*, so we can simply compare each
127      character with '\\'.  And this operation will alter the contents
128      of Lisp Object, PATH. */
129   {
130     unsigned char *p = path;
131
132     while (*p)
133       {
134         if (*p == '\\')
135           *p = '/';
136         p++;
137       }
138   }
139 #endif /* MSDOS */
140   return path;
141 }
142
143 #if 0 /* example of how they do it (similar junk deleted) ... */
144
145 int
146 mc_creat (unsigned char *path, int mode)
147 {
148   unsigned char buffer[MC_MAXPATHLEN];
149   return creat (mule_decode_path (path, buffer), mode);
150 }
151
152 int
153 mc_readlink (unsigned char *path, unsigned char *buf, int size)
154 {
155   unsigned char buffer[MC_MAXPATHLEN], buffer2[MAXPATHLEN];
156   int nread;
157
158   nread = readlink (mule_decode_path (path, buffer), buffer2, MAXPATHLEN);
159   if (nread > 0)
160     {
161       int len;
162       unsigned char *p;
163
164       len = mule_encode_path_1 (buffer2, nread, buffer, sizeof (buffer));
165       if (0 <= len && len <= size)
166         {
167           memcpy (buf, buffer, len);
168           return len;
169         }
170     }
171   return -1;
172 }
173
174 int
175 mc_chdir (unsigned char *path)
176 {
177   unsigned char buffer[MC_MAXPATHLEN];
178
179   path = mule_decode_path (path, buffer);
180
181 #ifdef MSDOS
182   if ((path[0] != 0) && (path[1] == ':'))
183     {
184       int drive = (tolower (path[0]) - 'a');
185       if (getdisk () != drive)
186         setdisk (drive);
187     }
188
189   /* If path != "/" and path != "a:/" and path ends with slash, remove
190      it. */
191   {
192     int len = strlen (path);
193
194     if (strcmp (path + 1, ":/") && (len > 1) && (path[len - 1] == '/'))
195       {
196         if (path != buffer)     /* It is not good to modify original path. */
197           {
198             memcpy (buffer, path, len - 1); /* no need to copy last /. */
199             path = buffer;
200           }
201         path[len - 1] = 0;
202       }
203   }
204 #endif /* MSDOS */
205
206   return chdir (path);
207 }
208
209 #ifdef MSDOS
210 #ifndef HAVE_GETWD
211 unsigned char *
212 mc_getcwd (unsigned char *null, size_t size)
213 {
214   unsigned char buffer[MAXPATHLEN];
215   unsigned char *path;
216
217   path = (unsigned char *) getcwd ((char *)buffer, MAXPATHLEN);
218   if (path)
219     {
220       /* here, shoule be (path == buffer). */
221       path = (unsigned char *) xmalloc (MC_MAXPATHLEN); /* MSDOS */
222       if (path)
223         {
224           int len;
225           int buffer_length = strlen (buffer) + 1;
226
227           len = mule_encode_path_1 (buffer, buffer_length, path, MC_MAXPATHLEN);
228           if (len < 0)
229             {
230               /* conversion failed.  use value that is returned from system. */
231               memcpy (path, buffer, buffer_length);
232             }
233         }
234     }
235   return path;
236 }
237 #else /* HAVE_GETWD */
238 unsigned char *
239 mc_getwd (unsigned char path[])
240 {
241   unsigned char *p;
242  
243   p = getwd (path);
244   if (p)
245     {
246       unsigned char buffer[MC_MAXPATHLEN];
247       int len;
248       
249       len = mule_encode_path_1 (path, strlen (path) + 1, buffer, sizeof buffer);
250       if (len > 0)
251         {
252           memcpy (path, buffer, len);
253         }
254     }
255   return p;
256 }
257 #endif /* HAVE_GETWD */
258 #endif /* MSDOS */
259
260 /* In callproc.c, execvp() is called like this:
261  *      execvp (new_argv[0], new_argv);
262  * following implement depends this.
263  */
264 #ifndef NO_MC_EXECVP
265 void
266 mc_execvp (unsigned char *path, unsigned char *argv[])
267 {
268   unsigned char buffer[MC_MAXPATHLEN];
269   argv[0] = path = mule_decode_path (path, buffer);
270   execvp (path, argv);
271 }
272 #endif /* !NO_MC_EXECVP */
273
274 static DIRENTRY mcpath_directory_entry;
275 DIRENTRY *
276 mc_readdir (DIR *d)
277 {
278   SYSTEM_DIRENTRY *sp;
279   DIRENTRY *dp = &mcpath_directory_entry;
280
281   sp = readdir (d);
282   if (!sp) return 0;
283
284 #ifndef MSDOS
285   dp->d_ino = sp->d_ino;
286 #endif /* MSDOS */
287   {                             /* copy d_name with conversion. */
288     int len;
289
290     len = mule_encode_path_1 (sp->d_name, NAMLEN (sp),
291                               dp->d_name, sizeof (dp->d_name) - 1);
292     if (len < 0)
293       {
294         len = NAMLEN (sp);
295 #ifdef MCPATH_ASSERT
296         assert (len < sizeof (dp->d_name));
297 #endif
298         memcpy (dp->d_name, sp->d_name, len);
299       }
300     dp->d_name[len] = 0;
301   }
302   return dp;
303 }
304
305 #endif /* 0 */
306