code ~/unix-v6/ken/main.c & nami.c

2026-10-05

//main.c

#include "../param.h"
#include "../user.h"
#include "../systm.h"
#include "../proc.h"
#include "../text.h"
#include "../inode.h"
#include "../seg.h"

#define CLOCK1  0177546
#define CLOCK2  0172540
/*
 * Icode is the octal bootstrap
 * program executed in user mode
 * to bring up the system.
 */
int icode[]
{
    0104413,    /* sys exec; init; initp */
    0000014,
    0000010,
    0000777,    /* br . */
    0000014,    /* initp: init; 0 */
    0000000,
    0062457,    /* init: </etc/init\0> */
    0061564,
    0064457,
    0064556,
    0000164,
};

/*
 * Initialization code.
 * Called from m40.s or m45.s as
 * soon as a stack and segmentation
 * have been established.
 * Functions:
 *  clear and free user core
 *  find which clock is configured
 *  hand craft 0th process
 *  call all initialization routines
 *  fork - process 0 to schedule
 *       - process 1 execute bootstrap
 *
 * panic: no clock -- neither clock responds
 * loop at loc 6 in user mode -- /etc/init
 *  cannot be executed.
 */
main()
{
    extern schar;
    register i, *p;

    /*
     * zero and free all of core
     */

    updlock = 0;
    i = *ka6 + USIZE;
    UISD->r[0] = 077406;
    for(;;) {
        UISA->r[0] = i;
        if(fuibyte(0) < 0)
            break;
        clearseg(i);
        maxmem++;
        mfree(coremap, 1, i);
        i++;
    }
    if(cputype == 70)
    for(i=0; i<62; i=+2) {
        UBMAP->r[i] = i<<12;
        UBMAP->r[i+1] = 0;
    }
    printf("mem = %l\n", maxmem*5/16);
    maxmem = min(maxmem, MAXMEM);
    mfree(swapmap, nswap, swplo);

    /*
     * determine clock
     */

    UISA->r[7] = ka6[1]; /* io segment */
    UISD->r[7] = 077406;
    lks = CLOCK1;
    if(fuiword(lks) == -1) {
        lks = CLOCK2;
        if(fuiword(lks) == -1)
            panic("no clock");
    }

    /*
     * set up system process
     */

    proc[0].p_addr = *ka6;
    proc[0].p_size = USIZE;
    proc[0].p_stat = SRUN;
    proc[0].p_flag =| SLOAD|SSYS;
    u.u_procp = &proc[0];

    /*
     * set up 'known' i-nodes
     */

    *lks = 0115;
    cinit();
    binit();
    iinit();
    rootdir = iget(rootdev, ROOTINO);
    rootdir->i_flag =& ~ILOCK;
    u.u_cdir = iget(rootdev, ROOTINO);
    u.u_cdir->i_flag =& ~ILOCK;

    /*
     * make init process
     * enter scheduling loop
     * with system process
     */

    if(newproc()) {
        expand(USIZE+1);
        estabur(0, 1, 0, 0);
        copyout(icode, 0, sizeof icode);
        /*
         * Return goes to loc. 0 of user init
         * code just copied out.
         */
        return;
    }
    sched();
}

/*
 * Load the user hardware segmentation
 * registers from the software prototype.
 * The software registers must have
 * been setup prior by estabur.
 */
sureg()
{
    register *up, *rp, a;

    a = u.u_procp->p_addr;
    up = &u.u_uisa[16];
    rp = &UISA->r[16];
    if(cputype == 40) {
        up =- 8;
        rp =- 8;
    }
    while(rp > &UISA->r[0])
        *--rp = *--up + a;
    if((up=u.u_procp->p_textp) != NULL)
        a =- up->x_caddr;
    up = &u.u_uisd[16];
    rp = &UISD->r[16];
    if(cputype == 40) {
        up =- 8;
        rp =- 8;
    }
    while(rp > &UISD->r[0]) {
        *--rp = *--up;
        if((*rp & WO) == 0)
            rp[(UISA-UISD)/2] =- a;
    }
}

/*
 * Set up software prototype segmentation
 * registers to implement the 3 pseudo
 * text,data,stack segment sizes passed
 * as arguments.
 * The argument sep specifies if the
 * text and data+stack segments are to
 * be separated.
 */
estabur(nt, nd, ns, sep)
{
    register a, *ap, *dp;

    if(sep) {
        if(cputype == 40)
            goto err;
        if(nseg(nt) > 8 || nseg(nd)+nseg(ns) > 8)
            goto err;
    } else
        if(nseg(nt)+nseg(nd)+nseg(ns) > 8)
            goto err;
    if(nt+nd+ns+USIZE > maxmem)
        goto err;
    a = 0;
    ap = &u.u_uisa[0];
    dp = &u.u_uisd[0];
    while(nt >= 128) {
        *dp++ = (127<<8) | RO;
        *ap++ = a;
        a =+ 128;
        nt =- 128;
    }
    if(nt) {
        *dp++ = ((nt-1)<<8) | RO;
        *ap++ = a;
    }
    if(sep)
    while(ap < &u.u_uisa[8]) {
        *ap++ = 0;
        *dp++ = 0;
    }
    a = USIZE;
    while(nd >= 128) {
        *dp++ = (127<<8) | RW;
        *ap++ = a;
        a =+ 128;
        nd =- 128;
    }
    if(nd) {
        *dp++ = ((nd-1)<<8) | RW;
        *ap++ = a;
        a =+ nd;
    }
    while(ap < &u.u_uisa[8]) {
        *dp++ = 0;
        *ap++ = 0;
    }
    if(sep)
    while(ap < &u.u_uisa[16]) {
        *dp++ = 0;
        *ap++ = 0;
    }
    a =+ ns;
    while(ns >= 128) {
        a =- 128;
        ns =- 128;
        *--dp = (127<<8) | RW;
        *--ap = a;
    }
    if(ns) {
        *--dp = ((128-ns)<<8) | RW | ED;
        *--ap = a-128;
    }
    if(!sep) {
        ap = &u.u_uisa[0];
        dp = &u.u_uisa[8];
        while(ap < &u.u_uisa[8])
            *dp++ = *ap++;
        ap = &u.u_uisd[0];
        dp = &u.u_uisd[8];
        while(ap < &u.u_uisd[8])
            *dp++ = *ap++;
    }
    sureg();
    return(0);

err:
    u.u_error = ENOMEM;
    return(-1);
}

/*
 * Return the arg/128 rounded up.
 */
nseg(n)
{

    return((n+127)>>7);
}

//nami.c


#include "../param.h"
#include "../inode.h"
#include "../user.h"
#include "../systm.h"
#include "../buf.h"

/*
 * Convert a pathname into a pointer to
 * an inode. Note that the inode is locked.
 *
 * func = function called to get next char of name
 *  &uchar if name is in user space
 *  &schar if name is in system space
 * flag = 0 if name is sought
 *  1 if name is to be created
 *  2 if name is to be deleted
 */
namei(func, flag)
int (*func)();
{
    register struct inode *dp;
    register c;
    register char *cp;
    int eo, *bp;

    /*
     * If name starts with '/' start from
     * root; otherwise start from current dir.
     */

    dp = u.u_cdir;
    if((c=(*func)()) == '/')
        dp = rootdir;
    iget(dp->i_dev, dp->i_number);
    while(c == '/')
        c = (*func)();
    if(c == '\0' && flag != 0) {
        u.u_error = ENOENT;
        goto out;
    }

cloop:
    /*
     * Here dp contains pointer
     * to last component matched.
     */

    if(u.u_error)
        goto out;
    if(c == '\0')
        return(dp);

    /*
     * If there is another component,
     * dp must be a directory and
     * must have x permission.
     */

    if((dp->i_mode&IFMT) != IFDIR) {
        u.u_error = ENOTDIR;
        goto out;
    }
    if(access(dp, IEXEC))
        goto out;

    /*
     * Gather up name into
     * users' dir buffer.
     */

    cp = &u.u_dbuf[0];
    while(c!='/' && c!='\0' && u.u_error==0) {
        if(cp < &u.u_dbuf[DIRSIZ])
            *cp++ = c;
        c = (*func)();
    }
    while(cp < &u.u_dbuf[DIRSIZ])
        *cp++ = '\0';
    while(c == '/')
        c = (*func)();
    if(u.u_error)
        goto out;

    /*
     * Set up to search a directory.
     */

    u.u_offset[1] = 0;
    u.u_offset[0] = 0;
    u.u_segflg = 1;
    eo = 0;
    u.u_count = ldiv(dp->i_size1, DIRSIZ+2);
    bp = NULL;

eloop:

    /*
     * If at the end of the directory,
     * the search failed. Report what
     * is appropriate as per flag.
     */

    if(u.u_count == 0) {
        if(bp != NULL)
            brelse(bp);
        if(flag==1 && c=='\0') {
            if(access(dp, IWRITE))
                goto out;
            u.u_pdir = dp;
            if(eo)
                u.u_offset[1] = eo-DIRSIZ-2; else
                dp->i_flag =| IUPD;
            return(NULL);
        }
        u.u_error = ENOENT;
        goto out;
    }

    /*
     * If offset is on a block boundary,
     * read the next directory block.
     * Release previous if it exists.
     */

    if((u.u_offset[1]&0777) == 0) {
        if(bp != NULL)
            brelse(bp);
        bp = bread(dp->i_dev,
            bmap(dp, ldiv(u.u_offset[1], 512)));
    }

    /*
     * Note first empty directory slot
     * in eo for possible creat.
     * String compare the directory entry
     * and the current component.
     * If they do not match, go back to eloop.
     */

    bcopy(bp->b_addr+(u.u_offset[1]&0777), &u.u_dent, (DIRSIZ+2)/2);
    u.u_offset[1] =+ DIRSIZ+2;
    u.u_count--;
    if(u.u_dent.u_ino == 0) {
        if(eo == 0)
            eo = u.u_offset[1];
        goto eloop;
    }
    for(cp = &u.u_dbuf[0]; cp < &u.u_dbuf[DIRSIZ]; cp++)
        if(*cp != cp[u.u_dent.u_name - u.u_dbuf])
            goto eloop;

    /*
     * Here a component matched in a directory.
     * If there is more pathname, go back to
     * cloop, otherwise return.
     */

    if(bp != NULL)
        brelse(bp);
    if(flag==2 && c=='\0') {
        if(access(dp, IWRITE))
            goto out;
        return(dp);
    }
    bp = dp->i_dev;
    iput(dp);
    dp = iget(bp, u.u_dent.u_ino);
    if(dp == NULL)
        return(NULL);
    goto cloop;

out:
    iput(dp);
    return(NULL);
}

/*
 * Return the next character from the
 * kernel string pointed at by dirp.
 */
schar()
{

    return(*u.u_dirp++ & 0377);
}

/*
 * Return the next character from the
 * user string pointed at by dirp.
 */
uchar()
{
    register c;

    c = fubyte(u.u_dirp++);
    if(c == -1)
        u.u_error = EFAULT;
    return(c);
}

appreciate and respect the origin of modern digital world