Re: sh and process management

2006-07-16 Thread Otto Moerbeek
On Sun, 16 Jul 2006, Gustavo Rios wrote:

> Ok, here you have it:

I'm sorry, but I'm not gonna go though this bit flag mess. 

Until you come up with a simple (let's say less than 10 lines) piece
of code to demonstrate the porblem you're seeing, my conclusion is the
bug is hiding in your code.

-Otto

> 
> Code for apx_setuid :
> #include 
> 
> long
> apx_setsid(void)
> {
>return setsid();
> }
> 
> Code for apx_setpgid :
> 
> #include 
> 
> int
> apx_setpgid(const long p, const long g)
> {
>return setpgid((pid_t)p, (pid_t)g);
> }
> 
> 
> Code for sux (main.c) : (the relevant part is option -s and function do_sid)
> 
> #include 
> #include 
> #include 
> 
> #include "abf.h"
> #include "amp.h"
> #include "apx.h"
> #include "msc.h"
> #include "rsc.h"
> #include "sdb.h"
> 
> extern int  r2e __P((int));
> extern void wrn __P((int)),
>die __P((int));
> 
> static int
> do_env(const xlong f, const char *e)
> {
>struct amp  a;
>xlong   n, x;
>int r = 0;
> 
>if (f) *apx_environ = NULL;
>if (e) {
>amp_opn(&a);
>r = env_h2b(&a, e, apx_strlen(e));
>if (!r) for (e = a.b, n = a.s.x; n; e += x, n -= x) {
>if (!(x = chr(e, n, '+'))) break;
>if (r = apx_putenv(e + x)) break;
>}
>amp_cls(&a);
>}
>return r;
> }
> 
> static int
> do_dir(const char * const d)
> {
>return d ? apx_chdir(d) : 0;
> }
> 
> static long
> do_fork(const xlong f)
> {
>return f ? apx_fork() : 0l;
> }
> 
> static int
> do_sid(const xlong f)
> {
>int r;
> 
>if (r = 0, f & 1)
>if (f & 2) { if (apx_setsid() == -1) r = -1; }
>else r = apx_setpgid(0l, apx_getpid());
> 
>return r;
> }
> 
> static int
> do_prio(const char * const s)
> {
>xlong   x;
>int r;
> 
>if (r = 0, s) {
>if (!scn_u(&x, s)) r = 5;
>if (!r) r = apx_setprio(prio_process, 0l, (int)x);
>}
>return r;
> }
> 
> static int
> do_ioe(const char * const s)
> {
>xlong   x;
>int r;
> 
>if (r = 0, s) {
>if (!scn_x(&x, s)) r = 5;
>if (!r) r = apx_setioe((int)x, NULL, NULL);
>}
>return r;
> }
> 
> static int
> do_rsc(const char * const s)
> {
>struct sdb  sd;
>struct rsc  rs;
>xlong   i;
>int r;
> 
>rsc_opn(&rs);
>sdb_opn(&sd);
>r = s ? getrsc(&rs, &sd, s) : 0;
>if (!r) for (i = 0; i < rs.sze.x; i++)
>(void)apx_setrlmt(rs.rds[i].idx, &rs.rds[i].val);
>sdb_cls(&sd);
>rsc_cls(&rs);
>return r;
> }
> 
> static int
> do_crd(const char * const u, const char * const g, const char * const G)
> {
>struct passwd   *pwd = NULL;
>struct group*grp = NULL;
>struct amp  a;
>xlong   v;
>xadk32_ts[ngroups_max];
>int r = 0;
>char*p;
> 
>if (u) if (!(pwd = getpwnam(u))) r = 4;
>if (!r) if (g) if (!(grp = getgrnam(g))) r = 4;
>if (!r) {
>v = grp ? grp->gr_gid : pwd ? pwd->pw_gid : -1ul;
>if (v + 1) r = apx_setgid(v);
>}
> 
>if (!r) if (G) {
>amp_opn(&a);
>r = amp_mem(&a, G, apx_strlen(G));
>if (!r) r = amp_chr(&a, '\0');
>if (!r) {
>for (p = a.b; *p; p++) if (*p == ',') *p = '\0';
>for (v = 0, p = a.b; p - a.b < a.s.x; v++, p++) {
>if (v == ngroups_max) break;
>if (!(grp = getgrnam(p))) break;
>s[v] = grp->gr_gid;
>while (*p) p++;
>}
>if (p - a.b < a.s.x) if (v < ngroups_max) r = 4;
>}
>amp_cls(&a);
>if (!r) if (!v) r = 5;
>if (!r) r = apx_setgrp(s, v);
>}
> 
>if (!r) if (pwd) r = apx_setuid(0ul+pwd->pw_uid);
> 
>return r;
> }
> 
> static int
> do_exec(char **a)
> {
>(void)apx_execve(*a, a + 1, apx_environ);
>return 2;
> }
> 
> static long
> __chk(char *s[8])
> {
>xlong   n;
> 
>for (n = 8; n; n--) if (s[n - 1]) break;
>return n;
> }
> 
> int
> main(int argc, char **argv)
> {
>xlong   i, f;
>int r;
>char*s[8],
>o[] = "fspeu:g:G:d:n:E:x:r:";
> 
>apx_memset(s, 0, sizeof s);
>apx_opterr = 0;
>i = f = 0;
> 
>while ((r = apx_getopt(argc, argv, o)) + 1)
>switch (r) {
>case 'f' : f |= 1; break;
>  

Re: sh and process management

2006-07-16 Thread Philip Guenther

On 7/16/06, Gustavo Rios <[EMAIL PROTECTED]> wrote:
...

static int
do_sid(const xlong f)
{
int r;

if (r = 0, f & 1)
if (f & 2) { if (apx_setsid() == -1) r = -1; }
else r = apx_setpgid(0l, apx_getpid());

return r;
}


Wow, what an annoying set of coding conventions you use.  The best
part is, the bug is in your use of one of them: use of unnamed bit
flags with particular flags being stored in _different_bits_ in
different parts of the code.  (i.e., the "do setsid()" flag is 4 in
main but 2 in the above.  Using the same values and defining symbolic
names would have kept this problem from occuring.   Not trying to be
too clever would have helped too.

So, please consider the above code and then think _really_ hard about
the code that determines the value of 'f' in that call:

...

case 's' : f |= 2, f |= 4; break;
case 'p' : f |= 2, f &= ~4; break;

...

if (!r) r = do_sid(f & 6 >> 1);


That last line contains the bug, but the _source_ of the bug is either
the lack of symbolic constants or your decision to use bitflags at all
instead of just putting the flags in separate variables.


Philip Guenther



Re: sh and process management

2006-07-16 Thread Gustavo Rios

Ok, here you have it:

Code for apx_setuid :
#include 

long
apx_setsid(void)
{
   return setsid();
}

Code for apx_setpgid :

#include 

int
apx_setpgid(const long p, const long g)
{
   return setpgid((pid_t)p, (pid_t)g);
}


Code for sux (main.c) : (the relevant part is option -s and function do_sid)

#include 
#include 
#include 

#include "abf.h"
#include "amp.h"
#include "apx.h"
#include "msc.h"
#include "rsc.h"
#include "sdb.h"

extern int  r2e __P((int));
extern void wrn __P((int)),
   die __P((int));

static int
do_env(const xlong f, const char *e)
{
   struct amp  a;
   xlong   n, x;
   int r = 0;

   if (f) *apx_environ = NULL;
   if (e) {
   amp_opn(&a);
   r = env_h2b(&a, e, apx_strlen(e));
   if (!r) for (e = a.b, n = a.s.x; n; e += x, n -= x) {
   if (!(x = chr(e, n, '+'))) break;
   if (r = apx_putenv(e + x)) break;
   }
   amp_cls(&a);
   }
   return r;
}

static int
do_dir(const char * const d)
{
   return d ? apx_chdir(d) : 0;
}

static long
do_fork(const xlong f)
{
   return f ? apx_fork() : 0l;
}

static int
do_sid(const xlong f)
{
   int r;

   if (r = 0, f & 1)
   if (f & 2) { if (apx_setsid() == -1) r = -1; }
   else r = apx_setpgid(0l, apx_getpid());

   return r;
}

static int
do_prio(const char * const s)
{
   xlong   x;
   int r;

   if (r = 0, s) {
   if (!scn_u(&x, s)) r = 5;
   if (!r) r = apx_setprio(prio_process, 0l, (int)x);
   }
   return r;
}

static int
do_ioe(const char * const s)
{
   xlong   x;
   int r;

   if (r = 0, s) {
   if (!scn_x(&x, s)) r = 5;
   if (!r) r = apx_setioe((int)x, NULL, NULL);
   }
   return r;
}

static int
do_rsc(const char * const s)
{
   struct sdb  sd;
   struct rsc  rs;
   xlong   i;
   int r;

   rsc_opn(&rs);
   sdb_opn(&sd);
   r = s ? getrsc(&rs, &sd, s) : 0;
   if (!r) for (i = 0; i < rs.sze.x; i++)
   (void)apx_setrlmt(rs.rds[i].idx, &rs.rds[i].val);
   sdb_cls(&sd);
   rsc_cls(&rs);
   return r;
}

static int
do_crd(const char * const u, const char * const g, const char * const G)
{
   struct passwd   *pwd = NULL;
   struct group*grp = NULL;
   struct amp  a;
   xlong   v;
   xadk32_ts[ngroups_max];
   int r = 0;
   char*p;

   if (u) if (!(pwd = getpwnam(u))) r = 4;
   if (!r) if (g) if (!(grp = getgrnam(g))) r = 4;
   if (!r) {
   v = grp ? grp->gr_gid : pwd ? pwd->pw_gid : -1ul;
   if (v + 1) r = apx_setgid(v);
   }

   if (!r) if (G) {
   amp_opn(&a);
   r = amp_mem(&a, G, apx_strlen(G));
   if (!r) r = amp_chr(&a, '\0');
   if (!r) {
   for (p = a.b; *p; p++) if (*p == ',') *p = '\0';
   for (v = 0, p = a.b; p - a.b < a.s.x; v++, p++) {
   if (v == ngroups_max) break;
   if (!(grp = getgrnam(p))) break;
   s[v] = grp->gr_gid;
   while (*p) p++;
   }
   if (p - a.b < a.s.x) if (v < ngroups_max) r = 4;
   }
   amp_cls(&a);
   if (!r) if (!v) r = 5;
   if (!r) r = apx_setgrp(s, v);
   }

   if (!r) if (pwd) r = apx_setuid(0ul+pwd->pw_uid);

   return r;
}

static int
do_exec(char **a)
{
   (void)apx_execve(*a, a + 1, apx_environ);
   return 2;
}

static long
__chk(char *s[8])
{
   xlong   n;

   for (n = 8; n; n--) if (s[n - 1]) break;
   return n;
}

int
main(int argc, char **argv)
{
   xlong   i, f;
   int r;
   char*s[8],
   o[] = "fspeu:g:G:d:n:E:x:r:";

   apx_memset(s, 0, sizeof s);
   apx_opterr = 0;
   i = f = 0;

   while ((r = apx_getopt(argc, argv, o)) + 1)
   switch (r) {
   case 'f' : f |= 1; break;
   case 's' : f |= 2, f |= 4; break;
   case 'p' : f |= 2, f &= ~4; break;
   case 'e' : f |= 8; break;
   case 'u' : s[0] = apx_optarg; break;
   case 'g' : s[1] = apx_optarg; break;
   case 'G' : s[2] = apx_optarg; break;
   case 'd' : s[3] = apx_optarg; break;
   case 'n' : s[4] = apx_optarg; break;
   case 'E' : s[5] = apx_optarg; break;
   case 'x' : s[6] = apx_optarg; break;
   case 'r' : s[7] = apx_optarg; break;
   }
   argc -= apx_optind, argv += apx_optind;

   r = f || __chk(s) ? 0 : argc < 3 ? 1 : (s[0] = *argv++, argc--, 0)

Re: sh and process management

2006-07-16 Thread Philip Guenther

On 7/15/06, Gustavo Rios <[EMAIL PROTECTED]> wrote:

i am trying to set a process as the session leader of its own. I wrote
a simple program that handles that. It is working when i call it from
my shell command line:

...

But when i write a simple shell script like in :



The process is not put on its own session as a leader the (setsid)
returns no errors.


/bin/sh doesn't change the process-group of the processes that it
invokes, while interactive shells with job-control support do change
it, so that's the difference between invocation from a script versus
an interactive shell.  Unfortunately, it would suggest the _opposite_
behavior: setsid() from a process run by an interactive shell should
fail.  Too bad you didn't provide a complete description of the system
calls made by your program, or direct evidence (say, the output of ps
-j) of the results of running it in the two cases.  As is, my current
guess is that you're misreading the 'ps' output and confusing the
concepts of process-group leader and session leader.


Philip Guenther



Re: sh and process management

2006-07-15 Thread Otto Moerbeek
On Sun, 16 Jul 2006, Gustavo Rios wrote:

> Hey folks,
> 
> i am trying to set a process as the session leader of its own. I wrote
> a simple program that handles that. It is working when i call it from
> my shell command line:
> 
> $ sux -s -e -E \
> PATH==/home/grios/.bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/usr/games:/asd/bin:/asd/sbin:/asd/thr=,ASDROOT==/asd=
> /asd/sbin/algr algr argm 
> 
> But when i write a simple shell script like in :
> 
> #!/bin/sh
> sux -s -e -E \
> PATH==/home/grios/.bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/usr/games:/asd/bin:/asd/sbin:/asd/thr=,ASDROOT==/asd=
> /asd/sbin/algr algr argm 
> 
> The process is not put on its own session as a leader the (setsid)
> returns no errors.
> 
> Does anybody have any ideia what the behavior problem i am not seeing ?

Please show the code.

How do you check if the program has become session leader?

Any other process group/session stuff being done in your program?

-Otto



sh and process management

2006-07-15 Thread Gustavo Rios

Hey folks,

i am trying to set a process as the session leader of its own. I wrote
a simple program that handles that. It is working when i call it from
my shell command line:

$ sux -s -e -E \
PATH==/home/grios/.bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/usr/games:/asd/bin:/asd/sbin:/asd/thr=,ASDROOT==/asd=
/asd/sbin/algr algr argm 

But when i write a simple shell script like in :

#!/bin/sh
sux -s -e -E \ 
PATH==/home/grios/.bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/usr/games:/asd/bin:/asd/sbin:/asd/thr=,ASDROOT==/asd=
/asd/sbin/algr algr argm 

The process is not put on its own session as a leader the (setsid)
returns no errors.

Does anybody have any ideia what the behavior problem i am not seeing ?

Thanks in advance.