/* Lisp functions for making directory listings.
- Copyright (C) 1985, 1986, 1993, 1994, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1985-1986, 1993-1994, 1999-2012 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <grp.h>
#include <errno.h>
-
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
/* The d_nameln member of a struct dirent includes the '\0' character
on some systems, but not on others. What's worse, you can't tell
Since applying strlen to the name always works, we'll just do that. */
#define NAMLEN(p) strlen (p->d_name)
-#ifdef SYSV_SYSTEM_DIR
+#ifdef HAVE_DIRENT_H
#include <dirent.h>
#define DIRENTRY struct dirent
-#else /* not SYSV_SYSTEM_DIR */
+#else /* not HAVE_DIRENT_H */
-#ifdef MSDOS
-#include <dirent.h>
-#else
#include <sys/dir.h>
-#endif
-
#include <sys/stat.h>
-#ifndef MSDOS
#define DIRENTRY struct direct
-extern DIR *opendir ();
-extern struct direct *readdir ();
+extern DIR *opendir (char *);
+extern struct direct *readdir (DIR *);
-#endif /* not MSDOS */
-#endif /* not SYSV_SYSTEM_DIR */
+#endif /* HAVE_DIRENT_H */
+
+#include <filemode.h>
+#include <stat-time.h>
#ifdef MSDOS
#define DIRENTRY_NONEMPTY(p) ((p)->d_name[0] != 0)
#include "lisp.h"
#include "systime.h"
+#include "character.h"
#include "buffer.h"
#include "commands.h"
-#include "character.h"
#include "charset.h"
#include "coding.h"
#include "regex.h"
#include "blockinput.h"
-/* Returns a search buffer, with a fastmap allocated and ready to go. */
-extern struct re_pattern_buffer *compile_pattern ();
-
-/* From filemode.c. Can't go in Lisp.h because of `stat'. */
-extern void filemodestring P_ ((struct stat *, char *));
-
-/* if system does not have symbolic links, it does not have lstat.
- In that case, use ordinary stat instead. */
-
-#ifndef S_IFLNK
-#define lstat stat
-#endif
+static Lisp_Object Qdirectory_files;
+static Lisp_Object Qdirectory_files_and_attributes;
+static Lisp_Object Qfile_name_completion;
+static Lisp_Object Qfile_name_all_completions;
+static Lisp_Object Qfile_attributes;
+static Lisp_Object Qfile_attributes_lessp;
-extern int completion_ignore_case;
-extern Lisp_Object Qcompletion_ignore_case;
-extern Lisp_Object Vcompletion_regexp_list;
-extern Lisp_Object Vw32_get_true_file_attributes;
-
-Lisp_Object Vcompletion_ignored_extensions;
-Lisp_Object Qdirectory_files;
-Lisp_Object Qdirectory_files_and_attributes;
-Lisp_Object Qfile_name_completion;
-Lisp_Object Qfile_name_all_completions;
-Lisp_Object Qfile_attributes;
-Lisp_Object Qfile_attributes_lessp;
-
-static int scmp P_ ((unsigned char *, unsigned char *, int));
+static ptrdiff_t scmp (const char *, const char *, ptrdiff_t);
\f
#ifdef WINDOWSNT
Lisp_Object
}
#endif
-Lisp_Object
-directory_files_internal_unwind (dh)
- Lisp_Object dh;
+static Lisp_Object
+directory_files_internal_unwind (Lisp_Object dh)
{
DIR *d = (DIR *) XSAVE_VALUE (dh)->pointer;
BLOCK_INPUT;
In the latter case, ID_FORMAT is passed to Ffile_attributes. */
Lisp_Object
-directory_files_internal (directory, full, match, nosort, attrs, id_format)
- Lisp_Object directory, full, match, nosort;
- int attrs;
- Lisp_Object id_format;
+directory_files_internal (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object nosort, int attrs, Lisp_Object id_format)
{
DIR *d;
- int directory_nbytes;
+ ptrdiff_t directory_nbytes;
Lisp_Object list, dirfilename, encoded_directory;
struct re_pattern_buffer *bufp = NULL;
int needsep = 0;
- int count = SPECPDL_INDEX ();
+ ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
DIRENTRY *dp;
#ifdef WINDOWSNT
# ifdef WINDOWSNT
/* Windows users want case-insensitive wildcards. */
bufp = compile_pattern (match, 0,
- buffer_defaults.case_canon_table, 0, 1);
+ BVAR (&buffer_defaults, case_canon_table), 0, 1);
# else /* !WINDOWSNT */
bufp = compile_pattern (match, 0, Qnil, 0, 1);
# endif /* !WINDOWSNT */
which might compile a new regexp until we're done with the loop! */
BLOCK_INPUT;
- d = opendir (SDATA (dirfilename));
+ d = opendir (SSDATA (dirfilename));
UNBLOCK_INPUT;
if (d == NULL)
report_file_error ("Opening directory", Fcons (directory, Qnil));
#ifdef WINDOWSNT
if (attrs)
{
- extern Lisp_Object Qlocal;
extern int is_slow_fs (const char *);
/* Do this only once to avoid doing it (in w32.c:stat) for each
if (DIRENTRY_NONEMPTY (dp))
{
- int len;
+ ptrdiff_t len;
int wanted = 0;
Lisp_Object name, finalname;
struct gcpro gcpro1, gcpro2;
QUIT;
if (NILP (match)
- || (0 <= re_search (bufp, SDATA (name), len, 0, len, 0)))
+ || (0 <= re_search (bufp, SSDATA (name), len, 0, len, 0)))
wanted = 1;
immediate_quit = 0;
if (!NILP (full))
{
Lisp_Object fullname;
- int nbytes = len + directory_nbytes + needsep;
- int nchars;
+ ptrdiff_t nbytes = len + directory_nbytes + needsep;
+ ptrdiff_t nchars;
fullname = make_uninit_multibyte_string (nbytes, nbytes);
- bcopy (SDATA (directory), SDATA (fullname),
- directory_nbytes);
+ memcpy (SDATA (fullname), SDATA (directory),
+ directory_nbytes);
if (needsep)
SSET (fullname, directory_nbytes, DIRECTORY_SEP);
- bcopy (SDATA (name),
- SDATA (fullname) + directory_nbytes + needsep,
- len);
+ memcpy (SDATA (fullname) + directory_nbytes + needsep,
+ SDATA (name), len);
nchars = chars_in_text (SDATA (fullname), nbytes);
If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
Otherwise, the list returned is sorted with `string-lessp'.
NOSORT is useful if you plan to sort the result yourself. */)
- (directory, full, match, nosort)
- Lisp_Object directory, full, match, nosort;
+ (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object nosort)
{
Lisp_Object handler;
directory = Fexpand_file_name (directory, Qnil);
`file-attributes' for further documentation.
On MS-Windows, performance depends on `w32-get-true-file-attributes',
which see. */)
- (directory, full, match, nosort, id_format)
- Lisp_Object directory, full, match, nosort, id_format;
+ (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object nosort, Lisp_Object id_format)
{
Lisp_Object handler;
directory = Fexpand_file_name (directory, Qnil);
}
\f
-Lisp_Object file_name_completion ();
+static Lisp_Object file_name_completion
+ (Lisp_Object file, Lisp_Object dirname, int all_flag, int ver_flag,
+ Lisp_Object predicate);
DEFUN ("file-name-completion", Ffile_name_completion, Sfile_name_completion,
2, 3, 0,
This function ignores some of the possible completions as
determined by the variable `completion-ignored-extensions', which see. */)
- (file, directory, predicate)
- Lisp_Object file, directory, predicate;
+ (Lisp_Object file, Lisp_Object directory, Lisp_Object predicate)
{
Lisp_Object handler;
+ directory = Fexpand_file_name (directory, Qnil);
/* If the directory name has special constructs in it,
call the corresponding file handler. */
Sfile_name_all_completions, 2, 2, 0,
doc: /* Return a list of all completions of file name FILE in directory DIRECTORY.
These are all file names in directory DIRECTORY which begin with FILE. */)
- (file, directory)
- Lisp_Object file, directory;
+ (Lisp_Object file, Lisp_Object directory)
{
Lisp_Object handler;
+ directory = Fexpand_file_name (directory, Qnil);
/* If the directory name has special constructs in it,
call the corresponding file handler. */
return file_name_completion (file, directory, 1, 0, Qnil);
}
-static int file_name_completion_stat ();
-Lisp_Object Qdefault_directory;
+static int file_name_completion_stat (Lisp_Object dirname, DIRENTRY *dp, struct stat *st_addr);
+static Lisp_Object Qdefault_directory;
-Lisp_Object
-file_name_completion (file, dirname, all_flag, ver_flag, predicate)
- Lisp_Object file, dirname;
- int all_flag, ver_flag;
- Lisp_Object predicate;
+static Lisp_Object
+file_name_completion (Lisp_Object file, Lisp_Object dirname, int all_flag, int ver_flag, Lisp_Object predicate)
{
DIR *d;
- int bestmatchsize = 0;
+ ptrdiff_t bestmatchsize = 0;
int matchcount = 0;
/* If ALL_FLAG is 1, BESTMATCH is the list of all matches, decoded.
If ALL_FLAG is 0, BESTMATCH is either nil
well as "." and "..". Until shown otherwise, assume we can't exclude
anything. */
int includeall = 1;
- int count = SPECPDL_INDEX ();
+ ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
elt = Qnil;
bestmatch = Qnil;
encoded_file = encoded_dir = Qnil;
GCPRO5 (file, dirname, bestmatch, encoded_file, encoded_dir);
- dirname = Fexpand_file_name (dirname, Qnil);
specbind (Qdefault_directory, dirname);
/* Do completion on the encoded file name
encoded_dir = ENCODE_FILE (dirname);
BLOCK_INPUT;
- d = opendir (SDATA (Fdirectory_file_name (encoded_dir)));
+ d = opendir (SSDATA (Fdirectory_file_name (encoded_dir)));
UNBLOCK_INPUT;
if (!d)
report_file_error ("Opening directory", Fcons (dirname, Qnil));
while (1)
{
DIRENTRY *dp;
- int len;
+ ptrdiff_t len;
int canexclude = 0;
errno = 0;
QUIT;
if (! DIRENTRY_NONEMPTY (dp)
|| len < SCHARS (encoded_file)
- || 0 <= scmp (dp->d_name, SDATA (encoded_file),
+ || 0 <= scmp (dp->d_name, SSDATA (encoded_file),
SCHARS (encoded_file)))
continue;
if (file_name_completion_stat (encoded_dir, dp, &st) < 0)
continue;
- directoryp = ((st.st_mode & S_IFMT) == S_IFDIR);
+ directoryp = S_ISDIR (st.st_mode);
tem = Qnil;
/* If all_flag is set, always include all.
It would not actually be helpful to the user to ignore any possible
completions when making a list of them. */
if (!all_flag)
{
- int skip;
+ ptrdiff_t skip;
#if 0 /* FIXME: The `scmp' call compares an encoded and a decoded string. */
/* If this entry matches the current bestmatch, the only
&& matchcount > 1
&& !includeall /* This match may allow includeall to 0. */
&& len >= bestmatchsize
- && 0 > scmp (dp->d_name, SDATA (bestmatch), bestmatchsize))
+ && 0 > scmp (dp->d_name, SSDATA (bestmatch), bestmatchsize))
continue;
#endif
for (tem = Vcompletion_ignored_extensions;
CONSP (tem); tem = XCDR (tem))
{
- int elt_len;
- unsigned char *p1;
+ ptrdiff_t elt_len;
+ char *p1;
elt = XCAR (tem);
if (!STRINGP (elt))
elt_len = SCHARS (elt) - 1; /* -1 for trailing / */
if (elt_len <= 0)
continue;
- p1 = SDATA (elt);
+ p1 = SSDATA (elt);
if (p1[elt_len] != '/')
continue;
skip = len - elt_len;
if (skip < 0) continue;
if (0 <= scmp (dp->d_name + skip,
- SDATA (elt),
+ SSDATA (elt),
SCHARS (elt)))
continue;
break;
if (includeall && !canexclude)
{ /* If we have one non-excludable file, we want to exclude the
- excudable files. */
+ excludable files. */
includeall = 0;
/* Throw away any previous excludable match found. */
bestmatch = Qnil;
{
Lisp_Object regexps;
- Lisp_Object zero;
- XSETFASTINT (zero, 0);
/* Ignore this element if it fails to match all the regexps. */
if (completion_ignore_case)
/* Suitably record this match. */
- matchcount++;
+ matchcount += matchcount <= 1;
if (all_flag)
bestmatch = Fcons (name, bestmatch);
{
Lisp_Object zero = make_number (0);
/* FIXME: This is a copy of the code in Ftry_completion. */
- int compare = min (bestmatchsize, SCHARS (name));
- Lisp_Object tem
+ ptrdiff_t compare = min (bestmatchsize, SCHARS (name));
+ Lisp_Object cmp
= Fcompare_strings (bestmatch, zero,
make_number (compare),
name, zero,
make_number (compare),
completion_ignore_case ? Qt : Qnil);
- int matchsize
- = (EQ (tem, Qt) ? compare
- : XINT (tem) < 0 ? - XINT (tem) - 1
- : XINT (tem) - 1);
+ ptrdiff_t matchsize
+ = (EQ (cmp, Qt) ? compare
+ : XINT (cmp) < 0 ? - XINT (cmp) - 1
+ : XINT (cmp) - 1);
if (completion_ignore_case)
{
(((matchsize == SCHARS (name))
==
(matchsize + !!directoryp == SCHARS (bestmatch)))
- && (tem = Fcompare_strings (name, zero,
+ && (cmp = Fcompare_strings (name, zero,
make_number (SCHARS (file)),
file, zero,
Qnil,
Qnil),
- EQ (Qt, tem))
- && (tem = Fcompare_strings (bestmatch, zero,
+ EQ (Qt, cmp))
+ && (cmp = Fcompare_strings (bestmatch, zero,
make_number (SCHARS (file)),
file, zero,
Qnil,
Qnil),
- ! EQ (Qt, tem))))
+ ! EQ (Qt, cmp))))
bestmatch = name;
}
bestmatchsize = matchsize;
Return -1 if strings match,
else number of chars that match at the beginning. */
-static int
-scmp (s1, s2, len)
- register unsigned char *s1, *s2;
- int len;
+static ptrdiff_t
+scmp (const char *s1, const char *s2, ptrdiff_t len)
{
- register int l = len;
+ register ptrdiff_t l = len;
if (completion_ignore_case)
{
- while (l && DOWNCASE (*s1++) == DOWNCASE (*s2++))
+ while (l
+ && (downcase ((unsigned char) *s1++)
+ == downcase ((unsigned char) *s2++)))
l--;
}
else
}
static int
-file_name_completion_stat (dirname, dp, st_addr)
- Lisp_Object dirname;
- DIRENTRY *dp;
- struct stat *st_addr;
+file_name_completion_stat (Lisp_Object dirname, DIRENTRY *dp, struct stat *st_addr)
{
- int len = NAMLEN (dp);
- int pos = SCHARS (dirname);
+ ptrdiff_t len = NAMLEN (dp);
+ ptrdiff_t pos = SCHARS (dirname);
int value;
- char *fullname = (char *) alloca (len + pos + 2);
+ char *fullname;
+ USE_SAFE_ALLOCA;
+ SAFE_ALLOCA (fullname, char *, len + pos + 2);
#ifdef MSDOS
-#if __DJGPP__ > 1
/* Some fields of struct stat are *very* expensive to compute on MS-DOS,
but aren't required here. Avoid computing the following fields:
st_inode, st_size and st_nlink for directories, and the execute bits
unsigned short save_djstat_flags = _djstat_flags;
_djstat_flags = _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
-#endif /* __DJGPP__ > 1 */
#endif /* MSDOS */
- bcopy (SDATA (dirname), fullname, pos);
+ memcpy (fullname, SDATA (dirname), pos);
if (!IS_DIRECTORY_SEP (fullname[pos - 1]))
fullname[pos++] = DIRECTORY_SEP;
- bcopy (dp->d_name, fullname + pos, len);
+ memcpy (fullname + pos, dp->d_name, len);
fullname[pos + len] = 0;
-#ifdef S_IFLNK
/* We want to return success if a link points to a nonexistent file,
but we want to return the status for what the link points to,
in case it is a directory. */
value = lstat (fullname, st_addr);
- stat (fullname, st_addr);
- return value;
-#else
- value = stat (fullname, st_addr);
+ if (value == 0 && S_ISLNK (st_addr->st_mode))
+ stat (fullname, st_addr);
#ifdef MSDOS
-#if __DJGPP__ > 1
_djstat_flags = save_djstat_flags;
-#endif /* __DJGPP__ > 1 */
#endif /* MSDOS */
+ SAFE_FREE ();
return value;
-#endif /* S_IFLNK */
}
\f
-Lisp_Object
-make_time (time)
- time_t time;
-{
- return Fcons (make_number (time >> 16),
- Fcons (make_number (time & 0177777), Qnil));
-}
-
static char *
stat_uname (struct stat *st)
{
2. File uid as a string or a number. If a string value cannot be
looked up, a numeric value, either an integer or a float, is returned.
3. File gid, likewise.
- 4. Last access time, as a list of two integers.
- First integer has high-order 16 bits of time, second has low 16 bits.
+ 4. Last access time, as a list of integers (HIGH LOW USEC PSEC) in the
+ same style as (current-time).
(See a note below about access time on FAT-based filesystems.)
5. Last modification time, likewise. This is the time of the last
change to the file's contents.
This is a floating point number if the size is too large for an integer.
8. File modes, as a string of ten letters or dashes as in ls -l.
9. t if file's gid would change if file were deleted and recreated.
-10. inode number. If inode number is larger than what Emacs integer
- can hold, but still fits into a 32-bit number, this is a cons cell
- containing two integers: first the high part, then the low 16 bits.
- If the inode number is wider than 32 bits, this is of the form
- (HIGH MIDDLE . LOW): first the high 24 bits, then middle 24 bits,
+10. inode number. If it is larger than what an Emacs integer can hold,
+ this is of the form (HIGH . LOW): first the high bits, then the low 16 bits.
+ If even HIGH is too large for an Emacs integer, this is instead of the form
+ (HIGH MIDDLE . LOW): first the high bits, then the middle 24 bits,
and finally the low 16 bits.
11. Filesystem device number. If it is larger than what the Emacs
integer can hold, this is a cons cell, similar to the inode number.
On some FAT-based filesystems, only the date of last access is recorded,
so last access time will always be midnight of that day. */)
- (filename, id_format)
- Lisp_Object filename, id_format;
+ (Lisp_Object filename, Lisp_Object id_format)
{
Lisp_Object values[12];
Lisp_Object encoded;
struct stat s;
-#if defined (BSD4_2) || defined (BSD4_3)
+#ifdef BSD4_2
Lisp_Object dirname;
struct stat sdir;
-#endif
- char modes[10];
+#endif /* BSD4_2 */
+
+ /* An array to hold the mode string generated by filemodestring,
+ including its terminating space and null byte. */
+ char modes[sizeof "-rwxr-xr-x "];
+
Lisp_Object handler;
struct gcpro gcpro1;
char *uname = NULL, *gname = NULL;
encoded = ENCODE_FILE (filename);
UNGCPRO;
- if (lstat (SDATA (encoded), &s) < 0)
+ if (lstat (SSDATA (encoded), &s) < 0)
return Qnil;
- switch (s.st_mode & S_IFMT)
- {
- default:
- values[0] = Qnil; break;
- case S_IFDIR:
- values[0] = Qt; break;
-#ifdef S_IFLNK
- case S_IFLNK:
- values[0] = Ffile_symlink_p (filename); break;
-#endif
- }
+ values[0] = (S_ISLNK (s.st_mode) ? Ffile_symlink_p (filename)
+ : S_ISDIR (s.st_mode) ? Qt : Qnil);
values[1] = make_number (s.st_nlink);
if (!(NILP (id_format) || EQ (id_format, Qinteger)))
else
values[3] = make_fixnum_or_float (s.st_gid);
- values[4] = make_time (s.st_atime);
- values[5] = make_time (s.st_mtime);
- values[6] = make_time (s.st_ctime);
- values[7] = make_fixnum_or_float (s.st_size);
- /* If the size is negative, and its type is long, convert it back to
- positive. */
- if (s.st_size < 0 && sizeof (s.st_size) == sizeof (long))
- values[7] = make_float ((double) ((unsigned long) s.st_size));
+ values[4] = make_lisp_time (get_stat_atime (&s));
+ values[5] = make_lisp_time (get_stat_mtime (&s));
+ values[6] = make_lisp_time (get_stat_ctime (&s));
+
+ /* If the file size is a 4-byte type, assume that files of sizes in
+ the 2-4 GiB range wrap around to negative values, as this is a
+ common bug on older 32-bit platforms. */
+ if (sizeof (s.st_size) == 4)
+ values[7] = make_fixnum_or_float (s.st_size & 0xffffffffu);
+ else
+ values[7] = make_fixnum_or_float (s.st_size);
filemodestring (&s, modes);
values[8] = make_string (modes, 10);
-#if defined (BSD4_2) || defined (BSD4_3) /* file gid will be dir gid */
+#ifdef BSD4_2 /* file gid will be dir gid */
dirname = Ffile_name_directory (filename);
if (! NILP (dirname))
encoded = ENCODE_FILE (dirname);
values[9] = Qt;
#else /* file gid will be egid */
values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
-#endif /* BSD4_2 (or BSD4_3) */
- if (!FIXNUM_OVERFLOW_P (s.st_ino))
- /* Keep the most common cases as integers. */
- values[10] = make_number (s.st_ino);
- else if (!FIXNUM_OVERFLOW_P (s.st_ino >> 16))
- /* To allow inode numbers larger than VALBITS, separate the bottom
- 16 bits. */
- values[10] = Fcons (make_number ((EMACS_INT)(s.st_ino >> 16)),
- make_number ((EMACS_INT)(s.st_ino & 0xffff)));
- else
- {
- /* To allow inode numbers beyond 32 bits, separate into 2 24-bit
- high parts and a 16-bit bottom part.
- The code on the next line avoids a compiler warning on
- systems where st_ino is 32 bit wide. (bug#766). */
- EMACS_INT high_ino = s.st_ino >> 31 >> 1;
- EMACS_INT low_ino = s.st_ino & 0xffffffff;
-
- values[10] = Fcons (make_number (high_ino >> 8),
- Fcons (make_number (((high_ino & 0xff) << 16)
- + (low_ino >> 16)),
- make_number (low_ino & 0xffff)));
- }
+#endif /* not BSD4_2 */
+ values[10] = INTEGER_TO_CONS (s.st_ino);
+ values[11] = INTEGER_TO_CONS (s.st_dev);
- /* Likewise for device. */
- if (FIXNUM_OVERFLOW_P (s.st_dev))
- values[11] = Fcons (make_number (s.st_dev >> 16),
- make_number (s.st_dev & 0xffff));
- else
- values[11] = make_number (s.st_dev);
-
- return Flist (sizeof(values) / sizeof(values[0]), values);
+ return Flist (sizeof (values) / sizeof (values[0]), values);
}
DEFUN ("file-attributes-lessp", Ffile_attributes_lessp, Sfile_attributes_lessp, 2, 2, 0,
doc: /* Return t if first arg file attributes list is less than second.
Comparison is in lexicographic order and case is significant. */)
- (f1, f2)
- Lisp_Object f1, f2;
+ (Lisp_Object f1, Lisp_Object f2)
{
return Fstring_lessp (Fcar (f1), Fcar (f2));
}
\f
+
+DEFUN ("system-users", Fsystem_users, Ssystem_users, 0, 0, 0,
+ doc: /* Return a list of user names currently registered in the system.
+If we don't know how to determine that on this platform, just
+return a list with one element, taken from `user-real-login-name'. */)
+ (void)
+{
+ Lisp_Object users = Qnil;
+#if defined HAVE_GETPWENT && defined HAVE_ENDPWENT
+ struct passwd *pw;
+
+ while ((pw = getpwent ()))
+ users = Fcons (DECODE_SYSTEM (build_string (pw->pw_name)), users);
+
+ endpwent ();
+#endif
+ if (EQ (users, Qnil))
+ /* At least current user is always known. */
+ users = Fcons (Vuser_real_login_name, Qnil);
+ return users;
+}
+
+DEFUN ("system-groups", Fsystem_groups, Ssystem_groups, 0, 0, 0,
+ doc: /* Return a list of user group names currently registered in the system.
+The value may be nil if not supported on this platform. */)
+ (void)
+{
+ Lisp_Object groups = Qnil;
+#if defined HAVE_GETGRENT && defined HAVE_ENDGRENT
+ struct group *gr;
+
+ while ((gr = getgrent ()))
+ groups = Fcons (DECODE_SYSTEM (build_string (gr->gr_name)), groups);
+
+ endgrent ();
+#endif
+ return groups;
+}
+
void
-syms_of_dired ()
+syms_of_dired (void)
{
- Qdirectory_files = intern_c_string ("directory-files");
- Qdirectory_files_and_attributes = intern_c_string ("directory-files-and-attributes");
- Qfile_name_completion = intern_c_string ("file-name-completion");
- Qfile_name_all_completions = intern_c_string ("file-name-all-completions");
- Qfile_attributes = intern_c_string ("file-attributes");
- Qfile_attributes_lessp = intern_c_string ("file-attributes-lessp");
- Qdefault_directory = intern_c_string ("default-directory");
-
- staticpro (&Qdirectory_files);
- staticpro (&Qdirectory_files_and_attributes);
- staticpro (&Qfile_name_completion);
- staticpro (&Qfile_name_all_completions);
- staticpro (&Qfile_attributes);
- staticpro (&Qfile_attributes_lessp);
- staticpro (&Qdefault_directory);
+ DEFSYM (Qdirectory_files, "directory-files");
+ DEFSYM (Qdirectory_files_and_attributes, "directory-files-and-attributes");
+ DEFSYM (Qfile_name_completion, "file-name-completion");
+ DEFSYM (Qfile_name_all_completions, "file-name-all-completions");
+ DEFSYM (Qfile_attributes, "file-attributes");
+ DEFSYM (Qfile_attributes_lessp, "file-attributes-lessp");
+ DEFSYM (Qdefault_directory, "default-directory");
defsubr (&Sdirectory_files);
defsubr (&Sdirectory_files_and_attributes);
defsubr (&Sfile_name_all_completions);
defsubr (&Sfile_attributes);
defsubr (&Sfile_attributes_lessp);
+ defsubr (&Ssystem_users);
+ defsubr (&Ssystem_groups);
- DEFVAR_LISP ("completion-ignored-extensions", &Vcompletion_ignored_extensions,
+ DEFVAR_LISP ("completion-ignored-extensions", Vcompletion_ignored_extensions,
doc: /* Completion ignores file names ending in any string in this list.
It does not ignore them if all possible completions end in one of
these strings or when displaying a list of completions.
ends in a slash. */);
Vcompletion_ignored_extensions = Qnil;
}
-
-/* arch-tag: 1ac8deca-4d8f-4d41-ade9-089154d98c03
- (do not change this comment) */