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 = &regloc[0]; cp < &regloc[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: /* ---------------------------       */