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 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <libintl.h> 32 #include <signal.h> 33 #include <errno.h> 34 #include <string.h> 35 #include <syslog.h> 36 #include "netpr.h" 37 #include "netdebug.h" 38 39 static int job_primitive(np_bsdjob_t *, char, char *); 40 static int create_cfA_file(np_bsdjob_t *); 41 static char * create_cfname(np_bsdjob_t *); 42 static char * create_dfname(np_bsdjob_t *); 43 extern char data_file_type; 44 45 np_bsdjob_t * 46 create_bsd_job(np_job_t * injob, int pr_order, int filesize) 47 { 48 49 np_bsdjob_t *job; 50 char *id; 51 int x; 52 np_data_t * jobdata; 53 54 if ((injob->request_id == NULL) || (injob->username == NULL) || 55 (injob->dest == NULL) || (injob->printer == NULL)) { 56 return (NULL); 57 } 58 59 job = (np_bsdjob_t *)malloc(sizeof (np_bsdjob_t)); 60 ASSERT(job, MALLOC_ERR); 61 (void) memset(job, 0, sizeof (np_bsdjob_t)); 62 /* 63 * request-id comes in as printer-number 64 * pull apart to create number 65 */ 66 if ((id = strrchr(injob->request_id, (int)'-')) == NULL) { 67 (void) fprintf(stderr, 68 gettext("Netpr: request_id in unknown format:<%s>\n"), 69 injob->request_id); 70 syslog(LOG_DEBUG, "request id in unknown format: %s", 71 injob->request_id); 72 return (NULL); 73 } 74 75 id++; 76 77 /* 78 * 4261563 - A ID collides with an existing one, it plus 79 * 1,000 with the ID causes breaking 80 * Max job id for bsd is 999. 81 */ 82 job->np_request_id = malloc(4); 83 ASSERT(job->np_request_id, MALLOC_ERR); 84 errno = 0; 85 x = atoi(id); 86 if ((errno != 0) || (x < 0)) { 87 x = 0; 88 } 89 (void) snprintf(job->np_request_id, (size_t) 4, 90 "%.3d", x % 1000); 91 92 /* seperate the user/host from host!user or user@host */ 93 if ((id = strchr(injob->username, '@')) != NULL) { 94 *id++ = '\0'; 95 job->np_username = strdup(injob->username); 96 job->np_host = strdup(id); 97 *--id = '@'; 98 } else if ((id = strrchr(injob->username, '!')) != NULL) { 99 *id++ = '\0'; 100 job->np_username = strdup(id); 101 job->np_host = strdup(injob->username); 102 *--id = '!'; 103 } else { 104 syslog(LOG_DEBUG, "using localhost for user %s", 105 injob->username); 106 job->np_username = strdup(injob->username); 107 job->np_host = strdup("localhost"); 108 } 109 110 job->np_printer = injob->printer; 111 job->np_filename = injob->filename; 112 113 job->np_df_letter = 'A'; 114 115 /* build cfAfilename: (cfA)(np_request_id)(np_host) */ 116 if ((job->np_cfAfilename = create_cfname(job)) == NULL) { 117 (void) fprintf(stderr, 118 gettext("Netpr: System error creating cfAfilename\n")); 119 syslog(LOG_DEBUG, "System error creating cfAfilename"); 120 return (NULL); 121 } 122 123 job->np_timeout = injob->timeout; 124 job->np_banner = injob->banner; 125 job->np_print_order = pr_order; 126 127 if (injob->title == NULL) 128 job->np_title = injob->filename; 129 else 130 job->np_title = injob->title; 131 132 if ((create_cfA_file(job)) == -1) { 133 (void) fprintf(stderr, 134 gettext("Netpr: Cannot create bsd control file\n")); 135 syslog(LOG_DEBUG, "Cannot create bsd control file"); 136 return (NULL); 137 } 138 139 /* Now we have a title, add to the control file */ 140 if (injob->banner == BANNER) { 141 (void) job_primitive(job, 'C', job->np_host); 142 (void) job_primitive(job, 'J', job->np_title); 143 (void) job_primitive(job, 'L', job->np_username); 144 } 145 146 147 /* create dfname for this file */ 148 149 /* allocate the jobdata and initialize what we have so far */ 150 jobdata = malloc(sizeof (np_data_t)); 151 ASSERT(jobdata, MALLOC_ERR); 152 (void) memset(jobdata, 0, sizeof (np_data_t)); 153 154 jobdata->np_path_file = malloc(strlen(job->np_filename) + 1); 155 ASSERT(jobdata->np_path_file, MALLOC_ERR); 156 (void) strcpy(jobdata->np_path_file, job->np_filename); 157 158 jobdata->np_data_size = filesize; 159 160 if ((jobdata->np_dfAfilename = create_dfname(job)) == NULL) { 161 return (NULL); 162 } 163 164 /* 165 * data_file_type should contain the RFC-1179 control file message 166 * type for the control file. The is is set via the "-f" option 167 * to netpr, which get it from the "destination-full-control-file-type" 168 * option passed in. Normally this will be either 'l' or 'f'. 169 */ 170 if (data_file_type != 0) { 171 (void) job_primitive(job, data_file_type, 172 jobdata->np_dfAfilename); 173 (void) job_primitive(job, 'U', jobdata->np_dfAfilename); 174 (void) job_primitive(job, 'N', "print-data"); 175 } 176 177 syslog(LOG_DEBUG, "data file info: %s", job->np_cfAfile); 178 179 /* 180 * attach np_data to bsdjob 181 */ 182 job->np_data = jobdata; 183 184 return (job); 185 } 186 187 188 /* 189 * Create df<x>name for this file 190 * df<X><nnn><hostname> 191 */ 192 static char * 193 create_dfname(np_bsdjob_t *job) 194 { 195 char * dfname; 196 197 if (job == NULL) 198 return (NULL); 199 200 /* Trying to print too many files */ 201 if (job->np_df_letter > 'z') { 202 errno = ENFILE; 203 return (NULL); 204 } 205 206 dfname = (char *)malloc(strlen(job->np_host) + 3 + 3 + 1); 207 ASSERT(dfname, MALLOC_ERR); 208 (void) memset(dfname, 0, strlen(job->np_host) + 3 + 3 + 1); 209 (void) sprintf(dfname, "%s%c%s%s", "df", job->np_df_letter, 210 job->np_request_id, job->np_host); 211 212 /* udate np_df_letter for the next caller */ 213 job->np_df_letter += 1; 214 if ((job->np_df_letter > 'Z') && (job->np_df_letter < 'a')) 215 job->np_df_letter = 'a'; 216 217 return (dfname); 218 } 219 220 static char * 221 create_cfname(np_bsdjob_t * job) 222 { 223 char * cfname; 224 225 if (job == NULL) 226 return (NULL); 227 228 cfname = (char *)malloc(strlen(job->np_host) + 3 + 3 + 1); 229 ASSERT(cfname, MALLOC_ERR); 230 (void) memset(cfname, 0, strlen(job->np_host) + 3 + 3 + 1); 231 (void) sprintf(cfname, "%s%s%s", "cfA", 232 job->np_request_id, job->np_host); 233 return (cfname); 234 } 235 236 static int 237 create_cfA_file(np_bsdjob_t *job) 238 { 239 /* 240 * Read through job structure, creating entries 241 * in control file as appropriate 242 */ 243 if ((job->np_host == NULL) || (job->np_username == NULL)) { 244 (void) fprintf(stderr, gettext( 245 "Netpr: Missing required data, cannot build control file\n")); 246 return (-1); 247 } 248 (void) job_primitive(job, 'H', job->np_host); 249 (void) job_primitive(job, 'P', job->np_username); 250 251 return (0); 252 } 253 254 static int 255 job_primitive(np_bsdjob_t * job, char option, char *value) 256 { 257 char buf[BUFSIZ]; 258 259 if ((job == NULL) || (value == NULL)) 260 return (-1); 261 262 job->np_cfAfilesize += strlen(value) + 2; /* (opt)(value)\n */ 263 if (job->np_cfAfile == NULL) { 264 /* Always allocate one greater than cfAfilesize for the \0 */ 265 job->np_cfAfile = calloc(1, job->np_cfAfilesize + 1); 266 ASSERT(job->np_cfAfile, MALLOC_ERR); 267 } else { 268 job->np_cfAfile = realloc(job->np_cfAfile, 269 job->np_cfAfilesize + 1); 270 ASSERT(job->np_cfAfile, REALLOC_ERR); 271 } 272 (void) snprintf(buf, sizeof (buf), "%c%s\n", option, value); 273 (void) strcat(job->np_cfAfile, buf); 274 syslog(LOG_DEBUG, "adding: %d %s", job->np_cfAfilesize, buf); 275 276 return (0); 277 } 278