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