sys1.c

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 fork() 3322 { 3323 register struct proc *p1, *p2; 3324 3325 p1 = u.u_procp; 3326 for(p2 = &proc[0]; p2 < &proc[NPROC]; p2++) 3327 if(p2->p_stat == NULL) 3328 goto found; 3329 u.u_error = EAGAIN; 3330 goto out; 3331 3332 found: 3333 if(newproc()) { 3334 u.u_ar0[R0] = p1->p_pid; 3335 u.u_cstime[0] = 0; 3336 u.u_cstime[1] = 0; 3337 u.u_stime = 0; 3338 u.u_cutime[0] = 0; 3339 u.u_cutime[1] = 0; 3340 u.u_utime = 0; 3341 return; 3342 } 3343 u.u_ar0[R0] = p2->p_pid; 3344 3345 out: 3346 u.u_ar0[R7] =+ 2; 3347 } 3348 /* ------------------------ */ 3349 3350 /* break system call. 3351 * -- bad planning: "break" is a dirty word in C. 3352 */ 3353 sbreak() 3354 { 3355 register a, n, d; 3356 int i; 3357 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 /* ------------------------ */ 3398 3399