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