/* return 1 if name found in one of the files * 0 if name not found in one of the files * -1 if neither file exists */ extern int lookup(char *cp, char *local, Biobuf **lfpp, char *global, Biobuf **gfpp) { static String *file = 0; if (local) { if (file == 0) file = s_new(); abspath(local, UPASLIB, s_restart(file)); if (*lfpp != 0 || (*lfpp = sysopen(s_to_c(file), "r", 0)) != 0) { if (okfile(cp, *lfpp)) return 1; } else local = 0; } if (global) { abspath(global, UPASLIB, s_restart(file)); if (*gfpp != 0 || (*gfpp = sysopen(s_to_c(file), "r", 0)) != 0) { if (okfile(cp, *gfpp)) return 1; } else global = 0; } return (local || global)? 0 : -1; }
/* dispose of local addresses */ int cat_mail(dest *dp, message *mp) { Biobuf *fp; char *rcvr, *cp; Mlock *l; String *tmp, *s; int i, n; s = unescapespecial(s_clone(dp->repl1)); if (nflg) { if(!xflg) print("cat >> %s\n", s_to_c(s)); else print("%s\n", s_to_c(dp->addr)); s_free(s); return 0; } for(i = 0;; i++){ l = syslock(s_to_c(s)); if(l == 0) return refuse(dp, mp, "can't lock mail file", 0, 0); fp = sysopen(s_to_c(s), "al", MBOXMODE); if(fp) break; tmp = s_append(0, s_to_c(s)); s_append(tmp, ".tmp"); fp = sysopen(s_to_c(tmp), "al", MBOXMODE); if(fp){ syslog(0, "mail", "error: used %s", s_to_c(tmp)); s_free(tmp); break; } s_free(tmp); sysunlock(l); if(i >= 5) return refuse(dp, mp, "mail file cannot be opened", 0, 0); sleep(1000); } s_free(s); n = m_print(mp, fp, (char *)0, 1); if (Bprint(fp, "\n") < 0 || Bflush(fp) < 0 || n < 0){ sysclose(fp); sysunlock(l); return refuse(dp, mp, "error writing mail file", 0, 0); } sysclose(fp); sysunlock(l); rcvr = s_to_c(dp->addr); if(cp = strrchr(rcvr, '!')) rcvr = cp+1; logdelivery(dp, rcvr, mp); return 0; }
void saveline(char *file, char *sender, Resub *rp) { char *p, *q; int i, c; Biobuf *bp; if(rp->sp == 0 || rp->ep == 0) return; /* back up approx 20 characters to whitespace */ for(p = rp->sp, i = 0; *p && i < 20; i++, p--) ; while(*p && *p != ' ') p--; p++; /* grab about 20 more chars beyond the end of the match */ for(q = rp->ep, i = 0; *q && i < 20; i++, q++) ; while(*q && *q != ' ') q++; c = *q; *q = 0; bp = sysopen(file, "al", 0644); if(bp) { Bprint(bp, "%s-> %s\n", sender, p); Bterm(bp); } else if(debug) fprint(2, "can't save line: (%s) %s\n", sender, p); *q = c; }
/* * rules are of the form: * <reg exp> <String> <repl exp> [<repl exp>] */ extern int getrules(void) { Biobuf *rfp; String *line; String *type; String *file; file = abspath("rewrite", UPASLIB, (String *)0); rfp = sysopen(s_to_c(file), "r", 0); if(rfp == 0) { rulep = 0; return -1; } rlastp = 0; line = s_new(); type = s_new(); while(s_getline(rfp, s_restart(line))) if(getrule(line, type, thissys) && altthissys) getrule(s_restart(line), type, altthissys); s_free(type); s_free(line); s_free(file); sysclose(rfp); return 0; }
/* * call up the connection server and get a translation */ static int nettrans(char *addr, char *naddr, int na, char *file, int nf) { int i, fd; char buf[Maxpath]; char netdir[NETPATHLEN]; char *p, *p2; long n; /* * parse, get network directory */ p = strchr(addr, '!'); if (p == 0) { set_errstr("bad dial string: %s", addr); return -1; } if (*addr != '/') { strlcpy(netdir, "/net", sizeof(netdir)); } else { for (p2 = p; *p2 != '/'; p2--) ; i = p2 - addr; if (i == 0 || i >= sizeof(netdir)) { set_errstr("bad dial string: %s", addr); return -1; } strlcpy(netdir, addr, i + 1); addr = p2 + 1; } /* * ask the connection server */ snprintf(buf, sizeof(buf), "%s/cs", netdir); fd = sysopen(buf, O_RDWR); if (fd < 0) return identtrans(netdir, addr, naddr, na, file, nf); if (syswrite(fd, addr, strlen(addr)) < 0) { sysclose(fd); return -1; } sysseek(fd, 0, 0); n = sysread(fd, buf, sizeof(buf) - 1); sysclose(fd); if (n <= 0) return -1; buf[n] = 0; /* * parse the reply */ p = strchr(buf, ' '); if (p == 0) return -1; *p++ = 0; strlcpy(naddr, p, na); strlcpy(file, buf, nf); return 0; }
extern int open(const char* path, int flags, ...) { int fd; int mode; int oerrno; char buf[PATH_MAX]; #if _win32_botch_copy struct stat st; #endif va_list ap; va_start(ap, flags); mode = (flags & O_CREAT) ? va_arg(ap, int) : 0; oerrno = errno; fd = sysopen(path, flags, mode); #if _win32_botch_open if (fd < 0 && errno == ENOENT && execrate(path, buf, sizeof(buf), 0)) { errno = oerrno; fd = sysopen(buf, flags, mode); } #endif #if _win32_botch_copy if (fd >= 0 && fd < elementsof(exe) && strlen(path) < PATH_MAX && (flags & (O_CREAT|O_TRUNC)) == (O_CREAT|O_TRUNC) && (mode & 0111)) { if (!suffix(path) && !fstat(fd, &st) && (exe[fd] || (exe[fd] = (Exe_test_t*)malloc(sizeof(Exe_test_t))))) { exe[fd]->test = -1; exe[fd]->ino = st.st_ino; strcpy(exe[fd]->path, path); } errno = oerrno; } #endif va_end(ap); return fd; }
/* * announce a network service. */ int kannounce(char *addr, char *dir, size_t dirlen) { int ctl, n, m; char buf[NETPATHLEN]; char buf2[Maxpath]; char netdir[NETPATHLEN]; char naddr[Maxpath]; char *cp; /* * translate the address */ if (nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0) return -1; /* * get a control channel */ ctl = sysopen(netdir, O_RDWR); if (ctl < 0) return -1; cp = strrchr(netdir, '/'); *cp = 0; /* * find out which line we have */ n = snprintf(buf, sizeof(buf), "%.*s/", sizeof buf, netdir); m = sysread(ctl, &buf[n], sizeof(buf) - n - 1); if (m <= 0) { sysclose(ctl); return -1; } buf[n + m] = 0; /* * make the call */ n = snprintf(buf2, sizeof buf2, "announce %s", naddr); if (syswrite(ctl, buf2, n) != n) { sysclose(ctl); return -1; } /* * return directory etc. */ if (dir) strlcpy(dir, buf, dirlen); return ctl; }
static int magic(const char* path, int* ux) { int fd; int r; int n; int m; int oerrno; #if CONVERT unsigned char buf[512]; #else unsigned char buf[2]; #endif oerrno = errno; if ((fd = sysopen(path, O_RDONLY, 0)) >= 0) { #if CONVERT if (ux) n = sizeof(buf); else #endif n = 2; r = (m = sysread(fd, buf, n)) >= 2 && (buf[1] == 0x5a && (buf[0] == 0x4c || buf[0] == 0x4d) || ux && buf[0] == '#' && buf[1] == '!' && (*ux = 1) && !(ux = 0)) ? 0 : -1; sysclose(fd); if (ux) { if (r) oerrno = ENOEXEC; else if (m > 61 && (n = buf[60] | (buf[61]<<8) + 92) < (m - 1)) *ux = (buf[n] | (buf[n+1]<<8)) == 3; else *ux = 0; } } else if (!ux) r = -1; else if (errno == ENOENT) { oerrno = errno; r = -1; } else { r = 0; *ux = 0; } errno = oerrno; return r; }
Biobuf* opencopy(char *sender) { int i; uint32_t h; char buf[512]; Biobuf *b; h = 0; while(*sender) h = h*257 + *sender++; for(i = 0; i < 50; i++) { h += lrand(); sprint(buf, "%s/%lud", copydir, h); b = sysopen(buf, "wlc", 0600); if(b) return b; } return 0; }
Biobuf* opendump(char *sender) { int i; uint32_t h; char buf[512]; Biobuf *b; char *cp; cp = ctime(time(0)); cp[7] = 0; cp[10] = 0; if(cp[8] == ' ') sprint(buf, "%s/queue.dump/%s%c", SPOOL, cp+4, cp[9]); else sprint(buf, "%s/queue.dump/%s%c%c", SPOOL, cp+4, cp[8], cp[9]); cp = buf+strlen(buf); if(access(buf, 0) < 0 && sysmkdir(buf, 0777) < 0) { syslog(0, "smtpd", "couldn't dump mail from %s: %r", sender); return 0; } h = 0; while(*sender) h = h*257 + *sender++; for(i = 0; i < 50; i++) { h += lrand(); sprint(cp, "/%lud", h); b = sysopen(buf, "wlc", 0644); if(b) { if(vflag) fprint(2, "saving in %s\n", buf); return b; } } return 0; }
/* * listen for an incoming call */ int klisten(char *dir, char *newdir, size_t newdirlen) { int ctl, n, m; char buf[NETPATHLEN + 1]; char *cp; /* * open listen, wait for a call */ snprintf(buf, sizeof buf, "%s/listen", dir); ctl = sysopen(buf, O_RDWR); if (ctl < 0) return -1; /* * find out which line we have */ strlcpy(buf, dir, sizeof(buf)); cp = strrchr(buf, '/'); *++cp = 0; n = cp - buf; m = sysread(ctl, cp, sizeof(buf) - n - 1); if (m <= 0) { sysclose(ctl); return -1; } buf[n + m] = 0; /* * return directory etc. */ if (newdir) strlcpy(newdir, buf, newdirlen); return ctl; }
static void _writembox(Mailbox *mb, Mlock *lk) { Dir *d; Message *m; String *tmp; int mode, errs; Biobuf *b; tmp = s_copy(mb->path); s_append(tmp, ".tmp"); /* * preserve old files permissions, if possible */ d = dirstat(mb->path); if(d != nil){ mode = d->mode&0777; free(d); } else mode = MBOXMODE; sysremove(s_to_c(tmp)); b = sysopen(s_to_c(tmp), "alc", mode); if(b == 0){ fprint(2, "can't write temporary mailbox %s: %r\n", s_to_c(tmp)); return; } logmsg("writing new mbox", nil); errs = 0; for(m = mb->root->part; m != nil; m = m->next){ if(lk != nil) syslockrefresh(lk); if(m->deleted) continue; logmsg("writing", m); if(Bwrite(b, m->start, m->end - m->start) < 0) errs = 1; if(Bwrite(b, "\n", 1) < 0) errs = 1; } logmsg("wrote new mbox", nil); if(sysclose(b) < 0) errs = 1; if(errs){ fprint(2, "error writing temporary mail file\n"); s_free(tmp); return; } sysremove(mb->path); if(sysrename(s_to_c(tmp), mb->path) < 0) fprint(2, "%s: can't rename %s to %s: %r\n", argv0, s_to_c(tmp), mb->path); s_free(tmp); if(mb->d != nil) free(mb->d); mb->d = dirstat(mb->path); }
static int call(char *clone, char *dest, DS * ds) { int fd, cfd, n, retval; char *name, *data, *err, *p; name = kmalloc(Maxpath, KMALLOC_WAIT); data = kmalloc(Maxpath, KMALLOC_WAIT); err = kmalloc(ERRMAX, KMALLOC_WAIT); cfd = sysopen(clone, O_RDWR); if (cfd < 0) { kerrstr(err, ERRMAX); set_errstr("%s (%s)", err, clone); retval = -1; goto out; } /* get directory name */ n = sysread(cfd, name, Maxpath - 1); if (n < 0) { kerrstr(err, ERRMAX); sysclose(cfd); set_errstr("read %s: %s", clone, err); retval = -1; goto out; } name[n] = 0; for (p = name; *p == ' '; p++) ; snprintf(name, Maxpath, "%ld", strtoul(p, 0, 0)); p = strrchr(clone, '/'); *p = 0; if (ds->dir) snprintf(ds->dir, NETPATHLEN, "%s/%s", clone, name); snprintf(data, Maxpath, "%s/%s/data", clone, name); /* connect */ if (ds->local) snprintf(name, Maxpath, "connect %s %s", dest, ds->local); else snprintf(name, Maxpath, "connect %s", dest); if (syswrite(cfd, name, strlen(name)) < 0) { err[0] = 0; kerrstr(err, ERRMAX); sysclose(cfd); set_errstr("%s (%s)", err, name); retval = -1; goto out; } /* open data connection */ fd = sysopen(data, O_RDWR); if (fd < 0) { err[0] = 0; kerrstr(err, ERRMAX); set_errstr("%s (%s)", err, data); sysclose(cfd); retval = -1; goto out; } if (ds->cfdp) *ds->cfdp = cfd; else sysclose(cfd); retval = fd; out: kfree(name); kfree(data); kfree(err); return retval; }
static void syscall_handler (struct intr_frame* frame) { // -------- System Call Handler Overview -------- // Get system call number // switch statement using system call number // collect arguments for system call function if necessary // call system call function // set frame->eax to return value if necessary // ---------------------------------------------- uintptr_t* kpaddr_sp = (uintptr_t*) frame->esp; int syscall_num = -1; if(check_uptr(kpaddr_sp)) syscall_num = next_value(&kpaddr_sp); else sysexit(-1); switch(syscall_num) { case SYS_HALT: { // Terminates Pintos shutdown_power_off(); } break; case SYS_EXIT: { uintptr_t status = -1; if(check_uptr(kpaddr_sp)) status = next_value(&kpaddr_sp); sysexit(status); } break; case SYS_EXEC: //pid_t exec (const char *file); { const char* file = next_charptr(&kpaddr_sp); if(file == NULL) sysexit(-1); unsigned len = strlen(file); if(!check_buffer(file, len)) sysexit(-1); else sysexec(frame, file); } break; case SYS_WAIT: //int wait (pid_t); { uintptr_t childid = -1; if(check_uptr(kpaddr_sp)) childid = next_value(&kpaddr_sp); else sysexit(childid); int retval = process_wait((tid_t) childid); frame->eax = retval; } break; case SYS_CREATE: //bool create (const char *file, unsigned initial_size); { const char* file = next_charptr(&kpaddr_sp); if(file == NULL) sysexit(-1); unsigned len = strlen(file); if(!check_buffer(file, len)) sysexit(-1); uintptr_t size = 0; if(check_uptr(kpaddr_sp)) size = next_value(&kpaddr_sp); else sysexit(-1); syscreate(frame, file, size); } break; case SYS_REMOVE: //bool remove (const char *file); { const char* file = next_charptr(&kpaddr_sp); if(file == NULL) sysexit(-1); unsigned len = strlen(file); if(!check_buffer(file, len)) sysexit(-1); sysremove(frame, file); } break; case SYS_OPEN: { //int open (const char *file); const char* file = next_charptr(&kpaddr_sp); if(file == NULL) sysexit(-1); unsigned len = strlen(file); if(!check_buffer(file, len)) sysexit(-1); sysopen(frame, file); } break; case SYS_FILESIZE: { //int filesize (int fd); int fd = 0; if (check_uptr(kpaddr_sp)) fd = (int) next_value(&kpaddr_sp); else sysexit(-1); sysfilesize(frame, fd); } break; case SYS_READ: { //int read (int fd, void *buffer, unsigned length); int fd = 0; if (check_uptr(kpaddr_sp)) fd = (int) next_value(&kpaddr_sp); else sysexit(-1); const char* file = next_charptr(&kpaddr_sp); if(file == NULL) sysexit(-1); unsigned len = strlen(file); if(!check_buffer(file, len)) sysexit(-1); unsigned length = 0; if (check_uptr(kpaddr_sp)) length = (unsigned) next_value(&kpaddr_sp); else sysexit(-1); sysread(frame, fd, (void*) file, length); } break; case SYS_WRITE: { //int write (int fd, const void *buffer, unsigned length); uintptr_t fd = 0; if(check_uptr(kpaddr_sp)) fd = next_value(&kpaddr_sp); else sysexit(-1); const char* file = next_charptr(&kpaddr_sp); if(file == NULL) sysexit(-1); unsigned len = strlen(file); if(!check_buffer(file, len)) sysexit(-1); uintptr_t length = 0; if(check_uptr(kpaddr_sp)) length = next_value(&kpaddr_sp); else sysexit(-1); if(fd == CONSOLEWRITE) // Write to Console { while(length > 0) { if(length > MAX_SIZE) { putbuf (file, MAX_SIZE); file += MAX_SIZE; length -= MAX_SIZE; } else { putbuf (file, length); length = 0; } } } else { syswrite(frame, fd, file, length); } } break; case SYS_SEEK: { //void seek (int fd, unsigned position); int fd = 0; if (check_uptr(kpaddr_sp)) fd = (int) next_value(&kpaddr_sp); else sysexit(-1); unsigned position = 0; if (check_uptr(kpaddr_sp)) position = (unsigned) next_value(&kpaddr_sp); else sysexit(-1); sysseek(fd, position); } break; case SYS_TELL: { //unsigned tell (int fd); int fd = 0; if (check_uptr(kpaddr_sp)) fd = (int) next_value(&kpaddr_sp); else sysexit(-1); systell(frame, fd); } break; case SYS_CLOSE: { //void close (int fd); int fd = 0; if (check_uptr(kpaddr_sp)) fd = (int) next_value(&kpaddr_sp); else sysexit(-1); sysclose(fd); } break; default: { printf("Unrecognized System Call\n"); sysexit(-1); } break; } }
static int openSyscall(int* args) { return sysopen((const char*)args[0], (Caps)args[1]); }
/* * try a message */ void dofile(Dir *dp) { Dir *d; int dfd, ac, dtime, efd, pid, i, etime; char *buf, *cp, **av; Waitmsg *wm; Biobuf *b; Mlock *l = nil; if(debug) fprint(2, "dofile %s\n", dp->name); /* * if no data file or empty control or data file, just clean up * the empty control file must be 15 minutes old, to minimize the * chance of a race. */ d = dirstat(file(dp->name, 'D')); if(d == nil){ syslog(0, runqlog, "no data file for %s", dp->name); remmatch(dp->name); return; } if(dp->length == 0){ if(time(0)-dp->mtime > 15*60){ syslog(0, runqlog, "empty ctl file for %s", dp->name); remmatch(dp->name); } return; } dtime = d->mtime; free(d); /* * retry times depend on the age of the errors file */ if(!Eflag && (d = dirstat(file(dp->name, 'E'))) != nil){ etime = d->mtime; free(d); if(etime - dtime < 15*60){ /* up to the first 15 minutes, every 30 seconds */ if(time(0) - etime < 30) return; } else if(etime - dtime < 60*60){ /* up to the first hour, try every 15 minutes */ if(time(0) - etime < 15*60) return; } else { /* after the first hour, try once an hour */ if(time(0) - etime < 60*60) return; } } /* * open control and data */ b = sysopen(file(dp->name, 'C'), "rl", 0660); if(b == 0) { if(debug) fprint(2, "can't open %s: %r\n", file(dp->name, 'C')); return; } dfd = open(file(dp->name, 'D'), OREAD); if(dfd < 0){ if(debug) fprint(2, "can't open %s: %r\n", file(dp->name, 'D')); Bterm(b); sysunlockfile(Bfildes(b)); return; } /* * make arg list * - read args into (malloc'd) buffer * - malloc a vector and copy pointers to args into it */ buf = malloc(dp->length+1); if(buf == 0){ warning("buffer allocation", 0); Bterm(b); sysunlockfile(Bfildes(b)); close(dfd); return; } if(Bread(b, buf, dp->length) != dp->length){ warning("reading control file %s\n", dp->name); Bterm(b); sysunlockfile(Bfildes(b)); close(dfd); free(buf); return; } buf[dp->length] = 0; av = malloc(2*sizeof(char*)); if(av == 0){ warning("argv allocation", 0); close(dfd); free(buf); Bterm(b); sysunlockfile(Bfildes(b)); return; } for(ac = 1, cp = buf; *cp; ac++){ while(isspace(*cp)) *cp++ = 0; if(*cp == 0) break; av = realloc(av, (ac+2)*sizeof(char*)); if(av == 0){ warning("argv allocation", 0); close(dfd); free(buf); Bterm(b); sysunlockfile(Bfildes(b)); return; } av[ac] = cp; while(*cp && !isspace(*cp)){ if(*cp++ == '"'){ while(*cp && *cp != '"') cp++; if(*cp) cp++; } } } av[0] = cmd; av[ac] = 0; if(!Eflag &&time(0) - dtime > giveup){ if(returnmail(av, dp->name, "Giveup") != 0) logit("returnmail failed", dp->name, av); remmatch(dp->name); goto done; } for(i = 0; i < nbad; i++){ if(strcmp(av[3], badsys[i]) == 0) goto done; } /* * Ken's fs, for example, gives us 5 minutes of inactivity before * the lock goes stale, so we have to keep reading it. */ l = keeplockalive(file(dp->name, 'C'), Bfildes(b)); /* * transfer */ pid = fork(); switch(pid){ case -1: sysunlock(l); sysunlockfile(Bfildes(b)); syslog(0, runqlog, "out of procs"); exits(0); case 0: if(debug) { fprint(2, "Starting %s", cmd); for(ac = 0; av[ac]; ac++) fprint(2, " %s", av[ac]); fprint(2, "\n"); } logit("execing", dp->name, av); close(0); dup(dfd, 0); close(dfd); close(2); efd = open(file(dp->name, 'E'), OWRITE); if(efd < 0){ if(debug) syslog(0, "runq", "open %s as %s: %r", file(dp->name,'E'), getuser()); efd = create(file(dp->name, 'E'), OWRITE, 0666); if(efd < 0){ if(debug) syslog(0, "runq", "create %s as %s: %r", file(dp->name, 'E'), getuser()); exits("could not open error file - Retry"); } } seek(efd, 0, 2); exec(cmd, av); error("can't exec %s", cmd); break; default: for(;;){ wm = wait(); if(wm == nil) error("wait failed: %r", ""); if(wm->pid == pid) break; free(wm); } if(debug) fprint(2, "wm->pid %d wm->msg == %s\n", wm->pid, wm->msg); if(wm->msg[0]){ if(debug) fprint(2, "[%d] wm->msg == %s\n", getpid(), wm->msg); syslog(0, runqlog, "message: %s\n", wm->msg); if(strstr(wm->msg, "Ignore") != nil){ /* fix for fish/chips, leave message alone */ logit("ignoring", dp->name, av); }else if(!Rflag && strstr(wm->msg, "Retry")==0){ /* return the message and remove it */ if(returnmail(av, dp->name, wm->msg) != 0) logit("returnmail failed", dp->name, av); remmatch(dp->name); } else { /* add sys to bad list and try again later */ nbad++; badsys = realloc(badsys, nbad*sizeof(char*)); badsys[nbad-1] = strdup(av[3]); } } else { /* it worked remove the message */ remmatch(dp->name); } free(wm); } done: if (l) sysunlock(l); Bterm(b); sysunlockfile(Bfildes(b)); free(buf); free(av); close(dfd); }
static int csdial(DS * ds) { int n, fd, rv = -1; char *p, *buf, *clone, *err, *besterr; buf = kmalloc(Maxstring, KMALLOC_WAIT); clone = kmalloc(Maxpath, KMALLOC_WAIT); err = kmalloc(ERRMAX, KMALLOC_WAIT); besterr = kmalloc(ERRMAX, KMALLOC_WAIT); /* * open connection server */ snprintf(buf, Maxstring, "%s/cs", ds->netdir); fd = sysopen(buf, O_RDWR); if (fd < 0) { /* no connection server, don't translate */ snprintf(clone, Maxpath, "%s/%s/clone", ds->netdir, ds->proto); rv = call(clone, ds->rem, ds); goto out; } /* * ask connection server to translate */ snprintf(buf, Maxstring, "%s!%s", ds->proto, ds->rem); if (syswrite(fd, buf, strlen(buf)) < 0) { kerrstr(err, ERRMAX); sysclose(fd); set_errstr("%s (%s)", err, buf); goto out; } /* * loop through each address from the connection server till * we get one that works. */ *besterr = 0; strlcpy(err, errno_to_string(ECONNRESET), ERRMAX); sysseek(fd, 0, 0); while ((n = sysread(fd, buf, Maxstring - 1)) > 0) { buf[n] = 0; p = strchr(buf, ' '); if (p == 0) continue; *p++ = 0; rv = call(buf, p, ds); if (rv >= 0) break; err[0] = 0; kerrstr(err, ERRMAX); if (strstr(err, "does not exist") == 0) memmove(besterr, err, ERRMAX); } sysclose(fd); if (rv < 0 && *besterr) kerrstr(besterr, ERRMAX); else kerrstr(err, ERRMAX); out: kfree(buf); kfree(clone); kfree(err); kfree(besterr); return rv; }