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