3000: #
3001: #include "../param.h"
3002: #include "../systm.h"
3003: #include "../user.h"
3004: #include "../proc.h"
3005: #include "../buf.h"
3006: #include "../reg.h"
3007: #include "../inode.h"
3008:
3009: /*
3010: * exec system call.
3011: * Because of the fact that an I/O buffer is used
3012: * to store the caller's arguments during exec,
3013: * and more buffers are needed to read in the text file,
3014: * deadly embraces waiting for free buffers are possible.
3015: * Therefore the number of processes simultaneously
3016: * running in exec has to be limited to NEXEC.
3017: */
3018: #define EXPRI -1
3019:
3020: exec()
3021: {
3022: int ap, na, nc, *bp;
3023: int ts, ds, sep;
3024: register c, *ip;
3025: register char *cp;
3026: extern uchar;
3027:
3028: /*
3029: * pick up file names
3030: * and check various modes
3031: * for execute permission
3032: */
3033:
3034: ip = namei(&uchar, 0);
3035: if(ip == NULL)
3036: return;
3037: while(execnt >= NEXEC)
3038: sleep(&execnt, EXPRI);
3039: execnt++;
3040: bp = getblk(NODEV);
3041: if(access(ip, IEXEC) || (ip->i_mode&IFMT)!=0)
3042: goto bad;
3043:
3044: /*
3045: * pack up arguments into
3046: * allocated disk buffer
3047: */
3048:
3049: cp = bp->b_addr;
3050: na = 0;
3051: nc = 0;
3052: while(ap = fuword(u.u_arg[1])) {
3053: na++;
3054: if(ap == -1)
3055: goto bad;
3056: u.u_arg[1] =+ 2;
3057: for(;;) {
3058: c = fubyte(ap++);
3059: if(c == -1)
3060: goto bad;
3061: *cp++ = c;
3062: nc++;
3063: if(nc > 510) {
3064: u.u_error = E2BIG;
3065: goto bad;
3066: }
3067: if(c == 0)
3068: break;
3069: }
3070: }
3071: if((nc&1) != 0) {
3072: *cp++ = 0;
3073: nc++;
3074: }
3075:
3076: /* read in first 8 bytes
3077: * of file for segment
3078: * sizes:
3079: * w0 = 407/410/411 (410 implies RO text) (411 implies sep ID)
3080: * w1 = text size
3081: * w2 = data size
3082: * w3 = bss size
3083: */
3084:
3085: u.u_base = &u.u_arg[0];
3086: u.u_count = 8;
3087: u.u_offset[1] = 0;
3088: u.u_offset[0] = 0;
3089: u.u_segflg = 1;
3090: readi(ip);
3091: u.u_segflg = 0;
3092: if(u.u_error)
3093: goto bad;
3094: sep = 0;
3095: if(u.u_arg[0] == 0407) {
3096: u.u_arg[2] =+ u.u_arg[1];
3097: u.u_arg[1] = 0;
3098: } else
3099: if(u.u_arg[0] == 0411)
3100: sep++; else
3101: if(u.u_arg[0] != 0410) {
3102: u.u_error = ENOEXEC;
3103: goto bad;
3104: }
3105: if(u.u_arg[1]!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) {
3106: u.u_error = ETXTBSY;
3107: goto bad;
3108: }
3109:
3110: /*
3111: * find text and data sizes
3112: * try them out for possible
3113: * exceed of max sizes
3114: */
3115:
3116: ts = ((u.u_arg[1]+63)>>6) & 01777;
3117: ds = ((u.u_arg[2]+u.u_arg[3]+63)>>6) & 01777;
3118: if(estabur(ts, ds, SSIZE, sep))
3119: goto bad;
3120:
3121: /*
3122: * allocate and clear core
3123: * at this point, committed
3124: * to the new image
3125: */
3126:
3127: u.u_prof[3] = 0;
3128: xfree();
3129: expand(USIZE);
3130: xalloc(ip);
3131: c = USIZE+ds+SSIZE;
3132: expand(c);
3133: while(--c >= USIZE)
3134: clearseg(u.u_procp->p_addr+c);
3135:
3136: /* read in data segment */
3137:
3138: estabur(0, ds, 0, 0);
3139: u.u_base = 0;
3140: u.u_offset[1] = 020+u.u_arg[1];
3141: u.u_count = u.u_arg[2];
3142: readi(ip);
3143:
3144: /*
3145: * initialize stack segment
3146: */
3147:
3148: u.u_tsize = ts;
3149: u.u_dsize = ds;
3150: u.u_ssize = SSIZE;
3151: u.u_sep = sep;
3152: estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep);
3153: cp = bp->b_addr;
3154: ap = -nc - na*2 - 4;
3155: u.u_ar0[R6] = ap;
3156: suword(ap, na);
3157: c = -nc;
3158: while(na--) {
3159: suword(ap=+2, c);
3160: do
3161: subyte(c++, *cp);
3162: while(*cp++);
3163: }
3164: suword(ap+2, -1);
3165:
3166: /*
3167: * set SUID/SGID protections, if no tracing
3168: */
3169:
3170: if ((u.u_procp->p_flag&STRC)==0) {
3171: if(ip->i_mode&ISUID)
3172: if(u.u_uid != 0) {
3173: u.u_uid = ip->i_uid;
3174: u.u_procp->p_uid = ip->i_uid;
3175: }
3176: if(ip->i_mode&ISGID)
3177: u.u_gid = ip->i_gid;
3178: }
3179:
3180: /* clear sigs, regs and return */
3181:
3182: c = ip;
3183: for(ip = &u.u_signal[0]; ip < &u.u_signal[NSIG]; ip++)
3184: if((*ip & 1) == 0)
3185: *ip = 0;
3186: for(cp = ®loc[0]; cp < ®loc[6];)
3187: u.u_ar0[*cp++] = 0;
3188: u.u_ar0[R7] = 0;
3189: for(ip = &u.u_fsav[0]; ip < &u.u_fsav[25];)
3190: *ip++ = 0;
3191: ip = c;
3192:
3193: bad:
3194: iput(ip);
3195: brelse(bp);
3196: if(execnt >= NEXEC)
3197: wakeup(&execnt);
3198: execnt--;
3199: }
3200: /* --------------------------- */
3201:
3202: /* exit system call:
3203: * pass back caller's r0
3204: */
3205: rexit()
3206: {
3207:
3208: u.u_arg[0] = u.u_ar0[R0] << 8;
3209: exit();
3210: }
3211: /* --------------------------- */
3212:
3213: /* Release resources.
3214: * Save u. area for parent to look at.
3215: * Enter zombie state.
3216: * Wake up parent and init processes,
3217: * and dispose of children.
3218: */
3219: exit()
3220: {
3221: register int *q, a;
3222: register struct proc *p;
3223:
3224: u.u_procp->p_flag =& ~STRC;
3225: for(q = &u.u_signal[0]; q < &u.u_signal[NSIG];)
3226: *q++ = 1;
3227: for(q = &u.u_ofile[0]; q < &u.u_ofile[NOFILE]; q++)
3228: if(a = *q) {
3229: *q = NULL;
3230: closef(a);
3231: }
3232: iput(u.u_cdir);
3233: xfree();
3234: a = malloc(swapmap, 1);
3235: if(a == NULL)
3236: panic("out of swap");
3237: p = getblk(swapdev, a);
3238: bcopy(&u, p->b_addr, 256);
3239: bwrite(p);
3240: q = u.u_procp;
3241: mfree(coremap, q->p_size, q->p_addr);
3242: q->p_addr = a;
3243: q->p_stat = SZOMB;
3244:
3245: loop:
3246: for(p = &proc[0]; p < &proc[NPROC]; p++)
3247: if(q->p_ppid == p->p_pid) {
3248: wakeup(&proc[1]);
3249: wakeup(p);
3250: for(p = &proc[0]; p < &proc[NPROC]; p++)
3251: if(q->p_pid == p->p_ppid) {
3252: p->p_ppid = 1;
3253: if (p->p_stat == SSTOP)
3254: setrun(p);
3255: }
3256: swtch();
3257: /* no return */
3258: }
3259: q->p_ppid = 1;
3260: goto loop;
3261: }
3262: /* --------------------------- */
3263:
3264: /* Wait system call.
3265: * Search for a terminated (zombie) child,
3266: * finally lay it to rest, and collect its status.
3267: * Look also for stopped (traced) children,
3268: * and pass back status from them.
3269: */
3270: wait()
3271: {
3272: register f, *bp;
3273: register struct proc *p;
3274:
3275: f = 0;
3276: loop:
3277: for(p = &proc[0]; p < &proc[NPROC]; p++)
3278: if(p->p_ppid == u.u_procp->p_pid) {
3279: f++;
3280: if(p->p_stat == SZOMB) {
3281: u.u_ar0[R0] = p->p_pid;
3282: bp = bread(swapdev, f=p->p_addr);
3283: mfree(swapmap, 1, f);
3284: p->p_stat = NULL;
3285: p->p_pid = 0;
3286: p->p_ppid = 0;
3287: p->p_sig = 0;
3288: p->p_ttyp = 0;
3289: p->p_flag = 0;
3290: p = bp->b_addr;
3291: u.u_cstime[0] =+ p->u_cstime[0];
3292: dpadd(u.u_cstime, p->u_cstime[1]);
3293: dpadd(u.u_cstime, p->u_stime);
3294: u.u_cutime[0] =+ p->u_cutime[0];
3295: dpadd(u.u_cutime, p->u_cutime[1]);
3296: dpadd(u.u_cutime, p->u_utime);
3297: u.u_ar0[R1] = p->u_arg[0];
3298: brelse(bp);
3299: return;
3300: }
3301: if(p->p_stat == SSTOP) {
3302: if((p->p_flag&SWTED) == 0) {
3303: p->p_flag =| SWTED;
3304: u.u_ar0[R0] = p->p_pid;
3305: u.u_ar0[R1] = (p->p_sig<<8) | 0177;
3306: return;
3307: }
3308: p->p_flag =& ~(STRC|SWTED);
3309: setrun(p);
3310: }
3311: }
3312: if(f) {
3313: sleep(u.u_procp, PWAIT);
3314: goto loop;
3315: }
3316: u.u_error = ECHILD;
3317: }
3318: /* --------------------------- */
3319:
3320: /* fork system call.
3321: */
3322: fork()
3323: {
3324: register struct proc *p1, *p2;
3325:
3326: p1 = u.u_procp;
3327: for(p2 = &proc[0]; p2 < &proc[NPROC]; p2++)
3328: if(p2->p_stat == NULL)
3329: goto found;
3330: u.u_error = EAGAIN;
3331: goto out;
3332:
3333: found:
3334: if(newproc()) {
3335: u.u_ar0[R0] = p1->p_pid;
3336: u.u_cstime[0] = 0;
3337: u.u_cstime[1] = 0;
3338: u.u_stime = 0;
3339: u.u_cutime[0] = 0;
3340: u.u_cutime[1] = 0;
3341: u.u_utime = 0;
3342: return;
3343: }
3344: u.u_ar0[R0] = p2->p_pid;
3345:
3346: out:
3347: u.u_ar0[R7] =+ 2;
3348: }
3349: /* --------------------------- */
3350:
3351: /* break system call.
3352: * -- bad planning: "break" is a dirty word in C.
3353: */
3354: sbreak()
3355: {
3356: register a, n, d;
3357: int i;
3358:
3359: /* set n to new data size
3360: * set d to new-old
3361: * set n to new total size
3362: */
3363:
3364: n = (((u.u_arg[0]+63)>>6) & 01777);
3365: if(!u.u_sep)
3366: n =- nseg(u.u_tsize) * 128;
3367: if(n < 0)
3368: n = 0;
3369: d = n - u.u_dsize;
3370: n =+ USIZE+u.u_ssize;
3371: if(estabur(u.u_tsize, u.u_dsize+d, u.u_ssize, u.u_sep))
3372: return;
3373: u.u_dsize =+ d;
3374: if(d > 0)
3375: goto bigger;
3376: a = u.u_procp->p_addr + n - u.u_ssize;
3377: i = n;
3378: n = u.u_ssize;
3379: while(n--) {
3380: copyseg(a-d, a);
3381: a++;
3382: }
3383: expand(i);
3384: return;
3385:
3386: bigger:
3387: expand(n);
3388: a = u.u_procp->p_addr + n;
3389: n = u.u_ssize;
3390: while(n--) {
3391: a--;
3392: copyseg(a-d, a);
3393: }
3394: while(d--)
3395: clearseg(--a);
3396: }
3397: /* --------------------------- */