1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate /* 26*7c478bd9Sstevel@tonic-gate * Copyright (c) 1998 by Sun Microsystems, Inc. 27*7c478bd9Sstevel@tonic-gate * All rights reserved. 28*7c478bd9Sstevel@tonic-gate */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #ident "%Z%%M% %I% %E% SMI" /* from SVR4 bnu:ct.c 2.27.2.1 */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate /* 33*7c478bd9Sstevel@tonic-gate * 34*7c478bd9Sstevel@tonic-gate * ct [-h] [-v] [-w n] [-x n] [-s speed] telno ... 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * dials the given telephone number, waits for the 37*7c478bd9Sstevel@tonic-gate * modem to answer, and initiates a login process. 38*7c478bd9Sstevel@tonic-gate * 39*7c478bd9Sstevel@tonic-gate * ct uses several routines from uucp: 40*7c478bd9Sstevel@tonic-gate * - getto(flds) takes a vector of fields needed to make 41*7c478bd9Sstevel@tonic-gate * a connection and returns a file descriptor or -1 42*7c478bd9Sstevel@tonic-gate * - rddev( ... ) takes several arguments and returns lines 43*7c478bd9Sstevel@tonic-gate * from the /etc/uucp/Devices that match the type 44*7c478bd9Sstevel@tonic-gate * (in ct the type will be ACU) 45*7c478bd9Sstevel@tonic-gate * - fdig(string) takes a string that is zero or more 46*7c478bd9Sstevel@tonic-gate * alphabetic characters follow by a number (baud rate) 47*7c478bd9Sstevel@tonic-gate * and returns a pointer to the first digit in the string. 48*7c478bd9Sstevel@tonic-gate * - fn_cklock(dev) takes a device name [/dev/]term/11 and 49*7c478bd9Sstevel@tonic-gate * checks whether the appropriate lock file exists. It returns 50*7c478bd9Sstevel@tonic-gate * FAIL if it does. 51*7c478bd9Sstevel@tonic-gate * - rmlock(pointer) removes the lock file. In ct pointer is 52*7c478bd9Sstevel@tonic-gate * always CNULL (a null pointer) causing rmlock to remove 53*7c478bd9Sstevel@tonic-gate * all lock files associated with this execution of ct. 54*7c478bd9Sstevel@tonic-gate */ 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #include "uucp.h" 57*7c478bd9Sstevel@tonic-gate #include "sysfiles.h" 58*7c478bd9Sstevel@tonic-gate #include <pwd.h> 59*7c478bd9Sstevel@tonic-gate #include <utmpx.h> 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #ifdef DATAKIT 62*7c478bd9Sstevel@tonic-gate #include <dk.h> 63*7c478bd9Sstevel@tonic-gate extern int dkminor(); 64*7c478bd9Sstevel@tonic-gate #endif 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #define ROOT 0 67*7c478bd9Sstevel@tonic-gate #define SYS 3 68*7c478bd9Sstevel@tonic-gate #define TTYGID (gid_t) 7 /* group id for terminal */ 69*7c478bd9Sstevel@tonic-gate #define TTYMOD (mode_t) 0622 70*7c478bd9Sstevel@tonic-gate #define DEV "/dev/" 71*7c478bd9Sstevel@tonic-gate #define TELNOSIZE 32 /* maximum phone # size is 31 */ 72*7c478bd9Sstevel@tonic-gate #define LEGAL "0123456789-*#=" 73*7c478bd9Sstevel@tonic-gate #define USAGE "[-h] [-v] [-w n] [-x n] [-s speed] telno ..." 74*7c478bd9Sstevel@tonic-gate #define LOG "/var/adm/ctlog" 75*7c478bd9Sstevel@tonic-gate #define TTYMON "/usr/lib/saf/ttymon" 76*7c478bd9Sstevel@tonic-gate #define TRUE 1 77*7c478bd9Sstevel@tonic-gate #define FALSE 0 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate static 80*7c478bd9Sstevel@tonic-gate int _Status; /* exit status of child */ 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate static 83*7c478bd9Sstevel@tonic-gate pid_t _Pid = 0; /* process id of child */ 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate static 86*7c478bd9Sstevel@tonic-gate char 87*7c478bd9Sstevel@tonic-gate _Tty[sizeof DEV+12] = "", /* /dev/term/xx for connection device */ 88*7c478bd9Sstevel@tonic-gate *_Dev[D_MAX + 1], /* Filled in by rddev and used globally */ 89*7c478bd9Sstevel@tonic-gate _Devbuf[BUFSIZ]; /* buffer for rddev */ 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate static 92*7c478bd9Sstevel@tonic-gate char 93*7c478bd9Sstevel@tonic-gate *_Num, /* pointer to a phone number */ 94*7c478bd9Sstevel@tonic-gate *_Flds[7]; /* Filled in as if finds() in uucp did it */ 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate static 97*7c478bd9Sstevel@tonic-gate time_t _Log_on, 98*7c478bd9Sstevel@tonic-gate _Log_elpsd; 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate static 101*7c478bd9Sstevel@tonic-gate FILE *_Fdl; 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate extern int optind; 104*7c478bd9Sstevel@tonic-gate extern char *optarg, *fdig(); 105*7c478bd9Sstevel@tonic-gate extern void cleanup(); 106*7c478bd9Sstevel@tonic-gate extern struct passwd *getpwuid (); 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate extern int getto(), rddev(); 109*7c478bd9Sstevel@tonic-gate static int gdev(), logproc(), exists(); 110*7c478bd9Sstevel@tonic-gate static void startat(), stopat(), disconnect(), zero(); 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate /* 113*7c478bd9Sstevel@tonic-gate * These two dummy routines are needed because the uucp routines 114*7c478bd9Sstevel@tonic-gate * used by ct reference them, but they will never be 115*7c478bd9Sstevel@tonic-gate * called when executing from ct 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate /*VARARGS*/ 119*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 120*7c478bd9Sstevel@tonic-gate void 121*7c478bd9Sstevel@tonic-gate assert (s1, s2, i1, s3, i2) 122*7c478bd9Sstevel@tonic-gate char *s1, *s2, *s3; 123*7c478bd9Sstevel@tonic-gate int i1, i2; 124*7c478bd9Sstevel@tonic-gate { } /* for ASSERT in gnamef.c */ 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 127*7c478bd9Sstevel@tonic-gate void 128*7c478bd9Sstevel@tonic-gate logent (s1, s2) 129*7c478bd9Sstevel@tonic-gate char *s1, *s2; 130*7c478bd9Sstevel@tonic-gate { } /* so we can load ulockf() */ 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate jmp_buf Sjbuf; /* used by uucp routines */ 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate main (argc, argv) 135*7c478bd9Sstevel@tonic-gate char *argv[]; 136*7c478bd9Sstevel@tonic-gate { 137*7c478bd9Sstevel@tonic-gate register int c; 138*7c478bd9Sstevel@tonic-gate int found = 0, 139*7c478bd9Sstevel@tonic-gate errors = 0, 140*7c478bd9Sstevel@tonic-gate first = TRUE; 141*7c478bd9Sstevel@tonic-gate int count, 142*7c478bd9Sstevel@tonic-gate logprocflag, /* is there a login process on the line */ 143*7c478bd9Sstevel@tonic-gate hangup = 1, /* hangup by default */ 144*7c478bd9Sstevel@tonic-gate minutes = 0; /* number of minutes to wait for dialer */ 145*7c478bd9Sstevel@tonic-gate int fdl; 146*7c478bd9Sstevel@tonic-gate struct termio termio; 147*7c478bd9Sstevel@tonic-gate typedef void (*save_sig)(); 148*7c478bd9Sstevel@tonic-gate save_sig save_hup, 149*7c478bd9Sstevel@tonic-gate save_quit, 150*7c478bd9Sstevel@tonic-gate save_int; 151*7c478bd9Sstevel@tonic-gate extern void setservice(), devreset(); 152*7c478bd9Sstevel@tonic-gate extern int sysaccess(); 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate save_hup = signal (SIGHUP, cleanup); 155*7c478bd9Sstevel@tonic-gate save_quit = signal (SIGQUIT, cleanup); 156*7c478bd9Sstevel@tonic-gate save_int = signal (SIGINT, cleanup); 157*7c478bd9Sstevel@tonic-gate (void) signal (SIGTERM, cleanup); 158*7c478bd9Sstevel@tonic-gate (void) strcpy (Progname, "ct"); 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate setservice("cu"); 161*7c478bd9Sstevel@tonic-gate if ( sysaccess(EACCESS_DEVICES) != 0 ) { 162*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ct: can't access Devices file\n"); 163*7c478bd9Sstevel@tonic-gate cleanup(101); 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* Set up the _Flds vector as if finds() [from uucico] built it */ 167*7c478bd9Sstevel@tonic-gate _Flds[F_NAME] = "dummy"; /* never used */ 168*7c478bd9Sstevel@tonic-gate _Flds[F_TIME] = "Any"; /* never used */ 169*7c478bd9Sstevel@tonic-gate _Flds[F_TYPE] = "ACU"; 170*7c478bd9Sstevel@tonic-gate _Flds[F_CLASS] = "1200"; /* default at 1200 */ 171*7c478bd9Sstevel@tonic-gate _Flds[F_PHONE] = ""; /* filled in by arguments */ 172*7c478bd9Sstevel@tonic-gate _Flds[F_LOGIN] = ""; /* never used */ 173*7c478bd9Sstevel@tonic-gate _Flds[6] = NULL; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate while ((c = getopt (argc, argv, "hvw:s:x:")) != EOF) { 176*7c478bd9Sstevel@tonic-gate switch (c) { 177*7c478bd9Sstevel@tonic-gate case 'h': 178*7c478bd9Sstevel@tonic-gate hangup = 0; 179*7c478bd9Sstevel@tonic-gate break; 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate case 'v': 182*7c478bd9Sstevel@tonic-gate Verbose = 1; 183*7c478bd9Sstevel@tonic-gate break; 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate case 'w': 186*7c478bd9Sstevel@tonic-gate minutes = atoi (optarg); 187*7c478bd9Sstevel@tonic-gate if (minutes < 1) { 188*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 189*7c478bd9Sstevel@tonic-gate "\tusage: %s %s\n", Progname, USAGE); 190*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "(-w %s) Wait time must be > 0\n", 191*7c478bd9Sstevel@tonic-gate optarg); 192*7c478bd9Sstevel@tonic-gate cleanup(101); 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate break; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate case 's': 197*7c478bd9Sstevel@tonic-gate _Flds[F_CLASS] = optarg; 198*7c478bd9Sstevel@tonic-gate break; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate case 'x': 201*7c478bd9Sstevel@tonic-gate Debug = atoi(optarg); 202*7c478bd9Sstevel@tonic-gate if (Debug < 0 || Debug > 9) { 203*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 204*7c478bd9Sstevel@tonic-gate "\tusage: %s %s\n", Progname, USAGE); 205*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "(-x %s) value must be 0-9\n", 206*7c478bd9Sstevel@tonic-gate optarg); 207*7c478bd9Sstevel@tonic-gate cleanup(101); 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate break; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate case '?': 212*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tusage: %s %s\n", Progname, USAGE); 213*7c478bd9Sstevel@tonic-gate cleanup(101); 214*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate if (optind == argc) { 219*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tusage: %s %s\n", Progname, USAGE); 220*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "No phone numbers specified!\n"); 221*7c478bd9Sstevel@tonic-gate cleanup(101); 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate /* check for valid phone number(s) */ 225*7c478bd9Sstevel@tonic-gate for (count = argc - 1; count >= optind; --count) { 226*7c478bd9Sstevel@tonic-gate _Num = argv[count]; 227*7c478bd9Sstevel@tonic-gate if (strlen(_Num) >= (size_t)(TELNOSIZE - 1)) { 228*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ct: phone number too long -- %s\n", _Num); 229*7c478bd9Sstevel@tonic-gate ++errors; 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate if ((int)strspn(_Num, LEGAL) < (int)strlen(_Num)) { 232*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ct: bad phone number -- %s\n", _Num); 233*7c478bd9Sstevel@tonic-gate ++errors; 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate if (errors) 237*7c478bd9Sstevel@tonic-gate cleanup(101); 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate /************************************************************/ 240*7c478bd9Sstevel@tonic-gate /* Begin Loop: Find an available Dialer */ 241*7c478bd9Sstevel@tonic-gate /************************************************************/ 242*7c478bd9Sstevel@tonic-gate for (count = 0;; count++) { /* count will be wait time after first 243*7c478bd9Sstevel@tonic-gate * time through the loop. 244*7c478bd9Sstevel@tonic-gate * break will be used exit loop. 245*7c478bd9Sstevel@tonic-gate */ 246*7c478bd9Sstevel@tonic-gate if ( (found = gdev (_Flds)) > 0) { /* found a dialer */ 247*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "Allocated dialer at %s baud\n", 248*7c478bd9Sstevel@tonic-gate _Flds[F_CLASS]); 249*7c478bd9Sstevel@tonic-gate break; 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate else if (found == 0) { /* no dialers of that on system */ 252*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "No %s dialers on this system\n", 253*7c478bd9Sstevel@tonic-gate fdig(_Flds[F_CLASS]) ); 254*7c478bd9Sstevel@tonic-gate cleanup(101); 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate if (!first) { /* not the first time in loop */ 258*7c478bd9Sstevel@tonic-gate VERBOSE("%s busy", (found == -1) ? "Dialer is" : "Dialers are"); 259*7c478bd9Sstevel@tonic-gate VERBOSE(" (%d minute(s))\n", count); 260*7c478bd9Sstevel@tonic-gate if (count < minutes) { 261*7c478bd9Sstevel@tonic-gate sleep(60); 262*7c478bd9Sstevel@tonic-gate continue; 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate /* This is the end of the loop - no time left */ 265*7c478bd9Sstevel@tonic-gate break; 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate /**************************************************************/ 269*7c478bd9Sstevel@tonic-gate /* First time through loop - get wait minutes if no -w option */ 270*7c478bd9Sstevel@tonic-gate /**************************************************************/ 271*7c478bd9Sstevel@tonic-gate first = FALSE; 272*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "The (%d) %s dialer%s busy\n", -found, 273*7c478bd9Sstevel@tonic-gate _Flds[F_CLASS], (found == -1 ? " is" : "s are")); 274*7c478bd9Sstevel@tonic-gate if (minutes) { /* -w already set wait minutes */ 275*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "Waiting for %d minute%s\n", minutes, 276*7c478bd9Sstevel@tonic-gate (minutes > 1 ? "s" : "") ); 277*7c478bd9Sstevel@tonic-gate sleep(60); 278*7c478bd9Sstevel@tonic-gate continue; 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate if (!isatty(0) ) { /* not a terminal - get out */ 282*7c478bd9Sstevel@tonic-gate cleanup(101); 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate /* Ask user if she/he wants to wait */ 286*7c478bd9Sstevel@tonic-gate (void) fputs("Do you want to wait for dialer? (y for yes): ", stdout); 287*7c478bd9Sstevel@tonic-gate if ((c = getchar ()) == EOF || tolower (c) != 'y') 288*7c478bd9Sstevel@tonic-gate cleanup(101); 289*7c478bd9Sstevel@tonic-gate while ( (c = getchar()) != EOF && c != '\n') 290*7c478bd9Sstevel@tonic-gate ; 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate (void) fputs ("Time, in minutes? ", stdout); 293*7c478bd9Sstevel@tonic-gate (void) scanf ("%d", &minutes); 294*7c478bd9Sstevel@tonic-gate while ( (c = getchar()) != EOF && c != '\n') 295*7c478bd9Sstevel@tonic-gate ; 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate if (minutes <= 0) 298*7c478bd9Sstevel@tonic-gate cleanup(101); 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate (void) fputs ("Waiting for dialer\n", stdout); 301*7c478bd9Sstevel@tonic-gate sleep(60); 302*7c478bd9Sstevel@tonic-gate continue; 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate /************************************************************/ 306*7c478bd9Sstevel@tonic-gate /* End Loop: Find an available Dialer */ 307*7c478bd9Sstevel@tonic-gate /************************************************************/ 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate /* check why loop terminated */ 310*7c478bd9Sstevel@tonic-gate if (found < 0) { /* no dialer found - get out */ 311*7c478bd9Sstevel@tonic-gate (void) fputs("*** TIMEOUT ***\n", stdout); 312*7c478bd9Sstevel@tonic-gate cleanup(101); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate (void) signal(SIGHUP, SIG_IGN); 316*7c478bd9Sstevel@tonic-gate /* found a dialer. now try to call */ 317*7c478bd9Sstevel@tonic-gate if (!isatty(0)) 318*7c478bd9Sstevel@tonic-gate hangup = 0; 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate if (hangup) { /* -h option not specified */ 321*7c478bd9Sstevel@tonic-gate do { 322*7c478bd9Sstevel@tonic-gate (void) fputs ("Confirm hang-up? (y/n): ", stdout); 323*7c478bd9Sstevel@tonic-gate switch (c=tolower(getchar())) { 324*7c478bd9Sstevel@tonic-gate case EOF: 325*7c478bd9Sstevel@tonic-gate case 'n': 326*7c478bd9Sstevel@tonic-gate cleanup(101); 327*7c478bd9Sstevel@tonic-gate break; 328*7c478bd9Sstevel@tonic-gate case 'y': 329*7c478bd9Sstevel@tonic-gate break; 330*7c478bd9Sstevel@tonic-gate default: 331*7c478bd9Sstevel@tonic-gate while ( c != EOF && c != '\n' ) 332*7c478bd9Sstevel@tonic-gate c=getchar(); 333*7c478bd9Sstevel@tonic-gate break; 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate } while (c != 'y'); 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* close stderr if it is not redirected */ 338*7c478bd9Sstevel@tonic-gate if ( isatty(2) ) { 339*7c478bd9Sstevel@tonic-gate Verbose = 0; 340*7c478bd9Sstevel@tonic-gate Debug = 0; 341*7c478bd9Sstevel@tonic-gate (void) close (2); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate (void) ioctl (0, TCGETA, &termio); 345*7c478bd9Sstevel@tonic-gate termio.c_cflag = 0; /* speed to zero for hangup */ 346*7c478bd9Sstevel@tonic-gate (void) ioctl (0, TCSETAW, &termio); /* hang up terminal */ 347*7c478bd9Sstevel@tonic-gate (void) sleep (5); 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate (void) close(0); 350*7c478bd9Sstevel@tonic-gate (void) close(1); 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* Try each phone number until a connection is made, or non work */ 353*7c478bd9Sstevel@tonic-gate for (count = optind; count < argc; count++) { 354*7c478bd9Sstevel@tonic-gate /* call getto routine to make connection */ 355*7c478bd9Sstevel@tonic-gate _Flds[F_PHONE] = argv[count]; 356*7c478bd9Sstevel@tonic-gate rmlock(CNULL); /* remove temporary lock set by gdev */ 357*7c478bd9Sstevel@tonic-gate devreset(); 358*7c478bd9Sstevel@tonic-gate fdl = getto(_Flds); 359*7c478bd9Sstevel@tonic-gate if (fdl >= 0) { 360*7c478bd9Sstevel@tonic-gate /* 361*7c478bd9Sstevel@tonic-gate * If there is a login process on the line, get rid 362*7c478bd9Sstevel@tonic-gate * of the lock file quickly so that when the process 363*7c478bd9Sstevel@tonic-gate * reads the first character, the lock file will be gone 364*7c478bd9Sstevel@tonic-gate * indicating that the process should handle the data. 365*7c478bd9Sstevel@tonic-gate */ 366*7c478bd9Sstevel@tonic-gate if ( (logprocflag = logproc(Dc)) ) /* really an assignment! */ 367*7c478bd9Sstevel@tonic-gate rmlock(CNULL); 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate _Fdl = fdopen(fdl, "r+"); 370*7c478bd9Sstevel@tonic-gate (void) sprintf(_Tty, "%s%s", DEV, Dc); 371*7c478bd9Sstevel@tonic-gate /* NOTE: Dc is set in the caller routines */ 372*7c478bd9Sstevel@tonic-gate break; 373*7c478bd9Sstevel@tonic-gate } 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate /* check why the loop ended (connected or no more numbers to try) */ 377*7c478bd9Sstevel@tonic-gate if (count == argc) 378*7c478bd9Sstevel@tonic-gate cleanup(101); 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate /****** Successfully made connection ******/ 381*7c478bd9Sstevel@tonic-gate VERBOSE("Connected\n%s", ""); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate #ifdef DATAKIT 384*7c478bd9Sstevel@tonic-gate if (!strcmp(_Dev[D_CALLER], "DK")) { 385*7c478bd9Sstevel@tonic-gate strcpy(_Tty, dtnamer(dkminor(fdl))); 386*7c478bd9Sstevel@tonic-gate strcpy(Dc, (strrchr(_Tty, '/')+1)); 387*7c478bd9Sstevel@tonic-gate if ((_Fdl = fopen(_Tty, "r+")) == NULL) { 388*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ct: Cannot open %s, errno %d\n", 389*7c478bd9Sstevel@tonic-gate _Tty, errno); 390*7c478bd9Sstevel@tonic-gate cleanup(101); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate #endif 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate /* ignore some signals if they were ignored upon invocation of ct */ 396*7c478bd9Sstevel@tonic-gate /* or else, have them go to graceful disconnect */ 397*7c478bd9Sstevel@tonic-gate if (save_hup == SIG_IGN) 398*7c478bd9Sstevel@tonic-gate (void) signal (SIGHUP, SIG_IGN); 399*7c478bd9Sstevel@tonic-gate else 400*7c478bd9Sstevel@tonic-gate (void) signal (SIGHUP, disconnect); 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate if (save_quit == SIG_IGN) 403*7c478bd9Sstevel@tonic-gate (void) signal (SIGQUIT, SIG_IGN); 404*7c478bd9Sstevel@tonic-gate else 405*7c478bd9Sstevel@tonic-gate (void) signal (SIGQUIT, disconnect); 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate if (save_int == SIG_IGN) 408*7c478bd9Sstevel@tonic-gate (void) signal (SIGINT, SIG_IGN); 409*7c478bd9Sstevel@tonic-gate else 410*7c478bd9Sstevel@tonic-gate (void) signal (SIGINT, disconnect); 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate (void) signal (SIGTERM, disconnect); 413*7c478bd9Sstevel@tonic-gate (void) signal (SIGALRM, disconnect); 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate (void) sleep (2); /* time for phone line/modem to settle */ 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate _Log_on = time ((time_t *) 0); 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /* 420*7c478bd9Sstevel@tonic-gate * if there is a login process on this line, 421*7c478bd9Sstevel@tonic-gate * tell the user to hit a carriage return to make 422*7c478bd9Sstevel@tonic-gate * the waiting process get past the inital read, 423*7c478bd9Sstevel@tonic-gate * Then exit. 424*7c478bd9Sstevel@tonic-gate */ 425*7c478bd9Sstevel@tonic-gate if (logprocflag) { /* there is a login process on the line */ 426*7c478bd9Sstevel@tonic-gate (void) fputs("Hit carriage return ", _Fdl); 427*7c478bd9Sstevel@tonic-gate (void) fclose(_Fdl); 428*7c478bd9Sstevel@tonic-gate CDEBUG(4, "there is a login process; exit\n%s", ""); 429*7c478bd9Sstevel@tonic-gate exit(0); 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate CDEBUG(4, "start login process (%s ", TTYMON); 433*7c478bd9Sstevel@tonic-gate CDEBUG(4, "-g -h -t 60 -l %s)\n", fdig(_Flds[F_CLASS])); 434*7c478bd9Sstevel@tonic-gate for (;;) { 435*7c478bd9Sstevel@tonic-gate pid_t w_ret; 436*7c478bd9Sstevel@tonic-gate switch(_Pid = fork()) { 437*7c478bd9Sstevel@tonic-gate case -1: /* fork failed */ 438*7c478bd9Sstevel@tonic-gate if ((!hangup || Verbose)) 439*7c478bd9Sstevel@tonic-gate (void) fputs ("ct: can't fork for login process\n", stderr); 440*7c478bd9Sstevel@tonic-gate cleanup(101); 441*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate case 0: /* child process */ 444*7c478bd9Sstevel@tonic-gate startat (); 445*7c478bd9Sstevel@tonic-gate (void) close(2); 446*7c478bd9Sstevel@tonic-gate /* ttymon will use open fd 0 for connection */ 447*7c478bd9Sstevel@tonic-gate if ( fdl != 0 ) { 448*7c478bd9Sstevel@tonic-gate (void) close(0); 449*7c478bd9Sstevel@tonic-gate dup(fdl); 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate (void) signal(SIGHUP, SIG_DFL); /* so child will exit on hangup */ 452*7c478bd9Sstevel@tonic-gate (void) execl(TTYMON, "ttymon", "-g", "-h", "-t", "60", 453*7c478bd9Sstevel@tonic-gate "-l", fdig(_Flds[F_CLASS]), (char *) 0); 454*7c478bd9Sstevel@tonic-gate /* exec failed */ 455*7c478bd9Sstevel@tonic-gate cleanup(101); 456*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate default: /* parent process */ 459*7c478bd9Sstevel@tonic-gate break; 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate /* Parent process */ 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate while ((w_ret = wait(&_Status)) != _Pid) 465*7c478bd9Sstevel@tonic-gate if (w_ret == -1 && errno != EINTR) { 466*7c478bd9Sstevel@tonic-gate VERBOSE("ct: wait failed errno=%d\n", errno); 467*7c478bd9Sstevel@tonic-gate cleanup(101); 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate if ((_Status & 0xff00) < 0) { 470*7c478bd9Sstevel@tonic-gate if (!hangup) 471*7c478bd9Sstevel@tonic-gate VERBOSE("ct: can't exec login process\n%s", ""); 472*7c478bd9Sstevel@tonic-gate cleanup(101); 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate stopat(_Flds[F_PHONE]); 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate rewind (_Fdl); /* flush line */ 478*7c478bd9Sstevel@tonic-gate (void) fputs ("\nReconnect? ", _Fdl); 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate rewind (_Fdl); 481*7c478bd9Sstevel@tonic-gate (void) alarm (20); 482*7c478bd9Sstevel@tonic-gate c = getc (_Fdl); 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate if (c == EOF || tolower (c) == 'n') 485*7c478bd9Sstevel@tonic-gate disconnect (0); /* normal disconnect */ 486*7c478bd9Sstevel@tonic-gate while ( (c = getc(_Fdl)) != EOF && c != '\n') 487*7c478bd9Sstevel@tonic-gate ; 488*7c478bd9Sstevel@tonic-gate (void) alarm (0); 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate static void 493*7c478bd9Sstevel@tonic-gate disconnect (code) 494*7c478bd9Sstevel@tonic-gate { 495*7c478bd9Sstevel@tonic-gate struct termio termio; 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate (void) alarm(0); 498*7c478bd9Sstevel@tonic-gate (void) signal (SIGALRM, SIG_IGN); 499*7c478bd9Sstevel@tonic-gate (void) signal (SIGINT, SIG_IGN); 500*7c478bd9Sstevel@tonic-gate (void) signal (SIGTERM, SIG_IGN); 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate _Log_elpsd = time ((time_t *) 0) - _Log_on; 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate (void) ioctl (fileno(_Fdl), TCGETA, &termio); 505*7c478bd9Sstevel@tonic-gate termio.c_cflag = 0; /* speed to zero for hangup */ 506*7c478bd9Sstevel@tonic-gate (void) ioctl (fileno(_Fdl), TCSETAW, &termio); /* hang up terminal */ 507*7c478bd9Sstevel@tonic-gate (void) fclose (_Fdl); 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate DEBUG(5, "Disconnect(%d)\n", code); 510*7c478bd9Sstevel@tonic-gate VERBOSE("Disconnected\n%s", ""); 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate /* For normal disconnect or timeout on "Reconnect?" message, 513*7c478bd9Sstevel@tonic-gate we already cleaned up above */ 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate if ((code != 0) && (code != SIGALRM)) 516*7c478bd9Sstevel@tonic-gate stopat(_Flds[F_PHONE]); 517*7c478bd9Sstevel@tonic-gate 518*7c478bd9Sstevel@tonic-gate cleanup(code); 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate /* 522*7c478bd9Sstevel@tonic-gate * clean and exit with "code" status 523*7c478bd9Sstevel@tonic-gate */ 524*7c478bd9Sstevel@tonic-gate void 525*7c478bd9Sstevel@tonic-gate cleanup (code) 526*7c478bd9Sstevel@tonic-gate register int code; 527*7c478bd9Sstevel@tonic-gate { 528*7c478bd9Sstevel@tonic-gate CDEBUG(5, "cleanup(%d)\n", code); 529*7c478bd9Sstevel@tonic-gate rmlock (CNULL); 530*7c478bd9Sstevel@tonic-gate if (*_Tty != '\0') { 531*7c478bd9Sstevel@tonic-gate CDEBUG(5, "chmod/chown %s\n", _Tty); 532*7c478bd9Sstevel@tonic-gate if (chown(_Tty , UUCPUID, TTYGID) < 0 ) { 533*7c478bd9Sstevel@tonic-gate CDEBUG(5, "Can't chown to uid=%ld, ", (long) UUCPUID); 534*7c478bd9Sstevel@tonic-gate CDEBUG(5, "gid=%ld\n", (long) TTYGID); 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate if (chmod(_Tty , TTYMOD) < 0) { 537*7c478bd9Sstevel@tonic-gate CDEBUG(5, "Can't chmod to %lo\n", (unsigned long) TTYMOD); 538*7c478bd9Sstevel@tonic-gate } 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate if (_Pid) { /* kill the child process */ 541*7c478bd9Sstevel@tonic-gate (void) signal(SIGHUP, SIG_IGN); 542*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN); 543*7c478bd9Sstevel@tonic-gate (void) kill (_Pid, SIGKILL); 544*7c478bd9Sstevel@tonic-gate } 545*7c478bd9Sstevel@tonic-gate exit (code); 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate /* gdev() 549*7c478bd9Sstevel@tonic-gate * Find an available line with a dialer on it. 550*7c478bd9Sstevel@tonic-gate * Set a temporary lock file for the line. 551*7c478bd9Sstevel@tonic-gate * Return: 552*7c478bd9Sstevel@tonic-gate * >0 - got a dialer 553*7c478bd9Sstevel@tonic-gate * <0 - failed - return the number of possible dialers 554*7c478bd9Sstevel@tonic-gate * 0 - not dialers of requested class on the system. 555*7c478bd9Sstevel@tonic-gate */ 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate static int 558*7c478bd9Sstevel@tonic-gate gdev (flds) 559*7c478bd9Sstevel@tonic-gate char *flds[]; 560*7c478bd9Sstevel@tonic-gate { 561*7c478bd9Sstevel@tonic-gate int count = 0; 562*7c478bd9Sstevel@tonic-gate extern void devreset(); 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate devreset(); 565*7c478bd9Sstevel@tonic-gate while (rddev ("ACU", _Dev, _Devbuf, D_MAX) != FAIL) { 566*7c478bd9Sstevel@tonic-gate /* check caller type */ 567*7c478bd9Sstevel@tonic-gate if (!EQUALS (flds[F_TYPE] /* "ACU" */, _Dev[D_TYPE])) 568*7c478bd9Sstevel@tonic-gate continue; 569*7c478bd9Sstevel@tonic-gate /* check class, check (and possibly set) speed */ 570*7c478bd9Sstevel@tonic-gate if (!EQUALS (flds[F_CLASS] /* speed */, _Dev[D_CLASS])) 571*7c478bd9Sstevel@tonic-gate continue; 572*7c478bd9Sstevel@tonic-gate count++; 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate if (fn_cklock(_Dev[D_LINE]) == FAIL) 575*7c478bd9Sstevel@tonic-gate continue; 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate /* found available dialer and set temporary lock */ 578*7c478bd9Sstevel@tonic-gate return (count); 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate } 581*7c478bd9Sstevel@tonic-gate return (- count); 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate 584*7c478bd9Sstevel@tonic-gate /* 585*7c478bd9Sstevel@tonic-gate * Check if there is a login process active on this line. 586*7c478bd9Sstevel@tonic-gate * Return: 587*7c478bd9Sstevel@tonic-gate * 0 - there is no login process on this line 588*7c478bd9Sstevel@tonic-gate * 1 - found a login process on this line 589*7c478bd9Sstevel@tonic-gate */ 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate static int 592*7c478bd9Sstevel@tonic-gate logproc(line) 593*7c478bd9Sstevel@tonic-gate char *line; 594*7c478bd9Sstevel@tonic-gate { 595*7c478bd9Sstevel@tonic-gate struct utmpx *u; 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate while ((u = getutxent()) != NULL) { 598*7c478bd9Sstevel@tonic-gate if (u->ut_type == LOGIN_PROCESS 599*7c478bd9Sstevel@tonic-gate && EQUALS(u->ut_line, line) 600*7c478bd9Sstevel@tonic-gate && EQUALS(u->ut_user, "LOGIN") ) { 601*7c478bd9Sstevel@tonic-gate CDEBUG(7, "ut_line %s, ", u->ut_line); 602*7c478bd9Sstevel@tonic-gate CDEBUG(7, "ut_user %s, ", u->ut_user); 603*7c478bd9Sstevel@tonic-gate CDEBUG(7, "ut_id %.4s, ", u->ut_id); 604*7c478bd9Sstevel@tonic-gate CDEBUG(7, "ut_pid %d\n", u->ut_pid); 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate /* see if the process is still active */ 607*7c478bd9Sstevel@tonic-gate if (kill(u->ut_pid, 0) == 0 || errno == EPERM) { 608*7c478bd9Sstevel@tonic-gate CDEBUG(4, "process still active\n%s", ""); 609*7c478bd9Sstevel@tonic-gate return(1); 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate } 612*7c478bd9Sstevel@tonic-gate } 613*7c478bd9Sstevel@tonic-gate return(0); 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate /* 617*7c478bd9Sstevel@tonic-gate * Create an entry in utmpx file if one does not already exist. 618*7c478bd9Sstevel@tonic-gate */ 619*7c478bd9Sstevel@tonic-gate static void 620*7c478bd9Sstevel@tonic-gate startat () 621*7c478bd9Sstevel@tonic-gate { 622*7c478bd9Sstevel@tonic-gate struct utmpx utmpxbuf, *u; 623*7c478bd9Sstevel@tonic-gate int fd; 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate /* Set up the prototype for the utmpx structure we want to write. */ 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate u = &utmpxbuf; 628*7c478bd9Sstevel@tonic-gate zero (&u -> ut_user[0], sizeof (u -> ut_user)); 629*7c478bd9Sstevel@tonic-gate zero (&u -> ut_line[0], sizeof (u -> ut_line)); 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate /* Fill in the various fields of the utmpx structure. */ 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate u -> ut_id[0] = 'c'; 634*7c478bd9Sstevel@tonic-gate u -> ut_id[1] = 't'; 635*7c478bd9Sstevel@tonic-gate u -> ut_id[2] = _Tty[strlen(_Tty)-2]; 636*7c478bd9Sstevel@tonic-gate u -> ut_id[3] = _Tty[strlen(_Tty)-1]; 637*7c478bd9Sstevel@tonic-gate u -> ut_pid = getpid (); 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate u -> ut_exit.e_termination = 0; 640*7c478bd9Sstevel@tonic-gate u -> ut_exit.e_exit = 0; 641*7c478bd9Sstevel@tonic-gate u -> ut_type = INIT_PROCESS; 642*7c478bd9Sstevel@tonic-gate time (&u -> ut_xtime); 643*7c478bd9Sstevel@tonic-gate setutxent (); /* Start at beginning of utmpx file. */ 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate /* For INIT_PROCESSes put in the name of the program in the */ 646*7c478bd9Sstevel@tonic-gate /* "ut_user" field. */ 647*7c478bd9Sstevel@tonic-gate 648*7c478bd9Sstevel@tonic-gate strncpy (&u -> ut_user[0], "ttymon", sizeof (u -> ut_user)); 649*7c478bd9Sstevel@tonic-gate strncpy (&u -> ut_line[0], Dc, sizeof (u -> ut_line)); 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate /* Write out the updated entry to utmpx file. */ 652*7c478bd9Sstevel@tonic-gate pututxline (u); 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate /* Now attempt to add to the end of the wtmpx file. Do not create */ 655*7c478bd9Sstevel@tonic-gate /* if it doesn't already exist. Do not overwrite any info already */ 656*7c478bd9Sstevel@tonic-gate /* in file. */ 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate if ((fd = open(WTMPX_FILE, O_WRONLY | O_APPEND)) != -1) { 659*7c478bd9Sstevel@tonic-gate (void) write(fd, u, sizeof(*u)); 660*7c478bd9Sstevel@tonic-gate (void) close(fd); 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate endutxent (); 663*7c478bd9Sstevel@tonic-gate return; 664*7c478bd9Sstevel@tonic-gate } 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate /* 667*7c478bd9Sstevel@tonic-gate * Change utmpx file entry to "dead". 668*7c478bd9Sstevel@tonic-gate * Make entry in ct log. 669*7c478bd9Sstevel@tonic-gate */ 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate static void 672*7c478bd9Sstevel@tonic-gate stopat (num) 673*7c478bd9Sstevel@tonic-gate char *num; 674*7c478bd9Sstevel@tonic-gate { 675*7c478bd9Sstevel@tonic-gate struct utmpx utmpxbuf, *u; 676*7c478bd9Sstevel@tonic-gate int fd; 677*7c478bd9Sstevel@tonic-gate FILE * fp; 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate /* Set up the prototype for the utmpx structure we want to write. */ 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate setutxent(); 682*7c478bd9Sstevel@tonic-gate u = &utmpxbuf; 683*7c478bd9Sstevel@tonic-gate zero (&u -> ut_user[0], sizeof (u -> ut_user)); 684*7c478bd9Sstevel@tonic-gate zero (&u -> ut_line[0], sizeof (u -> ut_line)); 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate /* Fill in the various fields of the utmpx structure. */ 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate u -> ut_id[0] = 'c'; 689*7c478bd9Sstevel@tonic-gate u -> ut_id[1] = 't'; 690*7c478bd9Sstevel@tonic-gate u -> ut_id[2] = _Tty[strlen(_Tty)-2]; 691*7c478bd9Sstevel@tonic-gate u -> ut_id[3] = _Tty[strlen(_Tty)-1]; 692*7c478bd9Sstevel@tonic-gate u -> ut_pid = (pid_t) _Pid; 693*7c478bd9Sstevel@tonic-gate u -> ut_type = USER_PROCESS; 694*7c478bd9Sstevel@tonic-gate 695*7c478bd9Sstevel@tonic-gate /* Find the old entry in the utmpx file with the user name and */ 696*7c478bd9Sstevel@tonic-gate /* copy it back. */ 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate if (u = getutxid (u)) { 699*7c478bd9Sstevel@tonic-gate utmpxbuf = *u; 700*7c478bd9Sstevel@tonic-gate u = &utmpxbuf; 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate u -> ut_exit.e_termination = _Status & 0xff; 704*7c478bd9Sstevel@tonic-gate u -> ut_exit.e_exit = (_Status >> 8) & 0xff; 705*7c478bd9Sstevel@tonic-gate u -> ut_type = DEAD_PROCESS; 706*7c478bd9Sstevel@tonic-gate time (&u -> ut_xtime); 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate /* Write out the updated entry to utmpx file. */ 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate pututxline (u); 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate /* Now attempt to add to the end of the wtmpx file. Do not create */ 713*7c478bd9Sstevel@tonic-gate /* if it doesn't already exist. Do not overwrite any info already */ 714*7c478bd9Sstevel@tonic-gate /* in file. */ 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate if ((fd = open(WTMPX_FILE, O_WRONLY | O_APPEND)) != -1) { 717*7c478bd9Sstevel@tonic-gate (void) write(fd, u, sizeof(*u)); 718*7c478bd9Sstevel@tonic-gate (void) close(fd); 719*7c478bd9Sstevel@tonic-gate } 720*7c478bd9Sstevel@tonic-gate endutxent (); 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate /* Do the log accounting */ 723*7c478bd9Sstevel@tonic-gate 724*7c478bd9Sstevel@tonic-gate if (exists (LOG) && (fp = fopen (LOG, "a")) != NULL) { 725*7c478bd9Sstevel@tonic-gate char *aptr; 726*7c478bd9Sstevel@tonic-gate int hrs, 727*7c478bd9Sstevel@tonic-gate mins, 728*7c478bd9Sstevel@tonic-gate secs; 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate /* ignore user set TZ for logfile purposes */ 731*7c478bd9Sstevel@tonic-gate if ( (aptr = getenv ("TZ")) != NULL ) 732*7c478bd9Sstevel@tonic-gate *aptr = '\0'; 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate (aptr = ctime (&_Log_on))[16] = '\0'; 735*7c478bd9Sstevel@tonic-gate hrs = _Log_elpsd / 3600; 736*7c478bd9Sstevel@tonic-gate mins = (_Log_elpsd %= 3600) / 60; 737*7c478bd9Sstevel@tonic-gate secs = _Log_elpsd % 60; 738*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%-8s ", getpwuid (getuid ()) -> pw_name); 739*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "(%4s) %s ", fdig(_Flds[F_CLASS]), aptr); 740*7c478bd9Sstevel@tonic-gate if (hrs) 741*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%2d:%.2d", hrs, mins); 742*7c478bd9Sstevel@tonic-gate else 743*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, " %2d", mins); 744*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, ":%.2d %s\n", secs, num); 745*7c478bd9Sstevel@tonic-gate (void) fclose (fp); 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate return; 748*7c478bd9Sstevel@tonic-gate } 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate static int 751*7c478bd9Sstevel@tonic-gate exists (file) 752*7c478bd9Sstevel@tonic-gate char *file; 753*7c478bd9Sstevel@tonic-gate { 754*7c478bd9Sstevel@tonic-gate struct stat statb; 755*7c478bd9Sstevel@tonic-gate 756*7c478bd9Sstevel@tonic-gate if (stat (file, &statb) == -1 && errno == ENOENT) 757*7c478bd9Sstevel@tonic-gate return (0); 758*7c478bd9Sstevel@tonic-gate return (1); 759*7c478bd9Sstevel@tonic-gate } 760*7c478bd9Sstevel@tonic-gate 761*7c478bd9Sstevel@tonic-gate static void 762*7c478bd9Sstevel@tonic-gate zero (adr, size) 763*7c478bd9Sstevel@tonic-gate register char *adr; 764*7c478bd9Sstevel@tonic-gate register int size; 765*7c478bd9Sstevel@tonic-gate { 766*7c478bd9Sstevel@tonic-gate while (size--) 767*7c478bd9Sstevel@tonic-gate *adr++ = '\0'; 768*7c478bd9Sstevel@tonic-gate return; 769*7c478bd9Sstevel@tonic-gate } 770