Module: Process::GID
- Defined in:
- process.c
Class Method Summary collapse
-
.Process::GID.change_privilege(group) ⇒ Integer
Change the current process’s real and effective group ID to that specified by group.
-
.eid ⇒ Object
Returns the effective group ID for the current process:.
-
.Process::GID.from_name(name) ⇒ Object
Get the group ID by the name.
-
.grant_privilege(id) ⇒ Object
Set the effective group ID, and if possible, the saved group ID of the process to the given group.
-
.Process::GID.re_exchange ⇒ Integer
Exchange real and effective group IDs and return the new effective group ID.
-
.Process::GID.re_exchangeable? ⇒ Boolean
Returns
true
if the real and effective group IDs of a process may be exchanged on the current platform. -
.rid ⇒ Object
Returns the (real) group ID for the current process:.
-
.Process::GID.sid_available? ⇒ Boolean
Returns
true
if the current platform has saved group ID functionality. - .switch ⇒ Object
Instance Method Summary collapse
-
#Process::GID.change_privilege(group) ⇒ Integer
private
Change the current process’s real and effective group ID to that specified by group.
-
#eid ⇒ Object
private
Returns the effective group ID for the current process:.
-
#Process::GID.from_name(name) ⇒ Object
private
Get the group ID by the name.
-
#grant_privilege(id) ⇒ Object
private
Set the effective group ID, and if possible, the saved group ID of the process to the given group.
-
#Process::GID.re_exchange ⇒ Integer
private
Exchange real and effective group IDs and return the new effective group ID.
-
#Process::GID.re_exchangeable? ⇒ Boolean
private
Returns
true
if the real and effective group IDs of a process may be exchanged on the current platform. -
#rid ⇒ Object
private
Returns the (real) group ID for the current process:.
-
#Process::GID.sid_available? ⇒ Boolean
private
Returns
true
if the current platform has saved group ID functionality. - #switch ⇒ Object private
Class Method Details
.Process::GID.change_privilege(group) ⇒ Integer
7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 |
# File 'process.c', line 7068
static VALUE
p_gid_change_privilege(VALUE obj, VALUE id)
{
rb_gid_t gid;
check_gid_switch();
gid = OBJ2GID(id);
if (geteuid() == 0) { /* root-user */
#if defined(HAVE_SETRESGID)
if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
#elif defined HAVE_SETGID
if (setgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
if (getgid() == gid) {
if (SAVED_GROUP_ID == gid) {
if (setregid(-1, gid) < 0) rb_sys_fail(0);
}
else {
if (gid == 0) { /* (r,e,s) == (root, y, x) */
if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
if (setregid(gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
else { /* (r,e,s) == (z, y, x) */
if (setregid(0, 0) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = 0;
if (setregid(gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
}
}
else {
if (setregid(gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
#elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
if (getgid() == gid) {
if (SAVED_GROUP_ID == gid) {
if (setegid(gid) < 0) rb_sys_fail(0);
}
else {
if (gid == 0) {
if (setegid(gid) < 0) rb_sys_fail(0);
if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = 0;
if (setrgid(0) < 0) rb_sys_fail(0);
}
else {
if (setrgid(0) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = 0;
if (setegid(gid) < 0) rb_sys_fail(0);
if (setrgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
}
}
else {
if (setegid(gid) < 0) rb_sys_fail(0);
if (setrgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
#else
rb_notimplement();
#endif
}
else { /* unprivileged user */
#if defined(HAVE_SETRESGID)
if (setresgid((getgid() == gid)? (rb_gid_t)-1: gid,
(getegid() == gid)? (rb_gid_t)-1: gid,
(SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
if (SAVED_GROUP_ID == gid) {
if (setregid((getgid() == gid)? (rb_uid_t)-1: gid,
(getegid() == gid)? (rb_uid_t)-1: gid) < 0)
rb_sys_fail(0);
}
else if (getgid() != gid) {
if (setregid(gid, (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
else if (/* getgid() == gid && */ getegid() != gid) {
if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (setregid(gid, -1) < 0) rb_sys_fail(0);
}
else { /* getgid() == gid && getegid() == gid */
if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (setregid(gid, -1) < 0) rb_sys_fail(0);
}
#elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
if (SAVED_GROUP_ID == gid) {
if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
}
else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
if (getgid() != gid) {
if (setrgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
else {
if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (setrgid(gid) < 0) rb_sys_fail(0);
}
}
else if (/* getegid() != gid && */ getgid() == gid) {
if (setegid(gid) < 0) rb_sys_fail(0);
if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (setrgid(gid) < 0) rb_sys_fail(0);
}
else {
rb_syserr_fail(EPERM, 0);
}
#elif defined HAVE_44BSD_SETGID
if (getgid() == gid) {
/* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
if (setgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
else {
rb_syserr_fail(EPERM, 0);
}
#elif defined HAVE_SETEGID
if (getgid() == gid && SAVED_GROUP_ID == gid) {
if (setegid(gid) < 0) rb_sys_fail(0);
}
else {
rb_syserr_fail(EPERM, 0);
}
#elif defined HAVE_SETGID
if (getgid() == gid && SAVED_GROUP_ID == gid) {
if (setgid(gid) < 0) rb_sys_fail(0);
}
else {
rb_syserr_fail(EPERM, 0);
}
#else
(void)gid;
rb_notimplement();
#endif
}
return id;
}
|
.egid ⇒ Integer .Process::GID.eid ⇒ Integer .Process::Sys.geteid ⇒ Integer
7362 7363 7364 7365 7366 7367 7368 |
# File 'process.c', line 7362
static VALUE
proc_getegid(VALUE obj)
{
rb_gid_t egid = getegid();
return GIDT2NUM(egid);
}
|
.Process::GID.from_name(name) ⇒ Object
6118 6119 6120 6121 6122 |
# File 'process.c', line 6118
static VALUE
p_gid_from_name(VALUE self, VALUE id)
{
return GIDT2NUM(OBJ2GID(id));
}
|
.Process::GID.grant_privilege(group) ⇒ Integer .Process::GID.eid( = group) ⇒ Integer
7473 7474 7475 7476 7477 7478 |
# File 'process.c', line 7473
static VALUE
p_gid_grant_privilege(VALUE obj, VALUE id)
{
rb_setegid_core(OBJ2GID(id));
return id;
}
|
.Process::GID.re_exchange ⇒ Integer
7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 |
# File 'process.c', line 7577
static VALUE
p_gid_exchange(VALUE obj)
{
rb_gid_t gid;
#if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
rb_gid_t egid;
#endif
check_gid_switch();
gid = getgid();
#if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
egid = getegid();
#endif
#if defined(HAVE_SETRESGID)
if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
if (setregid(egid,gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
#else
rb_notimplement();
#endif
return GIDT2NUM(gid);
}
|
.Process::GID.re_exchangeable? ⇒ Boolean
Returns true
if the real and effective group IDs of a process may be exchanged on the current platform.
7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 |
# File 'process.c', line 7552
static VALUE
p_gid_exchangeable(VALUE _)
{
#if defined(HAVE_SETRESGID)
return Qtrue;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
return Qtrue;
#else
return Qfalse;
#endif
}
|
.gid ⇒ Integer .Process::GID.rid ⇒ Integer .Process::Sys.getgid ⇒ Integer
6665 6666 6667 6668 6669 6670 |
# File 'process.c', line 6665
static VALUE
proc_getgid(VALUE obj)
{
rb_gid_t gid = getgid();
return GIDT2NUM(gid);
}
|
.Process::GID.sid_available? ⇒ Boolean
Returns true
if the current platform has saved group ID functionality.
7730 7731 7732 7733 7734 7735 7736 7737 7738 |
# File 'process.c', line 7730
static VALUE
p_gid_have_saved_id(VALUE _)
{
#if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
return Qtrue;
#else
return Qfalse;
#endif
}
|
.switch ⇒ Object
7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 |
# File 'process.c', line 7808
static VALUE
p_gid_switch(VALUE obj)
{
rb_gid_t gid, egid;
check_gid_switch();
gid = getgid();
egid = getegid();
if (gid == egid) {
rb_syserr_fail(EPERM, 0);
}
p_gid_exchange(obj);
if (rb_block_given_p()) {
under_gid_switch = 1;
return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, obj);
}
else {
return GIDT2NUM(egid);
}
}
|
Instance Method Details
#Process::GID.change_privilege(group) ⇒ Integer (private)
7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 |
# File 'process.c', line 7068
static VALUE
p_gid_change_privilege(VALUE obj, VALUE id)
{
rb_gid_t gid;
check_gid_switch();
gid = OBJ2GID(id);
if (geteuid() == 0) { /* root-user */
#if defined(HAVE_SETRESGID)
if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
#elif defined HAVE_SETGID
if (setgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
if (getgid() == gid) {
if (SAVED_GROUP_ID == gid) {
if (setregid(-1, gid) < 0) rb_sys_fail(0);
}
else {
if (gid == 0) { /* (r,e,s) == (root, y, x) */
if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
if (setregid(gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
else { /* (r,e,s) == (z, y, x) */
if (setregid(0, 0) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = 0;
if (setregid(gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
}
}
else {
if (setregid(gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
#elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
if (getgid() == gid) {
if (SAVED_GROUP_ID == gid) {
if (setegid(gid) < 0) rb_sys_fail(0);
}
else {
if (gid == 0) {
if (setegid(gid) < 0) rb_sys_fail(0);
if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = 0;
if (setrgid(0) < 0) rb_sys_fail(0);
}
else {
if (setrgid(0) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = 0;
if (setegid(gid) < 0) rb_sys_fail(0);
if (setrgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
}
}
else {
if (setegid(gid) < 0) rb_sys_fail(0);
if (setrgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
#else
rb_notimplement();
#endif
}
else { /* unprivileged user */
#if defined(HAVE_SETRESGID)
if (setresgid((getgid() == gid)? (rb_gid_t)-1: gid,
(getegid() == gid)? (rb_gid_t)-1: gid,
(SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
if (SAVED_GROUP_ID == gid) {
if (setregid((getgid() == gid)? (rb_uid_t)-1: gid,
(getegid() == gid)? (rb_uid_t)-1: gid) < 0)
rb_sys_fail(0);
}
else if (getgid() != gid) {
if (setregid(gid, (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
else if (/* getgid() == gid && */ getegid() != gid) {
if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (setregid(gid, -1) < 0) rb_sys_fail(0);
}
else { /* getgid() == gid && getegid() == gid */
if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (setregid(gid, -1) < 0) rb_sys_fail(0);
}
#elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
if (SAVED_GROUP_ID == gid) {
if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
}
else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
if (getgid() != gid) {
if (setrgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
else {
if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (setrgid(gid) < 0) rb_sys_fail(0);
}
}
else if (/* getegid() != gid && */ getgid() == gid) {
if (setegid(gid) < 0) rb_sys_fail(0);
if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (setrgid(gid) < 0) rb_sys_fail(0);
}
else {
rb_syserr_fail(EPERM, 0);
}
#elif defined HAVE_44BSD_SETGID
if (getgid() == gid) {
/* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
if (setgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
else {
rb_syserr_fail(EPERM, 0);
}
#elif defined HAVE_SETEGID
if (getgid() == gid && SAVED_GROUP_ID == gid) {
if (setegid(gid) < 0) rb_sys_fail(0);
}
else {
rb_syserr_fail(EPERM, 0);
}
#elif defined HAVE_SETGID
if (getgid() == gid && SAVED_GROUP_ID == gid) {
if (setgid(gid) < 0) rb_sys_fail(0);
}
else {
rb_syserr_fail(EPERM, 0);
}
#else
(void)gid;
rb_notimplement();
#endif
}
return id;
}
|
#egid ⇒ Integer (private) #Process::GID.eid ⇒ Integer (private) #Process::Sys.geteid ⇒ Integer (private)
7362 7363 7364 7365 7366 7367 7368 |
# File 'process.c', line 7362
static VALUE
proc_getegid(VALUE obj)
{
rb_gid_t egid = getegid();
return GIDT2NUM(egid);
}
|
#Process::GID.from_name(name) ⇒ Object (private)
6118 6119 6120 6121 6122 |
# File 'process.c', line 6118
static VALUE
p_gid_from_name(VALUE self, VALUE id)
{
return GIDT2NUM(OBJ2GID(id));
}
|
#Process::GID.grant_privilege(group) ⇒ Integer (private) #Process::GID.eid( = group) ⇒ Integer (private)
7473 7474 7475 7476 7477 7478 |
# File 'process.c', line 7473
static VALUE
p_gid_grant_privilege(VALUE obj, VALUE id)
{
rb_setegid_core(OBJ2GID(id));
return id;
}
|
#Process::GID.re_exchange ⇒ Integer (private)
7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 |
# File 'process.c', line 7577
static VALUE
p_gid_exchange(VALUE obj)
{
rb_gid_t gid;
#if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
rb_gid_t egid;
#endif
check_gid_switch();
gid = getgid();
#if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
egid = getegid();
#endif
#if defined(HAVE_SETRESGID)
if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
if (setregid(egid,gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
#else
rb_notimplement();
#endif
return GIDT2NUM(gid);
}
|
#Process::GID.re_exchangeable? ⇒ Boolean (private)
Returns true
if the real and effective group IDs of a process may be exchanged on the current platform.
7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 |
# File 'process.c', line 7552
static VALUE
p_gid_exchangeable(VALUE _)
{
#if defined(HAVE_SETRESGID)
return Qtrue;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
return Qtrue;
#else
return Qfalse;
#endif
}
|
#gid ⇒ Integer (private) #Process::GID.rid ⇒ Integer (private) #Process::Sys.getgid ⇒ Integer (private)
6665 6666 6667 6668 6669 6670 |
# File 'process.c', line 6665
static VALUE
proc_getgid(VALUE obj)
{
rb_gid_t gid = getgid();
return GIDT2NUM(gid);
}
|
#Process::GID.sid_available? ⇒ Boolean (private)
Returns true
if the current platform has saved group ID functionality.
7730 7731 7732 7733 7734 7735 7736 7737 7738 |
# File 'process.c', line 7730
static VALUE
p_gid_have_saved_id(VALUE _)
{
#if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
return Qtrue;
#else
return Qfalse;
#endif
}
|
#switch ⇒ Object (private)
7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 |
# File 'process.c', line 7808
static VALUE
p_gid_switch(VALUE obj)
{
rb_gid_t gid, egid;
check_gid_switch();
gid = getgid();
egid = getegid();
if (gid == egid) {
rb_syserr_fail(EPERM, 0);
}
p_gid_exchange(obj);
if (rb_block_given_p()) {
under_gid_switch = 1;
return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, obj);
}
else {
return GIDT2NUM(egid);
}
}
|