/* FILE: unix.c Routines: This file contains the following routines: fileinit() (moved this to main.c so MS-DOS could use it) sysreset() eihalt() kbread() clksec() tmpfile() for Coherent - K5JB restore() stxrdy() disable() memstat() filedir() check_time() getds() audit() doshell() dodir() rename() docd() ether_dump() mkdir() for those who don't have it rmdir() onshellrtn() part of forked shell process Written by Mikel Matthews, N9DVG SYS5 stuff added by Jere Sandidge, K4FUM Further cleanup, maintenance and etc. by Joe Buswell, K5JB #define FORK_SHELL for a child process that handles foreground while you are shelled out. */ #ifndef _OSK /* none of this applies to _OSK */ #include #include #include #include #include #include #include #include /* K5JB */ #include "global.h" #include "cmdparse.h" #include "iface.h" #include "unix.h" #include "unixopt.h" #include "ndir.h" #include "timer.h" #define MAXCMD 1024 int asy_attach(); extern struct cmds attab[]; extern struct termio savecon; extern struct interface *ifaces; unsigned nasy; /* action routine for remote reset */ void sysreset() { extern int exitval; int doexit(); /* in main.c */ exitval = 3; doexit(); #ifdef NOGOOD /* use exitval and a shell script */ extern char *netexe; execl(netexe,netexe,0); execl("net","net",0); printf("reset failed: exiting\n"); exit(); #endif } #ifdef NOTUSED void eihalt() { tnix_scan(); } #endif #ifdef FORKSHELL extern int mode; #include "session.h" int shellpid; extern int backgrd; int onquit(); extern int iostop(); #endif int kbread() { unsigned char c; #if defined(COH386) && !defined(COH4) int sleep2(); sleep2(COHWAIT); /* only needed when no async ports are used */ #endif #ifdef FORKSHELL /* note that if background, kbread won't be called */ if(shellpid) /* might put a micro sleep here to give up cycles */ return -1; #endif #ifdef USE_QUIT if(backgrd) return -1; #endif if (read(fileno(stdin), &c, 1) <= 0) return -1; return ((int) c); } int clksec() { long tim; (void) time(&tim); return ((int) tim); } #if defined(COH386) && !defined(COH4) FILE * tmpfile() { char *buf; FILE *fp; #ifdef LATER /* may come back later and do cleanup - K5JB */ static int nr_tmpfiles; if((buf = (char *)malloc(L_tempnam)) == NULLCHAR) return 0; #else buf = tmpnam(NULLCHAR); #endif if((fp = fopen(buf,"w+")) == NULLFILE) return 0; return fp; } #endif void restore() { } int stxrdy() { return 1; } int disable() { return 1; /* dummy function -- not used in Unix */ } int memstat() { return 0; } #define NULLDIR (DIR *)0 #define NULLDIRECT (struct direct *)0 /* wildcard filename lookup */ void filedir(name, times, ret_str) char *name; int times; char *ret_str; { static char dname[128], fname[128]; static DIR *dirp = NULLDIR; struct direct *dp; struct stat sbuf; char *cp, temp[128]; /* * Make sure that the NULL is there in case we don't find anything */ ret_str[0] = '\0'; if (times == 0) { /* default a null name to *.* */ if (name == NULLCHAR || *name == '\0') name = "*.*"; /* split path into directory and filename */ if ((cp = strrchr(name, '/')) == NULLCHAR) { strcpy(dname, "."); strcpy(fname, name); } else { strcpy(dname, name); dname[cp - name] = '\0'; strcpy(fname, cp + 1); /* root directory */ if (dname[0] == '\0') strcpy(dname, "/"); /* trailing '/' */ if (fname[0] == '\0') strcpy(fname, "*.*"); } /* close directory left over from another call */ if (dirp != NULLDIR) closedir(dirp); /* open directory */ if ((dirp = opendir(dname)) == NULLDIR) { printf("Could not open DIR (%s)\n", dname); return; } } else { /* for people who don't check return values */ if (dirp == NULLDIR) return; } /* scan directory */ while ((dp = readdir(dirp)) != NULLDIRECT) { /* test for name match */ if (wildmat(dp->d_name, fname)) { /* test for regular file */ sprintf(temp, "%s/%s", dname, dp->d_name); if (stat(temp, &sbuf) < 0) continue; if ((sbuf.st_mode & S_IFMT) != S_IFREG) continue; strcpy(ret_str, dp->d_name); break; } } /* close directory if we hit the end */ if (dp == NULLDIRECT) { closedir(dirp); dirp = NULLDIR; } } /* checks the time then ticks and updates ISS */ void check_time() { int32 iss(); void tickle(); #if defined(COH386) && !defined(COH4) long time(); #else struct tms tb; #ifndef COH4 long times(); #endif #endif static long clkval; long ntime, offset; /* With older Coherent, read elapsed real time in seconds, others * are done in machine clock ticks. Later Coherent has times() * fixed but it returns an int instead of a long */ #if defined(COH386) && !defined(COH4) time(&ntime); #else #ifdef COH4 /* damned thing returns an int */ ntime = (long)times(&tb); #else ntime = times(&tb); #endif #endif /* resynchronize if the error is large (10 seconds or more) */ offset = ntime - clkval; if (offset > (10000/MSPTICK) || offset < 0) clkval = ntime; /* Handle possibility of several missed ticks */ while (ntime != clkval) { ++clkval; icmpclk(); tickle(); (void) iss(); } } int getds() { return 0; } void audit() { } #ifdef FORKSHELL void onshellrtn() { (void)signal(SIGQUIT, onquit); /* restore normal signals */ (void)signal(SIGHUP, iostop); (void)signal(SIGINT, iostop); (void)signal(SIGTERM, iostop); /* in case someone had a session with us while we were gone */ if(mode != CMD_MODE) mode = CMD_MODE; } #endif int doshell(argc, argv) /* modified to make shell "stick" K5JB */ char **argv; /* later modified to make shell a child process */ { #ifndef FORKSHELL char str[MAXCMD]; int i,retn; #else int parentpid; #endif char *cp; struct termio tt_config; int saverunflg; char *getenv(); #ifndef FORKSHELL str[0] = '\0'; for (i = 1; i < argc; i++) { strcat(str, argv[i]); strcat(str, " "); } ioctl(0, TCGETA, &tt_config); ioctl(0, TCSETAW, &savecon); if ((saverunflg = fcntl(0, F_GETFL, 0)) == -1) { perror("Could not read console flags"); return -1; } fcntl(0, F_SETFL, saverunflg & ~O_NDELAY); /* blocking I/O */ if (argc > 1) retn = system(str); else if ((cp = getenv("SHELL")) != NULLCHAR && *cp != '\0') retn = system(cp); else retn = system("exec /bin/sh"); fcntl(0, F_SETFL, saverunflg); /* restore non-blocking I/O, if so */ ioctl(0, TCSETAW, &tt_config); printf("Returning you to net.\n"); return retn; #else /* will fork a child process */ signal(SIGQUIT,SIG_IGN); /* ignore these signals, and... */ signal(SIGHUP,SIG_IGN); signal(SIGINT,SIG_IGN); signal(SIGTERM,SIG_IGN); signal(SIGUSR1,onshellrtn); /* on return, this will restore them */ parentpid = getpid(); /* this will work if we don't detach */ printf("Type exit, or do Ctrl-D, to return to NET.\n"); fflush(stdout); if(!(shellpid = fork())){ /* is child process */ ioctl(0, TCGETA, &tt_config); ioctl(0, TCSETAW, &savecon); if ((saverunflg = fcntl(0, F_GETFL, 0)) == -1) { perror("Could not read console flags"); return -1; } fcntl(0, F_SETFL, saverunflg & ~O_NDELAY); /* blocking I/O */ #ifdef LATER_IFNEEDED while (ifaces != NULLIF) { if (ifaces->stop != NULLFP) (*ifaces->stop)(ifaces->dev); ifaces = ifaces->next; } #endif /* Note that system() can cause problems with forked process */ /* we use it though so we can signal our return with kill() */ if((cp = getenv("SHELL")) != NULLCHAR && *cp != '\0') system(cp); else system("exec /bin/sh"); fcntl(0, F_SETFL, saverunflg); /* restore non-blocking I/O, if so */ ioctl(0, TCSETAW, &tt_config); kill(parentpid,SIGUSR1); /* first restore signals, then use one */ /* this makes a newline so if we return with Ctrl-D NET> looks better */ printf("\n"); fflush(stdout); /* apparently need some time before second kill */ sleep(1); /* this should kill us and restore foreground */ kill(parentpid,SIGQUIT); sleep(10); /* will probably not awake from this one */ /* but if sleep time was insufficient... */ printf("You MAY have to use Ctrl-\\ to return to NET...\n"); fflush(stdout); /* quit signal handler will take care of killing child properly */ /* but if it don't... */ exit(0); }else return 0; #endif } int dodir(argc, argv) int argc; char **argv; { int i, stat; char str[MAXCMD]; struct termio tt_config; strcpy(str, "ls -l "); for (i = 1; i < argc; i++) { strcat(str, argv[i]); strcat(str, " "); } ioctl(0, TCGETA, &tt_config); ioctl(0, TCSETAW, &savecon); stat = system(str); ioctl(0, TCSETAW, &tt_config); return stat; } int rename(s1, s2) char *s1, *s2; { char tmp[MAXCMD]; (void) sprintf(tmp, "mv %s %s", s1, s2); return(system(tmp)); } /* enabled this command with k28 -- it was incomplete. Tried to do it in most portable way, though in SysV, it would be appropriate to feed getcwd a null pointer and free the memory pointed to by getcwd's return value. This command is used for "pwd" and "cd". - K5JB */ int docd(argc, argv) int argc; char **argv; { static char tmp[MAXCMD]; char *getcwd(); extern char *homedir; if(*argv[0] == 'c') if(chdir(argc > 1 ? argv[1] : homedir) == -1){ printf("Can't change directory\n"); return 1; } if (getcwd(tmp, sizeof(tmp) - 2) != NULL) printf("%s\n", tmp); return 0; } void ether_dump() { } #ifndef HAVEMKDIR int mkdir(s, m) char *s; int m; { char tmp[MAXCMD]; sprintf(tmp, "mkdir %s", s); if (system(tmp)) return -1; if (chmod(s, m) < 0) return -1; return 0; } #endif int rmdir(s) char *s; { char tmp[MAXCMD]; sprintf(tmp, "rmdir %s", s); if (system(tmp)) return -1; return 0; } #endif /* OSK */