ARG_MAX
| Shells
| portability
| permissions
| UUOC
| ancient
| -
| ../Various
| HOME
$()
vs )
| IFS
| using siginfo
| nanosleep
| line charset
| locale
Back to the main page.
I am glad that the following is available in the
TUHS
Research Unix archive.
The source code was released by Alcatel-Lucent with a
Statement Regarding Research Unix Editions 8, 9, and 10 about non-commercial usage.
Here are extracts from 8th edition
/usr/sys/h/user.h
and
/usr/src/sys/sys1.c
with some arbitrary emphasis in bold face.
user.h:
#define SHSIZE 32 struct user { [...] union { struct { /* header of executable file */ int Ux_mag; /* magic number */ unsigned Ux_tsize; /* text size */ unsigned Ux_dsize; /* data size */ unsigned Ux_bsize; /* bss size */ unsigned Ux_ssize; /* symbol table size */ unsigned Ux_entloc; /* entry location */ unsigned Ux_unused; unsigned Ux_relflg; } Ux_A; char ux_shell[SHSIZE]; /* #! and name of interpreter */ } u_exdata; [...] };
sys1.c
/* * exec system call, with and without environments. */ struct execa { char *fname; char **argp; char **envp; }; exec() { ((struct execa *)u.u_ap)->envp = NULL; exece(); } struct shdata { struct direct sd_save; int sd_gid; int sd_uid; int sd_indir; char sd_flag[SHSIZE]; }; struct swargs { char *sw_cp; int sw_argc; int sw_envc; int sw_chars; int sw_bn; struct buf *sw_bp; }; [...] exece() { register int i; register int ap; register int bsize; register char *cp; register char *ucp; register struct execa *uap; struct buf *bp; struct inode *ip; struct shdata sh; struct swargs sw; extern struct inode *gethead(); sh.sd_uid = u.u_uid; sh.sd_gid = u.u_gid; sh.sd_indir = 0; sh.sd_flag[0] = '\0'; if ((ip = gethead(&sh)) == NULL) return; [...] } /* * Get a shell after #! magic number. */ struct inode * getshell(ip, sp) struct inode *ip; struct shdata *sp; { register char *cp; extern struct inode *gethead(); if(u.u_exdata.ux_shell[0] != '#' || u.u_exdata.ux_shell[1] != '!' || sp->sd_indir) goto error; cp = &u.u_exdata.ux_shell[2]; for (;;) { if (cp == &u.u_exdata.ux_shell[SHSIZE]) goto error; if (*cp == '\n') { *cp = '\0'; break; } if (*cp == '\t') *cp = ' '; cp++; } for (cp = &u.u_exdata.ux_shell[2]; *cp == ' '; cp++); if (*cp == '\0') goto error; u.u_dirp = cp; while (*cp != '\0') { if (*cp == ' ') { *cp++ = '\0'; while (*cp == ' ') cp++; /* * Shell argument (one only). */ if (*cp != '\0') { register int i; i = 0; do sp->sd_flag[i++] = *cp++; while (*cp != ' ' && *cp != '\0'); sp->sd_flag[i] = '\0'; } break; } else cp++; } iput(ip); sp->sd_save = u.u_dent; sp->sd_indir = 1; return gethead(sp); error: iput(ip); u.u_error = ENOEXEC; return NULL; } /* * Get the header of an executable and do all the right tests. */ struct inode * gethead(sp) struct shdata *sp; { register struct inode *ip; if ((ip = namei(sp->sd_indir ? schar : uchar, 0, 1)) == NULL) return NULL; /* * Setuid and setgid denied for network root. */ if ((ip->i_mode & ISUID) != 0 && ip->i_uid != -1) sp->sd_uid = ip->i_uid; if ((ip->i_mode & ISGID) != 0 && ip->i_gid != -1) sp->sd_gid = ip->i_gid; /* * Check permission. May not trace something we can't read. */ if(access(ip, IEXEC) || (PTRACED(u.u_procp) && access(ip, IREAD))) goto out; /* * Must be a regular file and must really be executable. */ if ((ip->i_mode & IFMT) != IFREG || (ip->i_mode & (IEXEC | (IEXEC >> 3) | (IEXEC >> 6))) == 0) { u.u_error = EACCES; goto out; } /* * ux_mag = 407/410/413 * 407 is plain executable * 410 is RO text * 413 is demand paged RO text * * Also an ASCII line beginning with #! is * the file name of a ``shell'' and arguments may be prepended * to the argument list if given here. * * Shell names are limited in length. * * Only one argument may be passed to the shell from the ASCII line. */ u.u_base = (caddr_t)&u.u_exdata; u.u_count = sizeof(u.u_exdata); u.u_offset = 0; u.u_segflg = 1; readi(ip); u.u_segflg = 0; if (u.u_error) goto out; if (u.u_count > sizeof (u.u_exdata) - sizeof (u.u_exdata.Ux_A)) ip = getshell(ip, sp); else { switch (u.u_exdata.ux_mag) { case 0407: u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; u.u_exdata.ux_tsize = 0; break; case 0410: case 0413: if (u.u_exdata.ux_tsize == 0) u.u_error = ENOEXEC; break; default: ip = getshell(ip, sp); } } out: if (u.u_error && ip != NULL) { iput(ip); ip = NULL; } return ip; } [...]