1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 /* LINTLIBRARY */ 32 33 # include <unistd.h> 34 # include <fcntl.h> 35 # include <errno.h> 36 # include <sys/utsname.h> 37 # include <stdlib.h> 38 # include <sys/types.h> 39 # include <sys/stat.h> 40 41 #include "lp.h" 42 #include "msgs.h" 43 44 #define TURN_OFF(X,F) (void)Fcntl(X, F_SETFL, (Fcntl(X, F_GETFL, 0) & ~(F))) 45 46 #if defined(__STDC__) 47 static int checklock ( void ); 48 #else 49 static int checklock(); 50 #endif 51 52 /* 53 ** mconnect() - OPEN A MESSAGE PATH 54 */ 55 56 #if defined(__STDC__) 57 MESG * mconnect ( char * path, int id1, int id2 ) 58 #else 59 MESG * mconnect () 60 char *path; 61 int id1; 62 int id2; 63 #endif 64 { 65 int fd; 66 int wronly = 0; 67 int count = 0; 68 MESG *md; 69 struct stat stbuf; 70 71 /* 72 ** invoked as mconnect(path, 0, 0) 73 ** 74 ** Open <path>, if isastream() is true for the returned file 75 ** descriptor, then we're done. 76 */ 77 78 if (path) 79 { 80 /* 81 ** Verify that the spooler is running and that the 82 ** <path> identifies a pipe. 83 ** This prevents us from getting hung in the open 84 ** and from thinking the <path> is a non-streams pipe. 85 */ 86 if (checklock() == -1) 87 return(NULL); 88 Again: if (stat(path, &stbuf) == -1) 89 return(NULL); 90 if ((stbuf.st_mode & S_IFMT) != S_IFIFO) { 91 if (count++ > 20) 92 return (NULL); 93 sleep(1); 94 goto Again; 95 } 96 97 if ((fd = Open(path, O_RDWR, 0)) == -1) 98 if ((fd = Open(path, O_WRONLY, 0)) == -1) 99 return(NULL); 100 else 101 wronly = 1; 102 103 if (isastream(fd) && !wronly) 104 { 105 #if defined(NOCONNLD) 106 int fds[2]; 107 108 if (pipe(fds) != 0) 109 return(NULL); 110 111 if (ioctl(fd, I_SENDFD, fds[1]) != 0) 112 return(NULL); 113 114 (void)_Close(fd); 115 116 fd = fds[0]; 117 (void)_Close(fds[1]); 118 #endif 119 120 if ((md = (MESG *)Malloc(MDSIZE)) == NULL) 121 { 122 errno = ENOMEM; 123 return(NULL); 124 } 125 126 memset(md, 0, sizeof (MESG)); 127 md->gid = getgid(); 128 md->on_discon = NULL; 129 md->readfd = fd; 130 md->state = MDS_IDLE; 131 md->type = MD_STREAM; 132 md->uid = getuid(); 133 md->writefd = fd; 134 135 ResetFifoBuffer (md->readfd); 136 return(md); 137 } 138 139 return(NULL); 140 } 141 142 if (id1 > 0 && id2 > 0) 143 { 144 if ((md = (MESG *)Malloc(MDSIZE)) == NULL) 145 { 146 errno = ENOMEM; 147 return(NULL); 148 } 149 150 memset(md, 0, sizeof (MESG)); 151 md->gid = getgid(); 152 md->on_discon = NULL; 153 md->readfd = id1; 154 md->state = MDS_IDLE; 155 md->type = MD_BOUND; 156 md->uid = getuid(); 157 md->writefd = id2; 158 159 ResetFifoBuffer (md->readfd); 160 161 return(md); 162 } 163 164 errno = EINVAL; 165 return(NULL); 166 } 167 168 #if defined(__STDC__) 169 static int checklock ( void ) 170 #else 171 static int checklock() 172 #endif 173 { 174 int fd; 175 struct flock lock; 176 177 if ((fd = Open(Lp_Schedlock, O_RDONLY, 0666)) == -1) 178 return (-1); 179 180 /* 181 * Now, we try to read-lock the lock file. This can only succeed if 182 * the Spooler (lpsched) is down. 183 */ 184 185 lock.l_type = F_RDLCK; 186 lock.l_whence = 0; 187 lock.l_start = 0; 188 lock.l_len = 0; /* till end of file */ 189 190 if (Fcntl(fd, F_SETLK, &lock) != -1 || errno != EAGAIN) 191 { 192 (void)Close (fd); 193 return (-1); 194 } 195 196 /* 197 * We can get here only when fcntl() == -1 && errno == EAGAIN, 198 * i.e., spooler (lpsched) is running. 199 */ 200 201 (void)Close (fd); 202 203 return(0); 204 } 205