home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / libc / posix / unistd / getcwd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-31  |  2.5 KB  |  122 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. #include <libc/stubs.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include <string.h>
  8. #include <fcntl.h>
  9. #include <errno.h>
  10. #include <dpmi.h>
  11. #include <go32.h>
  12. #include <crt0.h>
  13. #include <libc/farptrgs.h>
  14. #include <libc/dosio.h>
  15.  
  16. char *
  17. __getcwd(char *buf, size_t size)
  18. {
  19.   char *bp;
  20.   __dpmi_regs r;
  21.   int needed_length, c;
  22.   unsigned use_lfn = _USE_LFN;
  23.   int preserve_case = _preserve_fncase();
  24.   char *name_start;
  25.  
  26.   if (!size)
  27.   {
  28.     errno = EINVAL;
  29.     return 0;
  30.   }
  31.   if (!buf)
  32.   {
  33.     buf = (char *)malloc(size);
  34.     if (!buf)
  35.     {
  36.       errno = ENOMEM;
  37.       return 0;
  38.     }
  39.   }
  40.  
  41.   /* make sure we don't overrun the TB */
  42.   if (size > _go32_info_block.size_of_transfer_buffer)
  43.     size = _go32_info_block.size_of_transfer_buffer;
  44.  
  45.   /* get the path into the transfer buffer at least */
  46.   if(use_lfn)
  47.     r.x.ax = 0x7147;
  48.   else
  49.     r.h.ah = 0x47;
  50.   r.h.dl = 0;
  51.   r.x.si = __tb_offset;
  52.   r.x.ds = __tb_segment;
  53.   __dpmi_int(0x21, &r);
  54.  
  55.   /* current drive may be invalid (it happens) */
  56.   if (r.x.flags & 1)
  57.   {
  58.     errno = __doserr_to_errno(r.x.ax);
  59.     return 0;
  60.   }
  61.  
  62.   /* path is ASCIIZ.  Scan it, filling in buf, watching for
  63.      end of buffer. */
  64.   _farsetsel(_dos_ds);
  65.   needed_length = 0;
  66.   while ((c = _farnspeekb(__tb+needed_length)))
  67.   {
  68.     if (needed_length+3 >= size)
  69.     {
  70.       errno = ERANGE;
  71.       return 0;
  72.     }
  73.     buf[3+needed_length] = c;
  74.     needed_length++;
  75.   }
  76.   buf[needed_length+3] = 0;
  77.  
  78.   /* switch FOO\BAR to foo/bar, downcase where appropriate */
  79.   buf[1] = ':';
  80.   buf[2] = '/';
  81.   for (bp = buf+3, name_start = bp - 1; *name_start; bp++)
  82.   {
  83.     char long_name[FILENAME_MAX], short_name[13];
  84.  
  85.     if (*bp == '\\')
  86.       *bp = '/';
  87.     if (!preserve_case && (*bp == '/' || *bp == '\0'))
  88.     {
  89.       memcpy(long_name, name_start+1, bp - name_start - 1);
  90.       long_name[bp - name_start - 1] = '\0';
  91.       if (!strcmp(_lfn_gen_short_fname(long_name, short_name), long_name))
  92.       {
  93.     while (++name_start < bp)
  94.       if (*name_start >= 'A' && *name_start <= 'Z')
  95.         *name_start += 'a' - 'A';
  96.       }
  97.       else
  98.     name_start = bp;
  99.     }
  100.     else if (*bp == '\0')
  101.       break;
  102.   }
  103.  
  104.   /* get current drive */
  105.   r.h.ah = 0x19;
  106.   __dpmi_int(0x21, &r);
  107.  
  108.   buf[0] = r.h.al + (r.h.al < 26 ? 'a' : 'A');
  109.  
  110.   return buf;
  111. }
  112.  
  113. #ifdef TEST
  114.  
  115. int main(void)
  116. {
  117.   printf (getcwd ((char *)0, FILENAME_MAX + 10));
  118.   return 0;
  119. }
  120.  
  121. #endif
  122.