void truncate(char *fname) { #ifdef __TURBOC__ struct ftime Ftime; #else unsigned short date, time; #endif fd = open(fname, O_WRONLY); #ifdef __TURBOC__ /* Save the time/date */ getftime(fd, &Ftime); #else GETFTIME(fd, (FTIME_T *)&date, (FTIME_T *)&time); #endif chsize(fd, 0L); /* Truncate the file */ #ifdef __TURBOC__ /* Restore the time/date */ setftime(fd, &Ftime); #else SETFTIME(fd, (FTIME_T)date, (FTIME_T)time); #endif close(fd); }
/* =========================================================================== * Set last updated and accessed time of file f to the DOS time d. * This is called by dllzip.c to set date/time of the zipfile. * RCV Removed __TURBOC__ version. *f :: name of file to change. d :: dos-style time to change it to. */ void stamp( char *f, ulg d ) { int h; /* file handle */ if ( (h = open( f, O_RDWR | O_BINARY )) != -1 ) { //v1.55 mode changed, was 0 setftime( h, (struct ftime *)&d ); close( h ); } }
arg_t _link(void) { inoptr ino; inoptr ino2; inoptr parent2; char fname[FILENAME_LEN + 1]; if (!(ino = n_open(name1, NULLINOPTR))) return (-1); if (getmode(ino) == F_DIR && esuper()) goto nogood; if (ino->c_node.i_nlink == 0xFFFF) { udata.u_error = EMLINK; goto nogood; } /* Make sure file2 doesn't exist, and get its parent */ if ((ino2 = n_open(name2, &parent2)) != NULL) { i_deref(ino2); i_deref(parent2); udata.u_error = EEXIST; goto nogood; } if (!parent2) goto nogood; if (ino->c_dev != parent2->c_dev) { i_deref(parent2); udata.u_error = EXDEV; goto nogood; } filename(name2, fname); if (!ch_link(parent2, "", fname, ino)) { i_deref(parent2); goto nogood; } /* Update the link count. */ ++ino->c_node.i_nlink; wr_inode(ino); setftime(ino, C_TIME); i_deref(parent2); i_deref(ino); return 0; nogood: i_deref(ino); return -1; }
static int chown_op(inoptr ino) { if (ino->c_node.i_uid != udata.u_euid && esuper()) { i_deref(ino); return (-1); } ino->c_node.i_uid = owner; ino->c_node.i_gid = group; setftime(ino, C_TIME); return 0; }
uint8_t write_core_image(void) { inoptr parent = NULLINODE; inoptr ino; udata.u_error = 0; /* FIXME: need to think more about the case sp is lala */ if (uput("core", (uint8_t *)udata.u_syscall_sp - 5, 5)) return 0; ino = n_open((char *)udata.u_syscall_sp - 5, &parent); if (ino) { i_deref(parent); return 0; } if (parent) { i_lock(parent); if ((ino = newfile(parent, "core")) != NULL) { ino->c_node.i_mode = F_REG | 0400; setftime(ino, A_TIME | M_TIME | C_TIME); wr_inode(ino); f_trunc(ino); #if 0 /* FIXME address ranges for different models - move core writer for address spaces into helpers ? */ /* FIXME: need to add some arch specific header bits, and also pull stuff like the true sp and registers out of the return stack properly */ corehdr.ch_base = pagemap_base; corehdr.ch_break = udata.u_break; corehdr.ch_sp = udata.u_syscall_sp; corehdr.ch_top = PROGTOP; udata.u_offset = 0; udata.u_base = (uint8_t *)&corehdr; udata.u_sysio = true; udata.u_count = sizeof(corehdr); writei(ino, 0); udata.u_sysio = false; udata.u_base = (uint8_t *)pagemap_base; udata.u_count = udata.u_break - pagemap_base; writei(ino, 0); udata.u_base = udata.u_sp; udata.u_count = PROGTOP - (uint32_t)udata.u_sp; writei(ino, 0); #endif i_unlock_deref(ino); return W_COREDUMP; } } return 0; }
static int16_t chmod_op(inoptr ino) { if (ino->c_node.i_uid != udata.u_euid && esuper()) { i_deref(ino); return (-1); } ino->c_node.i_mode = (mode & MODE_MASK) | (ino->c_node.i_mode & F_MASK); setftime(ino, C_TIME); return 0; }
static int chown_op(inoptr ino) { if (ino->c_node.i_uid != udata.u_euid && esuper()) return (-1); if (ino->c_flags & CRDONLY) { udata.u_error = EROFS; return -1; } ino->c_node.i_uid = owner; ino->c_node.i_gid = group; setftime(ino, C_TIME); return 0; }
uint8_t write_core_image(void) { inoptr parent = NULLINODE; inoptr ino; udata.u_error = 0; /* FIXME: need to think more about the case sp is lala */ if (uput("core", udata.u_syscall_sp - 5, 5)) return 0; ino = n_open(udata.u_syscall_sp - 5, &parent); if (ino) { i_deref(parent); return 0; } if (parent) { i_lock(parent); if (ino = newfile(parent, "core")) { ino->c_node.i_mode = F_REG | 0400; setftime(ino, A_TIME | M_TIME | C_TIME); wr_inode(ino); f_trunc(ino); /* FIXME: need to add some arch specific header bits, and also pull stuff like the true sp and registers out of the return stack properly */ corehdr.ch_base = MAPBASE; corehdr.ch_break = udata.u_break; corehdr.ch_sp = udata.u_syscall_sp; corehdr.ch_top = PROGTOP; udata.u_offset = 0; udata.u_base = (uint8_t *)&corehdr; udata.u_sysio = true; udata.u_count = sizeof(corehdr); writei(ino, 0); udata.u_sysio = false; udata.u_base = MAPBASE; udata.u_count = udata.u_break - MAPBASE; writei(ino, 0); udata.u_base = udata.u_sp; udata.u_count = PROGTOP - (uint16_t)udata.u_sp; writei(ino, 0); i_unlock_deref(ino); return W_COREDUMP; } } return 0; }
static arg_t chmod_op(inoptr ino) { if (ino->c_node.i_uid != udata.u_euid && esuper()) return (-1); if (ino->c_flags & CRDONLY) { udata.u_error = EROFS; return -1; } ino->c_node.i_mode = (mode & MODE_MASK) | (ino->c_node.i_mode & F_MASK); setftime(ino, C_TIME); return 0; }
int YMODEMCLASS::EndTransferBinaryFile(void) { struct tm *t ; struct ftime ft ; CommPutChar (oiConn, ACK) ; if (hFile!=HFILE_ERROR) { if (moddate) { putenv ("TZ=GMT0GMT") ; tzset() ; t = localtime(&moddate) ; ft.ft_tsec = t->tm_sec /2 ; ft.ft_min = t->tm_min ; ft.ft_hour = t->tm_hour ; ft.ft_day = t->tm_mday ; ft.ft_month= t->tm_mon +1 ; ft.ft_year = t->tm_year-80 ; setftime(hFile, &ft) ; } CloseHandle (hFile) ; rvDataCount = 0 ; waittimes = 0 ; bSeq = bLastSeq =0 ; dataBlock0 = TRUE ; lErrorCount =0 ; if (Status) { lpStatus->error = 0 ; lpStatus->blocksize = 0 ; lpStatus->blockno = 0 ; lstrcpy(lpStatus->filename, "") ; lpStatus->UpdateStatusWindow() ; if (lpStatus->transferStop) return FT_LOCALCANCEL ; } fltr_state = SEND_INIT ; } else { if(Status) DestroyWindow(lpStatus->hStatus) ; } return FT_SUCCESS; }
int main(int argc, char *argv[]) { int fd0, fd1; #ifdef __TURBOC__ struct ftime Ftime; #else unsigned date, time; #endif if (3 > argc) { puts("Usage: SETIMETO old_filename new_filename"); return EXIT_FAILURE; } if (-1 == (fd0 = open(argv[1], O_RDONLY))) { printf("Unable to open %s\n", argv[1]); return EXIT_FAILURE; } #ifdef __TURBOC__ /* Save the time/date */ getftime(fd0, &Ftime); #else GETFTIME(fd0, &date, &time); #endif if (-1 == (fd1 = open(argv[2], O_WRONLY))) { printf("Unable to open %s\n", argv[2]); return EXIT_FAILURE; } #ifdef __TURBOC__ /* Set the time/date */ setftime(fd1, &Ftime); #else SETFTIME(fd1, date, time); #endif close(fd0); close(fd1); return EXIT_SUCCESS; }
/* Helper for the bits shared with rename */ int16_t unlinki(inoptr ino, inoptr pino, char *fname) { if (getmode(ino) == F_DIR) { udata.u_error = EISDIR; return -1; } /* Remove the directory entry (ch_link checks perms) */ if (!ch_link(pino, fname, "", NULLINODE)) return -1; /* Decrease the link count of the inode */ if (!(ino->c_node.i_nlink--)) { ino->c_node.i_nlink += 2; kprintf("_unlink: bad nlink\n"); } setftime(ino, C_TIME); return (0); }
static int utime(char * path, struct utimbuf * times) { struct ftime ft; struct tm * ftm; int h, r; ftm=localtime(×->modtime); h=open(path,O_RDWR); if (h==-1) return -1; ft.ft_tsec=ftm->tm_sec/2; ft.ft_min=ftm->tm_min; ft.ft_hour=ftm->tm_hour; ft.ft_day=ftm->tm_mday; ft.ft_month=ftm->tm_mon; ft.ft_year=ftm->tm_year-80; r=setftime(h,&ft); close(h); return r; }
static void SetDate(void) { struct ftime filet; FILE *fp; if ((fp = fopen ("playgame.exe","r+b")) == NULL) { errorbox("Cannot Find PLAYGAME.EXE"," (E)xit"); return; } filet.ft_tsec=00; filet.ft_min=04; filet.ft_hour=2; filet.ft_day=11; filet.ft_month=11; filet.ft_year=11; setftime(fileno(fp), &filet); fclose(fp); }
arg_t _mknod(void) { inoptr ino; inoptr parent; char fname[FILENAME_LEN + 1]; udata.u_error = 0; if (!super() && ((mode & F_MASK) != F_PIPE)) { udata.u_error = EPERM; goto nogood3; } if ((ino = n_open(name, &parent)) != NULL) { udata.u_error = EEXIST; goto nogood; } if (!parent) { udata.u_error = ENOENT; return (-1); } filename(name, fname); ino = newfile(parent, fname); if(!ino) goto nogood3; /* parent inode is derefed in newfile. SN */ /* Initialize mode and dev */ ino->c_node.i_mode = mode & ~udata.u_mask; ino->c_node.i_addr[0] = isdevice(ino) ? dev : 0; setftime(ino, A_TIME | M_TIME | C_TIME); wr_inode(ino); i_deref(ino); return (0); nogood: i_deref(ino); i_deref(parent); nogood3: return (-1); }
void FName::SetFileTime(long t) { #ifdef WIN32 HANDLE f=CreateFile(Str,GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if (f==INVALID_HANDLE_VALUE) return; FILETIME ft; DosDateTimeToFileTime(HIWORD(t),LOWORD(t),&ft); ::SetFileTime(f,NULL,NULL,&ft); CloseHandle(f); #else int hand; union Time { ftime ft; DWORD dw; } ft; ft.dw=t; if ((hand=open(Str,O_RDONLY))<0) return; setftime(hand,&ft.ft); close(hand); #endif }
int16_t _utime(void) { inoptr ino; time_t t[2]; if (!valaddr(buf, 2 * sizeof(time_t))) return (-1); if (!(ino = n_open(file, NULLINOPTR))) return (-1); if (ino->c_node.i_uid != udata.u_euid && esuper()) { i_deref(ino); return (-1); } uget(buf, t, 2 * sizeof(time_t)); /* FIXME: needs updating once we pack top bits elsewhere in the inode */ ino->c_node.i_atime = t[0]; ino->c_node.i_mtime = t[1]; setftime(ino, C_TIME); i_deref(ino); return (0); }
arg_t _utime(void) { inoptr ino; time_t t[2]; if (!(ino = n_open(file, NULLINOPTR))) return (-1); if (ino->c_flags & CRDONLY) { udata.u_error = EROFS; goto out2; } /* Special case in the Unix API - NULL means now */ if (buf) { if (ino->c_node.i_uid != udata.u_euid && esuper()) goto out; if (!valaddr(buf, 2 * sizeof(time_t))) goto out2; uget(buf, t, 2 * sizeof(time_t)); } else { if (!(getperm(ino) & OTH_WR)) goto out; rdtime(&t[0]); memcpy(&t[1], &t[0], sizeof(t[1])); } /* FIXME: needs updating once we pack top bits elsewhere in the inode */ ino->c_node.i_atime = t[0].low; ino->c_node.i_mtime = t[1].low; setftime(ino, C_TIME); i_deref(ino); return (0); out: udata.u_error = EPERM; out2: i_deref(ino); return -1; }
void copydate(const char *srcfile, const char *dstfile) { int srchandle=open(srcfile,O_RDONLY); if(srchandle<0) { fprintf(stderr,"%s: could not open %s\n",PROGNAME,srcfile); exit(5); } struct ftime dt; if(getftime(srchandle,&dt)) { fprintf(stderr,"%s: could get date of %s\n",PROGNAME,srcfile); exit(5); } close(srchandle); int dsthandle=open(dstfile,O_RDONLY); if(srchandle<0) { fprintf(stderr,"%s: could not open %s\n",PROGNAME,dstfile); exit(5); } if(setftime(dsthandle,&dt)) { fprintf(stderr,"%s: could set date of %s\n",PROGNAME,dstfile); exit(5); } close(dsthandle); }
int utime (char *filename, struct utimbuf *utb) { struct tm *tm; struct ftime filetime; time_t when; int fd; int status; if (utb == 0) when = time (0); else when = utb->modtime; fd = _open (filename, O_RDWR); if (fd == -1) return -1; tm = localtime (&when); if (tm->tm_year < 80) filetime.ft_year = 0; else filetime.ft_year = tm->tm_year - 80; filetime.ft_month = tm->tm_mon + 1; filetime.ft_day = tm->tm_mday; if (tm->tm_hour < 0) filetime.ft_hour = 0; else filetime.ft_hour = tm->tm_hour; filetime.ft_min = tm->tm_min; filetime.ft_tsec = tm->tm_sec / 2; status = setftime (fd, &filetime); _close (fd); return status; }
arg_t _execve(void) { /* We aren't re-entrant where this matters */ uint8_t hdr[16]; staticfast inoptr ino; char **nargv; /* In user space */ char **nenvp; /* In user space */ struct s_argblk *abuf, *ebuf; int argc; uint16_t progptr; uint16_t progload; staticfast uint16_t top; uint16_t bin_size; /* Will need to be bigger on some cpus */ uint16_t bss; top = ramtop; if (!(ino = n_open_lock(name, NULLINOPTR))) return (-1); if (!((getperm(ino) & OTH_EX) && (ino->c_node.i_mode & F_REG) && (ino->c_node.i_mode & (OWN_EX | OTH_EX | GRP_EX)))) { udata.u_error = EACCES; goto nogood; } setftime(ino, A_TIME); udata.u_offset = 0; udata.u_count = 16; udata.u_base = hdr; udata.u_sysio = true; readi(ino, 0); if (udata.u_done != 16) { udata.u_error = ENOEXEC; goto nogood; } if (!header_ok(hdr)) { udata.u_error = ENOEXEC; goto nogood2; } progload = hdr[7] << 8; if (progload == 0) progload = PROGLOAD; top = *(uint16_t *)(hdr + 8); if (top == 0) /* Legacy 'all space' binary */ top = ramtop; else /* Requested an amount, so adjust for the base */ top += progload; bss = *(uint16_t *)(hdr + 14); /* Binary doesn't fit */ /* FIXME: review overflows */ bin_size = ino->c_node.i_size; progptr = bin_size + 1024 + bss; if (progload < PROGLOAD || top - progload < progptr || progptr < bin_size) { udata.u_error = ENOMEM; goto nogood2; } udata.u_ptab->p_status = P_NOSLEEP; /* If we made pagemap_realloc keep hold of some defined area we could in theory just move the arguments up or down as part of the process - that would save us all this hassle but replace it with new hassle */ /* Gather the arguments, and put them in temporary buffers. */ abuf = (struct s_argblk *) tmpbuf(); /* Put environment in another buffer. */ ebuf = (struct s_argblk *) tmpbuf(); /* Read args and environment from process memory */ if (rargs(argv, abuf) || rargs(envp, ebuf)) goto nogood3; /* SN */ /* This must be the last test as it makes changes if it works */ /* FIXME: once we sort out chmem we can make stack and data two elements. We never allocate 'code' as there is no split I/D */ /* This is only safe from deadlocks providing pagemap_realloc doesn't sleep */ if (pagemap_realloc(0, top - MAPBASE, 0)) goto nogood3; /* From this point on we are commmited to the exec() completing */ /* Core dump and ptrace permission logic */ #ifdef CONFIG_LEVEL_2 /* Q: should uid == 0 mean we always allow core */ if ((!(getperm(ino) & OTH_RD)) || (ino->c_node.i_mode & (SET_UID | SET_GID))) udata.u_flags |= U_FLAG_NOCORE; else udata.u_flags &= ~U_FLAG_NOCORE; #endif udata.u_top = top; udata.u_ptab->p_top = top; /* setuid, setgid if executable requires it */ if (ino->c_node.i_mode & SET_UID) udata.u_euid = ino->c_node.i_uid; if (ino->c_node.i_mode & SET_GID) udata.u_egid = ino->c_node.i_gid; /* FIXME: In the execve case we may on some platforms have space below PROGLOAD to clear... */ /* We are definitely going to succeed with the exec, * so we can start writing over the old program */ uput(hdr, (uint8_t *)progload, 16); /* At this point, we are committed to reading in and * executing the program. This call must not block. */ close_on_exec(); /* * Read in the rest of the program, block by block. We rely upon * the optimization path in readi to spot this is a big move to user * space and move it directly. */ progptr = progload + 16; if (bin_size > 16) { bin_size -= 16; udata.u_base = (uint8_t *)progptr; /* We copied the first block already */ udata.u_count = bin_size; udata.u_sysio = false; readi(ino, 0); if (udata.u_done != bin_size) goto nogood4; progptr += bin_size; } /* Wipe the memory in the BSS. We don't wipe the memory above that on 8bit boxes, but defer it to brk/sbrk() */ uzero((uint8_t *)progptr, bss); /* Set initial break for program */ udata.u_break = (int)ALIGNUP(progptr + bss); /* Turn off caught signals */ memset(udata.u_sigvec, 0, sizeof(udata.u_sigvec)); // place the arguments, environment and stack at the top of userspace memory, // Write back the arguments and the environment nargv = wargs(((char *) top - 2), abuf, &argc); nenvp = wargs((char *) (nargv), ebuf, NULL); // Fill in udata.u_name with program invocation name uget((void *) ugetw(nargv), udata.u_name, 8); memcpy(udata.u_ptab->p_name, udata.u_name, 8); tmpfree(abuf); tmpfree(ebuf); i_deref(ino); /* Shove argc and the address of argv just below envp FIXME: should flip them in crt0.S of app for R2L setups so we can get rid of the ifdefs */ #ifdef CONFIG_CALL_R2L /* Arguments are stacked the 'wrong' way around */ uputw((uint16_t) nargv, nenvp - 2); uputw((uint16_t) argc, nenvp - 1); #else uputw((uint16_t) nargv, nenvp - 1); uputw((uint16_t) argc, nenvp - 2); #endif /* Set stack pointer for the program */ udata.u_isp = nenvp - 2; /* Start execution (never returns) */ udata.u_ptab->p_status = P_RUNNING; doexec(progload); /* tidy up in various failure modes */ nogood4: /* Must not run userspace */ ssig(udata.u_ptab, SIGKILL); nogood3: udata.u_ptab->p_status = P_RUNNING; tmpfree(abuf); tmpfree(ebuf); nogood2: nogood: i_unlock_deref(ino); return (-1); }
int scan(char *filename) { struct tifile *ff; int handle; longint fdrtotalbytes; longint totalbytes; longint databytes; struct fdrstruc *fdr; char name[14]; word oldsize; struct ftime ftime; byte type,len; SAY printf("Scanning file %s\n",filename); if (!openti(filename,&handle)) { tierror(filename); return 0; } ff=&tifiles[handle]; getftime(ff->doshandle,&ftime); // Check FDR structure. fdr=&ff->fdr; type=fdr->flags; len=fdr->reclen; if (!validatename(fdr->name)) { if (fix) { getname(fdr->name,name); memcpy(fdr->name,name+2,10); } } if (!(type&F_PROGRAM) && len==0) { printf("Invalid record length (0)\n"); if (fix) { if (fdr->recspersec==1) len=255; // good guess for xxx/FIX else if (fdr->recspersec>1) len=256/fdr->recspersec; // very approx else len=80; // pure guess // For fixed files, we can tell what the record size is: // * EOF offset is exact multiple // * (256*secsused-EOF)/fixrecs is almost it if (!(type&F_VARIABLE) && fdr->fixrecs) { len=(256L*(swapbytes(fdr->secsused)+1)-fdr->eof) / fdr->fixrecs; if (fdr->eof) while (len%fdr->eof) len--; } if (!len) len=80; printf("\tAssume %d bytes?\n",len); if (getyesorno()) fdr->reclen=len; } } fdrtotalbytes=tigetfilesize(handle); totalbytes=tigetrealfilesize(handle); if ((fdrtotalbytes+255)/256!=totalbytes/256) { printf("File size mismatch in %s\n",filename); printf("TI Emulator! v5.0- probably made this error.\n"); if (fix) { if ((type&F_VARIABLE) && !(type&F_PROGRAM)) // xxx/VAR { fdr->fixrecs=totalbytes/256; fdr->secsused=swapbytes(fdr->fixrecs); } else if (type&F_PROGRAM) // program { // On a program file, most likely the FDR is // correct while the filesize is wrong. Sheesh! // if (fdrtotalbytes<totalbytes) if (!ff->doad) trunc(handle,swapbytes(fdr->secsused)); else ; else { fdr->secsused=swapbytes(totalbytes/256); fdr->eof=totalbytes&255; } } else if (!(type&F_VARIABLE)) // xxx/FIX { // reclen is assumed to be legal from above // oldsize=fdr->secsused; fdr->secsused=swapbytes( (fdr->fixrecs+fdr->recspersec-1)/fdr->recspersec); if (oldsize==fdr->secsused && !ff->doad) trunc(handle,swapbytes(oldsize)); } } } if (fix) { // printf("Fixing...\n"); if (!writetifdr(handle)) printf("Error! Couldn't write header!\n"); else setftime(ff->doshandle,&ftime); } closeti(handle); return 1; }
void do_one_file(const char *iname, char *oname) { int r; struct stat st; memset(&st, 0, sizeof(st)); #if (HAVE_LSTAT) r = lstat(iname, &st); #else r = stat(iname, &st); #endif if (r != 0) { if (errno == ENOENT) throw FileNotFoundException(iname, errno); else throwIOException(iname, errno); } if (!(S_ISREG(st.st_mode))) throwIOException("not a regular file -- skipped"); #if defined(__unix__) // no special bits may be set if ((st.st_mode & (S_ISUID | S_ISGID | S_ISVTX)) != 0) throwIOException("file has special permissions -- skipped"); #endif if (st.st_size <= 0) throwIOException("empty file -- skipped"); if (st.st_size < 512) throwIOException("file is too small -- skipped"); if (!mem_size_valid_bytes(st.st_size)) throwIOException("file is too large -- skipped"); if ((st.st_mode & S_IWUSR) == 0) { bool skip = true; if (opt->output_name) skip = false; else if (opt->to_stdout) skip = false; else if (opt->backup) skip = false; if (skip) throwIOException("file is write protected -- skipped"); } InputFile fi; fi.st = st; fi.sopen(iname, O_RDONLY | O_BINARY, SH_DENYWR); #if (USE_FTIME) struct ftime fi_ftime; memset(&fi_ftime, 0, sizeof(fi_ftime)); if (opt->preserve_timestamp) { if (getftime(fi.getFd(), &fi_ftime) != 0) throwIOException("cannot determine file timestamp"); } #endif // open output file OutputFile fo; if (opt->cmd == CMD_COMPRESS || opt->cmd == CMD_DECOMPRESS) { if (opt->to_stdout) { if (!fo.openStdout(1, opt->force ? true : false)) throwIOException("data not written to a terminal; Use '-f' to force."); } else { char tname[ACC_FN_PATH_MAX+1]; if (opt->output_name) strcpy(tname,opt->output_name); else { if (!maketempname(tname, sizeof(tname), iname, ".upx")) throwIOException("could not create a temporary file name"); } if (opt->force >= 2) { #if (HAVE_CHMOD) r = chmod(tname, 0777); IGNORE_ERROR(r); #endif r = unlink(tname); IGNORE_ERROR(r); } int flags = O_CREAT | O_WRONLY | O_BINARY; if (opt->force) flags |= O_TRUNC; else flags |= O_EXCL; int shmode = SH_DENYWR; #if defined(__MINT__) flags |= O_TRUNC; shmode = O_DENYRW; #endif // cannot rely on open() because of umask //int omode = st.st_mode | 0600; int omode = 0600; if (!opt->preserve_mode) omode = 0666; fo.sopen(tname,flags,shmode,omode); // open succeeded - now set oname[] strcpy(oname,tname); } } // handle command PackMaster pm(&fi, opt); if (opt->cmd == CMD_COMPRESS) pm.pack(&fo); else if (opt->cmd == CMD_DECOMPRESS) pm.unpack(&fo); else if (opt->cmd == CMD_TEST) pm.test(); else if (opt->cmd == CMD_LIST) pm.list(); else if (opt->cmd == CMD_FILEINFO) pm.fileInfo(); else throwInternalError("invalid command"); // copy time stamp if (opt->preserve_timestamp && oname[0] && fo.isOpen()) { #if (USE_FTIME) r = setftime(fo.getFd(), &fi_ftime); IGNORE_ERROR(r); #elif (USE__FUTIME) struct _utimbuf u; u.actime = st.st_atime; u.modtime = st.st_mtime; r = _futime(fo.getFd(), &u); IGNORE_ERROR(r); #endif } // close files fo.closex(); fi.closex(); // rename or delete files if (oname[0] && !opt->output_name) { // FIXME: .exe or .cof etc. if (!opt->backup) { #if (HAVE_CHMOD) r = chmod(iname, 0777); IGNORE_ERROR(r); #endif File::unlink(iname); } else { // make backup char bakname[ACC_FN_PATH_MAX+1]; if (!makebakname(bakname, sizeof(bakname), iname)) throwIOException("could not create a backup file name"); File::rename(iname,bakname); } File::rename(oname,iname); } // copy file attributes if (oname[0]) { oname[0] = 0; const char *name = opt->output_name ? opt->output_name : iname; UNUSED(name); #if (USE_UTIME) // copy time stamp if (opt->preserve_timestamp) { struct utimbuf u; u.actime = st.st_atime; u.modtime = st.st_mtime; r = utime(name, &u); IGNORE_ERROR(r); } #endif #if (HAVE_CHMOD) // copy permissions if (opt->preserve_mode) { r = chmod(name, st.st_mode); IGNORE_ERROR(r); } #endif #if (HAVE_CHOWN) // copy the ownership if (opt->preserve_ownership) { r = chown(name, st.st_uid, st.st_gid); IGNORE_ERROR(r); } #endif } UiPacker::uiConfirmUpdate(); }
bool ch_link(inoptr wd, char *oldname, char *newname, inoptr nindex) { struct direct curentry; int i; if(!(getperm(wd) & OTH_WR)) { udata.u_error = EPERM; return false; } /* Inserting a new blank entry ? */ if (!*newname && nindex != NULLINODE) { udata.u_error = EEXIST; return false; } /* Search the directory for the desired slot. */ udata.u_offset = 0; for(;;) { udata.u_count = DIR_LEN; udata.u_base =(char *)&curentry; udata.u_sysio = true; readi(wd, 0); /* Read until EOF or name is found. readi() advances udata.u_offset */ if(udata.u_count == 0 || namecomp(oldname, curentry.d_name)) break; } if(udata.u_count == 0 && *oldname) return false; /* Entry not found */ memcpy(curentry.d_name, newname, FILENAME_LEN); // pad name with NULLs for(i = 0; i < FILENAME_LEN; ++i) if(curentry.d_name[i] == '\0') break; for(; i < FILENAME_LEN; ++i) curentry.d_name[i] = '\0'; if(nindex) curentry.d_ino = nindex->c_num; else curentry.d_ino = 0; /* If an existing slot is being used, we must back up the file offset */ if(udata.u_count){ udata.u_offset -= DIR_LEN; } udata.u_count = DIR_LEN; udata.u_base = (char*)&curentry; udata.u_sysio = true; writei(wd, 0); if(udata.u_error) return false; setftime(wd, A_TIME|M_TIME|C_TIME); /* Sets c_dirty */ /* Update file length to next block */ if(wd->c_node.i_size & BLKMASK) wd->c_node.i_size += BLKSIZE - (wd->c_node.i_size & BLKMASK); return true; // success }
static int inner_copy( const char *src, const char *dst, int replaceOk) { int in = -1, out = -1; // file handles int result = -1; // default to error int bufsize = 0; void *buf = NULL; for(bufsize=0x4000; buf == NULL && bufsize >= 128; bufsize /= 2) buf = malloc(bufsize); if (buf==NULL) { /* no errors allowed here! */ static char dummy[4]; buf = dummy; bufsize = 4; } in = open(src,O_RDONLY|O_BINARY); if (in >= 0) { out = open(dst, O_BINARY | O_CREAT | O_RDWR | (replaceOk ? O_TRUNC : O_EXCL), S_IREAD|S_IWRITE); if (out >= 0) { int lastwrite, nbytes; while ((nbytes = read(in, buf, bufsize)) > 0) { lastwrite = write(out, buf, nbytes); if (lastwrite==-1) break; } if (lastwrite>=0) { #ifdef _WIN32 struct _timeb ftime; #else struct ftime ftime; #endif getftime(in,&ftime); setftime(out,&ftime); result = 0; } else mydir_errno = WRITE_ERROR; close(out); // put this here so if fail 'cause of existence, // we don't remove the unreplaced file! // also, the file must be closed to remove if (result) remove(dst); } else { mydir_errno = DST_OPEN_ERROR; switch(errno) { case EEXIST: mydir_errno = DST_ALREADY_EXIST; break; } } close(in); } else { mydir_errno = SRC_OPEN_ERROR; switch(errno) { case ENOENT: mydir_errno = SRC_NO_EXIST; break; } } assert(buf); if (bufsize != 4) free(buf); return result; }
arg_t _open(void) { int8_t uindex; int8_t oftindex; staticfast inoptr ino; int16_t perm; staticfast inoptr parent; char fname[FILENAME_LEN + 1]; int trunc; int r; int w; int j; parent = NULLINODE; trunc = flag & O_TRUNC; r = (flag + 1) & 1; w = (flag + 1) & 2; if (O_ACCMODE(flag) == 3 || (flag & O_BADBITS)) { udata.u_error = EINVAL; return (-1); } if ((uindex = uf_alloc()) == -1) return (-1); if ((oftindex = oft_alloc()) == -1) goto nooft; ino = n_open(name, &parent); if (ino) { i_deref(parent); /* O_EXCL test */ if ((flag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { udata.u_error = EEXIST; goto idrop; } } else { /* The n_open failed */ if (udata.u_error == EFAULT) goto cantopen; /* New file */ if (!(flag & O_CREAT)) { udata.u_error = ENOENT; goto cantopen; } filename(name, fname); /* newfile drops parent for us */ if (parent && (ino = newfile(parent, fname))) { ino->c_node.i_mode = (F_REG | (mode & MODE_MASK & ~udata.u_mask)); setftime(ino, A_TIME | M_TIME | C_TIME); wr_inode(ino); } else { udata.u_error = ENFILE; /* FIXME, should be set in newfile not bodged to a guessed code */ goto cantopen; } } /* Book our slot in case we block opening a device */ of_tab[oftindex].o_inode = ino; perm = getperm(ino); if ((r && !(perm & OTH_RD)) || (w && !(perm & OTH_WR))) { udata.u_error = EACCES; goto cantopen; } if (w) { if (getmode(ino) == F_DIR ) { udata.u_error = EISDIR; goto cantopen; } if (ino->c_flags & CRDONLY) { udata.u_error = EROFS; goto cantopen; } } if (isdevice(ino)) { inoptr *iptr = &of_tab[oftindex].o_inode; /* d_open may block and thus ino may become invalid as may parent (but we don't need it again). It may also be changed by the call to dev_openi */ if (dev_openi(iptr, flag) != 0) goto cantopen; /* May have changed */ /* get the static pointer back in case it changed via dev usage or just because we blocked */ ino = *iptr; } if (trunc && getmode(ino) == F_REG) { if (f_trunc(ino)) goto idrop; for (j = 0; j < OFTSIZE; ++j) /* Arguably should fix at read/write */ if (of_tab[j].o_inode == ino) of_tab[j].o_ptr = 0; } udata.u_files[uindex] = oftindex; of_tab[oftindex].o_ptr = 0; of_tab[oftindex].o_access = flag; /* Save the low bits only */ if (flag & O_CLOEXEC) udata.u_cloexec |= (1 << oftindex); /* FIXME: ATIME ? */ /* * Sleep process if no writer or reader */ if (getmode(ino) == F_PIPE && of_tab[oftindex].o_refs == 1 && !(flag & O_NDELAY)) psleep(ino); /* From the moment of the psleep ino is invalid */ return (uindex); idrop: i_deref(ino); cantopen: oft_deref(oftindex); /* This will call i_deref() */ nooft: udata.u_files[uindex] = NO_FILE; return (-1); }
int sbbs_t::exec_misc(csi_t* csi, char *path) { char str[512],tmp[512],buf[1025],ch,op,*p,**pp,**pp1,**pp2; ushort w; uint i=0,j; long l,*lp=NULL,*lp1=NULL,*lp2=NULL; void *vp; struct dirent *de; struct tm tm; switch(*(csi->ip++)) { case CS_VAR_INSTRUCTION: switch(*(csi->ip++)) { /* sub-op-code stored as next byte */ case PRINT_VAR: pp=getstrvar(csi,*(long *)csi->ip); if(!pp || !*pp) { lp=getintvar(csi,*(long *)csi->ip); if(lp) bprintf("%ld",*lp); } else putmsg(cmdstr(*pp,path,csi->str,buf) ,P_SAVEATR|P_NOABORT|P_NOATCODES); csi->ip+=4; return(0); case VAR_PRINTF: case VAR_PRINTF_LOCAL: op=*(csi->ip-1); p=format_string(this, csi); if(op==VAR_PRINTF) putmsg(cmdstr(p,path,csi->str,buf),P_SAVEATR|P_NOABORT|P_NOATCODES); else { if(online==ON_LOCAL) eprintf(LOG_INFO,"%s",cmdstr(p,path,csi->str,buf)); else lputs(LOG_INFO,cmdstr(p,path,csi->str,buf)); } free(p); return(0); case SHOW_VARS: bprintf("shell str=(%08lX) %s\r\n" ,csi->str,csi->str); for(i=0;i<csi->str_vars;i++) bprintf("local str[%d]=(%08lX) (%08lX) %s\r\n" ,i,csi->str_var_name[i] ,csi->str_var[i] ,csi->str_var[i]); for(i=0;i<csi->int_vars;i++) bprintf("local int[%d]=(%08lX) (%08lX) %ld\r\n" ,i,csi->int_var_name[i] ,csi->int_var[i] ,csi->int_var[i]); for(i=0;i<global_str_vars;i++) bprintf("global str[%d]=(%08lX) (%08lX) %s\r\n" ,i,global_str_var_name[i] ,global_str_var[i] ,global_str_var[i]); for(i=0;i<global_int_vars;i++) bprintf("global int[%d]=(%08lX) (%08lX) %ld\r\n" ,i,global_int_var_name[i] ,global_int_var[i] ,global_int_var[i]); return(0); case DEFINE_STR_VAR: if(getstrvar(csi,*(long *)csi->ip)) { csi->ip+=4; return(0); } csi->str_vars++; csi->str_var=(char **)realloc(csi->str_var ,sizeof(char *)*csi->str_vars); csi->str_var_name=(long *)realloc(csi->str_var_name ,sizeof(long)*csi->str_vars); if(csi->str_var==NULL || csi->str_var_name==NULL) { /* REALLOC failed */ errormsg(WHERE,ERR_ALLOC,"local str var" ,sizeof(char *)*csi->str_vars); if(csi->str_var_name) { free(csi->str_var_name); csi->str_var_name=0; } if(csi->str_var) { free(csi->str_var); csi->str_var=0; } csi->str_vars=0; } else { csi->str_var_name[csi->str_vars-1]=*(long *)csi->ip; csi->str_var[csi->str_vars-1]=0; } csi->ip+=4; /* Skip variable name */ return(0); case DEFINE_INT_VAR: if(getintvar(csi,*(long *)csi->ip)) { csi->ip+=4; return(0); } csi->int_vars++; csi->int_var=(long *)realloc(csi->int_var ,sizeof(char *)*csi->int_vars); csi->int_var_name=(long *)realloc(csi->int_var_name ,sizeof(long)*csi->int_vars); if(csi->int_var==NULL || csi->int_var_name==NULL) { /* REALLOC failed */ errormsg(WHERE,ERR_ALLOC,"local int var" ,sizeof(char *)*csi->int_vars); if(csi->int_var_name) { free(csi->int_var_name); csi->int_var_name=0; } if(csi->int_var) { free(csi->int_var); csi->int_var=0; } csi->int_vars=0; } else { csi->int_var_name[csi->int_vars-1]=*(long *)csi->ip; csi->int_var[csi->int_vars-1]=0; } csi->ip+=4; /* Skip variable name */ return(0); case DEFINE_GLOBAL_STR_VAR: if(getstrvar(csi,*(long *)csi->ip)) { csi->ip+=4; return(0); } global_str_vars++; global_str_var=(char **)realloc(global_str_var ,sizeof(char *)*global_str_vars); global_str_var_name=(long *)realloc(global_str_var_name ,sizeof(long)*global_str_vars); if(global_str_var==NULL || global_str_var_name==NULL) { /* REALLOC failed */ errormsg(WHERE,ERR_ALLOC,"global str var" ,sizeof(char *)*global_str_vars); if(global_str_var_name) { free(global_str_var_name); global_str_var_name=0; } if(global_str_var) { free(global_str_var); global_str_var=0; } global_str_vars=0; } else { global_str_var_name[global_str_vars-1]= *(long *)csi->ip; global_str_var[global_str_vars-1]=0; } csi->ip+=4; /* Skip variable name */ return(0); case DEFINE_GLOBAL_INT_VAR: if(getintvar(csi,*(long *)csi->ip)) { csi->ip+=4; return(0); } global_int_vars++; global_int_var=(long *)realloc(global_int_var ,sizeof(char *)*global_int_vars); global_int_var_name=(long *)realloc(global_int_var_name ,sizeof(long)*global_int_vars); if(global_int_var==NULL || global_int_var_name==NULL) { /* REALLOC failed */ errormsg(WHERE,ERR_ALLOC,"local int var" ,sizeof(char *)*global_int_vars); if(global_int_var_name) { free(global_int_var_name); global_int_var_name=0; } if(global_int_var) { free(global_int_var); global_int_var=0; } global_int_vars=0; } else { global_int_var_name[global_int_vars-1] =*(long *)csi->ip; global_int_var[global_int_vars-1]=0; } csi->ip+=4; /* Skip variable name */ return(0); case SET_STR_VAR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ if(pp) *pp=copystrvar(csi,*pp ,cmdstr((char *)csi->ip,path,csi->str,buf)); while(*(csi->ip++)); /* Find NULL */ return(0); case SET_INT_VAR: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ if(lp) *lp=*(long *)csi->ip; csi->ip+=4; /* Skip value */ return(0); case COMPARE_STR_VAR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ if(pp && *pp) csi->logic=stricmp(*pp ,cmdstr((char *)csi->ip,path,csi->str,buf)); else { /* Uninitialized str var */ if(*(csi->ip)==0) /* Blank static str */ csi->logic=LOGIC_TRUE; else csi->logic=LOGIC_FALSE; } while(*(csi->ip++)); /* Find NULL */ return(0); case STRSTR_VAR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ if(pp && *pp && strstr(*pp ,cmdstr((char *)csi->ip,path,csi->str,buf))) csi->logic=LOGIC_TRUE; else csi->logic=LOGIC_FALSE; while(*(csi->ip++)); /* Find NULL */ return(0); case STRNCMP_VAR: i=*csi->ip++; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ if(pp && *pp) csi->logic=strnicmp(*pp ,cmdstr((char *)csi->ip,path,csi->str,buf),i); else csi->logic=LOGIC_FALSE; while(*(csi->ip++)); /* Find NULL */ return(0); case STRNCMP_VARS: i=*csi->ip++; pp1=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ pp2=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp1 && *pp1 && pp2 && *pp2) csi->logic=strnicmp(*pp1,*pp2,i); else csi->logic=LOGIC_FALSE; return(0); case STRSTR_VARS: pp1=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ pp2=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp1 && *pp1 && pp2 && *pp2 && strstr(*pp1,*pp2)) csi->logic=LOGIC_TRUE; else csi->logic=LOGIC_FALSE; return(0); case COMPARE_INT_VAR: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ l=*(long *)csi->ip; csi->ip+=4; /* Skip static value */ if(!lp) { /* Unknown variable */ csi->logic=LOGIC_FALSE; return(0); } if(*lp>l) csi->logic=LOGIC_GREATER; else if(*lp<l) csi->logic=LOGIC_LESS; else csi->logic=LOGIC_EQUAL; return(0); case COMPARE_VARS: lp1=lp2=0; pp1=getstrvar(csi,*(long *)csi->ip); if(!pp1) lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ pp2=getstrvar(csi,*(long *)csi->ip); if(!pp2) lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ if(((!pp1 || !*pp1) && !lp1) || ((!pp2 || !*pp2) && !lp2)) { if(pp1 && pp2) /* Both unitialized or blank */ csi->logic=LOGIC_TRUE; else csi->logic=LOGIC_FALSE; return(0); } if(pp1) { /* ASCII */ if(!pp2) { ultoa(*lp2,tmp,10); csi->logic=stricmp(*pp1,tmp); } else csi->logic=stricmp(*pp1,*pp2); return(0); } /* Binary */ if(!lp2) { l=strtol(*pp2,0,0); if(*lp1>l) csi->logic=LOGIC_GREATER; else if(*lp1<l) csi->logic=LOGIC_LESS; else csi->logic=LOGIC_EQUAL; return(0); } if(*lp1>*lp2) csi->logic=LOGIC_GREATER; else if(*lp1<*lp2) csi->logic=LOGIC_LESS; else csi->logic=LOGIC_EQUAL; return(0); case COPY_VAR: lp1=lp2=0; pp1=getstrvar(csi,*(long *)csi->ip); if(!pp1) lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ pp2=getstrvar(csi,*(long *)csi->ip); if(!pp2) lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ if((!pp1 && !lp1) || ((!pp2 || !*pp2) && !lp2)) { csi->logic=LOGIC_FALSE; return(0); } csi->logic=LOGIC_TRUE; if(pp1) { /* ASCII */ if(!pp2) ultoa(*lp2,tmp,10); else strcpy(tmp,*pp2); *pp1=copystrvar(csi,*pp1,tmp); return(0); } if(!lp2) *lp1=strtol(*pp2,0,0); else *lp1=*lp2; return(0); case SWAP_VARS: lp1=lp2=0; pp1=getstrvar(csi,*(long *)csi->ip); if(!pp1) lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ pp2=getstrvar(csi,*(long *)csi->ip); if(!pp2) lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ if(((!pp1 || !*pp1) && !lp1) || ((!pp2 || !*pp2) && !lp2)) { csi->logic=LOGIC_FALSE; return(0); } csi->logic=LOGIC_TRUE; if(pp1) { /* ASCII */ if(!pp2) { if(!strnicmp(*pp2,"0x",2)) { l=strtol((*pp1)+2,0,16); ultoa(*lp2,tmp,16); } else { l=atol(*pp1); ultoa(*lp2,tmp,10); } *pp1=copystrvar(csi,*pp1,tmp); *lp2=l; } else { p=*pp1; *pp1=*pp2; *pp2=p; } return(0); } /* Binary */ if(!lp2) { if(!strnicmp(*pp2,"0x",2)) { l=strtol((*pp2)+2,0,16); ultoa(*lp1,tmp,16); } else { l=atol(*pp2); ultoa(*lp1,tmp,10); } *pp2=copystrvar(csi,*pp2,tmp); *lp1=l; } else { l=*lp1; *lp1=*lp2; *lp2=l; } return(0); case CAT_STR_VAR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ strcpy(tmp,(char *)csi->ip); while(*(csi->ip++)); if(pp && *pp) for(i=0;i<MAX_SYSVARS;i++) if(*pp==sysvar_p[i]) break; if(pp && *pp!=csi->str && i==MAX_SYSVARS) { if(*pp) *pp=(char *)realloc(*pp,strlen(*pp)+strlen(tmp)+1); else *pp=(char *)realloc(*pp,strlen(tmp)+1); } if(pp && *pp) strcat(*pp,tmp); return(0); case CAT_STR_VARS: pp1=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip dest variable name */ pp2=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip source variable name */ /* Concatenate an int var to a str var (as char) */ if(pp2==NULL) { lp=getintvar(csi,*(long *)(csi->ip-4)); if(lp==NULL) { csi->logic=LOGIC_FALSE; return(0); } pp=pp1; tmp[0]=(uchar)*lp; tmp[1]=0; if(pp && *pp) for(i=0;i<MAX_SYSVARS;i++) if(*pp==sysvar_p[i]) break; if(pp && *pp!=csi->str && i==MAX_SYSVARS) { if(*pp) *pp=(char *)realloc(*pp,strlen(*pp)+strlen(tmp)+1); else *pp=(char *)realloc(*pp,strlen(tmp)+1); } if(pp && *pp) strcat(*pp,tmp); return(0); } if(!pp1 || !pp2 || !*pp2) { csi->logic=LOGIC_FALSE; return(0); } csi->logic=LOGIC_TRUE; if(*pp1) for(i=0;i<MAX_SYSVARS;i++) if(*pp1==sysvar_p[i]) break; if(*pp1!=csi->str && (!*pp1 || i==MAX_SYSVARS)) { if(*pp1) *pp1=(char *)realloc(*pp1,strlen(*pp1)+strlen(*pp2)+1); else *pp1=(char *)realloc(*pp1,strlen(*pp2)+1); } strcat(*pp1,*pp2); return(0); case FORMAT_STR_VAR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ p=format_string(this, csi); cmdstr(p,path,csi->str,str); if(pp) *pp=copystrvar(csi,*pp,str); free(p); return(0); case FORMAT_TIME_STR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ strcpy(str,(char *)csi->ip); while(*(csi->ip++)); /* Find NULL */ lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp && lp) { if(localtime_r((time_t *)lp,&tm)!=NULL) { strftime(buf,128,str,&tm); *pp=copystrvar(csi,*pp,buf); } } return(0); case TIME_STR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip str variable name */ lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip int variable name */ if(pp && lp) { strcpy(str,timestr((time_t *)lp)); *pp=copystrvar(csi,*pp,str); } return(0); case DATE_STR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip str variable name */ lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip int variable name */ if(pp && lp) { unixtodstr(&cfg,*lp,str); *pp=copystrvar(csi,*pp,str); } return(0); case SECOND_STR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip str variable name */ lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip int variable name */ if(pp && lp) { sectostr(*lp,str); *pp=copystrvar(csi,*pp,str); } return(0); case STRUPR_VAR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp && *pp) strupr(*pp); return(0); case STRLWR_VAR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp && *pp) strlwr(*pp); return(0); case TRUNCSP_STR_VAR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp && *pp) truncsp(*pp); return(0); case STRIP_CTRL_STR_VAR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp && *pp) strip_ctrl(*pp); return(0); case ADD_INT_VAR: case SUB_INT_VAR: case MUL_INT_VAR: case DIV_INT_VAR: case MOD_INT_VAR: case AND_INT_VAR: case OR_INT_VAR: case NOT_INT_VAR: case XOR_INT_VAR: i=*(csi->ip-1); lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; l=*(long *)csi->ip; csi->ip+=4; if(!lp) return(0); switch(i) { case ADD_INT_VAR: *lp+=l; break; case SUB_INT_VAR: *lp-=l; break; case MUL_INT_VAR: *lp*=l; break; case DIV_INT_VAR: *lp/=l; break; case MOD_INT_VAR: *lp%=l; break; case AND_INT_VAR: *lp&=l; break; case OR_INT_VAR: *lp|=l; break; case NOT_INT_VAR: *lp&=~l; break; case XOR_INT_VAR: *lp^=l; break; } return(0); case COMPARE_ANY_BITS: case COMPARE_ALL_BITS: i=*(csi->ip-1); lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; l=*(long *)csi->ip; csi->ip+=4; csi->logic=LOGIC_FALSE; if(!lp) return(0); if(i==COMPARE_ANY_BITS) { if(((*lp)&l)!=0) csi->logic=LOGIC_TRUE; } else { if(((*lp)&l)==l) csi->logic=LOGIC_TRUE; } return(0); case ADD_INT_VARS: case SUB_INT_VARS: case MUL_INT_VARS: case DIV_INT_VARS: case MOD_INT_VARS: case AND_INT_VARS: case OR_INT_VARS: case NOT_INT_VARS: case XOR_INT_VARS: i=*(csi->ip-1); lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; lp2=getintvar(csi,*(long *)csi->ip); if(!lp2) { pp=getstrvar(csi,*(long *)csi->ip); if(!pp || !*pp) return(0); l=strtol(*pp,0,0); } else l=*lp2; csi->ip+=4; if(!lp1) return(0); switch(i) { case ADD_INT_VARS: *lp1+=l; break; case SUB_INT_VARS: *lp1-=l; break; case MUL_INT_VARS: *lp1*=l; break; case DIV_INT_VARS: *lp1/=l; break; case MOD_INT_VARS: *lp1%=l; break; case AND_INT_VARS: *lp1&=l; break; case OR_INT_VARS: *lp1|=l; break; case NOT_INT_VARS: *lp1&=~l; break; case XOR_INT_VARS: *lp1^=l; break; } return(0); case RANDOM_INT_VAR: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; l=*(long *)csi->ip; csi->ip+=4; if(lp) *lp=sbbs_random(l); return(0); case TIME_INT_VAR: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp) *lp=time(NULL); return(0); case DATE_STR_TO_INT: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp && pp && *pp) *lp=dstrtounix(&cfg,*pp); return(0); case STRLEN_INT_VAR: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp) { if(pp && *pp) *lp=strlen(*pp); else *lp=0; } return(0); case CRC16_TO_INT: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp) { if(pp && *pp) *lp=crc16(*pp,0); else *lp=0; } return(0); case CRC32_TO_INT: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp) { if(pp && *pp) *lp=crc32(*pp,0); else *lp=0; } return(0); case CHKSUM_TO_INT: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp) { *lp=0; if(pp && *pp) { i=0; while(*((*pp)+i)) *lp+=(uchar)*((*pp)+(i++)); } } return(0); case FLENGTH_TO_INT: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp) { if(pp && *pp) *lp=flength(*pp); else *lp=0; } return(0); case FTIME_TO_INT: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp) { if(pp && *pp) *lp=fdate(*pp); else *lp=0; } return(0); case CHARVAL_TO_INT: case COPY_FIRST_CHAR: // duplicate functionality - doh! lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp) { if(pp && *pp) *lp=**pp; else *lp=0; } return(0); case GETSTR_VAR: case GETLINE_VAR: case GETNAME_VAR: case GETSTRUPR_VAR: case GETSTR_MODE: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; i=*(csi->ip++); csi->logic=LOGIC_FALSE; switch(*(csi->ip-6)) { case GETNAME_VAR: getstr(buf,i,K_UPRLWR); break; case GETSTRUPR_VAR: getstr(buf,i,K_UPPER); break; case GETLINE_VAR: getstr(buf,i,K_LINE); break; case GETSTR_MODE: l=*(long *)csi->ip; csi->ip+=4; if(l&K_EDIT) { if(pp && *pp) strcpy(buf,*pp); else buf[0]=0; } getstr(buf,i,l); break; default: getstr(buf,i,0); } if(sys_status&SS_ABORT) return(0); if(pp) { *pp=copystrvar(csi,*pp,buf); csi->logic=LOGIC_TRUE; } return(0); case GETNUM_VAR: pp=getstrvar(csi,*(long *)csi->ip); if(!pp) lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; i=*(short *)csi->ip; csi->ip+=2; csi->logic=LOGIC_FALSE; l=getnum(i); if(!pp && !lp) return(0); if(pp) { if(l<=0) str[0]=0; else ultoa(l,str,10); *pp=copystrvar(csi,*pp,str); csi->logic=LOGIC_TRUE; return(0); } if(lp) { *lp=l; csi->logic=LOGIC_TRUE; } return(0); case SHIFT_STR_VAR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; i=*(csi->ip++); if(!pp || !*pp) return(0); if(strlen(*pp)>=i) memmove(*pp,*pp+i,strlen(*pp)+1); return(0); case SHIFT_TO_FIRST_CHAR: case SHIFT_TO_LAST_CHAR: i=*(csi->ip-1); pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; ch=*(csi->ip++); csi->logic=LOGIC_FALSE; if(!pp || !*pp) return(0); if(i==SHIFT_TO_FIRST_CHAR) p=strchr(*pp,ch); else /* _TO_LAST_CHAR */ p=strrchr(*pp,ch); if(p==NULL) return(0); csi->logic=LOGIC_TRUE; i=p-*pp; if(i>0) memmove(*pp,*pp+i,strlen(p)+1); return(0); case CHKFILE_VAR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp && *pp && fexistcase(cmdstr(*pp,path,csi->str,buf))) csi->logic=LOGIC_TRUE; else csi->logic=LOGIC_FALSE; return(0); case PRINTFILE_VAR_MODE: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; i=*(short *)(csi->ip); csi->ip+=2; if(pp && *pp) printfile(*pp,i); return(0); case PRINTTAIL_VAR_MODE: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; i=*(short *)(csi->ip); csi->ip+=2; j=*csi->ip; csi->ip++; if(pp && *pp) printtail(*pp,j,i); return(0); case TELNET_GATE_VAR: l=*(ulong *)(csi->ip); // Mode csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp && *pp) telnet_gate(*pp,l); return(0); case TELNET_GATE_STR: l=*(ulong *)(csi->ip); // Mode csi->ip+=4; strcpy(str,(char *)csi->ip); while(*(csi->ip++)); /* Find NULL */ telnet_gate(str,l); return(0); case COPY_CHAR: pp=getstrvar(csi,*(long *)csi->ip); if(pp==NULL) lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp==NULL && lp!=NULL) *lp=csi->cmd; else if(pp!=NULL) { sprintf(tmp,"%c",csi->cmd); *pp=copystrvar(csi,*pp,tmp); } return(0); case COMPARE_FIRST_CHAR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; ch=*(csi->ip++); /* char const */ if(pp==NULL || *pp==NULL) csi->logic=LOGIC_FALSE; else { if(**pp==ch) csi->logic=LOGIC_EQUAL; else if(**pp>ch) csi->logic=LOGIC_GREATER; else csi->logic=LOGIC_LESS; } return(0); case SEND_FILE_VIA: case RECEIVE_FILE_VIA: j=*(csi->ip-1); ch=*(csi->ip++); /* Protocol */ cmdstr((char *)csi->ip,csi->str,csi->str,str); while(*(csi->ip++)); /* Find NULL */ for(i=0;i<cfg.total_prots;i++) if(cfg.prot[i]->mnemonic==ch && chk_ar(cfg.prot[i]->ar,&useron)) break; csi->logic=LOGIC_FALSE; if(i<cfg.total_prots) if(protocol(cfg.prot[i],j==SEND_FILE_VIA ? XFER_DOWNLOAD : XFER_UPLOAD ,str,str,true)==0) csi->logic=LOGIC_TRUE; return(0); case SEND_FILE_VIA_VAR: case RECEIVE_FILE_VIA_VAR: j=*(csi->ip-1); ch=*(csi->ip++); /* Protocol */ pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; for(i=0;i<cfg.total_prots;i++) if(cfg.prot[i]->mnemonic==ch && chk_ar(cfg.prot[i]->ar,&useron)) break; csi->logic=LOGIC_FALSE; if(!pp || !(*pp)) return(0); if(i<cfg.total_prots) if(protocol(cfg.prot[i] ,j==SEND_FILE_VIA_VAR ? XFER_DOWNLOAD : XFER_UPLOAD ,*pp,*pp,true)==0) csi->logic=LOGIC_TRUE; return(0); case MATCHUSER: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp) { if(pp && *pp) *lp=matchuser(&cfg, *pp, TRUE /*sysop_alias*/); else *lp=0; } return(0); default: errormsg(WHERE,ERR_CHK,"var sub-instruction",*(csi->ip-1)); return(0); } case CS_FIO_FUNCTION: switch(*(csi->ip++)) { /* sub-op-code stored as next byte */ case FIO_OPEN: case FIO_OPEN_VAR: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; w=*(ushort *)csi->ip; csi->ip+=2; csi->logic=LOGIC_FALSE; if(*(csi->ip-7)==FIO_OPEN) { cmdstr((char *)csi->ip,path,csi->str,str); while(*(csi->ip++)); } /* skip filename */ else { pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(!pp || !*pp) return(0); strcpy(str,*pp); } if(csi->files>=MAX_FOPENS) return(0); if(lp) { /* Access flags are not cross-platform, so convert */ i=0; if(w&0x001) i|=O_RDONLY; if(w&0x002) i|=O_WRONLY; if(w&0x004) i|=O_RDWR; if(w&0x040) i|=O_DENYNONE; if(w&0x100) i|=O_CREAT; if(w&0x200) i|=O_TRUNC; if(w&0x400) i|=O_EXCL; if(w&0x800) i|=O_APPEND; *lp=(long)fnopen((int *)&j,str,i); if(*lp) { for(i=0;i<csi->files;i++) if(!csi->file[i]) break; csi->file[i]=(FILE *)*lp; if(i==csi->files) csi->files++; csi->logic=LOGIC_TRUE; } } return(0); case FIO_CLOSE: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp && *lp) { csi->logic=fclose((FILE *)*lp); for(i=0;i<csi->files;i++) if(csi->file[i]==(FILE *)*lp) csi->file[i]=0; *lp=0; } else csi->logic=LOGIC_FALSE; return(0); case FIO_FLUSH: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp && *lp) csi->logic=fflush((FILE *)*lp); else csi->logic=LOGIC_FALSE; return(0); case FIO_READ: case FIO_READ_VAR: lp1=getintvar(csi,*(long *)csi->ip); /* Handle */ csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); if(!pp) lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; csi->logic=LOGIC_FALSE; if(*(csi->ip-9)==FIO_READ) { i=*(short *)csi->ip; csi->ip+=2; /* Length */ } else { /* FIO_READ_VAR */ vp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(!vp) return(0); i=*(short *)vp; } if(i>sizeof(buf)-1) i=sizeof(buf)-1; if(!lp1 || !(*lp1) || (!pp && !lp2)) return(0); if(pp) { if(i<1) { if(*pp && **pp) i=strlen(*pp); else i=128; } if((j=fread(buf,1,i,(FILE *)*lp1))==i) csi->logic=LOGIC_TRUE; buf[j]=0; if(csi->etx) { p=strchr(buf,csi->etx); if(p) *p=0; } *pp=copystrvar(csi,*pp,buf); } else { *lp2=0; if(i>4 || i<1) i=4; if(fread(lp2,1,i,(FILE *)*lp1)==i) csi->logic=LOGIC_TRUE; } return(0); case FIO_READ_LINE: lp1=getintvar(csi,*(long *)csi->ip); /* Handle */ csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); if(!pp) lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; csi->logic=LOGIC_FALSE; if(!lp1 || !(*lp1) || feof((FILE *)*lp1) || (!pp && !lp2)) return(0); csi->logic=LOGIC_TRUE; for(i=0;i<sizeof(buf)-1;i++) { if(!fread(buf+i,1,1,(FILE *)*lp1)) break; if(*(buf+i)==LF) { i++; break; } } buf[i]=0; if(csi->etx) { p=strchr(buf,csi->etx); if(p) *p=0; } if(pp) *pp=copystrvar(csi,*pp,buf); else *lp2=strtol(buf,0,0); return(0); case FIO_WRITE: case FIO_WRITE_VAR: lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); if(!pp) lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; csi->logic=LOGIC_FALSE; if(*(csi->ip-9)==FIO_WRITE) { i=*(short *)csi->ip; csi->ip+=2; /* Length */ } else { /* FIO_WRITE_VAR */ vp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(!vp) return(0); i=*(short *)vp; } if(i>sizeof(buf)-1) i=sizeof(buf)-1; if(!lp1 || !(*lp1) || (!pp && !lp2) || (pp && !*pp)) return(0); if(pp) { j=strlen(*pp); if(i<1) i=j; if(j>i) j=i; if(fwrite(*pp,1,j,(FILE *)*lp1)!=j) csi->logic=LOGIC_FALSE; else { if(j<i) { memset(buf,csi->etx,i-j); fwrite(buf,1,i-j,(FILE *)*lp1); } csi->logic=LOGIC_TRUE; } } else { if(i<1 || i>4) i=4; if(fwrite(lp2,1,i,(FILE *)*lp1)==i) csi->logic=LOGIC_TRUE; } return(0); case FIO_GET_LENGTH: lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp1 && *lp1 && lp2) *lp2=filelength(fileno((FILE *)*lp1)); return(0); case FIO_GET_TIME: lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp1 && *lp1 && lp2) *lp2=filetime(fileno((FILE *)*lp1)); return(0); case FIO_SET_TIME: lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; #if 0 /* ftime */ if(lp1 && *lp1 && lp2) { ft=unixtoftime(*lp2); setftime(fileno((FILE *)*lp1),&ft); } #endif return(0); case FIO_EOF: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; csi->logic=LOGIC_FALSE; if(lp && *lp) if(ftell((FILE *)*lp)>=filelength(fileno((FILE *)*lp))) csi->logic=LOGIC_TRUE; return(0); case FIO_GET_POS: lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp1 && *lp1 && lp2) *lp2=ftell((FILE *)*lp1); return(0); case FIO_SEEK: case FIO_SEEK_VAR: lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; csi->logic=LOGIC_FALSE; if(*(csi->ip-5)==FIO_SEEK) { l=*(long *)csi->ip; csi->ip+=4; } else { lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(!lp2) { csi->ip+=2; return(0); } l=*lp2; } i=*(short *)csi->ip; csi->ip+=2; if(lp1 && *lp1) if(fseek((FILE *)*lp1,l,i)!=-1) csi->logic=LOGIC_TRUE; return(0); case FIO_LOCK: case FIO_LOCK_VAR: lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; csi->logic=LOGIC_FALSE; if(*(csi->ip-5)==FIO_LOCK) { l=*(long *)csi->ip; csi->ip+=4; } else { lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(!lp2) return(0); l=*lp2; } if(lp1 && *lp1) { fflush((FILE *)*lp1); csi->logic=!lock(fileno((FILE *)*lp1),ftell((FILE*)*lp1),l); } return(0); case FIO_UNLOCK: case FIO_UNLOCK_VAR: lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; csi->logic=LOGIC_FALSE; if(*(csi->ip-5)==FIO_UNLOCK) { l=*(long *)csi->ip; csi->ip+=4; } else { lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(!lp2) return(0); l=*lp2; } if(lp1 && *lp1) { fflush((FILE *)*lp1); csi->logic=!unlock(fileno((FILE *)*lp1),ftell((FILE*)*lp1),l); } return(0); case FIO_SET_LENGTH: case FIO_SET_LENGTH_VAR: lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; csi->logic=LOGIC_FALSE; if(*(csi->ip-5)==FIO_SET_LENGTH) { l=*(long *)csi->ip; csi->ip+=4; } else { lp2=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(!lp2) return(0); l=*lp2; } if(lp1 && *lp1) csi->logic=chsize(fileno((FILE *)*lp1),l); return(0); case FIO_PRINTF: lp1=getintvar(csi,*(long *)csi->ip); csi->ip+=4; p=format_string(this, csi); if(lp1 && *lp1) { cmdstr(p,path,csi->str,str); fwrite(str,1,strlen(str),(FILE *)*lp1); } free(p); return(0); case FIO_SET_ETX: csi->etx=*(csi->ip++); return(0); case REMOVE_FILE: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp && *pp && remove(*pp)==0) csi->logic=LOGIC_TRUE; else csi->logic=LOGIC_FALSE; return(0); case RENAME_FILE: case COPY_FILE: case MOVE_FILE: pp1=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; /* Skip variable name */ pp2=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp1 && *pp1 && pp2 && *pp2) switch(*(csi->ip-9)) { case RENAME_FILE: csi->logic=rename(*pp1,*pp2); break; case COPY_FILE: csi->logic=mv(*pp1,*pp2,1); break; case MOVE_FILE: csi->logic=mv(*pp1,*pp2,0); break; } else csi->logic=LOGIC_FALSE; return(0); case GET_FILE_ATTRIB: case SET_FILE_ATTRIB: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp && *pp && lp) { if(*(csi->ip-9)==GET_FILE_ATTRIB) *lp=getfattr(*pp); else *lp=CHMOD(*pp,(int)*lp); } return(0); case MAKE_DIR: case REMOVE_DIR: case CHANGE_DIR: pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; if(pp && *pp) switch(*(csi->ip-5)) { case MAKE_DIR: csi->logic=MKDIR(*pp); break; case REMOVE_DIR: csi->logic=rmdir(*pp); break; case CHANGE_DIR: csi->logic=chdir(*pp); break; } else csi->logic=LOGIC_FALSE; return(0); case OPEN_DIR: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; csi->logic=LOGIC_FALSE; if(pp && *pp && lp) { *lp=(long)opendir((char *)*pp); if(*lp) csi->logic=LOGIC_TRUE; } return(0); case READ_DIR: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; pp=getstrvar(csi,*(long *)csi->ip); csi->ip+=4; csi->logic=LOGIC_FALSE; if(pp && lp) { de=readdir((DIR *)(*lp)); if(de!=NULL) { csi->logic=LOGIC_TRUE; *pp=copystrvar(csi,*pp,de->d_name); } } return(0); case REWIND_DIR: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp) { rewinddir((DIR *)(*lp)); csi->logic=LOGIC_TRUE; } else csi->logic=LOGIC_FALSE; return(0); case CLOSE_DIR: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(lp && closedir((DIR *)(*lp))==0) csi->logic=LOGIC_TRUE; else csi->logic=LOGIC_FALSE; return(0); default: errormsg(WHERE,ERR_CHK,"fio sub-instruction",*(csi->ip-1)); return(0); } case CS_NET_FUNCTION: return(exec_net(csi)); case CS_SWITCH: lp=getintvar(csi,*(long *)csi->ip); csi->ip+=4; if(!lp) { skipto(csi,CS_END_SWITCH); csi->ip++; } else { csi->misc|=CS_IN_SWITCH; csi->switch_val=*lp; } return(0); case CS_CASE: l=*(long *)csi->ip; csi->ip+=4; if(csi->misc&CS_IN_SWITCH && csi->switch_val!=l) skipto(csi,CS_NEXTCASE); else csi->misc&=~CS_IN_SWITCH; return(0); case CS_COMPARE_ARS: i=*(csi->ip++); /* Length of ARS stored as byte before ARS */ csi->logic=!chk_ar(csi->ip,&useron); csi->ip+=i; return(0); case CS_TOGGLE_USER_MISC: useron.misc^=*(ulong *)csi->ip; putuserrec(&cfg,useron.number,U_MISC,8,ultoa(useron.misc,tmp,16)); csi->ip+=4; return(0); case CS_COMPARE_USER_MISC: if((useron.misc&*(ulong *)csi->ip)==*(ulong *)csi->ip) csi->logic=LOGIC_TRUE; else csi->logic=LOGIC_FALSE; csi->ip+=4; return(0); case CS_TOGGLE_USER_CHAT: useron.chat^=*(ulong *)csi->ip; putuserrec(&cfg,useron.number,U_CHAT,8,ultoa(useron.chat,tmp,16)); csi->ip+=4; return(0); case CS_COMPARE_USER_CHAT: if((useron.chat&*(ulong *)csi->ip)==*(ulong *)csi->ip) csi->logic=LOGIC_TRUE; else csi->logic=LOGIC_FALSE; csi->ip+=4; return(0); case CS_TOGGLE_USER_QWK: useron.qwk^=*(ulong *)csi->ip; putuserrec(&cfg,useron.number,U_QWK,8,ultoa(useron.qwk,tmp,16)); csi->ip+=4; return(0); case CS_COMPARE_USER_QWK: if((useron.qwk&*(ulong *)csi->ip)==*(ulong *)csi->ip) csi->logic=LOGIC_TRUE; else csi->logic=LOGIC_FALSE; csi->ip+=4; return(0); case CS_REPLACE_TEXT: i=*(ushort *)csi->ip; csi->ip+=2; i--; if(i>=TOTAL_TEXT) { errormsg(WHERE,ERR_CHK,"replace text #",i); while(*(csi->ip++)); /* Find NULL */ return(0); } if(text[i]!=text_sav[i] && text[i]!=nulstr) free(text[i]); j=strlen(cmdstr((char *)csi->ip,path,csi->str,buf)); if(!j) text[i]=nulstr; else text[i]=(char *)malloc(j+1); if(!text[i]) { errormsg(WHERE,ERR_ALLOC,"replacement text",j); while(*(csi->ip++)); /* Find NULL */ text[i]=text_sav[i]; return(0); } if(j) strcpy(text[i],buf); while(*(csi->ip++)); /* Find NULL */ return(0); case CS_USE_INT_VAR: // Self-modifying code! pp=getstrvar(csi,*(long *)csi->ip); if(pp && *pp) l=strtol(*pp,0,0); else { lp=getintvar(csi,*(long *)csi->ip); if(lp) l=*lp; else l=0; } csi->ip+=4; // Variable i=*(csi->ip++); // Offset if(i<1 || csi->ip+1+i>=csi->cs+csi->length) { errormsg(WHERE,ERR_CHK,"offset",i); csi->ip++; return(0); } switch(*(csi->ip++)) { // Length case sizeof(char): *(csi->ip+i)=(char)l; break; case sizeof(short): *((short *)(csi->ip+i))=(short)l; break; case sizeof(long): *((long *)(csi->ip+i))=l; break; default: errormsg(WHERE,ERR_CHK,"length",*(csi->ip-1)); break; } return(0); default: errormsg(WHERE,ERR_CHK,"shell instruction",*(csi->ip-1)); return(0); } }
arg_t _execve(void) { /* Not ideal on stack */ struct binfmt_flat binflat; inoptr ino; char **nargv; /* In user space */ char **nenvp; /* In user space */ struct s_argblk *abuf, *ebuf; int argc; uint32_t bin_size; /* Will need to be bigger on some cpus */ uaddr_t progbase, top; uaddr_t go; uint32_t true_brk; if (!(ino = n_open_lock(name, NULLINOPTR))) return (-1); if (!((getperm(ino) & OTH_EX) && (ino->c_node.i_mode & F_REG) && (ino->c_node.i_mode & (OWN_EX | OTH_EX | GRP_EX)))) { udata.u_error = EACCES; goto nogood; } setftime(ino, A_TIME); udata.u_offset = 0; udata.u_count = sizeof(struct binfmt_flat); udata.u_base = (void *)&binflat; udata.u_sysio = true; readi(ino, 0); if (udata.u_done != sizeof(struct binfmt_flat)) { udata.u_error = ENOEXEC; goto nogood; } /* FIXME: ugly - save this as valid_hdr modifies it */ true_brk = binflat.bss_end; /* Hard coded for our 68K format. We don't quite use the ucLinux names, we don't want to load a ucLinux binary in error! */ if (memcmp(binflat.magic, "bFLT", 4) || !valid_hdr(ino, &binflat)) { udata.u_error = ENOEXEC; goto nogood2; } /* Memory needed */ bin_size = binflat.bss_end + binflat.stack_size; /* Overflow ? */ if (bin_size < binflat.bss_end) { udata.u_error = ENOEXEC; goto nogood2; } /* Gather the arguments, and put them in temporary buffers. */ abuf = (struct s_argblk *) tmpbuf(); /* Put environment in another buffer. */ ebuf = (struct s_argblk *) tmpbuf(); /* Read args and environment from process memory */ if (rargs(argv, abuf) || rargs(envp, ebuf)) goto nogood3; /* This must be the last test as it makes changes if it works */ /* FIXME: need to update this to support split code/data and to fix stack handling nicely */ /* FIXME: ENOMEM fix needs to go to 16bit ? */ if ((udata.u_error = pagemap_realloc(0, bin_size, 0)) != 0) goto nogood3; /* Core dump and ptrace permission logic */ #ifdef CONFIG_LEVEL_2 /* Q: should uid == 0 mean we always allow core */ if ((!(getperm(ino) & OTH_RD)) || (ino->c_node.i_mode & (SET_UID | SET_GID))) udata.u_flags |= U_FLAG_NOCORE; else udata.u_flags &= ~U_FLAG_NOCORE; #endif udata.u_codebase = progbase = pagemap_base(); /* From this point on we are commmited to the exec() completing so we can start writing over the old program */ uput(&binflat, (uint8_t *)progbase, sizeof(struct binfmt_flat)); /* setuid, setgid if executable requires it */ if (ino->c_node.i_mode & SET_UID) udata.u_euid = ino->c_node.i_uid; if (ino->c_node.i_mode & SET_GID) udata.u_egid = ino->c_node.i_gid; top = progbase + bin_size; udata.u_top = top; udata.u_ptab->p_top = top; // kprintf("user space at %p\n", progbase); // kprintf("top at %p\n", progbase + bin_size); bin_size = binflat.reloc_start + 4 * binflat.reloc_count; go = (uint32_t)progbase + binflat.entry; close_on_exec(); /* * Read in the rest of the program, block by block. We rely upon * the optimization path in readi to spot this is a big move to user * space and move it directly. */ if (bin_size > sizeof(struct binfmt_flat)) { /* We copied the header already */ bin_size -= sizeof(struct binfmt_flat); udata.u_base = (uint8_t *)progbase + sizeof(struct binfmt_flat); udata.u_count = bin_size; udata.u_sysio = false; readi(ino, 0); if (udata.u_done != bin_size) goto nogood4; } /* Header isn't counted in relocations */ relocate(&binflat, progbase, bin_size); /* This may wipe the relocations */ uzero((uint8_t *)progbase + binflat.data_end, binflat.bss_end - binflat.data_end + binflat.stack_size); /* Use of brk eats into the stack allocation */ /* Use the temporary we saved (hack) as we mangled bss_end */ udata.u_break = udata.u_codebase + true_brk; /* Turn off caught signals */ memset(udata.u_sigvec, 0, sizeof(udata.u_sigvec)); /* place the arguments, environment and stack at the top of userspace memory. */ /* Write back the arguments and the environment */ nargv = wargs(((char *) top - 4), abuf, &argc); nenvp = wargs((char *) (nargv), ebuf, NULL); /* Fill in udata.u_name with Program invocation name */ uget((void *) ugetl(nargv, NULL), udata.u_name, 8); memcpy(udata.u_ptab->p_name, udata.u_name, 8); tmpfree(abuf); tmpfree(ebuf); i_unlock_deref(ino); /* Shove argc and the address of argv just below envp */ uputl((uint32_t) nargv, nenvp - 1); uputl((uint32_t) argc, nenvp - 2); // Set stack pointer for the program udata.u_isp = nenvp - 2; /* * Sort of - it's a good way to deal with all the stupidity of * random 68K platforms we will have to handle, and a nice place * to stuff the signal trampoline 8) */ install_vdso(); // kprintf("Go = %p ISP = %p\n", go, udata.u_isp); doexec(go); nogood4: /* Must not run userspace */ ssig(udata.u_ptab, SIGKILL); nogood3: tmpfree(abuf); tmpfree(ebuf); nogood2: nogood: i_unlock_deref(ino); return (-1); }