mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
List of changes: - Fixed some -Wuninitialized warnings and removed some unused variables. - Removed the unused extern for B_login (re:d8eba9d1
). - The libcmd builtins and the vmalloc memfatal function now handle memory errors with 'ERROR_SYSTEM|ERROR_PANIC' for consistency with how ksh itself handles out of memory errors. - Added usage of UNREACHABLE() where it was missing from error handling. - Extend many variables from short to int to prevent overflows (most variables involve file descriptors). - Backported a ksh2020 patch to fix unused value Coverity issues (https://github.com/att/ast/pull/740). - Note in src/cmd/ksh93/README that ksh compiles with Cygwin on Windows 10 and Windows 11, albeit with many test failures. - Add comments to detail some sections of code. Extensive list of commits related to this change:ca2443b5
,7e7f1372
,2db9953a
,7003aba4
,6f50ff64
,b1a41311
,222515bf
,a0dcdeea
,0aa9e03f
,61437b27
,352e68da
,88e8fa67
,bc8b36fa
,6e515f1d
,017d088c
,035a4cb3
,588a1ff7
,6d63b57d
,a2f13c19
,794d1c86
,ab98ec65
,1026006d
- Removed a lot of dead ifdef code. - edit/emacs.c: Hide an assignment to avoid a -Wunused warning. (See also https://github.com/att/ast/pull/753, which removed the assignment because ksh2020 removed the !SHOPT_MULTIBYTE code.) - sh/nvdisc.c: The sh_newof macro cannot return a null pointer because it will instead cause the shell to exit if memory cannot be allocated. That makes the if statement here a no-op, so remove it. - sh/xec.c: Fixed one unused variable warning in sh_funscope(). - sh/xec.c: Remove a fallthrough comment added in commited478ab7
because the TFORK code doesn't fall through (GCC also produces no -Wimplicit-fallthrough warning here). - data/builtins.c: The cd and pwd man pages state that these builtins default to -P if PATH_RESOLVE is 'physical', which isn't accurate: $ /opt/ast/bin/getconf PATH_RESOLVE physical $ mkdir /tmp/dir; ln -s /tmp/dir /tmp/sym $ cd /tmp/sym $ pwd /tmp/sym $ cd -P /tmp/sym $ pwd /tmp/dir The behavior described by these man pages isn't specified in the ksh man page or by POSIX, so to avoid changing these builtin's behavior the inaccurate PATH_RESOLVE information has been removed. - Mamfiles: Preserve multi-line errors by quoting the $x variable. This fix was backported from 93v-. (See also <a7e9cc82
>.) - sh/subshell.c: Remove set but not used sp->errcontext variable.
485 lines
11 KiB
C
485 lines
11 KiB
C
/***********************************************************************
|
|
* *
|
|
* This software is part of the ast package *
|
|
* Copyright (c) 1992-2012 AT&T Intellectual Property *
|
|
* Copyright (c) 2020-2021 Contributors to ksh 93u+m *
|
|
* and is licensed under the *
|
|
* Eclipse Public License, Version 1.0 *
|
|
* by AT&T Intellectual Property *
|
|
* *
|
|
* A copy of the License is available at *
|
|
* http://www.eclipse.org/org/documents/epl-v10.html *
|
|
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
|
|
* *
|
|
* Information and Software Systems Research *
|
|
* AT&T Research *
|
|
* Florham Park NJ *
|
|
* *
|
|
* Glenn Fowler <gsf@research.att.com> *
|
|
* David Korn <dgk@research.att.com> *
|
|
* *
|
|
***********************************************************************/
|
|
#pragma prototyped
|
|
/*
|
|
* David Korn
|
|
* Glenn Fowler
|
|
* AT&T Research
|
|
*
|
|
* id
|
|
*/
|
|
|
|
static const char usage[] =
|
|
"[-?\n@(#)$Id: id (AT&T Research) 2004-06-11 $\n]"
|
|
"[--catalog?" ERROR_CATALOG "]"
|
|
"[+NAME?id - return user identity]"
|
|
"[+DESCRIPTION?If no \auser\a operand is specified \bid\b writes user and "
|
|
"group IDs and the corresponding user and group names of the "
|
|
"invoking process to standard output. If the effective and "
|
|
"real IDs do not match, both are written. Any supplementary "
|
|
"groups the current process belongs to will also be written.]"
|
|
"[+?If a \auser\a operand is specified and the process has permission, "
|
|
"the user and group IDs and any supplementary group IDs of the "
|
|
"selected user will be written to standard output.]"
|
|
"[+?If any options are specified, then only a portion of the information "
|
|
"is written.]"
|
|
"[n:name?Write the name instead of the numeric ID.]"
|
|
"[r:real?Writes real ID instead of the effective ID.]"
|
|
"[a?This option is ignored.]"
|
|
"[g:group?Writes only the group ID.]"
|
|
"[u:user?Writes only the user ID.]"
|
|
"[G:groups?Writes only the supplementary group IDs.]"
|
|
"[s:fair-share?Writes fair share scheduler IDs and groups on systems that "
|
|
"support fair share scheduling.]"
|
|
"\n"
|
|
"\n[user]\n"
|
|
"\n"
|
|
"[+EXIT STATUS?]{"
|
|
"[+0?Successful completion.]"
|
|
"[+>0?An error occurred.]"
|
|
"}"
|
|
"[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2)]"
|
|
;
|
|
|
|
#include <cmd.h>
|
|
|
|
#include "FEATURE/ids"
|
|
|
|
#include <grp.h>
|
|
#include <pwd.h>
|
|
|
|
#if _lib_fsid
|
|
#if _lib_getfsgid && ( _sys_fss || _hdr_fsg )
|
|
#define fss_grp fs_grp
|
|
#define fss_id fs_id
|
|
#define fss_mem fs_mem
|
|
#define fss_passwd fs_passwd
|
|
#define fss_shares fs_shares
|
|
#if _sys_fss
|
|
#include <sys/fss.h>
|
|
#endif
|
|
#if _hdr_fsg
|
|
#include <fsg.h>
|
|
#endif
|
|
#if !_lib_isfsg && !defined(isfsg)
|
|
#define isfsg(p) (!(p)->fs_id&&!(p)->fs_shares&&(!(p)->fs_passwd||!*(p)->fs_passwd))
|
|
#endif
|
|
#else
|
|
#undef _lib_fsid
|
|
#endif
|
|
#endif
|
|
|
|
#define power2(n) (!((n)&((n)-1)))
|
|
|
|
#define GG_FLAG (1<<0)
|
|
#define G_FLAG (1<<1)
|
|
#define N_FLAG (1<<2)
|
|
#define R_FLAG (1<<3)
|
|
#define U_FLAG (1<<4)
|
|
#define S_FLAG (1<<5)
|
|
#define O_FLAG (1<<6)
|
|
#define X_FLAG (1<<7)
|
|
|
|
#if _lib_fsid
|
|
static void
|
|
getfsids(Sfio_t* sp, const char* name, int flags, register int lastchar)
|
|
{
|
|
register struct fsg* fs;
|
|
register char* s;
|
|
register char** p;
|
|
char** x;
|
|
|
|
if (lastchar)
|
|
{
|
|
if (flags & O_FLAG) flags = 1;
|
|
else flags = 0;
|
|
}
|
|
else if (flags & N_FLAG) flags = 1;
|
|
else flags = -1;
|
|
setfsgent();
|
|
while (fs = getfsgnam(name))
|
|
if (!isfsg(fs))
|
|
{
|
|
if (p = fs->fs_mem)
|
|
{
|
|
if (flags > 0) x = 0;
|
|
else
|
|
{
|
|
register char** q;
|
|
register char* t;
|
|
register int n;
|
|
|
|
n = 0;
|
|
q = p;
|
|
while (s = *q++)
|
|
n += strlen(s) + 1;
|
|
if (!(x = newof(0, char*, q - p, n)))
|
|
break;
|
|
s = (char*)(x + (q - p));
|
|
q = x;
|
|
while (t = *p++)
|
|
{
|
|
*q++ = s;
|
|
while (*s++ = *t++);
|
|
}
|
|
*q = 0;
|
|
p = x;
|
|
}
|
|
while (s = *p++)
|
|
{
|
|
if (lastchar == '=')
|
|
{
|
|
lastchar = ',';
|
|
sfputr(sp, " fsid=", -1);
|
|
}
|
|
else if (!lastchar) lastchar = ' ';
|
|
else sfputc(sp, lastchar);
|
|
if (flags > 0) sfprintf(sp, "%s", s);
|
|
else
|
|
{
|
|
setfsgent();
|
|
while (fs = getfsgnam(s))
|
|
if (isfsg(fs))
|
|
{
|
|
if (flags < 0) sfprintf(sp, "%u", fs->fs_id);
|
|
else sfprintf(sp, "%u(%s)", fs->fs_id, s);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (x) free(x);
|
|
}
|
|
break;
|
|
}
|
|
endfsgent();
|
|
if (lastchar == ' ') sfputc(sp, '\n');
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
putid(Sfio_t* sp, int flags, const char* label, const char* name, long number)
|
|
{
|
|
sfprintf(sp, "%s=", label);
|
|
if (flags & O_FLAG)
|
|
{
|
|
if (name) sfputr(sp, name, -1);
|
|
else sfprintf(sp, "%lu", number);
|
|
}
|
|
else
|
|
{
|
|
sfprintf(sp, "%u", number);
|
|
if (name) sfprintf(sp, "(%s)", name);
|
|
}
|
|
}
|
|
|
|
static int
|
|
getids(Sfio_t* sp, const char* name, register int flags)
|
|
{
|
|
register struct passwd* pw;
|
|
register struct group* grp;
|
|
register int i;
|
|
register int j;
|
|
register int k;
|
|
#if _lib_fsid
|
|
register struct fsg* fs;
|
|
const char* fs_name;
|
|
int fs_id;
|
|
#endif
|
|
char** p;
|
|
char* s;
|
|
int lastchar;
|
|
int ngroups = 0;
|
|
const char* gname;
|
|
uid_t user;
|
|
uid_t euid;
|
|
gid_t group;
|
|
gid_t egid;
|
|
|
|
static gid_t* groups;
|
|
|
|
if (flags & GG_FLAG)
|
|
{
|
|
static int maxgroups;
|
|
|
|
/*
|
|
* get supplemental groups if required
|
|
*/
|
|
|
|
if (!maxgroups)
|
|
{
|
|
/*
|
|
* first time
|
|
*/
|
|
|
|
if ((maxgroups = getgroups(0, groups)) <= 0)
|
|
maxgroups = NGROUPS_MAX;
|
|
if (!(groups = newof(0, gid_t, maxgroups + 1, 0)))
|
|
{
|
|
error(ERROR_SYSTEM|ERROR_PANIC, "out of memory [group array]");
|
|
UNREACHABLE();
|
|
}
|
|
}
|
|
ngroups = getgroups(maxgroups, groups);
|
|
for (i = j = 0; i < ngroups; i++)
|
|
{
|
|
for (k = 0; k < j && groups[k] != groups[i]; k++);
|
|
if (k >= j) groups[j++] = groups[i];
|
|
}
|
|
ngroups = j;
|
|
}
|
|
if (name)
|
|
{
|
|
flags |= X_FLAG;
|
|
if (!(flags & N_FLAG) || (flags & (G_FLAG|GG_FLAG)))
|
|
{
|
|
if (!(pw = getpwnam(name)))
|
|
{
|
|
user = strtol(name, &s, 0);
|
|
if (*s || !(pw = getpwuid(user)))
|
|
{
|
|
error(ERROR_exit(1), "%s: name not found", name);
|
|
UNREACHABLE();
|
|
}
|
|
name = pw->pw_name;
|
|
}
|
|
user = pw->pw_uid;
|
|
group = pw->pw_gid;
|
|
}
|
|
#if _lib_fsid
|
|
if (!(flags & N_FLAG) || (flags & S_FLAG))
|
|
{
|
|
setfsgent();
|
|
do
|
|
{
|
|
if (!(fs = getfsgnam(name)))
|
|
{
|
|
error(ERROR_exit(1), "%u: fss name not found", name);
|
|
UNREACHABLE();
|
|
}
|
|
} while (isfsg(fs));
|
|
fs_id = fs->fs_id;
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
if (flags & G_FLAG)
|
|
group = (flags & R_FLAG) ? getgid() : getegid();
|
|
if (flags & (GG_FLAG|N_FLAG|U_FLAG))
|
|
user = (flags & R_FLAG) ? getuid() : geteuid();
|
|
#if _lib_fsid
|
|
if (flags & S_FLAG)
|
|
fs_id = fsid(0);
|
|
#endif
|
|
if (flags & N_FLAG)
|
|
name = (pw = getpwuid(user)) ? pw->pw_name : (char*)0;
|
|
}
|
|
if (ngroups == 1 && groups[0] == group)
|
|
ngroups = 0;
|
|
if ((flags & N_FLAG) && (flags & G_FLAG))
|
|
gname = (grp = getgrgid(group)) ? grp->gr_name : (char*)0;
|
|
#if _lib_fsid
|
|
if ((flags & N_FLAG) && (flags & S_FLAG))
|
|
{
|
|
setfsgent();
|
|
fs_name = (fs = getfsgid(fs_id)) ? fs->fs_grp : (char*)0;
|
|
}
|
|
#endif
|
|
if ((flags & (U_FLAG|G_FLAG|S_FLAG)) == (U_FLAG|G_FLAG|S_FLAG))
|
|
{
|
|
putid(sp, flags, "uid", name, user);
|
|
putid(sp, flags, " gid", gname, group);
|
|
if ((flags & X_FLAG) && name)
|
|
{
|
|
#if _lib_getgrent
|
|
#if _lib_setgrent
|
|
setgrent();
|
|
#endif
|
|
lastchar = '=';
|
|
while (grp = getgrent())
|
|
if (p = grp->gr_mem)
|
|
while (s = *p++)
|
|
if (streq(s, name))
|
|
{
|
|
if (lastchar == '=')
|
|
sfputr(sp, " groups", -1);
|
|
sfputc(sp, lastchar);
|
|
lastchar = ',';
|
|
if (flags & O_FLAG)
|
|
sfprintf(sp, "%s", grp->gr_name);
|
|
else sfprintf(sp, "%u(%s)", grp->gr_gid, grp->gr_name);
|
|
}
|
|
#if _lib_endgrent
|
|
endgrent();
|
|
#endif
|
|
#endif
|
|
#if _lib_fsid
|
|
getfsids(sp, name, flags, '=');
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
if ((euid = geteuid()) != user)
|
|
putid(sp, flags, " euid", (pw = getpwuid(euid)) ? pw->pw_name : (char*)0, euid);
|
|
if ((egid = getegid()) != group)
|
|
putid(sp, flags, " egid", (grp = getgrgid(egid)) ? grp->gr_name : (char*)0, egid);
|
|
if (ngroups > 0)
|
|
{
|
|
sfputr(sp, " groups", -1);
|
|
lastchar = '=';
|
|
for (i = 0; i < ngroups; i++)
|
|
{
|
|
group = groups[i];
|
|
sfputc(sp, lastchar);
|
|
if (grp = getgrgid(group))
|
|
{
|
|
if (flags & O_FLAG) sfprintf(sp, "%s", grp->gr_name);
|
|
else sfprintf(sp, "%u(%s)", group, grp->gr_name);
|
|
}
|
|
else sfprintf(sp, "%u", group);
|
|
lastchar = ',';
|
|
}
|
|
}
|
|
#if _lib_fsid
|
|
putid(sp, flags, " fsid", fs_name, fs_id);
|
|
#endif
|
|
}
|
|
sfputc(sp,'\n');
|
|
return(0);
|
|
}
|
|
if (flags & U_FLAG)
|
|
{
|
|
if ((flags & N_FLAG) && name) sfputr(sp, name, '\n');
|
|
else sfprintf(sp, "%u\n", user);
|
|
}
|
|
else if (flags & G_FLAG)
|
|
{
|
|
if ((flags & N_FLAG) && gname) sfputr(sp, gname, '\n');
|
|
else sfprintf(sp, "%u\n", group);
|
|
}
|
|
else if (flags & GG_FLAG)
|
|
{
|
|
if ((flags & X_FLAG) && name)
|
|
{
|
|
#if _lib_getgrent
|
|
#if _lib_setgrent
|
|
setgrent();
|
|
#endif
|
|
i = 0;
|
|
while (grp = getgrent())
|
|
if (p = grp->gr_mem)
|
|
while (s = *p++)
|
|
if (streq(s, name))
|
|
{
|
|
if (i++) sfputc(sp, ' ');
|
|
if (flags & N_FLAG) sfprintf(sp, "%s", grp->gr_name);
|
|
else sfprintf(sp, "%u", grp->gr_gid);
|
|
}
|
|
#if _lib_endgrent
|
|
endgrent();
|
|
#endif
|
|
if (i) sfputc(sp, '\n');
|
|
#endif
|
|
}
|
|
else if (ngroups > 0)
|
|
{
|
|
for (i = 0;;)
|
|
{
|
|
group = groups[i];
|
|
if ((flags & N_FLAG) && (grp = getgrgid(group)))
|
|
sfprintf(sp, "%s", grp->gr_name);
|
|
else sfprintf(sp, "%u", group);
|
|
if (++i >= ngroups) break;
|
|
sfputc(sp, ' ');
|
|
}
|
|
sfputc(sp, '\n');
|
|
}
|
|
}
|
|
#if _lib_fsid
|
|
else if (flags & S_FLAG)
|
|
{
|
|
if ((flags & X_FLAG) && name) getfsids(sp, name, flags, 0);
|
|
else if ((flags & N_FLAG) && fs_name) sfputr(sp, fs_name, '\n');
|
|
else sfprintf(sp, "%u\n", fs_id);
|
|
}
|
|
#endif
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
b_id(int argc, char** argv, Shbltin_t* context)
|
|
{
|
|
register int flags = 0;
|
|
register int n;
|
|
|
|
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
|
|
for (;;)
|
|
{
|
|
switch (optget(argv, usage))
|
|
{
|
|
case 'a':
|
|
continue;
|
|
case 'G':
|
|
flags |= GG_FLAG;
|
|
continue;
|
|
case 'g':
|
|
flags |= G_FLAG;
|
|
continue;
|
|
case 'n':
|
|
flags |= N_FLAG;
|
|
continue;
|
|
case 'r':
|
|
flags |= R_FLAG;
|
|
continue;
|
|
case 's':
|
|
flags |= S_FLAG;
|
|
continue;
|
|
case 'u':
|
|
flags |= U_FLAG;
|
|
continue;
|
|
case ':':
|
|
error(2, "%s", opt_info.arg);
|
|
break;
|
|
case '?':
|
|
error(ERROR_usage(2), "%s", opt_info.arg);
|
|
UNREACHABLE();
|
|
}
|
|
break;
|
|
}
|
|
argv += opt_info.index;
|
|
argc -= opt_info.index;
|
|
n = (flags & (GG_FLAG|G_FLAG|S_FLAG|U_FLAG));
|
|
if (!power2(n))
|
|
error(2, "incompatible options selected");
|
|
if (error_info.errors || argc > 1)
|
|
{
|
|
error(ERROR_usage(2), "%s", optusage(NiL));
|
|
UNREACHABLE();
|
|
}
|
|
if (!(flags & ~(N_FLAG|R_FLAG)))
|
|
{
|
|
if (flags & N_FLAG) flags |= O_FLAG;
|
|
flags |= (U_FLAG|G_FLAG|N_FLAG|R_FLAG|S_FLAG|GG_FLAG);
|
|
}
|
|
error_info.errors = getids(sfstdout, *argv, flags);
|
|
return(error_info.errors);
|
|
}
|