/* * ckustr.c - string extraction/restoration routines */ #include <stdio.h> #include <sysexits.h> #include <varargs.h> #include <paths.h> /* STR_FILE must be defined as a quoted string on the cc command line, for example: -DSTR_FILE=\\\"/usr/local/lib/cku196.sr\\\" This is the file where the strings go, and where C-Kermit looks for them at runtime. */ #ifdef STR_FILE char *StringFile = STR_FILE; #else char *StringFile = "/usr/local/lib/cku196.sr"; #endif /* STR_FILE */ /* * If _PATH_CTIMED is defined (in <paths.h>) then use that definition. 2.11BSD * has this defined but 2.10BSD and other systems do not. */ #ifndef _PATH_CTIMED #define _PATH_CTIMED STR_CTIMED #endif extern int errno; static int strfile = -1, ourpid = 0; #define BUFLEN 256 errprep(offset, buf) unsigned short offset; char *buf; { register int pid = getpid(); if (pid != ourpid) { ourpid = pid; if (strfile >= 0) { close(strfile); strfile = -1; } } if (strfile < 0) { char *p, *getenv(); if (p = getenv("KSTR")) if (strlen(p)) StringFile = p; strfile = open(StringFile, 0); if (strfile < 0) { oops: fprintf(stderr, "Cannot find %s\r\n", StringFile); exit(EX_OSFILE); } } if (lseek(strfile, (long) offset, 0) < 0 || read(strfile, buf, BUFLEN) <= 0) goto oops; } /* extracted string front end for printf() */ /*VARARGS1*/ strprerror(fmt, va_alist) int fmt; va_dcl { va_list ap; char buf[BUFLEN]; errprep(fmt, buf); va_start(ap); vprintf(buf, ap); va_end(ap); } /* extracted string front end for sprintf() */ /*VARARGS1*/ strsrerror(fmt, obuf, va_alist) int fmt; char *obuf; va_dcl { char buf[BUFLEN]; va_list ap; errprep(fmt, buf); va_start(ap); vsprintf(obuf, buf, ap); va_end(ap); } /* extracted string front end for fprintf() */ /*VARARGS1*/ strfrerror(fmt, fd, va_alist) int fmt; FILE *fd; va_dcl { va_list ap; char buf[BUFLEN]; errprep(fmt, buf); va_start(ap); vfprintf(fd, buf, ap); va_end(ap); } /* extracted string front end for perror() */ strperror(fmt) int fmt; { char buf[BUFLEN]; register int saverr = errno; errprep(fmt, buf); errno = saverr; perror(buf); } perror(str) char *str; { printf("%s: errno %d\n", str, errno); } /* * The following is needed _only_ on systems which do not have the C library * stubs for the ctime() and getpw*() functions. In 2.11BSD these are * present in the libstubs.a library and accessed via "-lstubs" at link time. * * 2.10BSD's cpp has the BSD2_10 symbol builtin. Other systems without * libstubs.a will need to define (via a -D option in CFLAGS) 'BSD2_10'. */ #ifdef BSD2_10 #include <sys/types.h> #include <sys/time.h> #include <pwd.h> #include <utmp.h> #define SEND_FD W[1] #define RECV_FD R[0] #define CTIME 1 #define ASCTIME 2 #define TZSET 3 #define LOCALTIME 4 #define GMTIME 5 #define OFFTIME 6 #define GETPWENT 7 #define GETPWNAM 8 #define GETPWUID 9 #define SETPASSENT 10 #define ENDPWENT 11 static int R[2], W[2], inited; static char result[256 + 4]; static struct tm tmtmp; static struct passwd _pw, *getandfixpw(); char * ctime(t) time_t *t; { u_char fnc = CTIME; sewer(); write(SEND_FD, &fnc, sizeof fnc); write(SEND_FD, t, sizeof (*t)); getb(RECV_FD, result, 26); return(result); } char * asctime(tp) struct tm *tp; { u_char fnc = ASCTIME; sewer(); write(SEND_FD, &fnc, sizeof fnc); write(SEND_FD, tp, sizeof (*tp)); getb(RECV_FD, result, 26); return(result); } void tzset() { u_char fnc = TZSET; sewer(); write(SEND_FD, &fnc, sizeof fnc); } struct tm * localtime(tp) time_t *tp; { u_char fnc = LOCALTIME; sewer(); write(SEND_FD, &fnc, sizeof fnc); write(SEND_FD, tp, sizeof (*tp)); getb(RECV_FD, &tmtmp, sizeof tmtmp); getb(RECV_FD, result, 24); tmtmp.tm_zone = result; return(&tmtmp); } struct tm * gmtime(tp) time_t *tp; { u_char fnc = GMTIME; sewer(); write(SEND_FD, &fnc, sizeof fnc); write(SEND_FD, tp, sizeof (*tp)); getb(RECV_FD, &tmtmp, sizeof tmtmp); getb(RECV_FD, result, 24); tmtmp.tm_zone = result; return(&tmtmp); } struct tm * offtime(clock, offset) time_t *clock; long offset; { u_char fnc = OFFTIME; sewer(); write(SEND_FD, &fnc, sizeof fnc); write(SEND_FD, clock, sizeof (*clock)); write(SEND_FD, &offset, sizeof offset); getb(RECV_FD, &tmtmp, sizeof tmtmp); tmtmp.tm_zone = ""; return(&tmtmp); } struct passwd * getpwent() { u_char fnc = GETPWENT; sewer(); write(SEND_FD, &fnc, sizeof fnc); return(getandfixpw()); } struct passwd * getpwnam(nam) char *nam; { u_char fnc = GETPWNAM; char lnam[UT_NAMESIZE + 1]; int len; len = strlen(nam); if (len > UT_NAMESIZE) len = UT_NAMESIZE; bcopy(nam, lnam, len); lnam[len] = '\0'; sewer(); write(SEND_FD, &fnc, 1); write(SEND_FD, &len, sizeof (int)); write(SEND_FD, lnam, len); return(getandfixpw()); } struct passwd * getpwuid(uid) uid_t uid; { u_char fnc = GETPWUID; sewer(); write(SEND_FD, &fnc, sizeof fnc); write(SEND_FD, &uid, sizeof (uid_t)); return(getandfixpw()); } setpwent() { return(setpassent(0)); } setpassent(stayopen) int stayopen; { u_char fnc = SETPASSENT; int sts; sewer(); write(SEND_FD, &fnc, sizeof fnc); write(SEND_FD, &stayopen, sizeof (int)); getb(RECV_FD, &sts, sizeof (int)); return(sts); } void endpwent() { u_char fnc = ENDPWENT; sewer(); write(SEND_FD, &fnc, sizeof fnc); return; } /* setpwfile() is deprecated */ void setpwfile(file) char *file; { return; } struct passwd * getandfixpw() { short sz; getb(RECV_FD, &sz, sizeof (int)); if (sz == 0) return(NULL); getb(RECV_FD, &_pw, sizeof (_pw)); getb(RECV_FD, result, sz); _pw.pw_name += (int)result; _pw.pw_passwd += (int)result; _pw.pw_class += (int)result; _pw.pw_gecos += (int)result; _pw.pw_dir += (int)result; _pw.pw_shell += (int)result; return(&_pw); } getb(f, p, n) register int f, n; register char *p; { int i; while (n) { i = read(f, p, n); if (i <= 0) return; p += i; n -= i; } } sewer() { register int pid, ourpid = getpid(); if (inited == ourpid) return; if (inited) { close(SEND_FD); close(RECV_FD); } pipe(W); pipe(R); pid = vfork(); if (pid == 0) { /* child */ alarm(0); /* cancel alarms */ dup2(W[0], 0); /* parent write side to our stdin */ dup2(R[1], 1); /* parent read side to our stdout */ close(SEND_FD); /* copies made, close the... */ close(RECV_FD); /* originals now */ execl(_PATH_CTIMED, "ctimed", 0); _exit(EX_OSFILE); } if (pid == -1) abort(); /* nothing else really to do */ close(W[0]); /* close read side of SEND channel */ close(R[1]); /* close write side of RECV channel */ inited = ourpid; /* don't do this again in this proc */ } XXctime() { if (SEND_FD) close(SEND_FD); if (RECV_FD) close(RECV_FD); SEND_FD = RECV_FD = 0; inited = 0; } #endif /* BSD2_10 */