/* Copyright (C) 1985, 1996, Trustees of Columbia University in the City of New York. The C-Kermit software may not be, in whole or in part, licensed or sold for profit as a software product itself, nor may it be included in or distributed with commercial products or otherwise distributed by commercial concerns to their clients or customers without written permission of the Office of Kermit Development and Distribution, Columbia University. This copyright notice must not be removed, altered, or obscured. */ /* * ckustr.c - string extraction/restoration routines */ #include #include #include #include /* STR_FILE must be defined as a quoted string on the cc command line, for example: -DSTR_FILE=\\\"/usr/local/lib/cku192.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/cku192.sr"; #endif /* STR_FILE */ /* * If _PATH_CTIMED is defined (in ) 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 #include #include #include #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 */