URI:
       tlpdsend.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tlpdsend.c (9564B)
       ---
            1 #include <u.h>
            2 #include <sys/types.h>
            3 #include <unistd.h>
            4 #include <sys/stat.h>
            5 #include <sys/param.h>
            6 #include <stdlib.h>
            7 #include <fcntl.h>
            8 #include <stdio.h>
            9 #include <string.h>
           10 #include <signal.h>
           11 #include <libc.h>
           12 
           13 #define        REDIALTIMEOUT        15
           14 #define TIMEOUT 600
           15 
           16 char tmpfilename[L_tmpnam+1];
           17 int alarmstate = 0;
           18 int debugflag = 0;
           19 int killflag = 0;
           20 int statflag = 0;
           21 
           22 void
           23 cleanup(void) {
           24         unlink(tmpfilename);
           25 }
           26 
           27 #define SBSIZE 8192
           28 unsigned char sendbuf[SBSIZE];
           29 
           30 void
           31 debug(char *str) {
           32         if (debugflag)
           33                 fprintf(stderr, "%s", str);
           34 }
           35 
           36 void
           37 alarmhandler(int sig) {
           38         fprintf(stderr, "timeout occurred, check printer.\n");
           39         exit(2);
           40 }
           41 
           42 /* send a message after each WARNPC percent of data sent */
           43 #define WARNPC        5
           44 
           45 int
           46 copyfile(int in, int out, long tosend) {
           47         int n;
           48         int sent = 0;
           49         int percent = 0;
           50 
           51         if (debugflag)
           52                 fprintf(stderr, "lpdsend: copyfile(%d,%d,%ld)\n",
           53                         in, out, tosend);
           54         while ((n=read(in, sendbuf, SBSIZE)) > 0) {
           55                 if (debugflag)
           56                         fprintf(stderr, "lpdsend: copyfile read %d bytes from %d\n",
           57                                 n, in);
           58                 alarm(TIMEOUT); alarmstate = 1;
           59                 if (write(out, sendbuf, n) != n) {
           60                         alarm(0);
           61                         fprintf(stderr, "write to fd %d failed\n", out);
           62                         return(0);
           63                 }
           64                 alarm(0);
           65                 if (debugflag)
           66                         fprintf(stderr, "lpdsend: copyfile wrote %d bytes to %d\n",
           67                                 n, out);
           68                 sent += n;
           69                 if (tosend && ((sent*100/tosend)>=(percent+WARNPC))) {
           70                         percent += WARNPC;
           71                         fprintf(stderr, ": %5.2f%% sent\n", sent*100.0/tosend);
           72                 }
           73         }
           74         if (debugflag)
           75                 fprintf(stderr, "lpdsend: copyfile read %d bytes from %d\n",
           76                         n, in);
           77         return(!n);
           78 }
           79 
           80 char  strbuf[120];
           81 char hostname[MAXHOSTNAMELEN], *username, *printername, *killarg;
           82 char *inputname;
           83 char filetype = 'o';        /* 'o' is for PostScript */
           84 int seqno = 0;
           85 char *seqfilename;
           86 
           87 void
           88 killjob(int printerfd) {
           89         int strlength;
           90         if (printername==0) {
           91                 fprintf(stderr, "no printer name\n");
           92                 exit(1);
           93         }
           94         if (username==0) {
           95                 fprintf(stderr, "no user name given\n");
           96                 exit(1);
           97         }
           98         if (killarg==0) {
           99                 fprintf(stderr, "no job to kill\n");
          100                 exit(1);
          101         }
          102         sprintf(strbuf, "%c%s %s %s\n", '\5', printername, username, killarg);
          103         strlength = strlen(strbuf);
          104         if (write(printerfd, strbuf, strlength) != strlength) {
          105                 fprintf(stderr, "write(printer) error\n");
          106                 exit(1);
          107         }
          108         copyfile(printerfd, 2, 0L);
          109 }
          110 
          111 void
          112 checkqueue(int printerfd) {
          113         int strlength;
          114 
          115         sprintf(strbuf, "%c%s\n", '\4', printername);
          116         strlength = strlen(strbuf);
          117         if (write(printerfd, strbuf, strlength) != strlength) {
          118                 fprintf(stderr, "write(printer) error\n");
          119                 exit(1);
          120         }
          121         copyfile(printerfd, 2, 0L);
          122 /*
          123 {        int n;
          124         unsigned char sendbuf[1];
          125         while ((n=read(printerfd, sendbuf, 1)) > 0) {
          126                 write(2, sendbuf, n);
          127         }
          128 }
          129 */
          130 }
          131 
          132 void
          133 getack(int printerfd, int as) {
          134         char resp;
          135         int rv;
          136 
          137         alarm(TIMEOUT); alarmstate = as;
          138         if ((rv=read(printerfd, &resp, 1)) != 1 || resp != '\0') {
          139                 fprintf(stderr, "getack failed: read returned %d, read value (if any) %d, alarmstate=%d\n",
          140                         rv, resp, alarmstate);
          141                 exit(1);
          142         }
          143         alarm(0);
          144 }
          145 
          146 /* send control file */
          147 void
          148 sendctrl(int printerfd) {
          149         char cntrlstrbuf[256];
          150         int strlength, cntrlen;
          151 
          152         sprintf(cntrlstrbuf, "H%s\nP%s\n%cdfA%3.3d%s\n", hostname, username, filetype, seqno, hostname);
          153         cntrlen = strlen(cntrlstrbuf);
          154         sprintf(strbuf, "%c%d cfA%3.3d%s\n", '\2', cntrlen, seqno, hostname);
          155         strlength = strlen(strbuf);
          156         if (write(printerfd, strbuf, strlength) != strlength) {
          157                 fprintf(stderr, "write(printer) error\n");
          158                 exit(1);
          159         }
          160         getack(printerfd, 3);
          161         if (write(printerfd, cntrlstrbuf, cntrlen) != cntrlen) {
          162                 fprintf(stderr, "write(printer) error\n");
          163                 exit(1);
          164         }
          165         if (write(printerfd, "\0", 1) != 1) {
          166                 fprintf(stderr, "write(printer) error\n");
          167                 exit(1);
          168         }
          169         getack(printerfd, 4);
          170 }
          171 
          172 /* send data file */
          173 void
          174 senddata(int inputfd, int printerfd, long size) {
          175         int strlength;
          176 
          177         sprintf(strbuf, "%c%ld dfA%3.3d%s\n", '\3', size, seqno, hostname);
          178         strlength = strlen(strbuf);
          179         if (write(printerfd, strbuf, strlength) != strlength) {
          180                 fprintf(stderr, "write(printer) error\n");
          181                 exit(1);
          182         }
          183         getack(printerfd, 5);
          184         if (!copyfile(inputfd, printerfd, size)) {
          185                 fprintf(stderr, "failed to send file to printer\n");
          186                 exit(1);
          187         }
          188         if (write(printerfd, "\0", 1) != 1) {
          189                 fprintf(stderr, "write(printer) error\n");
          190                 exit(1);
          191         }
          192         fprintf(stderr, "%ld bytes sent, status: waiting for end of job\n", size);
          193         getack(printerfd, 6);
          194 }
          195 
          196 void
          197 sendjob(int inputfd, int printerfd) {
          198         struct stat statbuf;
          199         int strlength;
          200 
          201         if (fstat(inputfd, &statbuf) < 0) {
          202                 fprintf(stderr, "fstat(%s) failed\n", inputname);
          203                 exit(1);
          204         }
          205         sprintf(strbuf, "%c%s\n", '\2', printername);
          206         strlength = strlen(strbuf);
          207         if (write(printerfd, strbuf, strlength) != strlength) {
          208                 fprintf(stderr, "write(printer) error\n");
          209                 exit(1);
          210         }
          211         getack(printerfd, 2);
          212         debug("send data\n");
          213         senddata(inputfd, printerfd, statbuf.st_size);
          214         debug("send control info\n");
          215         sendctrl(printerfd);
          216         fprintf(stderr, "%ld bytes sent, status: end of job\n", (long)statbuf.st_size);
          217 }
          218 
          219 /*
          220  *  make an address, add the defaults
          221  */
          222 char *
          223 netmkaddr(char *linear, char *defnet, char *defsrv)
          224 {
          225         static char addr[512];
          226         char *cp;
          227 
          228         /*
          229          *  dump network name
          230          */
          231         cp = strchr(linear, '!');
          232         if(cp == 0){
          233                 if(defnet==0){
          234                         if(defsrv)
          235                                 sprintf(addr, "net!%s!%s", linear, defsrv);
          236                         else
          237                                 sprintf(addr, "net!%s", linear);
          238                 }
          239                 else {
          240                         if(defsrv)
          241                                 sprintf(addr, "%s!%s!%s", defnet, linear, defsrv);
          242                         else
          243                                 sprintf(addr, "%s!%s", defnet, linear);
          244                 }
          245                 return addr;
          246         }
          247 
          248         /*
          249          *  if there is already a service, use it
          250          */
          251         cp = strchr(cp+1, '!');
          252         if(cp)
          253                 return linear;
          254 
          255         /*
          256          *  add default service
          257          */
          258         if(defsrv == 0)
          259                 return linear;
          260         sprintf(addr, "%s!%s", linear, defsrv);
          261 
          262         return addr;
          263 }
          264 
          265 void
          266 main(int argc, char *argv[]) {
          267         int c, usgflg = 0;
          268         char *desthostname;
          269         int printerfd;
          270         int inputfd;
          271         int sendport;
          272         char portstr[4];
          273 
          274         desthostname = nil;
          275         if (signal(SIGALRM, alarmhandler) == SIG_ERR) {
          276                 fprintf(stderr, "failed to set alarm handler\n");
          277                 exit(1);
          278         }
          279         while ((c = getopt(argc, argv, "Dd:k:qs:t:H:P:")) != -1)
          280                 switch (c) {
          281                 case 'D':
          282                         debugflag = 1;
          283                         debug("debugging on\n");
          284                         break;
          285                 case 'd':
          286                         printername = optarg;
          287                         break;
          288                 case 'k':
          289                         if (statflag) {
          290                                 fprintf(stderr, "cannot have both -k and -q flags\n");
          291                                 exit(1);
          292                         }
          293                         killflag = 1;
          294                         killarg = optarg;
          295                         break;
          296                 case 'q':
          297                         if (killflag) {
          298                                 fprintf(stderr, "cannot have both -q and -k flags\n");
          299                                 exit(1);
          300                         }
          301                         statflag = 1;
          302                         break;
          303                 case 's':
          304                         seqno = strtol(optarg, NULL, 10);
          305                         if (seqno < 0 || seqno > 999)
          306                                 seqno = 0;
          307                         break;
          308                 case 't':
          309                         switch (filetype) {
          310                         case 'c':
          311                         case 'd':
          312                         case 'f':
          313                         case 'g':
          314                         case 'l':
          315                         case 'n':
          316                         case 'o':
          317                         case 'p':
          318                         case 'r':
          319                         case 't':
          320                         case 'v':
          321                         case 'z':
          322                                 filetype = optarg[0];
          323                                 break;
          324                         default:
          325                                 usgflg++;
          326                                 break;
          327                         }
          328                         break;
          329                 case 'H':
          330                         strncpy(hostname, optarg, MAXHOSTNAMELEN);
          331                         break;
          332                 case 'P':
          333                         username = optarg;
          334                         break;
          335                 default:
          336                 case '?':
          337                         fprintf(stderr, "unknown option %c\n", c);
          338                         usgflg++;
          339                 }
          340         if (argc < 2) usgflg++;
          341         if (optind < argc) {
          342                 desthostname = argv[optind++];
          343         } else
          344                 usgflg++;
          345         if (usgflg) {
          346                 fprintf(stderr, "usage: to send a job - %s -d printer -H hostname -P username [-s seqno] [-t[cdfgklnoprtvz]] desthost [filename]\n", argv[0]);
          347                 fprintf(stderr, "     to check status - %s -d printer -q desthost\n", argv[0]);
          348                 fprintf(stderr, "       to kill a job - %s -d printer -P username -k jobname desthost\n", argv[0]);
          349                 exit(1);
          350         }
          351 
          352 /* make sure the file to send is here and ready
          353  * otherwise the TCP connection times out.
          354  */
          355          inputfd = -1;
          356         if (!statflag && !killflag) {
          357                 if (optind < argc) {
          358                         inputname = argv[optind++];
          359                         debug("open("); debug(inputname); debug(")\n");
          360                         inputfd = open(inputname, O_RDONLY);
          361                         if (inputfd < 0) {
          362                                 fprintf(stderr, "open(%s) failed\n", inputname);
          363                                 exit(1);
          364                         }
          365                 } else {
          366                         inputname = "stdin";
          367                         tmpnam(tmpfilename);
          368                         debug("using stdin\n");
          369                         if ((inputfd = create(tmpfilename, ORDWR, 0600)) < 0) {
          370                                 fprintf(stderr, "open(%s) failed\n", tmpfilename);
          371                                 exit(1);
          372                         }
          373                         atexit(cleanup);
          374                         debug("copy input to temp file ");
          375                         debug(tmpfilename);
          376                         debug("\n");
          377                         if (!copyfile(0, inputfd, 0L)) {
          378                                 fprintf(stderr, "failed to copy file to temporary file\n");
          379                                 exit(1);
          380                         }
          381                         if (lseek(inputfd, 0L, 0) < 0) {
          382                                 fprintf(stderr, "failed to seek back to the beginning of the temporary file\n");
          383                                 exit(1);
          384                         }
          385                 }
          386         }
          387 
          388         sprintf(strbuf, "%s", netmkaddr(desthostname, "tcp", "printer"));
          389         fprintf(stderr, "connecting to %s\n", strbuf);
          390         for (sendport=721; sendport<=731; sendport++) {
          391                 sprintf(portstr, "%3.3d", sendport);
          392                 fprintf(stderr, " trying from port %s...", portstr);
          393                 debug(" dial("); debug(strbuf); debug(", "); debug(portstr); debug(", 0, 0) ...");
          394                 printerfd = dial(strbuf, portstr, 0, 0);
          395                 if (printerfd >= 0) {
          396                         fprintf(stderr, "connected\n");
          397                         break;
          398                 }
          399                 fprintf(stderr, "failed\n");
          400                 sleep(REDIALTIMEOUT);
          401         }
          402         if (printerfd < 0) {
          403                 fprintf(stderr, "Cannot open a valid port!\n");
          404                 fprintf(stderr, "-  All source ports [721-731] may be busy.\n");
          405                 fprintf(stderr, "-  Is recipient ready and online?\n");
          406                 fprintf(stderr, "-  If all else fails, cycle the power!\n");
          407                 exit(1);
          408         }
          409 /*        hostname[8] = '\0'; */
          410 #ifndef PLAN9
          411         if (gethostname(hostname, sizeof(hostname)) < 0) {
          412                 perror("gethostname");
          413                 exit(1);
          414         }
          415 #endif
          416 /*        char *hnend;
          417         if ((hnend = strchr(hostname, '.')) != NULL)
          418                 *hnend = '\0';
          419  */
          420         if (statflag) {
          421                 checkqueue(printerfd);
          422         } else if (killflag) {
          423                 killjob(printerfd);
          424         } else {
          425                 sendjob(inputfd, printerfd);
          426         }
          427         exit(0);
          428 }