1/* Coherent tty locking support. This file was contributed by Bob 2 Hemedinger <bob@dalek.mwc.com> of Mark Williams Corporation and 3 lightly edited by Ian Lance Taylor. */ 4 5/* The bottom part of this file is lock.c. 6 * This is a hacked lock.c. A full lock.c can be found in the libmisc sources 7 * under /usr/src/misc.tar.Z. 8 * 9 * These are for checking for the existence of locks: 10 * lockexist(resource) 11 * lockttyexist(ttyname) 12 */ 13 14#include "uucp.h" 15 16#if HAVE_COHERENT_LOCKFILES 17 18/* cohtty.c: Given a serial device name, read /etc/ttys and determine if 19 * the device is already enabled. If it is, disable the 20 * device and return a string so that it can be re-enabled 21 * at the completion of the uucico session as part of the 22 * function that resets the serial device before uucico 23 * terminates. 24 * 25 */ 26 27#include "uudefs.h" 28#include "sysdep.h" 29 30#include <ctype.h> 31#include <access.h> 32 33/* fscoherent_disable_tty() is a COHERENT specific function. It takes the name 34 * of a serial device and then scans /etc/ttys for a match. If it finds one, 35 * it checks the first field of the entry. If it is a '1', then it will disable 36 * the port and set a flag. The flag will be checked later when uucico wants to 37 * reset the serial device to see if the device needs to be re-enabled. 38 */ 39 40/* May 10, 1993: This function will always return true for the following 41 * reasons: 42 * 1) lock files have already been dealt with 43 * 2) if someone else already has the port open, uucico should fail anyways 44 * 3) Coherent's disable command return can return '0' or '1', but will 45 * succeed in any event. 46 * 4) It doesn't matter if there is a ttys entry for the port in question. 47 * /etc/ttys generally only lists devices that MAY be enabled for logins. 48 * If a device will never be used for logins, then there may not be a 49 * ttys entry, in which case, disable won't be called anyways. 50 * ---bob@mwc.com 51 */ 52 53boolean 54fscoherent_disable_tty (zdevice, pzenable) 55 const char *zdevice; 56 char **pzenable; 57{ 58 59 60struct ttyentry{ /* this is an /etc/ttys entry */ 61 char enable_disable[1]; 62 char remote_local[1]; 63 char baud_rate[1]; 64 char tty_device[16]; 65}; 66 67struct ttyentry sought_tty; 68 69int x,y,z; /* dummy */ 70FILE * infp; /* this will point to /etc/ttys */ 71char disable_command[66]; /* this will be the disable command 72 * passed to the system. 73 */ 74char enable_device[16]; /* this will hold our device name 75 * to enable. 76 */ 77 78 *pzenable = NULL; 79 80 strcpy(enable_device,""); /* initialize our strings */ 81 strcpy(sought_tty.tty_device,""); 82 83 if( (infp = fopen("/etc/ttys","r")) == NULL){ 84 ulog(LOG_ERROR,"Error: check_disable_tty: failed to open /etc/ttys\n"); 85 return FALSE; 86 } 87 88 while (NULL !=(fgets(&sought_tty, sizeof (sought_tty), infp ))){ 89 sought_tty.tty_device[strlen(sought_tty.tty_device) -1] = '\0'; 90 strcpy(enable_device,sought_tty.tty_device); 91 92 /* we must strip away the suffix to the com port name or 93 * we will never find a match. For example, if we are passed 94 * /dev/com4l to call out with and the port is already enabled, 95 * 9/10 the port enabled will be com4r. After we strip away the 96 * suffix of the port found in /etc/ttys, then we can test 97 * if the base port name appears in the device name string 98 * passed to us. 99 */ 100 101 for(z = strlen(sought_tty.tty_device) ; z > 0 ; z--){ 102 if(isdigit(sought_tty.tty_device[z])){ 103 break; 104 } 105 } 106 y = strlen(sought_tty.tty_device); 107 for(x = z+1 ; x <= y; x++){ 108 sought_tty.tty_device[x] = '\0'; 109 } 110 111 112/* ulog(LOG_NORMAL,"found device {%s}\n",sought_tty.tty_device); */ 113 if(strstr(zdevice, sought_tty.tty_device)){ 114 if(sought_tty.enable_disable[0] == '1'){ 115 ulog(LOG_NORMAL, "coh_tty: Disabling device %s {%s}\n", 116 zdevice, sought_tty.tty_device); 117 sprintf(disable_command, "/etc/disable %s",enable_device); 118 { 119 pid_t ipid; 120 const char *azargs[3]; 121 int aidescs[3]; 122 123 azargs[0] = "/etc/disable"; 124 azargs[1] = enable_device; 125 azargs[2] = NULL; 126 aidescs[0] = SPAWN_NULL; 127 aidescs[1] = SPAWN_NULL; 128 aidescs[2] = SPAWN_NULL; 129 ipid = ixsspawn (azargs, aidescs, TRUE, 130 FALSE, 131 (const char *) NULL, TRUE, 132 TRUE, 133 (const char *) NULL, 134 (const char *) NULL, 135 (const char *) NULL); 136 if (ipid < 0) 137 x = 1; 138 else 139 x = ixswait ((unsigned long) ipid, 140 (const char *) NULL); 141 } 142 *pzenable = zbufalc (sizeof "/dev/" 143 + strlen (enable_device)); 144 sprintf(*pzenable,"/dev/%s", enable_device); 145/* ulog(LOG_NORMAL,"Enable string is {%s}",*pzenable); */ 146 return TRUE; 147 }else{ 148 /* device not enabled */ 149 return TRUE; 150 } 151 } 152 } 153 return TRUE; /* no ttys entry found */ 154} 155 156/* The following is COHERENT 4.0 specific. It is used to test for any 157 * existing lockfiles on a port which would have been created by init 158 * when a user logs into a port. 159 */ 160 161#define LOCKSIG 9 /* Significant Chars of Lockable Resources. */ 162#define LOKFLEN 64 /* Max Length of UUCP Lock File Name. */ 163 164#define LOCKPRE "LCK.." 165#define PIDLEN 6 /* Maximum length of string representing a pid. */ 166 167#ifndef LOCKDIR 168#define LOCKDIR SPOOLDIR 169#endif 170 171/* There is a special version of DEVMASK for the PE multiport driver 172 * because of the peculiar way it uses the minor device number. For 173 * all other drivers, the lower 5 bits describe the physical port-- 174 * the upper 3 bits give attributes for the port. 175 */ 176 177#define PE_DRIVER 21 /* Major device number for the PE driver. */ 178#define PE_DEVMASK 0x3f /* PE driver minor device mask. */ 179#define DEVMASK 0x1f /* Minor device mask. */ 180 181/* 182 * Generates a resource name for locking, based on the major number 183 * and the lower 4 bits of the minor number of the tty device. 184 * 185 * Builds the name in buff as two "." separated decimal numbers. 186 * Returns NULL on failure, buff on success. 187 */ 188static char * 189gen_res_name(path, buff) 190char *path; 191char *buff; 192{ 193 struct stat sbuf; 194 int status; 195 196 if (0 != (status = stat(path, &sbuf))) { 197 /* Can't stat the file. */ 198 return (NULL); 199 } 200 201 if (PE_DRIVER == major(sbuf.st_rdev)) { 202 sprintf(buff, "%d.%d", major(sbuf.st_rdev), 203 PE_DEVMASK & minor(sbuf.st_rdev)); 204 } else { 205 sprintf(buff, "%d.%d", major(sbuf.st_rdev), 206 DEVMASK & minor(sbuf.st_rdev)); 207 } 208 209 return(buff); 210} /* gen_res_name */ 211 212/* 213 * lockexist(resource) char *resource; 214 * 215 * Test for existance of a lock on the given resource. 216 * 217 * Returns: (1) Resource is locked. 218 * (0) Resource is not locked. 219 */ 220 221static boolean 222lockexist(resource) 223const char *resource; 224{ 225 char lockfn[LOKFLEN]; 226 227 if ( resource == NULL ) 228 return(0); 229 sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource); 230 231 return (!access(lockfn, AEXISTS)); 232} /* lockexist() */ 233 234/* 235 * lockttyexist(ttyname) char *ttyname; 236 * 237 * Test for existance of a lock on the given tty. 238 * 239 * Returns: (1) Resource is locked. 240 * (0) Resource is not locked. 241 */ 242boolean 243lockttyexist(ttyn) 244const char *ttyn; 245{ 246 char resource[LOKFLEN]; 247 char filename[LOKFLEN]; 248 249 sprintf(filename, "/dev/%s", ttyn); 250 if (NULL == gen_res_name(filename, resource)){ 251 return(0); /* Non-existent tty can not be locked :-) */ 252 } 253 254 return(lockexist(resource)); 255} /* lockttyexist() */ 256 257#endif /* HAVE_COHERENT_LOCKFILES */ 258