1 #include <sys/types.h> 2 #include <time.h> 3 #include <termios.h> 4 #include <signal.h> 5 #include <pwd.h> 6 #include <sched.h> 7 #include <sys/resource.h> 8 #include <sys/wait.h> 9 #include <sys/time.h> 10 11 #include <stdint.h> 12 13 #include "dat.h" 14 #include "fns.h" 15 #include "error.h" 16 #include <fpuctl.h> 17 18 #include <semaphore.h> 19 20 #include <raise.h> 21 22 /* glibc 2.3.3-NTPL messes up getpid() by trying to cache the result, so we'll do it ourselves */ 23 #include <sys/syscall.h> 24 #define getpid() syscall(SYS_getpid) 25 26 enum 27 { 28 DELETE = 0x7f, 29 CTRLC = 'C'-'@', 30 NSTACKSPERALLOC = 16, 31 X11STACK= 256*1024 32 }; 33 char *hosttype = "Linux"; 34 35 typedef sem_t Sem; 36 37 extern int dflag; 38 39 int gidnobody = -1; 40 int uidnobody = -1; 41 static struct termios tinit; 42 43 static void 44 sysfault(char *what, void *addr) 45 { 46 char buf[64]; 47 48 snprint(buf, sizeof(buf), "sys: %s%#p", what, addr); 49 disfault(nil, buf); 50 } 51 52 static void 53 trapILL(int signo, siginfo_t *si, void *a) 54 { 55 USED(signo); 56 USED(a); 57 sysfault("illegal instruction pc=", si->si_addr); 58 } 59 60 static int 61 isnilref(siginfo_t *si) 62 { 63 return si != 0 && (si->si_addr == (void*)~(uintptr_t)0 || (uintptr_t)si->si_addr < 512); 64 } 65 66 static void 67 trapmemref(int signo, siginfo_t *si, void *a) 68 { 69 USED(a); /* ucontext_t*, could fetch pc in machine-dependent way */ 70 if(isnilref(si)) 71 disfault(nil, exNilref); 72 else if(signo == SIGBUS) 73 sysfault("bad address addr=", si->si_addr); /* eg, misaligned */ 74 else 75 sysfault("segmentation violation addr=", si->si_addr); 76 } 77 78 static void 79 trapFPE(int signo, siginfo_t *si, void *a) 80 { 81 char buf[64]; 82 83 USED(signo); 84 USED(a); 85 snprint(buf, sizeof(buf), "sys: fp: exception status=%.4lux pc=%#p", getfsr(), si->si_addr); 86 disfault(nil, buf); 87 } 88 89 static void 90 trapUSR1(int signo) 91 { 92 int intwait; 93 94 USED(signo); 95 96 intwait = up->intwait; 97 up->intwait = 0; /* clear it to let proc continue in osleave */ 98 99 if(up->type != Interp) /* Used to unblock pending I/O */ 100 return; 101 102 if(intwait == 0) /* Not posted so it's a sync error */ 103 disfault(nil, Eintr); /* Should never happen */ 104 } 105 106 void 107 oslongjmp(void *regs, osjmpbuf env, int val) 108 { 109 USED(regs); 110 siglongjmp(env, val); 111 } 112 113 static void 114 termset(void) 115 { 116 struct termios t; 117 118 tcgetattr(0, &t); 119 tinit = t; 120 t.c_lflag &= ~(ICANON|ECHO|ISIG); 121 t.c_cc[VMIN] = 1; 122 t.c_cc[VTIME] = 0; 123 tcsetattr(0, TCSANOW, &t); 124 } 125 126 static void 127 termrestore(void) 128 { 129 tcsetattr(0, TCSANOW, &tinit); 130 } 131 132 void 133 cleanexit(int x) 134 { 135 USED(x); 136 137 if(up->intwait) { 138 up->intwait = 0; 139 return; 140 } 141 142 if(dflag == 0) 143 termrestore(); 144 145 kill(0, SIGKILL); 146 exit(0); 147 } 148 149 void 150 osreboot(char *file, char **argv) 151 { 152 if(dflag == 0) 153 termrestore(); 154 execvp(file, argv); 155 error("reboot failure"); 156 } 157 158 void 159 libinit(char *imod) 160 { 161 struct sigaction act; 162 struct passwd *pw; 163 Proc *p; 164 char sys[64]; 165 166 setsid(); 167 168 gethostname(sys, sizeof(sys)); 169 kstrdup(&ossysname, sys); 170 pw = getpwnam("nobody"); 171 if(pw != nil) { 172 uidnobody = pw->pw_uid; 173 gidnobody = pw->pw_gid; 174 } 175 176 if(dflag == 0) 177 termset(); 178 179 memset(&act, 0, sizeof(act)); 180 act.sa_handler = trapUSR1; 181 sigaction(SIGUSR1, &act, nil); 182 183 act.sa_handler = SIG_IGN; 184 sigaction(SIGCHLD, &act, nil); 185 186 /* 187 * For the correct functioning of devcmd in the 188 * face of exiting slaves 189 */ 190 signal(SIGPIPE, SIG_IGN); 191 if(signal(SIGTERM, SIG_IGN) != SIG_IGN) 192 signal(SIGTERM, cleanexit); 193 if(signal(SIGINT, SIG_IGN) != SIG_IGN) 194 signal(SIGINT, cleanexit); 195 196 if(sflag == 0) { 197 act.sa_flags = SA_SIGINFO; 198 act.sa_sigaction = trapILL; 199 sigaction(SIGILL, &act, nil); 200 act.sa_sigaction = trapFPE; 201 sigaction(SIGFPE, &act, nil); 202 act.sa_sigaction = trapmemref; 203 sigaction(SIGBUS, &act, nil); 204 sigaction(SIGSEGV, &act, nil); 205 act.sa_flags &= ~SA_SIGINFO; 206 } 207 208 p = newproc(); 209 kprocinit(p); 210 211 pw = getpwuid(getuid()); 212 if(pw != nil) 213 kstrdup(&eve, pw->pw_name); 214 else 215 print("cannot getpwuid\n"); 216 217 p->env->uid = getuid(); 218 p->env->gid = getgid(); 219 220 emuinit(imod); 221 } 222 223 int 224 readkbd(void) 225 { 226 int n; 227 char buf[1]; 228 229 n = read(0, buf, sizeof(buf)); 230 if(n < 0) 231 print("keyboard close (n=%d, %s)\n", n, strerror(errno)); 232 if(n <= 0) 233 pexit("keyboard thread", 0); 234 235 switch(buf[0]) { 236 case '\r': 237 buf[0] = '\n'; 238 break; 239 case DELETE: 240 buf[0] = 'H' - '@'; 241 break; 242 case CTRLC: 243 cleanexit(0); 244 break; 245 } 246 return buf[0]; 247 } 248 249 /* 250 * Return an abitrary millisecond clock time 251 */ 252 long 253 osmillisec(void) 254 { 255 static long sec0 = 0, usec0; 256 struct timeval t; 257 258 if(gettimeofday(&t,(struct timezone*)0)<0) 259 return 0; 260 261 if(sec0 == 0) { 262 sec0 = t.tv_sec; 263 usec0 = t.tv_usec; 264 } 265 return (t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000; 266 } 267 268 /* 269 * Return the time since the epoch in nanoseconds and microseconds 270 * The epoch is defined at 1 Jan 1970 271 */ 272 vlong 273 osnsec(void) 274 { 275 struct timeval t; 276 277 gettimeofday(&t, nil); 278 return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000; 279 } 280 281 vlong 282 osusectime(void) 283 { 284 struct timeval t; 285 286 gettimeofday(&t, nil); 287 return (vlong)t.tv_sec * 1000000 + t.tv_usec; 288 } 289 290 int 291 osmillisleep(ulong milsec) 292 { 293 struct timespec time; 294 295 time.tv_sec = milsec/1000; 296 time.tv_nsec= (milsec%1000)*1000000; 297 nanosleep(&time, NULL); 298 return 0; 299 } 300 301 int 302 limbosleep(ulong milsec) 303 { 304 return osmillisleep(milsec); 305 } 306