1: /* 2: * Steven Schultz - sms@moe.2bsd.com 3: * 4: * @(#)ctimed.c 1.0 (2.11BSD) 1996/6/25 5: * 6: * ctimed - the daemon that supports the ctime() and getpw*() stubs 7: * in 'libcstubs.a'. 8: */ 9: 10: #include <signal.h> 11: #include <stdio.h> 12: #include <setjmp.h> 13: #include <sys/ioctl.h> 14: #include <sys/types.h> 15: #include <sys/time.h> 16: #include <pwd.h> 17: #include <utmp.h> 18: 19: /* 20: * These should probably be placed in an include file. If you add anything 21: * here then you will also have to modify /usr/src/usr.lib/libstubs/stubs.c 22: * (if for no other reason than to add the stub code). 23: */ 24: 25: #define CTIME 1 26: #define ASCTIME 2 27: #define TZSET 3 28: #define LOCALTIME 4 29: #define GMTIME 5 30: #define OFFTIME 6 31: 32: #define GETPWENT 7 33: #define GETPWNAM 8 34: #define GETPWUID 9 35: #define SETPASSENT 10 36: #define ENDPWENT 11 37: 38: extern struct tm *offtime(); 39: 40: jmp_buf env; 41: char *cp; 42: char junk[256 + sizeof (struct passwd) + 4]; 43: long off; 44: time_t l; 45: void timeout(), checkppid(); 46: struct tm tmtmp, *tp; 47: 48: main() 49: { 50: register int i; 51: register struct passwd *pw; 52: struct itimerval it; 53: u_char c, xxx; 54: int len, tosslen; 55: uid_t uid; 56: 57: signal(SIGPIPE, SIG_DFL); 58: for (i = getdtablesize(); --i > 2; ) 59: close(i); 60: /* 61: * Need a timer running while we disassociate from the control terminal 62: * in case of a modem line which has lost carrier. 63: */ 64: timerclear(&it.it_interval); 65: it.it_value.tv_sec = 5; 66: it.it_value.tv_usec = 0; 67: signal(SIGALRM, timeout); 68: setitimer(ITIMER_REAL, &it, (struct itimerval *) NULL); 69: if (setjmp(env) == 0) 70: { 71: i = open("/dev/tty", 0); 72: if (i >= 0) 73: { 74: ioctl(i, TIOCNOTTY, NULL); 75: close(i); 76: } 77: } 78: /* 79: * Now start a timer with one minute refresh. In the signal service 80: * routine, check the parent process id to see if this process has 81: * been orphaned and if so exit. This is primarily aimed at removing 82: * the 'ctimed' process left behind by 'sendmail's multi-fork startup 83: * but may prove useful in preventing accumulation of 'ctimed' processes 84: * in other circumstances as well. Normally this process is short 85: * lived. 86: */ 87: it.it_interval.tv_sec = 60; 88: it.it_interval.tv_usec = 0; 89: it.it_value.tv_sec = 60; 90: it.it_value.tv_usec = 0; 91: signal(SIGALRM, checkppid); 92: setitimer(ITIMER_REAL, &it, (struct itimerval *) NULL); 93: 94: while (read(fileno(stdin), &c, 1) == 1) 95: { 96: switch (c) 97: { 98: case CTIME: 99: l = 0L; 100: getb(fileno(stdin), &l, sizeof l); 101: cp = ctime(&l); 102: write(fileno(stdout), cp, 26); 103: break; 104: case ASCTIME: 105: getb(fileno(stdin), &tmtmp, sizeof tmtmp); 106: cp = asctime(&tmtmp); 107: write(fileno(stdout), cp, 26); 108: break; 109: case TZSET: 110: (void) tzset(); 111: break; 112: case LOCALTIME: 113: l = 0L; 114: getb(fileno(stdin), &l, sizeof l); 115: tp = localtime(&l); 116: write(fileno(stdout), tp, sizeof (*tp)); 117: strcpy(junk, tp->tm_zone); 118: junk[24] = '\0'; 119: write(fileno(stdout), junk, 24); 120: break; 121: case GMTIME: 122: l = 0L; 123: getb(fileno(stdin), &l, sizeof l); 124: tp = gmtime(&l); 125: write(fileno(stdout), tp, sizeof (*tp)); 126: strcpy(junk, tp->tm_zone); 127: junk[24] = '\0'; 128: write(fileno(stdout), junk, 24); 129: break; 130: case OFFTIME: 131: getb(fileno(stdin), &l, sizeof l); 132: getb(fileno(stdin), &off, sizeof off); 133: #ifdef __bsdi__ 134: l += off; 135: tp = localtime(&l); 136: #else 137: tp = offtime(&l, off); 138: #endif 139: write(fileno(stdout), tp, sizeof (*tp)); 140: break; 141: case GETPWENT: 142: pw = getpwent(); 143: do_pw(pw); 144: break; 145: case GETPWNAM: 146: getb(fileno(stdin), &len, sizeof (int)); 147: if (len > UT_NAMESIZE) 148: { 149: tosslen = len - UT_NAMESIZE; 150: len = UT_NAMESIZE; 151: } 152: else 153: tosslen = 0; 154: getb(fileno(stdin), junk, len); 155: for (;tosslen; tosslen--) 156: getb(fileno(stdin), &xxx, 1); 157: junk[len] = '\0'; 158: pw = getpwnam(junk); 159: do_pw(pw); 160: break; 161: case GETPWUID: 162: getb(fileno(stdin), &uid, sizeof (uid_t)); 163: pw = getpwuid(uid); 164: do_pw(pw); 165: break; 166: case SETPASSENT: 167: getb(fileno(stdin), &len, sizeof (int)); 168: if (setpassent(len)) 169: len = 1; 170: else 171: len = 0; 172: write(fileno(stdout), &len, sizeof (int)); 173: break; 174: case ENDPWENT: 175: endpwent(); 176: break; 177: default: 178: abort("switch"); 179: } 180: } 181: } 182: 183: getb(f, p, n) 184: int f; 185: register char *p; 186: register int n; 187: { 188: register int i; 189: 190: while (n) 191: { 192: i = read(f, p, n); 193: if (i <= 0) 194: return; 195: p += i; 196: n -= i; 197: } 198: } 199: 200: void 201: timeout() 202: { 203: 204: longjmp(env, 1); 205: } 206: 207: void 208: checkppid() 209: { 210: 211: if (getppid() == 1) 212: exit(0); 213: } 214: 215: do_pw(pw) 216: struct passwd *pw; 217: { 218: int len; 219: 220: if (!pw) 221: { 222: len = 0; 223: write(fileno(stdout), &len, sizeof (int)); 224: return; 225: } 226: len = packpwtobuf(pw, junk); 227: write(fileno(stdout), &len, sizeof (int)); 228: write(fileno(stdout), pw, sizeof (*pw)); 229: write(fileno(stdout), junk, len); 230: return; 231: } 232: 233: packpwtobuf(pw, buf) 234: register struct passwd *pw; 235: char *buf; 236: { 237: register char *cp = buf; 238: register char *dp; 239: 240: dp = pw->pw_name; 241: pw->pw_name = (char*) 0; 242: while (*cp++ = *dp++) 243: ; 244: dp = pw->pw_passwd; 245: pw->pw_passwd = (char*) (cp - buf); 246: while (*cp++ = *dp++) 247: ; 248: dp = pw->pw_class; 249: pw->pw_class = (char*) (cp - buf); 250: while (*cp++ = *dp++) 251: ; 252: dp = pw->pw_gecos; 253: pw->pw_gecos = (char*) (cp - buf); 254: while (*cp++ = *dp++) 255: ; 256: dp = pw->pw_dir; 257: pw->pw_dir = (char*) (cp - buf); 258: while (*cp++ = *dp++) 259: ; 260: dp = pw->pw_shell; 261: pw->pw_shell = (char*) (cp - buf); 262: while (*cp++ = *dp++) 263: ; 264: return(cp - buf); 265: }