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 /* LINTLIBRARY */ 31 32 # include <unistd.h> 33 # include <fcntl.h> 34 # include <errno.h> 35 # include <sys/utsname.h> 36 # include <stdlib.h> 37 # include <sys/types.h> 38 # include <sys/stat.h> 39 40 #include "lp.h" 41 #include "msgs.h" 42 43 #define TURN_OFF(X,F) (void)Fcntl(X, F_SETFL, (Fcntl(X, F_GETFL, 0) & ~(F))) 44 45 #if defined(__STDC__) 46 static int checklock ( void ); 47 #else 48 static int checklock(); 49 #endif 50 51 /* 52 ** mconnect() - OPEN A MESSAGE PATH 53 */ 54 55 #if defined(__STDC__) 56 MESG * mconnect ( char * path, int id1, int id2 ) 57 #else 58 MESG * mconnect () 59 char *path; 60 int id1; 61 int id2; 62 #endif 63 { 64 int fd; 65 int wronly = 0; 66 int count = 0; 67 MESG *md; 68 struct stat stbuf; 69 70 /* 71 ** invoked as mconnect(path, 0, 0) 72 ** 73 ** Open <path>, if isastream() is true for the returned file 74 ** descriptor, then we're done. 75 */ 76 77 if (path) 78 { 79 /* 80 ** Verify that the spooler is running and that the 81 ** <path> identifies a pipe. 82 ** This prevents us from getting hung in the open 83 ** and from thinking the <path> is a non-streams pipe. 84 */ 85 if (checklock() == -1) 86 return(NULL); 87 Again: if (stat(path, &stbuf) == -1) 88 return(NULL); 89 if ((stbuf.st_mode & S_IFMT) != S_IFIFO) { 90 if (count++ > 20) 91 return (NULL); 92 sleep(1); 93 goto Again; 94 } 95 96 if ((fd = Open(path, O_RDWR, 0)) == -1) 97 if ((fd = Open(path, O_WRONLY, 0)) == -1) 98 return(NULL); 99 else 100 wronly = 1; 101 102 if (isastream(fd) && !wronly) 103 { 104 #if defined(NOCONNLD) 105 int fds[2]; 106 107 if (pipe(fds) != 0) 108 return(NULL); 109 110 if (ioctl(fd, I_SENDFD, fds[1]) != 0) 111 return(NULL); 112 113 (void)_Close(fd); 114 115 fd = fds[0]; 116 (void)_Close(fds[1]); 117 #endif 118 119 if ((md = (MESG *)Malloc(MDSIZE)) == NULL) 120 { 121 errno = ENOMEM; 122 return(NULL); 123 } 124 125 memset(md, 0, sizeof (MESG)); 126 md->gid = getgid(); 127 md->on_discon = NULL; 128 md->readfd = fd; 129 md->state = MDS_IDLE; 130 md->type = MD_STREAM; 131 md->uid = getuid(); 132 md->writefd = fd; 133 134 ResetFifoBuffer (md->readfd); 135 return(md); 136 } 137 138 return(NULL); 139 } 140 141 if (id1 > 0 && id2 > 0) 142 { 143 if ((md = (MESG *)Malloc(MDSIZE)) == NULL) 144 { 145 errno = ENOMEM; 146 return(NULL); 147 } 148 149 memset(md, 0, sizeof (MESG)); 150 md->gid = getgid(); 151 md->on_discon = NULL; 152 md->readfd = id1; 153 md->state = MDS_IDLE; 154 md->type = MD_BOUND; 155 md->uid = getuid(); 156 md->writefd = id2; 157 158 ResetFifoBuffer (md->readfd); 159 160 return(md); 161 } 162 163 errno = EINVAL; 164 return(NULL); 165 } 166 167 #if defined(__STDC__) 168 static int checklock ( void ) 169 #else 170 static int checklock() 171 #endif 172 { 173 int fd; 174 struct flock lock; 175 176 if ((fd = Open(Lp_Schedlock, O_RDONLY, 0666)) == -1) 177 return (-1); 178 179 /* 180 * Now, we try to read-lock the lock file. This can only succeed if 181 * the Spooler (lpsched) is down. 182 */ 183 184 lock.l_type = F_RDLCK; 185 lock.l_whence = 0; 186 lock.l_start = 0; 187 lock.l_len = 0; /* till end of file */ 188 189 if (Fcntl(fd, F_SETLK, &lock) != -1 || errno != EAGAIN) 190 { 191 (void)Close (fd); 192 return (-1); 193 } 194 195 /* 196 * We can get here only when fcntl() == -1 && errno == EAGAIN, 197 * i.e., spooler (lpsched) is running. 198 */ 199 200 (void)Close (fd); 201 202 return(0); 203 } 204