tlpdsend.c - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
tlpdsend.c (9564B)
---
     1 #include 
     2 #include 
     3 #include 
     4 #include 
     5 #include 
     6 #include 
     7 #include 
     8 #include 
     9 #include 
    10 #include 
    11 #include 
    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 }